xref: /freebsd/usr.sbin/ppp/ip.c (revision b601c69bdbe8755d26570261d7fd4c02ee4eff74)
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];
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       return 1;
189     /* permit fragments on in and out filter */
190     return !filter->fragok;
191   }
192 
193   cproto = gotinfo = estab = syn = finrst = didname = 0;
194   sport = dport = 0;
195   for (n = 0; n < MAXFILTERS; ) {
196     if (fp->f_action == A_NONE) {
197       n++;
198       fp++;
199       continue;
200     }
201 
202     if (!didname) {
203       log_Printf(LogDEBUG, "%s filter:\n", filter->name);
204       didname = 1;
205     }
206 
207     match = 0;
208     if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
209           fp->f_src.mask.s_addr) &&
210         !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
211           fp->f_dst.mask.s_addr)) {
212       if (fp->f_proto != P_NONE) {
213         if (!gotinfo) {
214           const char *ptop = (const char *) pip + (pip->ip_hl << 2);
215           const struct tcphdr *th;
216           const struct udphdr *uh;
217           const struct icmp *ih;
218           int datalen;	/* IP datagram length */
219 
220           datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
221           switch (pip->ip_p) {
222           case IPPROTO_ICMP:
223             cproto = P_ICMP;
224             if (datalen < 8)	/* ICMP must be at least 8 octets */
225               return 1;
226             ih = (const struct icmp *) ptop;
227             sport = ih->icmp_type;
228             estab = syn = finrst = -1;
229             if (log_IsKept(LogDEBUG))
230               snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
231             break;
232           case IPPROTO_IGMP:
233             cproto = P_IGMP;
234             if (datalen < 8)	/* IGMP uses 8-octet messages */
235               return 1;
236             estab = syn = finrst = -1;
237             sport = ntohs(0);
238             break;
239 #ifdef IPPROTO_GRE
240           case IPPROTO_GRE:
241             cproto = P_GRE;
242             if (datalen < 2)    /* GRE uses 2-octet+ messages */
243               return 1;
244             estab = syn = finrst = -1;
245             sport = ntohs(0);
246             break;
247 #endif
248 #ifdef IPPROTO_OSPFIGP
249           case IPPROTO_OSPFIGP:
250             cproto = P_OSPF;
251             if (datalen < 8)	/* IGMP uses 8-octet messages */
252               return 1;
253             estab = syn = finrst = -1;
254             sport = ntohs(0);
255             break;
256 #endif
257           case IPPROTO_UDP:
258           case IPPROTO_IPIP:
259             cproto = P_UDP;
260             if (datalen < 8)	/* UDP header is 8 octets */
261               return 1;
262             uh = (const struct udphdr *) ptop;
263             sport = ntohs(uh->uh_sport);
264             dport = ntohs(uh->uh_dport);
265             estab = syn = finrst = -1;
266             if (log_IsKept(LogDEBUG))
267               snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
268                        sport, dport);
269             break;
270           case IPPROTO_TCP:
271             cproto = P_TCP;
272             th = (const struct tcphdr *) ptop;
273             /* TCP headers are variable length.  The following code
274              * ensures that the TCP header length isn't de-referenced if
275              * the datagram is too short
276              */
277             if (datalen < 20 || datalen < (th->th_off << 2))
278               return 1;
279             sport = ntohs(th->th_sport);
280             dport = ntohs(th->th_dport);
281             estab = (th->th_flags & TH_ACK);
282             syn = (th->th_flags & TH_SYN);
283             finrst = (th->th_flags & (TH_FIN|TH_RST));
284             if (log_IsKept(LogDEBUG)) {
285               if (!estab)
286                 snprintf(dbuff, sizeof dbuff,
287                          "flags = %02x, sport = %d, dport = %d",
288                          th->th_flags, sport, dport);
289               else
290                 *dbuff = '\0';
291             }
292             break;
293           default:
294             return 1;		/* We'll block unknown type of packet */
295           }
296 
297           if (log_IsKept(LogDEBUG)) {
298             if (estab != -1) {
299               len = strlen(dbuff);
300               snprintf(dbuff + len, sizeof dbuff - len,
301                        ", estab = %d, syn = %d, finrst = %d",
302                        estab, syn, finrst);
303             }
304             log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
305                        filter_Proto2Nam(cproto), dbuff);
306           }
307           gotinfo = 1;
308         }
309         if (log_IsKept(LogDEBUG)) {
310           if (fp->f_srcop != OP_NONE) {
311             snprintf(dbuff, sizeof dbuff, ", src %s %d",
312                      filter_Op2Nam(fp->f_srcop), fp->f_srcport);
313             len = strlen(dbuff);
314           } else
315             len = 0;
316           if (fp->f_dstop != OP_NONE) {
317             snprintf(dbuff + len, sizeof dbuff - len,
318                      ", dst %s %d", filter_Op2Nam(fp->f_dstop),
319                      fp->f_dstport);
320           } else if (!len)
321             *dbuff = '\0';
322 
323           log_Printf(LogDEBUG, "  rule = %d: Address match, "
324                      "check against proto %s%s, action = %s\n",
325                      n, filter_Proto2Nam(fp->f_proto),
326                      dbuff, filter_Action2Nam(fp->f_action));
327         }
328 
329         if (cproto == fp->f_proto) {
330           if ((fp->f_srcop == OP_NONE ||
331                PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
332               (fp->f_dstop == OP_NONE ||
333                PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
334               (fp->f_estab == 0 || estab) &&
335               (fp->f_syn == 0 || syn) &&
336               (fp->f_finrst == 0 || finrst)) {
337             match = 1;
338           }
339         }
340       } else {
341         /* Address is matched and no protocol specified. Make a decision. */
342         log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
343                    filter_Action2Nam(fp->f_action));
344         match = 1;
345       }
346     } else
347       log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
348 
349     if (match != fp->f_invert) {
350       /* Take specified action */
351       if (fp->f_action < A_NONE)
352         fp = &filter->rule[n = fp->f_action];
353       else
354         if (fp->f_action == A_PERMIT) {
355           if (psecs != NULL)
356             *psecs = fp->timeout;
357           return 0;
358         } else
359           return 1;
360     } else {
361       n++;
362       fp++;
363     }
364   }
365   return 1;		/* No rule is mached. Deny this packet */
366 }
367 
368 #ifdef notdef
369 static void
370 IcmpError(struct ip *pip, int code)
371 {
372   struct mbuf *bp;
373 
374   if (pip->ip_p != IPPROTO_ICMP) {
375     bp = m_get(m_len, MB_IPIN);
376     memcpy(MBUF_CTOP(bp), ptr, m_len);
377     vj_SendFrame(bp);
378     ipcp_AddOutOctets(m_len);
379   }
380 }
381 #endif
382 
383 static void
384 ip_LogDNS(const struct udphdr *uh, const char *direction)
385 {
386   struct dns_header header;
387   const u_short *pktptr;
388   const u_char *ptr;
389   u_short *hptr;
390   int len;
391 
392   ptr = (const char *)uh + sizeof *uh;
393   len = ntohs(uh->uh_ulen) - sizeof *uh;
394   if (len < sizeof header + 5)		/* rfc1024 */
395     return;
396 
397   pktptr = (const u_short *)ptr;
398   hptr = (u_short *)&header;
399   ptr += sizeof header;
400   len -= sizeof header;
401 
402   while (pktptr < (const u_short *)ptr) {
403     *hptr++ = ntohs(*pktptr);		/* Careful of macro side-effects ! */
404     pktptr++;
405   }
406 
407   if (header.opcode == OPCODE_QUERY && header.qr == 0) {
408     /* rfc1035 */
409     char name[MAXHOSTNAMELEN + 1], *n;
410     const char *qtype, *qclass;
411     const u_char *end;
412 
413     n = name;
414     end = ptr + len - 4;
415     if (end - ptr > MAXHOSTNAMELEN)
416       end = ptr + MAXHOSTNAMELEN;
417     while (ptr < end) {
418       len = *ptr++;
419       if (len > end - ptr)
420         len = end - ptr;
421       if (n != name)
422         *n++ = '.';
423       memcpy(n, ptr, len);
424       ptr += len;
425       n += len;
426     }
427     *n = '\0';
428     qtype = dns_Qtype2Txt(ntohs(*(const u_short *)end));
429     qclass = dns_Qclass2Txt(ntohs(*(const u_short *)(end + 2)));
430 
431     log_Printf(LogDNS, "%sbound query %s %s %s\n",
432                direction, qclass, qtype, name);
433   }
434 }
435 
436 /*
437  *  For debugging aid.
438  */
439 int
440 PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
441             struct filter *filter, const char *prefix, unsigned *psecs)
442 {
443   static const char *const TcpFlags[] = {
444     "FIN", "SYN", "RST", "PSH", "ACK", "URG"
445   };
446   struct ip *pip;
447   struct tcphdr *th;
448   struct udphdr *uh;
449   struct icmp *icmph;
450   unsigned char *ptop;
451   int mask, len, n, pri, logit, loglen, result;
452   char logbuf[200];
453 
454   logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) &&
455           (!filter || filter->logok);
456   loglen = 0;
457   pri = 0;
458 
459   pip = (struct ip *)cp;
460   uh = NULL;
461 
462   if (logit && loglen < sizeof logbuf) {
463     if (prefix)
464       snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s", prefix);
465     else if (filter)
466       snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
467     else
468       snprintf(logbuf + loglen, sizeof logbuf - loglen, "  ");
469     loglen += strlen(logbuf + loglen);
470   }
471   ptop = (cp + (pip->ip_hl << 2));
472 
473   switch (pip->ip_p) {
474   case IPPROTO_ICMP:
475     if (logit && loglen < sizeof logbuf) {
476       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *icmph;
477       icmph = (struct icmp *) ptop;
478       snprintf(logbuf + loglen, sizeof logbuf - loglen,
479                "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
480       loglen += strlen(logbuf + loglen);
481       snprintf(logbuf + loglen, sizeof logbuf - loglen,
482                "%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), icmph->icmp_type,
483                len, nb);
484       loglen += strlen(logbuf + loglen);
485     }
486     break;
487 
488   case IPPROTO_UDP:
489     uh = (struct udphdr *) ptop;
490     if (pip->ip_tos == IPTOS_LOWDELAY && bundle->ncp.ipcp.cfg.urgent.tos)
491       pri++;
492 
493     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
494         ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport),
495                           ntohs(uh->uh_dport)))
496       pri++;
497 
498     if (logit && loglen < sizeof logbuf) {
499       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *uh;
500       snprintf(logbuf + loglen, sizeof logbuf - loglen,
501                "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
502       loglen += strlen(logbuf + loglen);
503       snprintf(logbuf + loglen, sizeof logbuf - loglen,
504                "%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport),
505                len, nb);
506       loglen += strlen(logbuf + loglen);
507     }
508 
509     if (Enabled(bundle, OPT_FILTERDECAP) &&
510         ptop[sizeof *uh] == HDLC_ADDR && ptop[sizeof *uh + 1] == HDLC_UI) {
511       u_short proto;
512       const char *type;
513 
514       memcpy(&proto, ptop + sizeof *uh + 2, sizeof proto);
515       type = NULL;
516 
517       switch (ntohs(proto)) {
518         case PROTO_IP:
519           snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
520           result = PacketCheck(bundle, ptop + sizeof *uh + 4,
521                                nb - (ptop - cp) - sizeof *uh - 4, filter,
522                                logbuf, psecs);
523           if (result != -2)
524               return result;
525           type = "IP";
526           break;
527 
528         case PROTO_VJUNCOMP: type = "compressed VJ";   break;
529         case PROTO_VJCOMP:   type = "uncompressed VJ"; break;
530         case PROTO_MP:       type = "Multi-link"; break;
531         case PROTO_ICOMPD:   type = "Individual link CCP"; break;
532         case PROTO_COMPD:    type = "CCP"; break;
533         case PROTO_IPCP:     type = "IPCP"; break;
534         case PROTO_LCP:      type = "LCP"; break;
535         case PROTO_PAP:      type = "PAP"; break;
536         case PROTO_CBCP:     type = "CBCP"; break;
537         case PROTO_LQR:      type = "LQR"; break;
538         case PROTO_CHAP:     type = "CHAP"; break;
539       }
540       if (type) {
541         snprintf(logbuf + loglen, sizeof logbuf - loglen,
542                  " - %s data", type);
543         loglen += strlen(logbuf + loglen);
544       }
545     }
546 
547     break;
548 
549 #ifdef IPPROTO_GRE
550   case IPPROTO_GRE:
551     if (logit && loglen < sizeof logbuf) {
552       len = ntohs(pip->ip_len) - (pip->ip_hl << 2);
553       snprintf(logbuf + loglen, sizeof logbuf - loglen,
554           "GRE: %s ---> ", inet_ntoa(pip->ip_src));
555       loglen += strlen(logbuf + loglen);
556       snprintf(logbuf + loglen, sizeof logbuf - loglen,
557               "%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
558       loglen += strlen(logbuf + loglen);
559     }
560     break;
561 #endif
562 
563 #ifdef IPPROTO_OSPFIGP
564   case IPPROTO_OSPFIGP:
565     if (logit && loglen < sizeof logbuf) {
566       len = ntohs(pip->ip_len) - (pip->ip_hl << 2);
567       snprintf(logbuf + loglen, sizeof logbuf - loglen,
568                "OSPF: %s ---> ", inet_ntoa(pip->ip_src));
569       loglen += strlen(logbuf + loglen);
570       snprintf(logbuf + loglen, sizeof logbuf - loglen,
571                "%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
572       loglen += strlen(logbuf + loglen);
573     }
574     break;
575 #endif
576 
577   case IPPROTO_IPIP:
578     if (logit && loglen < sizeof logbuf) {
579       uh = (struct udphdr *) ptop;
580       snprintf(logbuf + loglen, sizeof logbuf - loglen,
581                "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src),
582                ntohs(uh->uh_sport));
583       loglen += strlen(logbuf + loglen);
584       snprintf(logbuf + loglen, sizeof logbuf - loglen,
585                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
586       loglen += strlen(logbuf + loglen);
587     }
588     break;
589 
590   case IPPROTO_IGMP:
591     if (logit && loglen < sizeof logbuf) {
592       uh = (struct udphdr *) ptop;
593       snprintf(logbuf + loglen, sizeof logbuf - loglen,
594                "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src),
595                ntohs(uh->uh_sport));
596       loglen += strlen(logbuf + loglen);
597       snprintf(logbuf + loglen, sizeof logbuf - loglen,
598                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
599       loglen += strlen(logbuf + loglen);
600     }
601     break;
602 
603   case IPPROTO_TCP:
604     th = (struct tcphdr *) ptop;
605     if (pip->ip_tos == IPTOS_LOWDELAY && bundle->ncp.ipcp.cfg.urgent.tos)
606       pri++;
607 
608     if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
609         ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport),
610                           ntohs(th->th_dport)))
611       pri++;
612 
613     if (logit && loglen < sizeof logbuf) {
614       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
615       snprintf(logbuf + loglen, sizeof logbuf - loglen,
616            "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
617       loglen += strlen(logbuf + loglen);
618       snprintf(logbuf + loglen, sizeof logbuf - loglen,
619                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
620       loglen += strlen(logbuf + loglen);
621       n = 0;
622       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
623         if (th->th_flags & mask) {
624           snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
625           loglen += strlen(logbuf + loglen);
626         }
627         n++;
628       }
629       snprintf(logbuf + loglen, sizeof logbuf - loglen,
630                "  seq:%lx  ack:%lx (%d/%d)",
631                (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
632       loglen += strlen(logbuf + loglen);
633       if ((th->th_flags & TH_SYN) && nb > 40) {
634         u_short *sp;
635 
636         ptop += 20;
637         sp = (u_short *) ptop;
638         if (ntohs(sp[0]) == 0x0204) {
639           snprintf(logbuf + loglen, sizeof logbuf - loglen,
640                    " MSS = %d", ntohs(sp[1]));
641           loglen += strlen(logbuf + loglen);
642         }
643       }
644     }
645     break;
646 
647   default:
648     if (prefix)
649       return -2;
650   }
651 
652   if (filter && FilterCheck(pip, filter, psecs)) {
653     if (logit)
654       log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
655 #ifdef notdef
656     if (direction == 0)
657       IcmpError(pip, pri);
658 #endif
659     result = -1;
660   } else {
661     /* Check Keep Alive filter */
662     if (logit && log_IsKept(LogTCPIP)) {
663       unsigned alivesecs;
664 
665       alivesecs = 0;
666       if (filter && FilterCheck(pip, &bundle->filter.alive, &alivesecs))
667         log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
668       else if (psecs != NULL) {
669         if(*psecs == 0)
670           *psecs = alivesecs;
671         if (*psecs) {
672           if (*psecs != alivesecs)
673             log_Printf(LogTCPIP, "%s - (timeout = %d / ALIVE = %d secs)\n",
674                        logbuf, *psecs, alivesecs);
675           else
676             log_Printf(LogTCPIP, "%s - (timeout = %d secs)\n", logbuf, *psecs);
677         } else
678           log_Printf(LogTCPIP, "%s\n", logbuf);
679       }
680     }
681     result = pri;
682   }
683 
684   if (filter && uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS))
685     ip_LogDNS(uh, filter->name);
686 
687   return result;
688 }
689 
690 struct mbuf *
691 ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
692 {
693   int nb, nw;
694   struct tun_data tun;
695   struct ip *pip;
696   char *data;
697   unsigned secs, alivesecs;
698 
699   if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
700     log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
701     m_freem(bp);
702     return NULL;
703   }
704 
705   m_settype(bp, MB_IPIN);
706   nb = m_length(bp);
707   if (nb > sizeof tun.data) {
708     log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
709                l->name, nb, (int)(sizeof tun.data));
710     m_freem(bp);
711     return NULL;
712   }
713   mbuf_Read(bp, tun.data, nb);
714 
715   secs = 0;
716   if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in, NULL, &secs) < 0)
717     return NULL;
718 
719   pip = (struct ip *)tun.data;
720   alivesecs = 0;
721   if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) {
722     if (secs == 0)
723       secs = alivesecs;
724     bundle_StartIdleTimer(bundle, secs);
725   }
726 
727   ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
728 
729   if (bundle->dev.header) {
730     tun.header.family = htonl(AF_INET);
731     nb += sizeof tun - sizeof tun.data;
732     data = (char *)&tun;
733   } else
734     data = tun.data;
735 
736   nw = write(bundle->dev.fd, data, nb);
737   if (nw != nb) {
738     if (nw == -1)
739       log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
740                  l->name, nb, strerror(errno));
741     else
742       log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
743   }
744 
745   return NULL;
746 }
747 
748 void
749 ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
750 {
751   struct mbuf *bp;
752 
753   if (pri < 0 || pri >= IPCP_QUEUES(ipcp))
754     log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
755   else {
756     /*
757      * We allocate an extra 6 bytes, four at the front and two at the end.
758      * This is an optimisation so that we need to do less work in
759      * m_prepend() in acf_LayerPush() and proto_LayerPush() and
760      * appending in hdlc_LayerPush().
761      */
762     bp = m_get(count + 6, MB_IPOUT);
763     bp->m_offset += 4;
764     bp->m_len -= 6;
765     memcpy(MBUF_CTOP(bp), ptr, count);
766     m_enqueue(ipcp->Queue + pri, bp);
767   }
768 }
769 
770 void
771 ip_DeleteQueue(struct ipcp *ipcp)
772 {
773   struct mqueue *queue;
774 
775   for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
776     while (queue->top)
777       m_freem(m_dequeue(queue));
778 }
779 
780 size_t
781 ip_QueueLen(struct ipcp *ipcp)
782 {
783   struct mqueue *queue;
784   size_t result;
785 
786   result = 0;
787   for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
788     result += queue->len;
789 
790   return result;
791 }
792 
793 int
794 ip_PushPacket(struct link *l, struct bundle *bundle)
795 {
796   struct ipcp *ipcp = &bundle->ncp.ipcp;
797   struct mqueue *queue;
798   struct mbuf *bp;
799   struct ip *pip;
800   int m_len;
801   u_int32_t secs = 0;
802   unsigned alivesecs = 0;
803 
804   if (ipcp->fsm.state != ST_OPENED)
805     return 0;
806 
807   queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1;
808   do {
809     if (queue->top) {
810       bp = m_dequeue(queue);
811       bp = mbuf_Read(bp, &secs, sizeof secs);
812       bp = m_pullup(bp);
813       m_len = m_length(bp);
814       pip = (struct ip *)MBUF_CTOP(bp);
815       if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) {
816         if (secs == 0)
817           secs = alivesecs;
818         bundle_StartIdleTimer(bundle, secs);
819       }
820       link_PushPacket(l, bp, bundle, 0, PROTO_IP);
821       ipcp_AddOutOctets(ipcp, m_len);
822       return 1;
823     }
824   } while (queue-- != ipcp->Queue);
825 
826   return 0;
827 }
828