]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/ppp/ip.c
This commit was generated by cvs2svn to compensate for changes in r53796,
[FreeBSD/FreeBSD.git] / usr.sbin / ppp / ip.c
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$
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
71 static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
72
73 static __inline int
74 PortMatch(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  */
96 static int
97 FilterCheck(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_GRE
174           case IPPROTO_GRE:
175             cproto = P_GRE;
176             if (datalen < 2)    /* GRE uses 2-octet+ messages */
177               return (1);
178             estab = syn = finrst = -1;
179             sport = ntohs(0);
180             break;
181 #endif
182 #ifdef IPPROTO_OSPFIGP
183           case IPPROTO_OSPFIGP:
184             cproto = P_OSPF;
185             if (datalen < 8)    /* IGMP uses 8-octet messages */
186               return (1);
187             estab = syn = finrst = -1;
188             sport = ntohs(0);
189             break;
190 #endif
191           case IPPROTO_UDP:
192           case IPPROTO_IPIP:
193             cproto = P_UDP;
194             if (datalen < 8)    /* UDP header is 8 octets */
195               return (1);
196             uh = (const struct udphdr *) ptop;
197             sport = ntohs(uh->uh_sport);
198             dport = ntohs(uh->uh_dport);
199             estab = syn = finrst = -1;
200             if (log_IsKept(LogDEBUG))
201               snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
202                        sport, dport);
203             break;
204           case IPPROTO_TCP:
205             cproto = P_TCP;
206             th = (const struct tcphdr *) ptop;
207             /* TCP headers are variable length.  The following code
208              * ensures that the TCP header length isn't de-referenced if
209              * the datagram is too short
210              */
211             if (datalen < 20 || datalen < (th->th_off << 2))
212               return (1);
213             sport = ntohs(th->th_sport);
214             dport = ntohs(th->th_dport);
215             estab = (th->th_flags & TH_ACK);
216             syn = (th->th_flags & TH_SYN);
217             finrst = (th->th_flags & (TH_FIN|TH_RST));
218             if (log_IsKept(LogDEBUG)) {
219               if (!estab)
220                 snprintf(dbuff, sizeof dbuff,
221                          "flags = %02x, sport = %d, dport = %d",
222                          th->th_flags, sport, dport);
223               else
224                 *dbuff = '\0';
225             }
226             break;
227           default:
228             return (1); /* We'll block unknown type of packet */
229           }
230
231           if (log_IsKept(LogDEBUG)) {
232             if (estab != -1) {
233               len = strlen(dbuff);
234               snprintf(dbuff + len, sizeof dbuff - len,
235                        ", estab = %d, syn = %d, finrst = %d",
236                        estab, syn, finrst);
237             }
238             log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
239                        filter_Proto2Nam(cproto), dbuff);
240           }
241           gotinfo = 1;
242         }
243         if (log_IsKept(LogDEBUG)) {
244           if (fp->f_srcop != OP_NONE) {
245             snprintf(dbuff, sizeof dbuff, ", src %s %d",
246                      filter_Op2Nam(fp->f_srcop), fp->f_srcport);
247             len = strlen(dbuff);
248           } else
249             len = 0;
250           if (fp->f_dstop != OP_NONE) {
251             snprintf(dbuff + len, sizeof dbuff - len,
252                      ", dst %s %d", filter_Op2Nam(fp->f_dstop),
253                      fp->f_dstport);
254           } else if (!len)
255             *dbuff = '\0';
256
257           log_Printf(LogDEBUG, "  rule = %d: Address match, "
258                      "check against proto %s%s, action = %s\n",
259                      n, filter_Proto2Nam(fp->f_proto),
260                      dbuff, filter_Action2Nam(fp->f_action));
261         }
262
263         if (cproto == fp->f_proto) {
264           if ((fp->f_srcop == OP_NONE ||
265                PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
266               (fp->f_dstop == OP_NONE ||
267                PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
268               (fp->f_estab == 0 || estab) &&
269               (fp->f_syn == 0 || syn) &&
270               (fp->f_finrst == 0 || finrst)) {
271             match = 1;
272           }
273         }
274       } else {
275         /* Address is matched and no protocol specified. Make a decision. */
276         log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
277                    filter_Action2Nam(fp->f_action));
278         match = 1;
279       }
280     } else
281       log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
282
283     if (match != fp->f_invert) {
284       /* Take specified action */
285       if (fp->f_action < A_NONE)
286         fp = &filter->rule[n = fp->f_action];
287       else
288         return (fp->f_action != A_PERMIT);
289     } else {
290       n++;
291       fp++;
292     }
293   }
294   return (1);           /* No rule is mached. Deny this packet */
295 }
296
297 #ifdef notdef
298 static void
299 IcmpError(struct ip *pip, int code)
300 {
301   struct mbuf *bp;
302
303   if (pip->ip_p != IPPROTO_ICMP) {
304     bp = mbuf_Alloc(cnt, MB_IPIN);
305     memcpy(MBUF_CTOP(bp), ptr, cnt);
306     vj_SendFrame(bp);
307     ipcp_AddOutOctets(cnt);
308   }
309 }
310 #endif
311
312 /*
313  *  For debugging aid.
314  */
315 int
316 PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
317 {
318   struct ip *pip;
319   struct tcphdr *th;
320   struct udphdr *uh;
321   struct icmp *icmph;
322   char *ptop;
323   int mask, len, n;
324   int pri = 0;
325   int logit, loglen;
326   char logbuf[200];
327
328   logit = log_IsKept(LogTCPIP) && filter->logok;
329   loglen = 0;
330
331   pip = (struct ip *) cp;
332
333   if (logit && loglen < sizeof logbuf) {
334     snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
335     loglen += strlen(logbuf + loglen);
336   }
337   ptop = (cp + (pip->ip_hl << 2));
338
339   switch (pip->ip_p) {
340   case IPPROTO_ICMP:
341     if (logit && loglen < sizeof logbuf) {
342       icmph = (struct icmp *) ptop;
343       snprintf(logbuf + loglen, sizeof logbuf - loglen,
344              "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
345       loglen += strlen(logbuf + loglen);
346       snprintf(logbuf + loglen, sizeof logbuf - loglen,
347                "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
348       loglen += strlen(logbuf + loglen);
349     }
350     break;
351
352   case IPPROTO_UDP:
353     uh = (struct udphdr *) ptop;
354     if (pip->ip_tos == IPTOS_LOWDELAY)
355       pri++;
356
357     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
358         ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport),
359                           ntohs(uh->uh_dport)))
360       pri++;
361
362     if (logit && loglen < sizeof logbuf) {
363       snprintf(logbuf + loglen, sizeof logbuf - loglen,
364            "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
365       loglen += strlen(logbuf + loglen);
366       snprintf(logbuf + loglen, sizeof logbuf - loglen,
367                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
368       loglen += strlen(logbuf + loglen);
369     }
370     break;
371
372 #ifdef IPPROTO_GRE
373   case IPPROTO_GRE:
374     if (logit && loglen < sizeof logbuf) {
375       snprintf(logbuf + loglen, sizeof logbuf - loglen,
376           "GRE: %s ---> ", inet_ntoa(pip->ip_src));
377       loglen += strlen(logbuf + loglen);
378       snprintf(logbuf + loglen, sizeof logbuf - loglen,
379               "%s", inet_ntoa(pip->ip_dst));
380       loglen += strlen(logbuf + loglen);
381     }
382     break;
383 #endif
384
385 #ifdef IPPROTO_OSPFIGP
386   case IPPROTO_OSPFIGP:
387     if (logit && loglen < sizeof logbuf) {
388       snprintf(logbuf + loglen, sizeof logbuf - loglen,
389            "OSPF: %s ---> ", inet_ntoa(pip->ip_src));
390       loglen += strlen(logbuf + loglen);
391       snprintf(logbuf + loglen, sizeof logbuf - loglen,
392                "%s", inet_ntoa(pip->ip_dst));
393       loglen += strlen(logbuf + loglen);
394     }
395     break;
396 #endif
397
398   case IPPROTO_IPIP:
399     if (logit && loglen < sizeof logbuf) {
400       uh = (struct udphdr *) ptop;
401       snprintf(logbuf + loglen, sizeof logbuf - loglen,
402            "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
403       loglen += strlen(logbuf + loglen);
404       snprintf(logbuf + loglen, sizeof logbuf - loglen,
405                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
406       loglen += strlen(logbuf + loglen);
407     }
408     break;
409
410   case IPPROTO_IGMP:
411     if (logit && loglen < sizeof logbuf) {
412       uh = (struct udphdr *) ptop;
413       snprintf(logbuf + loglen, sizeof logbuf - loglen,
414            "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
415       loglen += strlen(logbuf + loglen);
416       snprintf(logbuf + loglen, sizeof logbuf - loglen,
417                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
418       loglen += strlen(logbuf + loglen);
419     }
420     break;
421
422   case IPPROTO_TCP:
423     th = (struct tcphdr *) ptop;
424     if (pip->ip_tos == IPTOS_LOWDELAY)
425       pri++;
426
427     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
428         ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport),
429                           ntohs(th->th_dport)))
430       pri++;
431
432     if (logit && loglen < sizeof logbuf) {
433       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
434       snprintf(logbuf + loglen, sizeof logbuf - loglen,
435            "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
436       loglen += strlen(logbuf + loglen);
437       snprintf(logbuf + loglen, sizeof logbuf - loglen,
438                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
439       loglen += strlen(logbuf + loglen);
440       n = 0;
441       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
442         if (th->th_flags & mask) {
443           snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
444           loglen += strlen(logbuf + loglen);
445         }
446         n++;
447       }
448       snprintf(logbuf + loglen, sizeof logbuf - loglen,
449                "  seq:%lx  ack:%lx (%d/%d)",
450                (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
451       loglen += strlen(logbuf + loglen);
452       if ((th->th_flags & TH_SYN) && nb > 40) {
453         u_short *sp;
454
455         ptop += 20;
456         sp = (u_short *) ptop;
457         if (ntohs(sp[0]) == 0x0204) {
458           snprintf(logbuf + loglen, sizeof logbuf - loglen,
459                    " MSS = %d", ntohs(sp[1]));
460           loglen += strlen(logbuf + loglen);
461         }
462       }
463     }
464     break;
465   }
466
467   if (FilterCheck(pip, filter)) {
468     if (logit)
469       log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
470 #ifdef notdef
471     if (direction == 0)
472       IcmpError(pip, pri);
473 #endif
474     return (-1);
475   } else {
476     /* Check Keep Alive filter */
477     if (logit) {
478       if (FilterCheck(pip, &bundle->filter.alive))
479         log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
480       else
481         log_Printf(LogTCPIP, "%s\n", logbuf);
482     }
483     return (pri);
484   }
485 }
486
487 struct mbuf *
488 ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
489 {
490   int nb, nw;
491   struct tun_data tun;
492   struct ip *pip;
493
494   if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
495     log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
496     mbuf_Free(bp);
497     return NULL;
498   }
499
500   mbuf_SetType(bp, MB_IPIN);
501   tun_fill_header(tun, AF_INET);
502   nb = mbuf_Length(bp);
503   if (nb > sizeof tun.data) {
504     log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
505                l->name, nb, (int)(sizeof tun.data));
506     mbuf_Free(bp);
507     return NULL;
508   }
509   mbuf_Read(bp, tun.data, nb);
510
511   if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
512     return NULL;
513
514   pip = (struct ip *)tun.data;
515   if (!FilterCheck(pip, &bundle->filter.alive))
516     bundle_StartIdleTimer(bundle);
517
518   ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
519
520   nb += sizeof tun - sizeof tun.data;
521   nw = write(bundle->dev.fd, &tun, nb);
522   if (nw != nb) {
523     if (nw == -1)
524       log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
525                  l->name, nb, strerror(errno));
526     else
527       log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
528   }
529
530   return NULL;
531 }
532
533 void
534 ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
535 {
536   struct mbuf *bp;
537
538   if (pri < 0 || pri >= IPCP_QUEUES(ipcp))
539     log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
540   else {
541     /*
542      * We allocate an extra 6 bytes, four at the front and two at the end.
543      * This is an optimisation so that we need to do less work in
544      * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and
545      * appending in hdlc_LayerPush().
546      */
547     bp = mbuf_Alloc(count + 6, MB_IPOUT);
548     bp->offset += 4;
549     bp->cnt -= 6;
550     memcpy(MBUF_CTOP(bp), ptr, count);
551     mbuf_Enqueue(ipcp->Queue + pri, bp);
552   }
553 }
554
555 void
556 ip_DeleteQueue(struct ipcp *ipcp)
557 {
558   struct mqueue *queue;
559
560   for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
561     while (queue->top)
562       mbuf_Free(mbuf_Dequeue(queue));
563 }
564
565 int
566 ip_QueueLen(struct ipcp *ipcp)
567 {
568   struct mqueue *queue;
569   int result = 0;
570
571   for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
572     result += queue->qlen;
573
574   return result;
575 }
576
577 int
578 ip_PushPacket(struct link *l, struct bundle *bundle)
579 {
580   struct ipcp *ipcp = &bundle->ncp.ipcp;
581   struct mqueue *queue;
582   struct mbuf *bp;
583   struct ip *pip;
584   int cnt;
585
586   if (ipcp->fsm.state != ST_OPENED)
587     return 0;
588
589   queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1;
590   do {
591     if (queue->top) {
592       bp = mbuf_Contiguous(mbuf_Dequeue(queue));
593       cnt = mbuf_Length(bp);
594       pip = (struct ip *)MBUF_CTOP(bp);
595       if (!FilterCheck(pip, &bundle->filter.alive))
596         bundle_StartIdleTimer(bundle);
597       link_PushPacket(l, bp, bundle, 0, PROTO_IP);
598       ipcp_AddOutOctets(ipcp, cnt);
599       return 1;
600     }
601   } while (queue-- != ipcp->Queue);
602
603   return 0;
604 }