xref: /freebsd/usr.sbin/ppp/ip.c (revision 057f1760)
1 /*-
2  * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3  *          based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4  *                           Internet Initiative Japan, Inc (IIJ)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36 #ifndef NOINET6
37 #include <netinet/icmp6.h>
38 #include <netinet/ip6.h>
39 #endif
40 #include <netinet/ip_icmp.h>
41 #include <netinet/udp.h>
42 #include <netinet/tcp.h>
43 #include <sys/un.h>
44 
45 #include <errno.h>
46 #include <netdb.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <termios.h>
50 #include <unistd.h>
51 
52 #include "layer.h"
53 #include "proto.h"
54 #include "mbuf.h"
55 #include "log.h"
56 #include "defs.h"
57 #include "timer.h"
58 #include "fsm.h"
59 #include "lqr.h"
60 #include "hdlc.h"
61 #include "throughput.h"
62 #include "iplist.h"
63 #include "slcompress.h"
64 #include "ncpaddr.h"
65 #include "ip.h"
66 #include "ipcp.h"
67 #include "filter.h"
68 #include "descriptor.h"
69 #include "lcp.h"
70 #include "ccp.h"
71 #include "link.h"
72 #include "mp.h"
73 #ifndef NORADIUS
74 #include "radius.h"
75 #endif
76 #include "ipv6cp.h"
77 #include "ncp.h"
78 #include "bundle.h"
79 #include "tun.h"
80 
81 
82 #define OPCODE_QUERY	0
83 #define OPCODE_IQUERY	1
84 #define OPCODE_STATUS	2
85 
86 struct dns_header {
87   u_short id;
88   unsigned qr : 1;
89   unsigned opcode : 4;
90   unsigned aa : 1;
91   unsigned tc : 1;
92   unsigned rd : 1;
93   unsigned ra : 1;
94   unsigned z : 3;
95   unsigned rcode : 4;
96   u_short qdcount;
97   u_short ancount;
98   u_short nscount;
99   u_short arcount;
100 };
101 
102 static const char *
103 dns_Qclass2Txt(u_short qclass)
104 {
105   static char failure[6];
106   struct {
107     u_short id;
108     const char *txt;
109   } qtxt[] = {
110     /* rfc1035 */
111     { 1, "IN" }, { 2, "CS" }, { 3, "CH" }, { 4, "HS" }, { 255, "*" }
112   };
113   unsigned f;
114 
115   for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++)
116     if (qtxt[f].id == qclass)
117       return qtxt[f].txt;
118 
119   return HexStr(qclass, failure, sizeof failure);
120 }
121 
122 static const char *
123 dns_Qtype2Txt(u_short qtype)
124 {
125   static char failure[6];
126   struct {
127     u_short id;
128     const char *txt;
129   } qtxt[] = {
130     /* rfc1035/rfc1700 */
131     { 1, "A" }, { 2, "NS" }, { 3, "MD" }, { 4, "MF" }, { 5, "CNAME" },
132     { 6, "SOA" }, { 7, "MB" }, { 8, "MG" }, { 9, "MR" }, { 10, "NULL" },
133     { 11, "WKS" }, { 12, "PTR" }, { 13, "HINFO" }, { 14, "MINFO" },
134     { 15, "MX" }, { 16, "TXT" }, { 17, "RP" }, { 18, "AFSDB" },
135     { 19, "X25" }, { 20, "ISDN" }, { 21, "RT" }, { 22, "NSAP" },
136     { 23, "NSAP-PTR" }, { 24, "SIG" }, { 25, "KEY" }, { 26, "PX" },
137     { 27, "GPOS" }, { 28, "AAAA" }, { 252, "AXFR" }, { 253, "MAILB" },
138     { 254, "MAILA" }, { 255, "*" }
139   };
140   unsigned f;
141 
142   for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++)
143     if (qtxt[f].id == qtype)
144       return qtxt[f].txt;
145 
146   return HexStr(qtype, failure, sizeof failure);
147 }
148 
149 static __inline int
150 PortMatch(int op, u_short pport, u_short rport)
151 {
152   switch (op) {
153   case OP_EQ:
154     return pport == rport;
155   case OP_GT:
156     return pport > rport;
157   case OP_LT:
158     return pport < rport;
159   default:
160     return 0;
161   }
162 }
163 
164 /*
165  * Return a text string representing the cproto protocol number.
166  *
167  * The purpose of this routine is calculate this result, for
168  * the many times it is needed in FilterCheck, only on demand
169  * (i.e. when the corresponding logging functions are invoked).
170  *
171  * This optimization saves, over the previous implementation, which
172  * calculated prototxt at the beginning of FilterCheck, an
173  * open/read/close system call sequence per packet, approximately
174  * halving the ppp system overhead and reducing the overall (u + s)
175  * time by 38%.
176  *
177  * The caching performed here is just a side effect.
178  */
179 static const char *
180 prototxt(int cproto)
181 {
182   static int oproto = -1;
183   static char protobuff[16] = "-1";
184   struct protoent *pe;
185 
186   if (cproto == oproto)
187 	return protobuff;
188   if ((pe = getprotobynumber(cproto)) == NULL)
189     snprintf(protobuff, sizeof protobuff, "%d", cproto);
190   else
191     snprintf(protobuff, sizeof protobuff, "%s", pe->p_name);
192   oproto = cproto;
193   return (protobuff);
194 }
195 
196 /*
197  * Check a packet against the given filter
198  * Returns 0 to accept the packet, non-zero to drop the packet.
199  * If psecs is not NULL, populate it with the timeout associated
200  * with the filter rule matched.
201  *
202  * If filtering is enabled, the initial fragment of a datagram must
203  * contain the complete protocol header, and subsequent fragments
204  * must not attempt to over-write it.
205  *
206  * One (and only one) of pip or pip6 must be set.
207  */
208 int
209 FilterCheck(const unsigned char *packet, u_int32_t family,
210             const struct filter *filter, unsigned *psecs)
211 {
212   int gotinfo;			/* true if IP payload decoded */
213   int cproto;			/* IPPROTO_* protocol number if (gotinfo) */
214   int estab, syn, finrst;	/* TCP state flags if (gotinfo) */
215   u_short sport, dport;		/* src, dest port from packet if (gotinfo) */
216   int n;			/* filter rule to process */
217   int len;			/* bytes used in dbuff */
218   int didname;			/* true if filter header printed */
219   int match;			/* true if condition matched */
220   int mindata;			/* minimum data size or zero */
221   const struct filterent *fp = filter->rule;
222   char dbuff[100], dstip[16];
223   struct ncpaddr srcaddr, dstaddr;
224   const char *payload;		/* IP payload */
225   int datalen;			/* IP datagram length */
226 
227   if (fp->f_action == A_NONE)
228     return 0;		/* No rule is given. Permit this packet */
229 
230 #ifndef NOINET6
231   if (family == AF_INET6) {
232     const struct ip6_hdr *pip6 = (const struct ip6_hdr *)packet;
233 
234     ncpaddr_setip6(&srcaddr, &pip6->ip6_src);
235     ncpaddr_setip6(&dstaddr, &pip6->ip6_dst);
236     datalen = ntohs(pip6->ip6_plen);
237     payload = packet + sizeof *pip6;
238     cproto = pip6->ip6_nxt;
239   } else
240 #endif
241   {
242     /*
243      * Deny any packet fragment that tries to over-write the header.
244      * Since we no longer have the real header available, punt on the
245      * largest normal header - 20 bytes for TCP without options, rounded
246      * up to the next possible fragment boundary.  Since the smallest
247      * `legal' MTU is 576, and the smallest recommended MTU is 296, any
248      * fragmentation within this range is dubious at best
249      */
250     const struct ip *pip = (const struct ip *)packet;
251 
252     len = ntohs(pip->ip_off) & IP_OFFMASK;	/* fragment offset */
253     if (len > 0) {		/* Not first fragment within datagram */
254       if (len < (24 >> 3)) {	/* don't allow fragment to over-write header */
255         log_Printf(LogFILTER, " error: illegal header\n");
256         return 1;
257       }
258       /* permit fragments on in and out filter */
259       if (!filter->fragok) {
260         log_Printf(LogFILTER, " error: illegal fragmentation\n");
261         return 1;
262       } else
263         return 0;
264     }
265 
266     ncpaddr_setip4(&srcaddr, pip->ip_src);
267     ncpaddr_setip4(&dstaddr, pip->ip_dst);
268     datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
269     payload = packet + (pip->ip_hl << 2);
270     cproto = pip->ip_p;
271   }
272 
273 
274   gotinfo = estab = syn = finrst = didname = 0;
275   sport = dport = 0;
276 
277   for (n = 0; n < MAXFILTERS; ) {
278     if (fp->f_action == A_NONE) {
279       n++;
280       fp++;
281       continue;
282     }
283 
284     if (!didname) {
285       log_Printf(LogDEBUG, "%s filter:\n", filter->name);
286       didname = 1;
287     }
288 
289     match = 0;
290 
291     if ((ncprange_family(&fp->f_src) == AF_UNSPEC ||
292          ncprange_contains(&fp->f_src, &srcaddr)) &&
293         (ncprange_family(&fp->f_dst) == AF_UNSPEC ||
294          ncprange_contains(&fp->f_dst, &dstaddr))) {
295       if (fp->f_proto != 0) {
296         if (!gotinfo) {
297           const struct tcphdr *th;
298           const struct udphdr *uh;
299           const struct icmp *ih;
300 #ifndef NOINET6
301           const struct icmp6_hdr *ih6;
302 #endif
303           mindata = 0;
304           sport = dport = 0;
305           estab = syn = finrst = -1;
306 
307           switch (cproto) {
308           case IPPROTO_ICMP:
309             mindata = 8;	/* ICMP must be at least 8 octets */
310             ih = (const struct icmp *)payload;
311             sport = ih->icmp_type;
312             if (log_IsKept(LogDEBUG))
313               snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
314             break;
315 
316 #ifndef NOINET6
317           case IPPROTO_ICMPV6:
318             mindata = 8;	/* ICMP must be at least 8 octets */
319             ih6 = (const struct icmp6_hdr *)payload;
320             sport = ih6->icmp6_type;
321             if (log_IsKept(LogDEBUG))
322               snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
323             break;
324 #endif
325 
326           case IPPROTO_IGMP:
327             mindata = 8;	/* IGMP uses 8-octet messages */
328             break;
329 
330 #ifdef IPPROTO_GRE
331           case IPPROTO_GRE:
332             mindata = 2;	/* GRE uses 2-octet+ messages */
333             break;
334 #endif
335 #ifdef IPPROTO_OSPFIGP
336           case IPPROTO_OSPFIGP:
337             mindata = 8;	/* IGMP uses 8-octet messages */
338             break;
339 #endif
340 #ifndef NOINET6
341           case IPPROTO_IPV6:
342             mindata = 20;	/* RFC2893 Section 3.5: 5 * 32bit words */
343             break;
344 #endif
345 
346           case IPPROTO_UDP:
347             mindata = 8;	/* UDP header is 8 octets */
348             uh = (const struct udphdr *)payload;
349             sport = ntohs(uh->uh_sport);
350             dport = ntohs(uh->uh_dport);
351             if (log_IsKept(LogDEBUG))
352               snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
353                        sport, dport);
354             break;
355 
356           case IPPROTO_TCP:
357             th = (const struct tcphdr *)payload;
358             /*
359              * TCP headers are variable length.  The following code
360              * ensures that the TCP header length isn't de-referenced if
361              * the datagram is too short
362              */
363             if (datalen < 20 || datalen < (th->th_off << 2)) {
364               log_Printf(LogFILTER, " error: TCP header incorrect\n");
365               return 1;
366             }
367             sport = ntohs(th->th_sport);
368             dport = ntohs(th->th_dport);
369             estab = (th->th_flags & TH_ACK);
370             syn = (th->th_flags & TH_SYN);
371             finrst = (th->th_flags & (TH_FIN|TH_RST));
372             if (log_IsKept(LogDEBUG)) {
373               if (!estab)
374                 snprintf(dbuff, sizeof dbuff,
375                          "flags = %02x, sport = %d, dport = %d",
376                          th->th_flags, sport, dport);
377               else
378                 *dbuff = '\0';
379             }
380             break;
381           default:
382             break;
383           }
384 
385           if (datalen < mindata) {
386             log_Printf(LogFILTER, " error: proto %s must be at least"
387                        " %d octets\n", prototxt(cproto), mindata);
388             return 1;
389           }
390 
391           if (log_IsKept(LogDEBUG)) {
392             if (estab != -1) {
393               len = strlen(dbuff);
394               snprintf(dbuff + len, sizeof dbuff - len,
395                        ", estab = %d, syn = %d, finrst = %d",
396                        estab, syn, finrst);
397             }
398             log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
399                        prototxt(cproto), dbuff);
400           }
401           gotinfo = 1;
402         }
403 
404         if (log_IsKept(LogDEBUG)) {
405           if (fp->f_srcop != OP_NONE) {
406             snprintf(dbuff, sizeof dbuff, ", src %s %d",
407                      filter_Op2Nam(fp->f_srcop), fp->f_srcport);
408             len = strlen(dbuff);
409           } else
410             len = 0;
411           if (fp->f_dstop != OP_NONE) {
412             snprintf(dbuff + len, sizeof dbuff - len,
413                      ", dst %s %d", filter_Op2Nam(fp->f_dstop),
414                      fp->f_dstport);
415           } else if (!len)
416             *dbuff = '\0';
417 
418           log_Printf(LogDEBUG, "  rule = %d: Address match, "
419                      "check against proto %d%s, action = %s\n",
420                      n, fp->f_proto, dbuff, filter_Action2Nam(fp->f_action));
421         }
422 
423         if (cproto == fp->f_proto) {
424           if ((fp->f_srcop == OP_NONE ||
425                PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
426               (fp->f_dstop == OP_NONE ||
427                PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
428               (fp->f_estab == 0 || estab) &&
429               (fp->f_syn == 0 || syn) &&
430               (fp->f_finrst == 0 || finrst)) {
431             match = 1;
432           }
433         }
434       } else {
435         /* Address is matched and no protocol specified. Make a decision. */
436         log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
437                    filter_Action2Nam(fp->f_action));
438         match = 1;
439       }
440     } else
441       log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
442 
443     if (match != fp->f_invert) {
444       /* Take specified action */
445       if (fp->f_action < A_NONE)
446         fp = &filter->rule[n = fp->f_action];
447       else {
448         if (fp->f_action == A_PERMIT) {
449           if (psecs != NULL)
450             *psecs = fp->timeout;
451           if (strcmp(filter->name, "DIAL") == 0) {
452             /* If dial filter then even print out accept packets */
453             if (log_IsKept(LogFILTER)) {
454               snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
455               log_Printf(LogFILTER, "%sbound rule = %d accept %s "
456                          "src = %s:%d dst = %s:%d\n", filter->name, n,
457                          prototxt(cproto), ncpaddr_ntoa(&srcaddr), sport,
458                          dstip, dport);
459             }
460           }
461           return 0;
462         } else {
463           if (log_IsKept(LogFILTER)) {
464             snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
465             log_Printf(LogFILTER,
466                        "%sbound rule = %d deny %s src = %s/%d dst = %s/%d\n",
467                        filter->name, n, prototxt(cproto),
468                        ncpaddr_ntoa(&srcaddr), sport, dstip, dport);
469           }
470           return 1;
471         }		/* Explict match.  Deny this packet */
472       }
473     } else {
474       n++;
475       fp++;
476     }
477   }
478 
479   if (log_IsKept(LogFILTER)) {
480     snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
481     log_Printf(LogFILTER,
482                "%sbound rule = implicit deny %s src = %s/%d dst = %s/%d\n",
483                filter->name, prototxt(cproto), ncpaddr_ntoa(&srcaddr),
484                sport, dstip, dport);
485   }
486 
487   return 1;		/* No rule matched, deny this packet */
488 }
489 
490 static void
491 ip_LogDNS(const struct udphdr *uh, const char *direction)
492 {
493   struct dns_header header;
494   const u_short *pktptr;
495   const u_char *ptr;
496   u_short *hptr, tmp;
497   unsigned len;
498 
499   ptr = (const char *)uh + sizeof *uh;
500   len = ntohs(uh->uh_ulen) - sizeof *uh;
501   if (len < sizeof header + 5)		/* rfc1024 */
502     return;
503 
504   pktptr = (const u_short *)ptr;
505   hptr = (u_short *)&header;
506   ptr += sizeof header;
507   len -= sizeof header;
508 
509   while (pktptr < (const u_short *)ptr) {
510     *hptr++ = ntohs(*pktptr);		/* Careful of macro side-effects ! */
511     pktptr++;
512   }
513 
514   if (header.opcode == OPCODE_QUERY && header.qr == 0) {
515     /* rfc1035 */
516     char namewithdot[MAXHOSTNAMELEN + 1], *n;
517     const char *qtype, *qclass;
518     const u_char *end;
519 
520     n = namewithdot;
521     end = ptr + len - 4;
522     if (end - ptr >= (int)sizeof namewithdot)
523       end = ptr + sizeof namewithdot - 1;
524     while (ptr < end) {
525       len = *ptr++;
526       if ((int)len > end - ptr)
527         len = end - ptr;
528       if (n != namewithdot)
529         *n++ = '.';
530       memcpy(n, ptr, len);
531       ptr += len;
532       n += len;
533     }
534     *n = '\0';
535 
536     if (log_IsKept(LogDNS)) {
537       memcpy(&tmp, end, sizeof tmp);
538       qtype = dns_Qtype2Txt(ntohs(tmp));
539       memcpy(&tmp, end + 2, sizeof tmp);
540       qclass = dns_Qclass2Txt(ntohs(tmp));
541 
542       log_Printf(LogDNS, "%sbound query %s %s %s\n",
543                  direction, qclass, qtype, namewithdot);
544     }
545   }
546 }
547 
548 /*
549  * Check if the given packet matches the given filter.
550  * One of pip or pip6 must be set.
551  */
552 int
553 PacketCheck(struct bundle *bundle, u_int32_t family,
554             const unsigned char *packet, int nb, struct filter *filter,
555             const char *prefix, unsigned *psecs)
556 {
557   char logbuf[200];
558   static const char *const TcpFlags[] = {
559     "FIN", "SYN", "RST", "PSH", "ACK", "URG"
560   };
561   const struct tcphdr *th;
562   const struct udphdr *uh;
563   const struct icmp *icmph;
564 #ifndef NOINET6
565   const struct icmp6_hdr *icmp6h;
566 #endif
567   const unsigned char *payload;
568   struct ncpaddr srcaddr, dstaddr;
569   int cproto, mask, len, n, pri, logit, result, datalen, frag;
570   unsigned loglen;
571   u_char tos;
572 
573   logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) &&
574           (!filter || filter->logok);
575   loglen = 0;
576   pri = 0;
577 
578 #ifndef NOINET6
579   if (family == AF_INET6) {
580     const struct ip6_hdr *pip6 = (const struct ip6_hdr *)packet;
581 
582     ncpaddr_setip6(&srcaddr, &pip6->ip6_src);
583     ncpaddr_setip6(&dstaddr, &pip6->ip6_dst);
584     datalen = ntohs(pip6->ip6_plen);
585     payload = packet + sizeof *pip6;
586     cproto = pip6->ip6_nxt;
587     tos = 0;					/* XXX: pip6->ip6_vfc >> 4 ? */
588     frag = 0;					/* XXX: ??? */
589   } else
590 #endif
591   {
592     const struct ip *pip = (const struct ip *)packet;
593 
594     ncpaddr_setip4(&srcaddr, pip->ip_src);
595     ncpaddr_setip4(&dstaddr, pip->ip_dst);
596     datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
597     payload = packet + (pip->ip_hl << 2);
598     cproto = pip->ip_p;
599     tos = pip->ip_tos;
600     frag = ntohs(pip->ip_off) & IP_OFFMASK;
601   }
602 
603   uh = NULL;
604 
605   if (logit && loglen < sizeof logbuf) {
606     if (prefix)
607       snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s", prefix);
608     else if (filter)
609       snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
610     else
611       snprintf(logbuf + loglen, sizeof logbuf - loglen, "  ");
612     loglen += strlen(logbuf + loglen);
613   }
614 
615   switch (cproto) {
616   case IPPROTO_ICMP:
617     if (logit && loglen < sizeof logbuf) {
618       len = datalen - sizeof *icmph;
619       icmph = (const struct icmp *)payload;
620       snprintf(logbuf + loglen, sizeof logbuf - loglen,
621                "ICMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), icmph->icmp_type);
622       loglen += strlen(logbuf + loglen);
623       snprintf(logbuf + loglen, sizeof logbuf - loglen,
624                "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), len, nb);
625       loglen += strlen(logbuf + loglen);
626     }
627     break;
628 
629 #ifndef NOINET6
630   case IPPROTO_ICMPV6:
631     if (logit && loglen < sizeof logbuf) {
632       len = datalen - sizeof *icmp6h;
633       icmp6h = (const struct icmp6_hdr *)payload;
634       snprintf(logbuf + loglen, sizeof logbuf - loglen,
635                "ICMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), icmp6h->icmp6_type);
636       loglen += strlen(logbuf + loglen);
637       snprintf(logbuf + loglen, sizeof logbuf - loglen,
638                "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), len, nb);
639       loglen += strlen(logbuf + loglen);
640     }
641     break;
642 #endif
643 
644   case IPPROTO_UDP:
645     uh = (const struct udphdr *)payload;
646     if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos)
647       pri++;
648 
649     if (!frag && ncp_IsUrgentUdpPort(&bundle->ncp, ntohs(uh->uh_sport),
650                                      ntohs(uh->uh_dport)))
651       pri++;
652 
653     if (logit && loglen < sizeof logbuf) {
654       len = datalen - sizeof *uh;
655       snprintf(logbuf + loglen, sizeof logbuf - loglen,
656                "UDP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(uh->uh_sport));
657       loglen += strlen(logbuf + loglen);
658       snprintf(logbuf + loglen, sizeof logbuf - loglen,
659                "%s:%d (%d/%d)", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport),
660                len, nb);
661       loglen += strlen(logbuf + loglen);
662     }
663 
664     if (Enabled(bundle, OPT_FILTERDECAP) &&
665         payload[sizeof *uh] == HDLC_ADDR &&
666         payload[sizeof *uh + 1] == HDLC_UI) {
667       u_short proto;
668       const char *type;
669 
670       memcpy(&proto, payload + sizeof *uh + 2, sizeof proto);
671       type = NULL;
672 
673       switch (ntohs(proto)) {
674         case PROTO_IP:
675           snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
676           result = PacketCheck(bundle, AF_INET, payload + sizeof *uh + 4,
677                                nb - (payload - packet) - sizeof *uh - 4, filter,
678                                logbuf, psecs);
679           if (result != -2)
680               return result;
681           type = "IP";
682           break;
683 
684         case PROTO_VJUNCOMP: type = "compressed VJ";   break;
685         case PROTO_VJCOMP:   type = "uncompressed VJ"; break;
686         case PROTO_MP:       type = "Multi-link"; break;
687         case PROTO_ICOMPD:   type = "Individual link CCP"; break;
688         case PROTO_COMPD:    type = "CCP"; break;
689         case PROTO_IPCP:     type = "IPCP"; break;
690         case PROTO_LCP:      type = "LCP"; break;
691         case PROTO_PAP:      type = "PAP"; break;
692         case PROTO_CBCP:     type = "CBCP"; break;
693         case PROTO_LQR:      type = "LQR"; break;
694         case PROTO_CHAP:     type = "CHAP"; break;
695       }
696       if (type) {
697         snprintf(logbuf + loglen, sizeof logbuf - loglen,
698                  " - %s data", type);
699         loglen += strlen(logbuf + loglen);
700       }
701     }
702 
703     break;
704 
705 #ifdef IPPROTO_GRE
706   case IPPROTO_GRE:
707     if (logit && loglen < sizeof logbuf) {
708       snprintf(logbuf + loglen, sizeof logbuf - loglen,
709           "GRE: %s ---> ", ncpaddr_ntoa(&srcaddr));
710       loglen += strlen(logbuf + loglen);
711       snprintf(logbuf + loglen, sizeof logbuf - loglen,
712               "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
713       loglen += strlen(logbuf + loglen);
714     }
715     break;
716 #endif
717 
718 #ifdef IPPROTO_OSPFIGP
719   case IPPROTO_OSPFIGP:
720     if (logit && loglen < sizeof logbuf) {
721       snprintf(logbuf + loglen, sizeof logbuf - loglen,
722                "OSPF: %s ---> ", ncpaddr_ntoa(&srcaddr));
723       loglen += strlen(logbuf + loglen);
724       snprintf(logbuf + loglen, sizeof logbuf - loglen,
725                "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
726       loglen += strlen(logbuf + loglen);
727     }
728     break;
729 #endif
730 
731 #ifndef NOINET6
732   case IPPROTO_IPV6:
733     if (logit && loglen < sizeof logbuf) {
734       snprintf(logbuf + loglen, sizeof logbuf - loglen,
735                "IPv6: %s ---> ", ncpaddr_ntoa(&srcaddr));
736       loglen += strlen(logbuf + loglen);
737       snprintf(logbuf + loglen, sizeof logbuf - loglen,
738                "%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
739       loglen += strlen(logbuf + loglen);
740     }
741 
742     if (Enabled(bundle, OPT_FILTERDECAP)) {
743       snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
744       result = PacketCheck(bundle, AF_INET6, payload, nb - (payload - packet),
745                            filter, logbuf, psecs);
746       if (result != -2)
747         return result;
748     }
749     break;
750 #endif
751 
752   case IPPROTO_IPIP:
753     if (logit && loglen < sizeof logbuf) {
754       snprintf(logbuf + loglen, sizeof logbuf - loglen,
755                "IPIP: %s ---> ", ncpaddr_ntoa(&srcaddr));
756       loglen += strlen(logbuf + loglen);
757       snprintf(logbuf + loglen, sizeof logbuf - loglen,
758                "%s", ncpaddr_ntoa(&dstaddr));
759       loglen += strlen(logbuf + loglen);
760     }
761 
762     if (Enabled(bundle, OPT_FILTERDECAP) &&
763         ((const struct ip *)payload)->ip_v == 4) {
764       snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
765       result = PacketCheck(bundle, AF_INET, payload, nb - (payload - packet),
766                            filter, logbuf, psecs);
767       loglen += strlen(logbuf + loglen);
768       if (result != -2)
769         return result;
770     }
771     break;
772 
773   case IPPROTO_ESP:
774     if (logit && loglen < sizeof logbuf) {
775       snprintf(logbuf + loglen, sizeof logbuf - loglen,
776                "ESP: %s ---> ", ncpaddr_ntoa(&srcaddr));
777       loglen += strlen(logbuf + loglen);
778       snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p",
779                ncpaddr_ntoa(&dstaddr), payload);
780       loglen += strlen(logbuf + loglen);
781     }
782     break;
783 
784   case IPPROTO_AH:
785     if (logit && loglen < sizeof logbuf) {
786       snprintf(logbuf + loglen, sizeof logbuf - loglen,
787                "AH: %s ---> ", ncpaddr_ntoa(&srcaddr));
788       loglen += strlen(logbuf + loglen);
789       snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p",
790                ncpaddr_ntoa(&dstaddr), payload + sizeof(u_int32_t));
791       loglen += strlen(logbuf + loglen);
792     }
793     break;
794 
795   case IPPROTO_IGMP:
796     if (logit && loglen < sizeof logbuf) {
797       uh = (const struct udphdr *)payload;
798       snprintf(logbuf + loglen, sizeof logbuf - loglen,
799                "IGMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr),
800                ntohs(uh->uh_sport));
801       loglen += strlen(logbuf + loglen);
802       snprintf(logbuf + loglen, sizeof logbuf - loglen,
803                "%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport));
804       loglen += strlen(logbuf + loglen);
805     }
806     break;
807 
808   case IPPROTO_TCP:
809     th = (const struct tcphdr *)payload;
810     if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos)
811       pri++;
812 
813     if (!frag && ncp_IsUrgentTcpPort(&bundle->ncp, ntohs(th->th_sport),
814                                      ntohs(th->th_dport)))
815       pri++;
816 
817     if (logit && loglen < sizeof logbuf) {
818       len = datalen - (th->th_off << 2);
819       snprintf(logbuf + loglen, sizeof logbuf - loglen,
820            "TCP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(th->th_sport));
821       loglen += strlen(logbuf + loglen);
822       snprintf(logbuf + loglen, sizeof logbuf - loglen,
823                "%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(th->th_dport));
824       loglen += strlen(logbuf + loglen);
825       n = 0;
826       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
827         if (th->th_flags & mask) {
828           snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
829           loglen += strlen(logbuf + loglen);
830         }
831         n++;
832       }
833       snprintf(logbuf + loglen, sizeof logbuf - loglen,
834                "  seq:%lx  ack:%lx (%d/%d)",
835                (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
836       loglen += strlen(logbuf + loglen);
837       if ((th->th_flags & TH_SYN) && nb > 40) {
838         const u_short *sp;
839 
840         sp = (const u_short *)(payload + 20);
841         if (ntohs(sp[0]) == 0x0204) {
842           snprintf(logbuf + loglen, sizeof logbuf - loglen,
843                    " MSS = %d", ntohs(sp[1]));
844           loglen += strlen(logbuf + loglen);
845         }
846       }
847     }
848     break;
849 
850   default:
851     if (prefix)
852       return -2;
853 
854     if (logit && loglen < sizeof logbuf) {
855       snprintf(logbuf + loglen, sizeof logbuf - loglen,
856                "<%d>: %s ---> ", cproto, ncpaddr_ntoa(&srcaddr));
857       loglen += strlen(logbuf + loglen);
858       snprintf(logbuf + loglen, sizeof logbuf - loglen,
859                "%s (%d)", ncpaddr_ntoa(&dstaddr), nb);
860       loglen += strlen(logbuf + loglen);
861     }
862     break;
863   }
864 
865   if (filter && FilterCheck(packet, family, filter, psecs)) {
866     if (logit)
867       log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
868     result = -1;
869   } else {
870     /* Check Keep Alive filter */
871     if (logit && log_IsKept(LogTCPIP)) {
872       unsigned alivesecs;
873 
874       alivesecs = 0;
875       if (filter &&
876           FilterCheck(packet, family, &bundle->filter.alive, &alivesecs))
877         log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
878       else if (psecs != NULL) {
879         if(*psecs == 0)
880           *psecs = alivesecs;
881         if (*psecs) {
882           if (*psecs != alivesecs)
883             log_Printf(LogTCPIP, "%s - (timeout = %d / ALIVE = %d secs)\n",
884                        logbuf, *psecs, alivesecs);
885           else
886             log_Printf(LogTCPIP, "%s - (timeout = %d secs)\n", logbuf, *psecs);
887         } else
888           log_Printf(LogTCPIP, "%s\n", logbuf);
889       }
890     }
891     result = pri;
892   }
893 
894   if (filter && uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS))
895     ip_LogDNS(uh, filter->name);
896 
897   return result;
898 }
899 
900 static size_t
901 ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp, u_int32_t af)
902 {
903   ssize_t nw;
904   size_t nb;
905   struct tun_data tun;
906   char *data;
907   unsigned secs, alivesecs;
908 
909   nb = m_length(bp);
910   if (nb > sizeof tun.data) {
911     log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
912                l->name, nb, (int)(sizeof tun.data));
913     m_freem(bp);
914     return 0;
915   }
916   mbuf_Read(bp, tun.data, nb);
917 
918   secs = 0;
919   if (PacketCheck(bundle, af, tun.data, nb, &bundle->filter.in,
920                   NULL, &secs) < 0)
921     return 0;
922 
923   alivesecs = 0;
924   if (!FilterCheck(tun.data, af, &bundle->filter.alive, &alivesecs)) {
925     if (secs == 0)
926       secs = alivesecs;
927     bundle_StartIdleTimer(bundle, secs);
928   }
929 
930   if (bundle->dev.header) {
931     tun.header.family = htonl(af);
932     nb += sizeof tun - sizeof tun.data;
933     data = (char *)&tun;
934   } else
935     data = tun.data;
936 
937   nw = write(bundle->dev.fd, data, nb);
938   if (nw != (ssize_t)nb) {
939     if (nw == -1)
940       log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
941                  l->name, nb, strerror(errno));
942     else
943       log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
944   }
945 
946   return nb;
947 }
948 
949 struct mbuf *
950 ipv4_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
951 {
952   int nb;
953 
954   if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
955     log_Printf(LogWARN, "ipv4_Input: IPCP not open - packet dropped\n");
956     m_freem(bp);
957     return NULL;
958   }
959 
960   m_settype(bp, MB_IPIN);
961 
962   nb = ip_Input(bundle, l, bp, AF_INET);
963   ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
964 
965   return NULL;
966 }
967 
968 #ifndef NOINET6
969 struct mbuf *
970 ipv6_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
971 {
972   int nb;
973 
974   if (bundle->ncp.ipv6cp.fsm.state != ST_OPENED) {
975     log_Printf(LogWARN, "ipv6_Input: IPV6CP not open - packet dropped\n");
976     m_freem(bp);
977     return NULL;
978   }
979 
980   m_settype(bp, MB_IPV6IN);
981 
982   nb = ip_Input(bundle, l, bp, AF_INET6);
983   ipv6cp_AddInOctets(&bundle->ncp.ipv6cp, nb);
984 
985   return NULL;
986 }
987 #endif
988