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