Deleted Added
full compact
1/*
2 * PPP IP Protocol Interface
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $FreeBSD: head/usr.sbin/ppp/ip.c 50479 1999-08-28 01:35:59Z peter $
20 * $FreeBSD: head/usr.sbin/ppp/ip.c 50867 1999-09-04 00:00:21Z brian $
21 *
22 * TODO:
23 * o Return ICMP message for filterd packet
24 * and optionaly record it into log.
25 */
26#include <sys/param.h>
27#if defined(__OpenBSD__) || defined(__NetBSD__)
28#include <sys/socket.h>
29#endif
30#include <netinet/in.h>
31#include <netinet/in_systm.h>
32#include <netinet/ip.h>
33#include <netinet/ip_icmp.h>
34#include <netinet/udp.h>
35#include <netinet/tcp.h>
36#include <arpa/inet.h>
37#include <sys/un.h>
38
39#include <errno.h>
40#include <stdio.h>
41#include <string.h>
42#include <termios.h>
43#include <unistd.h>
44
45#include "layer.h"
46#include "proto.h"
47#include "mbuf.h"
48#include "log.h"
49#include "defs.h"
50#include "timer.h"
51#include "fsm.h"
52#include "lqr.h"
53#include "hdlc.h"
54#include "throughput.h"
55#include "iplist.h"
56#include "slcompress.h"
57#include "ipcp.h"
58#include "filter.h"
59#include "descriptor.h"
60#include "lcp.h"
61#include "ccp.h"
62#include "link.h"
63#include "mp.h"
64#ifndef NORADIUS
65#include "radius.h"
66#endif
67#include "bundle.h"
68#include "tun.h"
69#include "ip.h"
70
71static const u_short interactive_ports[32] = {
72 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
74};
75
76#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p))
77
71static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
72
73static __inline int
74PortMatch(int op, u_short pport, u_short rport)
75{
76 switch (op) {
77 case OP_EQ:
78 return (pport == rport);
79 case OP_GT:
80 return (pport > rport);
81 case OP_LT:
82 return (pport < rport);
83 default:
84 return (0);
85 }
86}
87
88/*
89 * Check a packet against a defined filter
90 * Returns 0 to accept the packet, non-zero to drop the packet
91 *
92 * If filtering is enabled, the initial fragment of a datagram must
93 * contain the complete protocol header, and subsequent fragments
94 * must not attempt to over-write it.
95 */
96static int
97FilterCheck(const struct ip *pip, const struct filter *filter)
98{
99 int gotinfo; /* true if IP payload decoded */
100 int cproto; /* P_* protocol type if (gotinfo) */
101 int estab, syn, finrst; /* TCP state flags if (gotinfo) */
102 u_short sport, dport; /* src, dest port from packet if (gotinfo) */
103 int n; /* filter rule to process */
104 int len; /* bytes used in dbuff */
105 int didname; /* true if filter header printed */
106 int match; /* true if condition matched */
107 const struct filterent *fp = filter->rule;
108 char dbuff[100];
109
110 if (fp->f_action == A_NONE)
111 return (0); /* No rule is given. Permit this packet */
112
113 /* Deny any packet fragment that tries to over-write the header.
114 * Since we no longer have the real header available, punt on the
115 * largest normal header - 20 bytes for TCP without options, rounded
116 * up to the next possible fragment boundary. Since the smallest
117 * `legal' MTU is 576, and the smallest recommended MTU is 296, any
118 * fragmentation within this range is dubious at best */
119 len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */
120 if (len > 0) { /* Not first fragment within datagram */
121 if (len < (24 >> 3)) /* don't allow fragment to over-write header */
122 return (1);
123 /* permit fragments on in and out filter */
124 return (filter->fragok);
125 }
126
127 cproto = gotinfo = estab = syn = finrst = didname = 0;
128 sport = dport = 0;
129 for (n = 0; n < MAXFILTERS; ) {
130 if (fp->f_action == A_NONE) {
131 n++;
132 fp++;
133 continue;
134 }
135
136 if (!didname) {
137 log_Printf(LogDEBUG, "%s filter:\n", filter->name);
138 didname = 1;
139 }
140
141 match = 0;
142 if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
143 fp->f_src.mask.s_addr) &&
144 !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
145 fp->f_dst.mask.s_addr)) {
146 if (fp->f_proto != P_NONE) {
147 if (!gotinfo) {
148 const char *ptop = (const char *) pip + (pip->ip_hl << 2);
149 const struct tcphdr *th;
150 const struct udphdr *uh;
151 const struct icmp *ih;
152 int datalen; /* IP datagram length */
153
154 datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
155 switch (pip->ip_p) {
156 case IPPROTO_ICMP:
157 cproto = P_ICMP;
158 if (datalen < 8) /* ICMP must be at least 8 octets */
159 return (1);
160 ih = (const struct icmp *) ptop;
161 sport = ih->icmp_type;
162 estab = syn = finrst = -1;
163 if (log_IsKept(LogDEBUG))
164 snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
165 break;
166 case IPPROTO_IGMP:
167 cproto = P_IGMP;
168 if (datalen < 8) /* IGMP uses 8-octet messages */
169 return (1);
170 estab = syn = finrst = -1;
171 sport = ntohs(0);
172 break;
173#ifdef IPPROTO_OSPFIGP
174 case IPPROTO_OSPFIGP:
175 cproto = P_OSPF;
176 if (datalen < 8) /* IGMP uses 8-octet messages */
177 return (1);
178 estab = syn = finrst = -1;
179 sport = ntohs(0);
180 break;
181#endif
182 case IPPROTO_UDP:
183 case IPPROTO_IPIP:
184 cproto = P_UDP;
185 if (datalen < 8) /* UDP header is 8 octets */
186 return (1);
187 uh = (const struct udphdr *) ptop;
188 sport = ntohs(uh->uh_sport);
189 dport = ntohs(uh->uh_dport);
190 estab = syn = finrst = -1;
191 if (log_IsKept(LogDEBUG))
192 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
193 sport, dport);
194 break;
195 case IPPROTO_TCP:
196 cproto = P_TCP;
197 th = (const struct tcphdr *) ptop;
198 /* TCP headers are variable length. The following code
199 * ensures that the TCP header length isn't de-referenced if
200 * the datagram is too short
201 */
202 if (datalen < 20 || datalen < (th->th_off << 2))
203 return (1);
204 sport = ntohs(th->th_sport);
205 dport = ntohs(th->th_dport);
206 estab = (th->th_flags & TH_ACK);
207 syn = (th->th_flags & TH_SYN);
208 finrst = (th->th_flags & (TH_FIN|TH_RST));
209 if (log_IsKept(LogDEBUG)) {
210 if (!estab)
211 snprintf(dbuff, sizeof dbuff,
212 "flags = %02x, sport = %d, dport = %d",
213 th->th_flags, sport, dport);
214 else
215 *dbuff = '\0';
216 }
217 break;
218 default:
219 return (1); /* We'll block unknown type of packet */
220 }
221
222 if (log_IsKept(LogDEBUG)) {
223 if (estab != -1) {
224 len = strlen(dbuff);
225 snprintf(dbuff + len, sizeof dbuff - len,
226 ", estab = %d, syn = %d, finrst = %d",
227 estab, syn, finrst);
228 }
229 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
230 filter_Proto2Nam(cproto), dbuff);
231 }
232 gotinfo = 1;
233 }
234 if (log_IsKept(LogDEBUG)) {
235 if (fp->f_srcop != OP_NONE) {
236 snprintf(dbuff, sizeof dbuff, ", src %s %d",
237 filter_Op2Nam(fp->f_srcop), fp->f_srcport);
238 len = strlen(dbuff);
239 } else
240 len = 0;
241 if (fp->f_dstop != OP_NONE) {
242 snprintf(dbuff + len, sizeof dbuff - len,
243 ", dst %s %d", filter_Op2Nam(fp->f_dstop),
244 fp->f_dstport);
245 } else if (!len)
246 *dbuff = '\0';
247
248 log_Printf(LogDEBUG, " rule = %d: Address match, "
249 "check against proto %s%s, action = %s\n",
250 n, filter_Proto2Nam(fp->f_proto),
251 dbuff, filter_Action2Nam(fp->f_action));
252 }
253
254 if (cproto == fp->f_proto) {
255 if ((fp->f_srcop == OP_NONE ||
256 PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
257 (fp->f_dstop == OP_NONE ||
258 PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
259 (fp->f_estab == 0 || estab) &&
260 (fp->f_syn == 0 || syn) &&
261 (fp->f_finrst == 0 || finrst)) {
262 match = 1;
263 }
264 }
265 } else {
266 /* Address is matched and no protocol specified. Make a decision. */
267 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
268 filter_Action2Nam(fp->f_action));
269 match = 1;
270 }
271 } else
272 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
273
274 if (match != fp->f_invert) {
275 /* Take specified action */
276 if (fp->f_action < A_NONE)
277 fp = &filter->rule[n = fp->f_action];
278 else
279 return (fp->f_action != A_PERMIT);
280 } else {
281 n++;
282 fp++;
283 }
284 }
285 return (1); /* No rule is mached. Deny this packet */
286}
287
288#ifdef notdef
289static void
290IcmpError(struct ip *pip, int code)
291{
292 struct mbuf *bp;
293
294 if (pip->ip_p != IPPROTO_ICMP) {
295 bp = mbuf_Alloc(cnt, MB_IPIN);
296 memcpy(MBUF_CTOP(bp), ptr, cnt);
297 vj_SendFrame(bp);
298 ipcp_AddOutOctets(cnt);
299 }
300}
301#endif
302
303/*
304 * For debugging aid.
305 */
306int
307PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
308{
309 struct ip *pip;
310 struct tcphdr *th;
311 struct udphdr *uh;
312 struct icmp *icmph;
313 char *ptop;
314 int mask, len, n;
322 int pri = PRI_NORMAL;
315 int pri = 0;
316 int logit, loglen;
317 char logbuf[200];
318
319 logit = log_IsKept(LogTCPIP) && filter->logok;
320 loglen = 0;
321
322 pip = (struct ip *) cp;
323
324 if (logit && loglen < sizeof logbuf) {
325 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
326 loglen += strlen(logbuf + loglen);
327 }
328 ptop = (cp + (pip->ip_hl << 2));
329
330 switch (pip->ip_p) {
331 case IPPROTO_ICMP:
332 if (logit && loglen < sizeof logbuf) {
333 icmph = (struct icmp *) ptop;
334 snprintf(logbuf + loglen, sizeof logbuf - loglen,
335 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
336 loglen += strlen(logbuf + loglen);
337 snprintf(logbuf + loglen, sizeof logbuf - loglen,
338 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
339 loglen += strlen(logbuf + loglen);
340 }
341 break;
342 case IPPROTO_UDP:
343 if (logit && loglen < sizeof logbuf) {
344 uh = (struct udphdr *) ptop;
345 snprintf(logbuf + loglen, sizeof logbuf - loglen,
346 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
347 loglen += strlen(logbuf + loglen);
348 snprintf(logbuf + loglen, sizeof logbuf - loglen,
349 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
350 loglen += strlen(logbuf + loglen);
351 }
352 break;
353#ifdef IPPROTO_OSPFIGP
354 case IPPROTO_OSPFIGP:
355 if (logit && loglen < sizeof logbuf) {
356 snprintf(logbuf + loglen, sizeof logbuf - loglen,
357 "OSPF: %s ---> ", inet_ntoa(pip->ip_src));
358 loglen += strlen(logbuf + loglen);
359 snprintf(logbuf + loglen, sizeof logbuf - loglen,
360 "%s", inet_ntoa(pip->ip_dst));
361 loglen += strlen(logbuf + loglen);
362 }
363 break;
364#endif
365 case IPPROTO_IPIP:
366 if (logit && loglen < sizeof logbuf) {
367 uh = (struct udphdr *) ptop;
368 snprintf(logbuf + loglen, sizeof logbuf - loglen,
369 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
370 loglen += strlen(logbuf + loglen);
371 snprintf(logbuf + loglen, sizeof logbuf - loglen,
372 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
373 loglen += strlen(logbuf + loglen);
374 }
375 break;
376 case IPPROTO_IGMP:
377 if (logit && loglen < sizeof logbuf) {
378 uh = (struct udphdr *) ptop;
379 snprintf(logbuf + loglen, sizeof logbuf - loglen,
380 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
381 loglen += strlen(logbuf + loglen);
382 snprintf(logbuf + loglen, sizeof logbuf - loglen,
383 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
384 loglen += strlen(logbuf + loglen);
385 }
386 break;
387 case IPPROTO_TCP:
388 th = (struct tcphdr *) ptop;
389 if (pip->ip_tos == IPTOS_LOWDELAY)
397 pri = PRI_FAST;
398 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
399 if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
400 pri = PRI_FAST;
401 }
390 pri++;
391 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
392 ipcp_IsUrgentPort(&bundle->ncp.ipcp, ntohs(th->th_sport),
393 ntohs(th->th_dport)))
394 pri++;
395
396 if (logit && loglen < sizeof logbuf) {
397 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
398 snprintf(logbuf + loglen, sizeof logbuf - loglen,
399 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
400 loglen += strlen(logbuf + loglen);
401 snprintf(logbuf + loglen, sizeof logbuf - loglen,
402 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
403 loglen += strlen(logbuf + loglen);
404 n = 0;
405 for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
406 if (th->th_flags & mask) {
407 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
408 loglen += strlen(logbuf + loglen);
409 }
410 n++;
411 }
412 snprintf(logbuf + loglen, sizeof logbuf - loglen,
413 " seq:%lx ack:%lx (%d/%d)",
414 (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
415 loglen += strlen(logbuf + loglen);
416 if ((th->th_flags & TH_SYN) && nb > 40) {
417 u_short *sp;
418
419 ptop += 20;
420 sp = (u_short *) ptop;
421 if (ntohs(sp[0]) == 0x0204) {
422 snprintf(logbuf + loglen, sizeof logbuf - loglen,
423 " MSS = %d", ntohs(sp[1]));
424 loglen += strlen(logbuf + loglen);
425 }
426 }
427 }
428 break;
429 }
430
431 if (FilterCheck(pip, filter)) {
432 if (logit)
433 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
434#ifdef notdef
435 if (direction == 0)
436 IcmpError(pip, pri);
437#endif
438 return (-1);
439 } else {
440 /* Check Keep Alive filter */
441 if (logit) {
442 if (FilterCheck(pip, &bundle->filter.alive))
443 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
444 else
445 log_Printf(LogTCPIP, "%s\n", logbuf);
446 }
447 return (pri);
448 }
449}
450
451struct mbuf *
452ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
453{
454 int nb, nw;
455 struct tun_data tun;
456 struct ip *pip;
457
458 if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
459 log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
460 mbuf_Free(bp);
461 return NULL;
462 }
463
464 mbuf_SetType(bp, MB_IPIN);
465 tun_fill_header(tun, AF_INET);
466 nb = mbuf_Length(bp);
467 if (nb > sizeof tun.data) {
468 log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
469 l->name, nb, (int)(sizeof tun.data));
470 mbuf_Free(bp);
471 return NULL;
472 }
473 mbuf_Read(bp, tun.data, nb);
474
475 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
476 return NULL;
477
478 pip = (struct ip *)tun.data;
479 if (!FilterCheck(pip, &bundle->filter.alive))
480 bundle_StartIdleTimer(bundle);
481
482 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
483
484 nb += sizeof tun - sizeof tun.data;
485 nw = write(bundle->dev.fd, &tun, nb);
486 if (nw != nb) {
487 if (nw == -1)
488 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
489 l->name, nb, strerror(errno));
490 else
491 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
492 }
493
494 return NULL;
495}
496
497void
498ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
499{
500 struct mbuf *bp;
501
508 if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0])
502 if (pri < 0 || pri >= IPCP_QUEUES(ipcp))
503 log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
504 else {
505 /*
506 * We allocate an extra 6 bytes, four at the front and two at the end.
507 * This is an optimisation so that we need to do less work in
508 * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and
509 * appending in hdlc_LayerPush().
510 */
511 bp = mbuf_Alloc(count + 6, MB_IPOUT);
512 bp->offset += 4;
513 bp->cnt -= 6;
514 memcpy(MBUF_CTOP(bp), ptr, count);
521 mbuf_Enqueue(&ipcp->Queue[pri], bp);
515 mbuf_Enqueue(ipcp->Queue + pri, bp);
516 }
517}
518
519void
520ip_DeleteQueue(struct ipcp *ipcp)
521{
522 struct mqueue *queue;
523
530 for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
524 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
525 while (queue->top)
526 mbuf_Free(mbuf_Dequeue(queue));
527}
528
529int
530ip_QueueLen(struct ipcp *ipcp)
531{
532 struct mqueue *queue;
533 int result = 0;
534
541 for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
535 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
536 result += queue->qlen;
537
538 return result;
539}
540
541int
542ip_PushPacket(struct link *l, struct bundle *bundle)
543{
544 struct ipcp *ipcp = &bundle->ncp.ipcp;
545 struct mqueue *queue;
546 struct mbuf *bp;
547 struct ip *pip;
548 int cnt;
549
550 if (ipcp->fsm.state != ST_OPENED)
551 return 0;
552
559 for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--)
553 queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1;
554 do {
555 if (queue->top) {
556 bp = mbuf_Contiguous(mbuf_Dequeue(queue));
557 cnt = mbuf_Length(bp);
558 pip = (struct ip *)MBUF_CTOP(bp);
559 if (!FilterCheck(pip, &bundle->filter.alive))
560 bundle_StartIdleTimer(bundle);
566 link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP);
561 link_PushPacket(l, bp, bundle, 0, PROTO_IP);
562 ipcp_AddOutOctets(ipcp, cnt);
563 return 1;
564 }
565 } while (queue-- != ipcp->Queue);
566
567 return 0;
568}