xref: /freebsd/usr.sbin/ppp/ip.c (revision 5d9e6103663c28d3986c674a772142f29e6584be)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *		PPP IP Protocol Interface
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
205d9e6103SBrian Somers  * $Id: ip.c,v 1.58 1999/05/01 11:31:29 brian Exp $
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *	TODO:
23af57ed9fSAtsushi Murai  *		o Return ICMP message for filterd packet
24af57ed9fSAtsushi Murai  *		  and optionaly record it into log.
25af57ed9fSAtsushi Murai  */
26972a1bcfSBrian Somers #include <sys/param.h>
277884358fSBrian Somers #if defined(__OpenBSD__) || defined(__NetBSD__)
286a6b4bbbSBrian Somers #include <sys/socket.h>
2992b09558SBrian Somers #endif
3075240ed1SBrian Somers #include <netinet/in.h>
31af57ed9fSAtsushi Murai #include <netinet/in_systm.h>
32af57ed9fSAtsushi Murai #include <netinet/ip.h>
33af57ed9fSAtsushi Murai #include <netinet/ip_icmp.h>
34af57ed9fSAtsushi Murai #include <netinet/udp.h>
35af57ed9fSAtsushi Murai #include <netinet/tcp.h>
36ed6a16c1SPoul-Henning Kamp #include <arpa/inet.h>
371fa665f5SBrian Somers #include <sys/un.h>
3875240ed1SBrian Somers 
3957fd05c4SBrian Somers #include <errno.h>
4075240ed1SBrian Somers #include <stdio.h>
4175240ed1SBrian Somers #include <stdlib.h>
4275240ed1SBrian Somers #include <string.h>
435d9e6103SBrian Somers #include <termios.h>
4475240ed1SBrian Somers #include <unistd.h>
4575240ed1SBrian Somers 
465d9e6103SBrian Somers #include "layer.h"
475d9e6103SBrian Somers #include "proto.h"
48927145beSBrian Somers #include "mbuf.h"
49927145beSBrian Somers #include "log.h"
5075240ed1SBrian Somers #include "defs.h"
5175240ed1SBrian Somers #include "timer.h"
5275240ed1SBrian Somers #include "fsm.h"
53879ed6faSBrian Somers #include "lqr.h"
5475240ed1SBrian Somers #include "hdlc.h"
555828db6dSBrian Somers #include "throughput.h"
565828db6dSBrian Somers #include "iplist.h"
57eaa4df37SBrian Somers #include "slcompress.h"
5875240ed1SBrian Somers #include "ipcp.h"
591ae349f5Scvs2svn #include "filter.h"
602f786681SBrian Somers #include "descriptor.h"
6175240ed1SBrian Somers #include "lcp.h"
623b0f8d2eSBrian Somers #include "ccp.h"
633b0f8d2eSBrian Somers #include "link.h"
643b0f8d2eSBrian Somers #include "mp.h"
65972a1bcfSBrian Somers #ifndef NORADIUS
66972a1bcfSBrian Somers #include "radius.h"
67972a1bcfSBrian Somers #endif
687a6f8720SBrian Somers #include "bundle.h"
691ae349f5Scvs2svn #include "vjcomp.h"
706a6b4bbbSBrian Somers #include "tun.h"
7175240ed1SBrian Somers #include "ip.h"
72af57ed9fSAtsushi Murai 
73b6e82f33SBrian Somers static const u_short interactive_ports[32] = {
7476bd0c0aSDoug Rabson   544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7522d1222bSBrian Somers   80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
76af57ed9fSAtsushi Murai };
77af57ed9fSAtsushi Murai 
7876bd0c0aSDoug Rabson #define	INTERACTIVE(p)	(interactive_ports[(p) & 0x1F] == (p))
79af57ed9fSAtsushi Murai 
80b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
81af57ed9fSAtsushi Murai 
82af57ed9fSAtsushi Murai static int
83944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport)
84af57ed9fSAtsushi Murai {
85af57ed9fSAtsushi Murai   switch (op) {
86af57ed9fSAtsushi Murai     case OP_EQ:
87af57ed9fSAtsushi Murai     return (pport == rport);
88af57ed9fSAtsushi Murai   case OP_GT:
89af57ed9fSAtsushi Murai     return (pport > rport);
90af57ed9fSAtsushi Murai   case OP_LT:
91af57ed9fSAtsushi Murai     return (pport < rport);
92af57ed9fSAtsushi Murai   default:
93af57ed9fSAtsushi Murai     return (0);
94af57ed9fSAtsushi Murai   }
95af57ed9fSAtsushi Murai }
96af57ed9fSAtsushi Murai 
97af57ed9fSAtsushi Murai /*
985d9e6103SBrian Somers  *  Check a packet against a defined filter
99af57ed9fSAtsushi Murai  */
100af57ed9fSAtsushi Murai static int
1015ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter)
102af57ed9fSAtsushi Murai {
10363f98b41SBrian Somers   int gotinfo, cproto, estab, syn, finrst, n, len, didname;
104af57ed9fSAtsushi Murai   struct tcphdr *th;
105af57ed9fSAtsushi Murai   struct udphdr *uh;
106af57ed9fSAtsushi Murai   struct icmp *ih;
107af57ed9fSAtsushi Murai   char *ptop;
108af57ed9fSAtsushi Murai   u_short sport, dport;
1095ca5389aSBrian Somers   struct filterent *fp = filter->rule;
1108390b576SBrian Somers   char dbuff[100];
111af57ed9fSAtsushi Murai 
112af57ed9fSAtsushi Murai   if (fp->action) {
11363f98b41SBrian Somers     cproto = gotinfo = estab = syn = finrst = didname = 0;
114af57ed9fSAtsushi Murai     sport = dport = 0;
115af57ed9fSAtsushi Murai     for (n = 0; n < MAXFILTERS; n++) {
116af57ed9fSAtsushi Murai       if (fp->action) {
117f1884650SAtsushi Murai 	/* permit fragments on in and out filter */
1185ca5389aSBrian Somers         if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0)
119f1884650SAtsushi Murai 	  return (A_PERMIT);
1205ca5389aSBrian Somers 
1218390b576SBrian Somers         if (!didname)
122dd7e2610SBrian Somers           log_Printf(LogDEBUG, "%s filter:\n", filter->name);
1238390b576SBrian Somers         didname = 1;
1248390b576SBrian Somers 
125a272e47dSBrian Somers 	if ((pip->ip_src.s_addr & fp->smask.s_addr) ==
126a272e47dSBrian Somers 	    (fp->saddr.s_addr & fp->smask.s_addr) &&
127a272e47dSBrian Somers 	    (pip->ip_dst.s_addr & fp->dmask.s_addr) ==
128a272e47dSBrian Somers 	    (fp->daddr.s_addr & fp->dmask.s_addr)) {
129af57ed9fSAtsushi Murai 	  if (fp->proto) {
130af57ed9fSAtsushi Murai 	    if (!gotinfo) {
131af57ed9fSAtsushi Murai 	      ptop = (char *) pip + (pip->ip_hl << 2);
132af57ed9fSAtsushi Murai 
133af57ed9fSAtsushi Murai 	      switch (pip->ip_p) {
134af57ed9fSAtsushi Murai 	      case IPPROTO_ICMP:
135944f7098SBrian Somers 		cproto = P_ICMP;
136944f7098SBrian Somers 		ih = (struct icmp *) ptop;
137944f7098SBrian Somers 		sport = ih->icmp_type;
13863f98b41SBrian Somers 		estab = syn = finrst = -1;
139dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG))
1408390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
141af57ed9fSAtsushi Murai 		break;
142af57ed9fSAtsushi Murai 	      case IPPROTO_UDP:
143eee772ecSBrian Somers 	      case IPPROTO_IGMP:
144eee772ecSBrian Somers 	      case IPPROTO_IPIP:
145944f7098SBrian Somers 		cproto = P_UDP;
146944f7098SBrian Somers 		uh = (struct udphdr *) ptop;
147944f7098SBrian Somers 		sport = ntohs(uh->uh_sport);
148944f7098SBrian Somers 		dport = ntohs(uh->uh_dport);
14963f98b41SBrian Somers 		estab = syn = finrst = -1;
150dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG))
1518390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
1528390b576SBrian Somers                            sport, dport);
153af57ed9fSAtsushi Murai 		break;
154af57ed9fSAtsushi Murai 	      case IPPROTO_TCP:
155944f7098SBrian Somers 		cproto = P_TCP;
156944f7098SBrian Somers 		th = (struct tcphdr *) ptop;
157944f7098SBrian Somers 		sport = ntohs(th->th_sport);
158944f7098SBrian Somers 		dport = ntohs(th->th_dport);
159af57ed9fSAtsushi Murai 		estab = (th->th_flags & TH_ACK);
16063f98b41SBrian Somers 		syn = (th->th_flags & TH_SYN);
16163f98b41SBrian Somers 		finrst = (th->th_flags & (TH_FIN|TH_RST));
1622b81c773SBrian Somers                 if (log_IsKept(LogDEBUG)) {
1632b81c773SBrian Somers                   if (!estab)
1648390b576SBrian Somers 		    snprintf(dbuff, sizeof dbuff,
1658390b576SBrian Somers                              "flags = %02x, sport = %d, dport = %d",
166927145beSBrian Somers                              th->th_flags, sport, dport);
1672b81c773SBrian Somers                   else
1682b81c773SBrian Somers                     *dbuff = '\0';
1692b81c773SBrian Somers                 }
170af57ed9fSAtsushi Murai 		break;
171af57ed9fSAtsushi Murai 	      default:
172af57ed9fSAtsushi Murai 		return (A_DENY);       /* We'll block unknown type of packet */
173af57ed9fSAtsushi Murai 	      }
174dd7e2610SBrian Somers               if (log_IsKept(LogDEBUG)) {
1758390b576SBrian Somers                 if (estab != -1) {
1768390b576SBrian Somers                   len = strlen(dbuff);
17763f98b41SBrian Somers                   snprintf(dbuff + len, sizeof dbuff - len,
17863f98b41SBrian Somers                            ", estab = %d, syn = %d, finrst = %d",
17963f98b41SBrian Somers                            estab, syn, finrst);
180af57ed9fSAtsushi Murai                 }
181dd7e2610SBrian Somers 	        log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
1828390b576SBrian Somers                           filter_Proto2Nam(cproto), dbuff);
1838390b576SBrian Somers               }
1848390b576SBrian Somers 	      gotinfo = 1;
1858390b576SBrian Somers 	    }
186dd7e2610SBrian Somers             if (log_IsKept(LogDEBUG)) {
1878390b576SBrian Somers 	      if (fp->opt.srcop != OP_NONE) {
1888390b576SBrian Somers                 snprintf(dbuff, sizeof dbuff, ", src %s %d",
1898390b576SBrian Somers                          filter_Op2Nam(fp->opt.srcop), fp->opt.srcport);
1908390b576SBrian Somers                 len = strlen(dbuff);
1918390b576SBrian Somers               } else
1928390b576SBrian Somers                 len = 0;
1938390b576SBrian Somers 	      if (fp->opt.dstop != OP_NONE) {
1948390b576SBrian Somers                 snprintf(dbuff + len, sizeof dbuff - len,
1958390b576SBrian Somers                          ", dst %s %d", filter_Op2Nam(fp->opt.dstop),
1968390b576SBrian Somers                          fp->opt.dstport);
1978390b576SBrian Somers               } else if (!len)
1988390b576SBrian Somers                 *dbuff = '\0';
1998390b576SBrian Somers 
200dd7e2610SBrian Somers 	      log_Printf(LogDEBUG, "  rule = %d: Address match, "
2018390b576SBrian Somers                         "check against proto %s%s, action = %s\n",
2028390b576SBrian Somers                         n, filter_Proto2Nam(fp->proto),
2038390b576SBrian Somers                         dbuff, filter_Action2Nam(fp->action));
2048390b576SBrian Somers             }
205927145beSBrian Somers 
206af57ed9fSAtsushi Murai 	    if (cproto == fp->proto) {
207af57ed9fSAtsushi Murai 	      if ((fp->opt.srcop == OP_NONE ||
20863f98b41SBrian Somers 		   PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) &&
209af57ed9fSAtsushi Murai 		  (fp->opt.dstop == OP_NONE ||
21063f98b41SBrian Somers 		   PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) &&
21163f98b41SBrian Somers 		  (fp->opt.estab == 0 || estab) &&
21263f98b41SBrian Somers 		  (fp->opt.syn == 0 || syn) &&
21363f98b41SBrian Somers 		  (fp->opt.finrst == 0 || finrst)) {
214af57ed9fSAtsushi Murai 		return (fp->action);
215af57ed9fSAtsushi Murai 	      }
216af57ed9fSAtsushi Murai 	    }
217af57ed9fSAtsushi Murai 	  } else {
218af57ed9fSAtsushi Murai 	    /* Address is mached. Make a decision. */
219dd7e2610SBrian Somers 	    log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
2208390b576SBrian Somers                       filter_Action2Nam(fp->action));
221af57ed9fSAtsushi Murai 	    return (fp->action);
222af57ed9fSAtsushi Murai 	  }
2238390b576SBrian Somers 	} else
224dd7e2610SBrian Somers 	  log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
225af57ed9fSAtsushi Murai       }
226af57ed9fSAtsushi Murai       fp++;
227af57ed9fSAtsushi Murai     }
228af57ed9fSAtsushi Murai     return (A_DENY);		/* No rule is mached. Deny this packet */
229af57ed9fSAtsushi Murai   }
230af57ed9fSAtsushi Murai   return (A_PERMIT);		/* No rule is given. Permit this packet */
231af57ed9fSAtsushi Murai }
232af57ed9fSAtsushi Murai 
2335ca5389aSBrian Somers #ifdef notdef
234af57ed9fSAtsushi Murai static void
235944f7098SBrian Somers IcmpError(struct ip * pip, int code)
236af57ed9fSAtsushi Murai {
237af57ed9fSAtsushi Murai   struct mbuf *bp;
238af57ed9fSAtsushi Murai 
239af57ed9fSAtsushi Murai   if (pip->ip_p != IPPROTO_ICMP) {
240dd7e2610SBrian Somers     bp = mbuf_Alloc(cnt, MB_IPIN);
24175240ed1SBrian Somers     memcpy(MBUF_CTOP(bp), ptr, cnt);
242dd7e2610SBrian Somers     vj_SendFrame(bp);
2435828db6dSBrian Somers     ipcp_AddOutOctets(cnt);
2441ae349f5Scvs2svn   }
245af57ed9fSAtsushi Murai }
246af57ed9fSAtsushi Murai #endif
247af57ed9fSAtsushi Murai 
248af57ed9fSAtsushi Murai /*
249af57ed9fSAtsushi Murai  *  For debugging aid.
250af57ed9fSAtsushi Murai  */
251af57ed9fSAtsushi Murai int
2525ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
253af57ed9fSAtsushi Murai {
254af57ed9fSAtsushi Murai   struct ip *pip;
255af57ed9fSAtsushi Murai   struct tcphdr *th;
256af57ed9fSAtsushi Murai   struct udphdr *uh;
257af57ed9fSAtsushi Murai   struct icmp *icmph;
258af57ed9fSAtsushi Murai   char *ptop;
259af57ed9fSAtsushi Murai   int mask, len, n;
260af57ed9fSAtsushi Murai   int pri = PRI_NORMAL;
26155a8cdeaSBrian Somers   int logit, loglen;
262d93d3a9cSBrian Somers   char logbuf[200];
263af57ed9fSAtsushi Murai 
264dd7e2610SBrian Somers   logit = log_IsKept(LogTCPIP) && filter->logok;
26555a8cdeaSBrian Somers   loglen = 0;
266af57ed9fSAtsushi Murai 
267af57ed9fSAtsushi Murai   pip = (struct ip *) cp;
268af57ed9fSAtsushi Murai 
26955a8cdeaSBrian Somers   if (logit && loglen < sizeof logbuf) {
2705ca5389aSBrian Somers     snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
27155a8cdeaSBrian Somers     loglen += strlen(logbuf + loglen);
27255a8cdeaSBrian Somers   }
273af57ed9fSAtsushi Murai   ptop = (cp + (pip->ip_hl << 2));
274af57ed9fSAtsushi Murai 
275af57ed9fSAtsushi Murai   switch (pip->ip_p) {
276af57ed9fSAtsushi Murai   case IPPROTO_ICMP:
27755a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
278af57ed9fSAtsushi Murai       icmph = (struct icmp *) ptop;
27955a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
28055a8cdeaSBrian Somers 	     "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
28155a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
28255a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
28355a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
28455a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
285af57ed9fSAtsushi Murai     }
286af57ed9fSAtsushi Murai     break;
287af57ed9fSAtsushi Murai   case IPPROTO_UDP:
28855a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
289af57ed9fSAtsushi Murai       uh = (struct udphdr *) ptop;
29055a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
29155a8cdeaSBrian Somers 	   "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
29255a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
29355a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
29455a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
29555a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
296af57ed9fSAtsushi Murai     }
297af57ed9fSAtsushi Murai     break;
298eee772ecSBrian Somers   case IPPROTO_IPIP:
299eee772ecSBrian Somers     if (logit && loglen < sizeof logbuf) {
300eee772ecSBrian Somers       uh = (struct udphdr *) ptop;
301eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
302eee772ecSBrian Somers 	   "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
303eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
304eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
305eee772ecSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
306eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
307eee772ecSBrian Somers     }
308eee772ecSBrian Somers     break;
309eee772ecSBrian Somers   case IPPROTO_IGMP:
310eee772ecSBrian Somers     if (logit && loglen < sizeof logbuf) {
311eee772ecSBrian Somers       uh = (struct udphdr *) ptop;
312eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
313eee772ecSBrian Somers 	   "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
314eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
315eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
316eee772ecSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
317eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
318eee772ecSBrian Somers     }
319eee772ecSBrian Somers     break;
320af57ed9fSAtsushi Murai   case IPPROTO_TCP:
321af57ed9fSAtsushi Murai     th = (struct tcphdr *) ptop;
322af57ed9fSAtsushi Murai     if (pip->ip_tos == IPTOS_LOWDELAY)
323af57ed9fSAtsushi Murai       pri = PRI_FAST;
32476bd0c0aSDoug Rabson     else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
325af57ed9fSAtsushi Murai       if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
326af57ed9fSAtsushi Murai 	pri = PRI_FAST;
327af57ed9fSAtsushi Murai     }
32855a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
329af57ed9fSAtsushi Murai       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
33055a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
33155a8cdeaSBrian Somers 	   "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
33255a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
33355a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
33455a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
33555a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
336af57ed9fSAtsushi Murai       n = 0;
337af57ed9fSAtsushi Murai       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
33855a8cdeaSBrian Somers 	if (th->th_flags & mask) {
33955a8cdeaSBrian Somers 	  snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
34055a8cdeaSBrian Somers 	  loglen += strlen(logbuf + loglen);
34155a8cdeaSBrian Somers 	}
342af57ed9fSAtsushi Murai 	n++;
343af57ed9fSAtsushi Murai       }
34455a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
3453a2e4f62SBrian Somers 	       "  seq:%lx  ack:%lx (%d/%d)",
3463a2e4f62SBrian Somers 	       (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
34755a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
348af57ed9fSAtsushi Murai       if ((th->th_flags & TH_SYN) && nb > 40) {
349af57ed9fSAtsushi Murai 	u_short *sp;
350af57ed9fSAtsushi Murai 
351af57ed9fSAtsushi Murai 	ptop += 20;
352af57ed9fSAtsushi Murai 	sp = (u_short *) ptop;
35355a8cdeaSBrian Somers 	if (ntohs(sp[0]) == 0x0204) {
35455a8cdeaSBrian Somers 	  snprintf(logbuf + loglen, sizeof logbuf - loglen,
35555a8cdeaSBrian Somers 		   " MSS = %d", ntohs(sp[1]));
35655a8cdeaSBrian Somers 	  loglen += strlen(logbuf + loglen);
35755a8cdeaSBrian Somers 	}
358af57ed9fSAtsushi Murai       }
359af57ed9fSAtsushi Murai     }
360af57ed9fSAtsushi Murai     break;
361af57ed9fSAtsushi Murai   }
36276bd0c0aSDoug Rabson 
3635ca5389aSBrian Somers   if ((FilterCheck(pip, filter) & A_DENY)) {
364710e9c29SBrian Somers     if (logit)
365dd7e2610SBrian Somers       log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
3665ca5389aSBrian Somers #ifdef notdef
367944f7098SBrian Somers     if (direction == 0)
368944f7098SBrian Somers       IcmpError(pip, pri);
3695ca5389aSBrian Somers #endif
370af57ed9fSAtsushi Murai     return (-1);
371af57ed9fSAtsushi Murai   } else {
3725ca5389aSBrian Somers     /* Check Keep Alive filter */
373e43ebac1SBrian Somers     if (logit) {
3741e991daaSBrian Somers       if (FilterCheck(pip, &bundle->filter.alive) & A_DENY)
375dd7e2610SBrian Somers         log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
3761e991daaSBrian Somers       else
377dd7e2610SBrian Somers         log_Printf(LogTCPIP, "%s\n", logbuf);
37853c9f6c0SAtsushi Murai     }
379af57ed9fSAtsushi Murai     return (pri);
380af57ed9fSAtsushi Murai   }
381af57ed9fSAtsushi Murai }
382af57ed9fSAtsushi Murai 
3835d9e6103SBrian Somers struct mbuf *
3845d9e6103SBrian Somers ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
3857a6f8720SBrian Somers {
386af57ed9fSAtsushi Murai   int nb, nw;
387b6e82f33SBrian Somers   struct tun_data tun;
3885d9e6103SBrian Somers   struct ip *pip;
3895d9e6103SBrian Somers 
3905d9e6103SBrian Somers   if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
3915d9e6103SBrian Somers     log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
3925d9e6103SBrian Somers     mbuf_Free(bp);
3935d9e6103SBrian Somers     return NULL;
3945d9e6103SBrian Somers   }
395af57ed9fSAtsushi Murai 
3966a6b4bbbSBrian Somers   tun_fill_header(tun, AF_INET);
3975d9e6103SBrian Somers   nb = mbuf_Length(bp);
3985d9e6103SBrian Somers   mbuf_Read(bp, tun.data, nb);
399af57ed9fSAtsushi Murai 
4005d9e6103SBrian Somers   if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
4015d9e6103SBrian Somers     return NULL;
4026db75539SBrian Somers 
4035d9e6103SBrian Somers   pip = (struct ip *)tun.data;
4041e991daaSBrian Somers   if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
4051e991daaSBrian Somers     bundle_StartIdleTimer(bundle);
4061e991daaSBrian Somers 
4075828db6dSBrian Somers   ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
4081e991daaSBrian Somers 
40970ee81ffSBrian Somers   nb += sizeof tun - sizeof tun.data;
410faefde08SBrian Somers   nw = write(bundle->dev.fd, &tun, nb);
411c4c4aaacSBrian Somers   if (nw != nb) {
41257fd05c4SBrian Somers     if (nw == -1)
413dd7e2610SBrian Somers       log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno));
41457fd05c4SBrian Somers     else
415dd7e2610SBrian Somers       log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
4166db75539SBrian Somers   }
4175d9e6103SBrian Somers 
4185d9e6103SBrian Somers   return NULL;
419af57ed9fSAtsushi Murai }
420af57ed9fSAtsushi Murai 
421af57ed9fSAtsushi Murai void
4225a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
423af57ed9fSAtsushi Murai {
424af57ed9fSAtsushi Murai   struct mbuf *bp;
425af57ed9fSAtsushi Murai 
4265a72b6edSBrian Somers   if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0])
4275a72b6edSBrian Somers     log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
4285a72b6edSBrian Somers   else {
4295d9e6103SBrian Somers     /*
4305d9e6103SBrian Somers      * We allocate an extra 6 bytes, four at the front and two at the end.
4315d9e6103SBrian Somers      * This is an optimisation so that we need to do less work in
4325d9e6103SBrian Somers      * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and
4335d9e6103SBrian Somers      * appending in hdlc_LayerPush().
4345d9e6103SBrian Somers      */
4355d9e6103SBrian Somers     bp = mbuf_Alloc(count + 6, MB_IPQ);
4365d9e6103SBrian Somers     bp->offset += 4;
4375d9e6103SBrian Somers     bp->cnt -= 6;
43875240ed1SBrian Somers     memcpy(MBUF_CTOP(bp), ptr, count);
4395a72b6edSBrian Somers     mbuf_Enqueue(&ipcp->Queue[pri], bp);
4405a72b6edSBrian Somers   }
441af57ed9fSAtsushi Murai }
442af57ed9fSAtsushi Murai 
4436f8e9f0aSBrian Somers void
4445a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp)
4456f8e9f0aSBrian Somers {
4466f8e9f0aSBrian Somers   struct mqueue *queue;
4476f8e9f0aSBrian Somers 
4485a72b6edSBrian Somers   for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
4496f8e9f0aSBrian Somers     while (queue->top)
4506f8e9f0aSBrian Somers       mbuf_Free(mbuf_Dequeue(queue));
4516f8e9f0aSBrian Somers }
4526f8e9f0aSBrian Somers 
45384b8a6ebSAtsushi Murai int
4545a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp)
45584b8a6ebSAtsushi Murai {
45684b8a6ebSAtsushi Murai   struct mqueue *queue;
457f4768038SBrian Somers   int result = 0;
458944f7098SBrian Somers 
4595a72b6edSBrian Somers   for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
460f4768038SBrian Somers     result += queue->qlen;
46184b8a6ebSAtsushi Murai 
462f4768038SBrian Somers   return result;
4631ae349f5Scvs2svn }
4641ae349f5Scvs2svn 
4653b0f8d2eSBrian Somers int
4665d9e6103SBrian Somers ip_PushPacket(struct link *l, struct bundle *bundle)
467af57ed9fSAtsushi Murai {
4685a72b6edSBrian Somers   struct ipcp *ipcp = &bundle->ncp.ipcp;
469af57ed9fSAtsushi Murai   struct mqueue *queue;
470af57ed9fSAtsushi Murai   struct mbuf *bp;
4715d9e6103SBrian Somers   struct ip *pip;
472274e766cSBrian Somers   int cnt;
473af57ed9fSAtsushi Murai 
4745a72b6edSBrian Somers   if (ipcp->fsm.state != ST_OPENED)
4753b0f8d2eSBrian Somers     return 0;
4761e991daaSBrian Somers 
4775a72b6edSBrian Somers   for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--)
478af57ed9fSAtsushi Murai     if (queue->top) {
479aad80d9fSBrian Somers       bp = mbuf_Contiguous(mbuf_Dequeue(queue));
480dd7e2610SBrian Somers       cnt = mbuf_Length(bp);
4815d9e6103SBrian Somers       pip = (struct ip *)MBUF_CTOP(bp);
4821e991daaSBrian Somers       if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
483ab886ad0SBrian Somers         bundle_StartIdleTimer(bundle);
4845d9e6103SBrian Somers       link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP);
4855a72b6edSBrian Somers       ipcp_AddOutOctets(ipcp, cnt);
4863b0f8d2eSBrian Somers       return 1;
487af57ed9fSAtsushi Murai     }
4881e991daaSBrian Somers 
4893b0f8d2eSBrian Somers   return 0;
490af57ed9fSAtsushi Murai }
491