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