xref: /freebsd/usr.sbin/ppp/ip.c (revision eee772ec70cd9667a62b8edef5f70ceb6d6c5ade)
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  *
20eee772ecSBrian Somers  * $Id: ip.c,v 1.41 1998/05/21 21:45:37 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  */
262764b86aSBrian Somers #include <sys/types.h>
276a6b4bbbSBrian Somers #include <sys/socket.h>
2875240ed1SBrian Somers #include <netinet/in.h>
29af57ed9fSAtsushi Murai #include <netinet/in_systm.h>
30af57ed9fSAtsushi Murai #include <netinet/ip.h>
31af57ed9fSAtsushi Murai #include <netinet/ip_icmp.h>
32af57ed9fSAtsushi Murai #include <netinet/udp.h>
33af57ed9fSAtsushi Murai #include <netinet/tcp.h>
34ed6a16c1SPoul-Henning Kamp #include <arpa/inet.h>
35e43ebac1SBrian Somers #include <net/if_tun.h>
361fa665f5SBrian Somers #include <sys/un.h>
3775240ed1SBrian Somers 
38b6e82f33SBrian Somers #ifndef NOALIAS
396db75539SBrian Somers #include <alias.h>
40b6e82f33SBrian Somers #endif
4157fd05c4SBrian Somers #include <errno.h>
4275240ed1SBrian Somers #include <stdio.h>
4375240ed1SBrian Somers #include <stdlib.h>
4475240ed1SBrian Somers #include <string.h>
4575240ed1SBrian Somers #include <unistd.h>
4675240ed1SBrian Somers 
47927145beSBrian Somers #include "mbuf.h"
48927145beSBrian Somers #include "log.h"
4975240ed1SBrian Somers #include "defs.h"
5075240ed1SBrian Somers #include "timer.h"
5175240ed1SBrian Somers #include "fsm.h"
52879ed6faSBrian Somers #include "lqr.h"
5375240ed1SBrian Somers #include "hdlc.h"
5475240ed1SBrian Somers #include "loadalias.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"
657a6f8720SBrian Somers #include "bundle.h"
661ae349f5Scvs2svn #include "vjcomp.h"
676a6b4bbbSBrian Somers #include "tun.h"
6875240ed1SBrian Somers #include "ip.h"
69af57ed9fSAtsushi Murai 
70b6e82f33SBrian Somers static const u_short interactive_ports[32] = {
7176bd0c0aSDoug Rabson   544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7276bd0c0aSDoug Rabson   0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
73af57ed9fSAtsushi Murai };
74af57ed9fSAtsushi Murai 
7576bd0c0aSDoug Rabson #define	INTERACTIVE(p)	(interactive_ports[(p) & 0x1F] == (p))
76af57ed9fSAtsushi Murai 
77b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
78af57ed9fSAtsushi Murai 
79af57ed9fSAtsushi Murai static int
80944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport)
81af57ed9fSAtsushi Murai {
82af57ed9fSAtsushi Murai   switch (op) {
83af57ed9fSAtsushi Murai     case OP_EQ:
84af57ed9fSAtsushi Murai     return (pport == rport);
85af57ed9fSAtsushi Murai   case OP_GT:
86af57ed9fSAtsushi Murai     return (pport > rport);
87af57ed9fSAtsushi Murai   case OP_LT:
88af57ed9fSAtsushi Murai     return (pport < rport);
89af57ed9fSAtsushi Murai   default:
90af57ed9fSAtsushi Murai     return (0);
91af57ed9fSAtsushi Murai   }
92af57ed9fSAtsushi Murai }
93af57ed9fSAtsushi Murai 
94af57ed9fSAtsushi Murai /*
95af57ed9fSAtsushi Murai  *  Check a packet against with defined filters
96af57ed9fSAtsushi Murai  */
97af57ed9fSAtsushi Murai static int
985ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter)
99af57ed9fSAtsushi Murai {
10063f98b41SBrian Somers   int gotinfo, cproto, estab, syn, finrst, n, len, didname;
101af57ed9fSAtsushi Murai   struct tcphdr *th;
102af57ed9fSAtsushi Murai   struct udphdr *uh;
103af57ed9fSAtsushi Murai   struct icmp *ih;
104af57ed9fSAtsushi Murai   char *ptop;
105af57ed9fSAtsushi Murai   u_short sport, dport;
1065ca5389aSBrian Somers   struct filterent *fp = filter->rule;
1078390b576SBrian Somers   char dbuff[100];
108af57ed9fSAtsushi Murai 
109af57ed9fSAtsushi Murai   if (fp->action) {
11063f98b41SBrian Somers     cproto = gotinfo = estab = syn = finrst = didname = 0;
111af57ed9fSAtsushi Murai     sport = dport = 0;
112af57ed9fSAtsushi Murai     for (n = 0; n < MAXFILTERS; n++) {
113af57ed9fSAtsushi Murai       if (fp->action) {
114f1884650SAtsushi Murai 	/* permit fragments on in and out filter */
1155ca5389aSBrian Somers         if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0)
116f1884650SAtsushi Murai 	  return (A_PERMIT);
1175ca5389aSBrian Somers 
1188390b576SBrian Somers         if (!didname)
119dd7e2610SBrian Somers           log_Printf(LogDEBUG, "%s filter:\n", filter->name);
1208390b576SBrian Somers         didname = 1;
1218390b576SBrian Somers 
122a272e47dSBrian Somers 	if ((pip->ip_src.s_addr & fp->smask.s_addr) ==
123a272e47dSBrian Somers 	    (fp->saddr.s_addr & fp->smask.s_addr) &&
124a272e47dSBrian Somers 	    (pip->ip_dst.s_addr & fp->dmask.s_addr) ==
125a272e47dSBrian Somers 	    (fp->daddr.s_addr & fp->dmask.s_addr)) {
126af57ed9fSAtsushi Murai 	  if (fp->proto) {
127af57ed9fSAtsushi Murai 	    if (!gotinfo) {
128af57ed9fSAtsushi Murai 	      ptop = (char *) pip + (pip->ip_hl << 2);
129af57ed9fSAtsushi Murai 
130af57ed9fSAtsushi Murai 	      switch (pip->ip_p) {
131af57ed9fSAtsushi Murai 	      case IPPROTO_ICMP:
132944f7098SBrian Somers 		cproto = P_ICMP;
133944f7098SBrian Somers 		ih = (struct icmp *) ptop;
134944f7098SBrian Somers 		sport = ih->icmp_type;
13563f98b41SBrian Somers 		estab = syn = finrst = -1;
136dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG))
1378390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
138af57ed9fSAtsushi Murai 		break;
139af57ed9fSAtsushi Murai 	      case IPPROTO_UDP:
140eee772ecSBrian Somers 	      case IPPROTO_IGMP:
141eee772ecSBrian Somers 	      case IPPROTO_IPIP:
142944f7098SBrian Somers 		cproto = P_UDP;
143944f7098SBrian Somers 		uh = (struct udphdr *) ptop;
144944f7098SBrian Somers 		sport = ntohs(uh->uh_sport);
145944f7098SBrian Somers 		dport = ntohs(uh->uh_dport);
14663f98b41SBrian Somers 		estab = syn = finrst = -1;
147dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG))
1488390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
1498390b576SBrian Somers                            sport, dport);
150af57ed9fSAtsushi Murai 		break;
151af57ed9fSAtsushi Murai 	      case IPPROTO_TCP:
152944f7098SBrian Somers 		cproto = P_TCP;
153944f7098SBrian Somers 		th = (struct tcphdr *) ptop;
154944f7098SBrian Somers 		sport = ntohs(th->th_sport);
155944f7098SBrian Somers 		dport = ntohs(th->th_dport);
156af57ed9fSAtsushi Murai 		estab = (th->th_flags & TH_ACK);
15763f98b41SBrian Somers 		syn = (th->th_flags & TH_SYN);
15863f98b41SBrian Somers 		finrst = (th->th_flags & (TH_FIN|TH_RST));
159dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG) && !estab)
1608390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff,
1618390b576SBrian Somers                            "flags = %02x, sport = %d, dport = %d",
162927145beSBrian Somers                            th->th_flags, sport, dport);
163af57ed9fSAtsushi Murai 		break;
164af57ed9fSAtsushi Murai 	      default:
165af57ed9fSAtsushi Murai 		return (A_DENY);       /* We'll block unknown type of packet */
166af57ed9fSAtsushi Murai 	      }
167dd7e2610SBrian Somers               if (log_IsKept(LogDEBUG)) {
1688390b576SBrian Somers                 if (estab != -1) {
1698390b576SBrian Somers                   len = strlen(dbuff);
17063f98b41SBrian Somers                   snprintf(dbuff + len, sizeof dbuff - len,
17163f98b41SBrian Somers                            ", estab = %d, syn = %d, finrst = %d",
17263f98b41SBrian Somers                            estab, syn, finrst);
173af57ed9fSAtsushi Murai                 }
174dd7e2610SBrian Somers 	        log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
1758390b576SBrian Somers                           filter_Proto2Nam(cproto), dbuff);
1768390b576SBrian Somers               }
1778390b576SBrian Somers 	      gotinfo = 1;
1788390b576SBrian Somers 	    }
179dd7e2610SBrian Somers             if (log_IsKept(LogDEBUG)) {
1808390b576SBrian Somers 	      if (fp->opt.srcop != OP_NONE) {
1818390b576SBrian Somers                 snprintf(dbuff, sizeof dbuff, ", src %s %d",
1828390b576SBrian Somers                          filter_Op2Nam(fp->opt.srcop), fp->opt.srcport);
1838390b576SBrian Somers                 len = strlen(dbuff);
1848390b576SBrian Somers               } else
1858390b576SBrian Somers                 len = 0;
1868390b576SBrian Somers 	      if (fp->opt.dstop != OP_NONE) {
1878390b576SBrian Somers                 snprintf(dbuff + len, sizeof dbuff - len,
1888390b576SBrian Somers                          ", dst %s %d", filter_Op2Nam(fp->opt.dstop),
1898390b576SBrian Somers                          fp->opt.dstport);
1908390b576SBrian Somers               } else if (!len)
1918390b576SBrian Somers                 *dbuff = '\0';
1928390b576SBrian Somers 
193dd7e2610SBrian Somers 	      log_Printf(LogDEBUG, "  rule = %d: Address match, "
1948390b576SBrian Somers                         "check against proto %s%s, action = %s\n",
1958390b576SBrian Somers                         n, filter_Proto2Nam(fp->proto),
1968390b576SBrian Somers                         dbuff, filter_Action2Nam(fp->action));
1978390b576SBrian Somers             }
198927145beSBrian Somers 
199af57ed9fSAtsushi Murai 	    if (cproto == fp->proto) {
200af57ed9fSAtsushi Murai 	      if ((fp->opt.srcop == OP_NONE ||
20163f98b41SBrian Somers 		   PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) &&
202af57ed9fSAtsushi Murai 		  (fp->opt.dstop == OP_NONE ||
20363f98b41SBrian Somers 		   PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) &&
20463f98b41SBrian Somers 		  (fp->opt.estab == 0 || estab) &&
20563f98b41SBrian Somers 		  (fp->opt.syn == 0 || syn) &&
20663f98b41SBrian Somers 		  (fp->opt.finrst == 0 || finrst)) {
207af57ed9fSAtsushi Murai 		return (fp->action);
208af57ed9fSAtsushi Murai 	      }
209af57ed9fSAtsushi Murai 	    }
210af57ed9fSAtsushi Murai 	  } else {
211af57ed9fSAtsushi Murai 	    /* Address is mached. Make a decision. */
212dd7e2610SBrian Somers 	    log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
2138390b576SBrian Somers                       filter_Action2Nam(fp->action));
214af57ed9fSAtsushi Murai 	    return (fp->action);
215af57ed9fSAtsushi Murai 	  }
2168390b576SBrian Somers 	} else
217dd7e2610SBrian Somers 	  log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
218af57ed9fSAtsushi Murai       }
219af57ed9fSAtsushi Murai       fp++;
220af57ed9fSAtsushi Murai     }
221af57ed9fSAtsushi Murai     return (A_DENY);		/* No rule is mached. Deny this packet */
222af57ed9fSAtsushi Murai   }
223af57ed9fSAtsushi Murai   return (A_PERMIT);		/* No rule is given. Permit this packet */
224af57ed9fSAtsushi Murai }
225af57ed9fSAtsushi Murai 
2265ca5389aSBrian Somers #ifdef notdef
227af57ed9fSAtsushi Murai static void
228944f7098SBrian Somers IcmpError(struct ip * pip, int code)
229af57ed9fSAtsushi Murai {
230af57ed9fSAtsushi Murai   struct mbuf *bp;
231af57ed9fSAtsushi Murai 
232af57ed9fSAtsushi Murai   if (pip->ip_p != IPPROTO_ICMP) {
233dd7e2610SBrian Somers     bp = mbuf_Alloc(cnt, MB_IPIN);
23475240ed1SBrian Somers     memcpy(MBUF_CTOP(bp), ptr, cnt);
235dd7e2610SBrian Somers     vj_SendFrame(bp);
2365828db6dSBrian Somers     ipcp_AddOutOctets(cnt);
2371ae349f5Scvs2svn   }
238af57ed9fSAtsushi Murai }
239af57ed9fSAtsushi Murai #endif
240af57ed9fSAtsushi Murai 
241af57ed9fSAtsushi Murai /*
242af57ed9fSAtsushi Murai  *  For debugging aid.
243af57ed9fSAtsushi Murai  */
244af57ed9fSAtsushi Murai int
2455ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
246af57ed9fSAtsushi Murai {
247af57ed9fSAtsushi Murai   struct ip *pip;
248af57ed9fSAtsushi Murai   struct tcphdr *th;
249af57ed9fSAtsushi Murai   struct udphdr *uh;
250af57ed9fSAtsushi Murai   struct icmp *icmph;
251af57ed9fSAtsushi Murai   char *ptop;
252af57ed9fSAtsushi Murai   int mask, len, n;
253af57ed9fSAtsushi Murai   int pri = PRI_NORMAL;
25455a8cdeaSBrian Somers   int logit, loglen;
25555a8cdeaSBrian Somers   static char logbuf[200];
256af57ed9fSAtsushi Murai 
257dd7e2610SBrian Somers   logit = log_IsKept(LogTCPIP) && filter->logok;
25855a8cdeaSBrian Somers   loglen = 0;
259af57ed9fSAtsushi Murai 
260af57ed9fSAtsushi Murai   pip = (struct ip *) cp;
261af57ed9fSAtsushi Murai 
26255a8cdeaSBrian Somers   if (logit && loglen < sizeof logbuf) {
2635ca5389aSBrian Somers     snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
26455a8cdeaSBrian Somers     loglen += strlen(logbuf + loglen);
26555a8cdeaSBrian Somers   }
266af57ed9fSAtsushi Murai   ptop = (cp + (pip->ip_hl << 2));
267af57ed9fSAtsushi Murai 
268af57ed9fSAtsushi Murai   switch (pip->ip_p) {
269af57ed9fSAtsushi Murai   case IPPROTO_ICMP:
27055a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
271af57ed9fSAtsushi Murai       icmph = (struct icmp *) ptop;
27255a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
27355a8cdeaSBrian Somers 	     "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
27455a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
27555a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
27655a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
27755a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
278af57ed9fSAtsushi Murai     }
279af57ed9fSAtsushi Murai     break;
280af57ed9fSAtsushi Murai   case IPPROTO_UDP:
28155a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
282af57ed9fSAtsushi Murai       uh = (struct udphdr *) ptop;
28355a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
28455a8cdeaSBrian Somers 	   "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
28555a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
28655a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
28755a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
28855a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
289af57ed9fSAtsushi Murai     }
290af57ed9fSAtsushi Murai     break;
291eee772ecSBrian Somers   case IPPROTO_IPIP:
292eee772ecSBrian Somers     if (logit && loglen < sizeof logbuf) {
293eee772ecSBrian Somers       uh = (struct udphdr *) ptop;
294eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
295eee772ecSBrian Somers 	   "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
296eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
297eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
298eee772ecSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
299eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
300eee772ecSBrian Somers     }
301eee772ecSBrian Somers     break;
302eee772ecSBrian Somers   case IPPROTO_IGMP:
303eee772ecSBrian Somers     if (logit && loglen < sizeof logbuf) {
304eee772ecSBrian Somers       uh = (struct udphdr *) ptop;
305eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
306eee772ecSBrian Somers 	   "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
307eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
308eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
309eee772ecSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
310eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
311eee772ecSBrian Somers     }
312eee772ecSBrian Somers     break;
313af57ed9fSAtsushi Murai   case IPPROTO_TCP:
314af57ed9fSAtsushi Murai     th = (struct tcphdr *) ptop;
315af57ed9fSAtsushi Murai     if (pip->ip_tos == IPTOS_LOWDELAY)
316af57ed9fSAtsushi Murai       pri = PRI_FAST;
31776bd0c0aSDoug Rabson     else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
318af57ed9fSAtsushi Murai       if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
319af57ed9fSAtsushi Murai 	pri = PRI_FAST;
320af57ed9fSAtsushi Murai     }
32155a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
322af57ed9fSAtsushi Murai       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
32355a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
32455a8cdeaSBrian Somers 	   "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
32555a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
32655a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
32755a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
32855a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
329af57ed9fSAtsushi Murai       n = 0;
330af57ed9fSAtsushi Murai       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
33155a8cdeaSBrian Somers 	if (th->th_flags & mask) {
33255a8cdeaSBrian Somers 	  snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
33355a8cdeaSBrian Somers 	  loglen += strlen(logbuf + loglen);
33455a8cdeaSBrian Somers 	}
335af57ed9fSAtsushi Murai 	n++;
336af57ed9fSAtsushi Murai       }
33755a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
33855a8cdeaSBrian Somers 	       "  seq:%x  ack:%x (%d/%d)",
339af57ed9fSAtsushi Murai 	       ntohl(th->th_seq), ntohl(th->th_ack), len, nb);
34055a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
341af57ed9fSAtsushi Murai       if ((th->th_flags & TH_SYN) && nb > 40) {
342af57ed9fSAtsushi Murai 	u_short *sp;
343af57ed9fSAtsushi Murai 
344af57ed9fSAtsushi Murai 	ptop += 20;
345af57ed9fSAtsushi Murai 	sp = (u_short *) ptop;
34655a8cdeaSBrian Somers 	if (ntohs(sp[0]) == 0x0204) {
34755a8cdeaSBrian Somers 	  snprintf(logbuf + loglen, sizeof logbuf - loglen,
34855a8cdeaSBrian Somers 		   " MSS = %d", ntohs(sp[1]));
34955a8cdeaSBrian Somers 	  loglen += strlen(logbuf + loglen);
35055a8cdeaSBrian Somers 	}
351af57ed9fSAtsushi Murai       }
352af57ed9fSAtsushi Murai     }
353af57ed9fSAtsushi Murai     break;
354af57ed9fSAtsushi Murai   }
35576bd0c0aSDoug Rabson 
3565ca5389aSBrian Somers   if ((FilterCheck(pip, filter) & A_DENY)) {
357710e9c29SBrian Somers     if (logit)
358dd7e2610SBrian Somers       log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
3595ca5389aSBrian Somers #ifdef notdef
360944f7098SBrian Somers     if (direction == 0)
361944f7098SBrian Somers       IcmpError(pip, pri);
3625ca5389aSBrian Somers #endif
363af57ed9fSAtsushi Murai     return (-1);
364af57ed9fSAtsushi Murai   } else {
3655ca5389aSBrian Somers     /* Check Keep Alive filter */
366e43ebac1SBrian Somers     if (logit) {
3671e991daaSBrian Somers       if (FilterCheck(pip, &bundle->filter.alive) & A_DENY)
368dd7e2610SBrian Somers         log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
3691e991daaSBrian Somers       else
370dd7e2610SBrian Somers         log_Printf(LogTCPIP, "%s\n", logbuf);
37153c9f6c0SAtsushi Murai     }
372af57ed9fSAtsushi Murai     return (pri);
373af57ed9fSAtsushi Murai   }
374af57ed9fSAtsushi Murai }
375af57ed9fSAtsushi Murai 
376af57ed9fSAtsushi Murai void
377dd7e2610SBrian Somers ip_Input(struct bundle *bundle, struct mbuf * bp)
3787a6f8720SBrian Somers {
379af57ed9fSAtsushi Murai   u_char *cp;
380af57ed9fSAtsushi Murai   struct mbuf *wp;
381af57ed9fSAtsushi Murai   int nb, nw;
382b6e82f33SBrian Somers   struct tun_data tun;
3831e991daaSBrian Somers   struct ip *pip = (struct ip *)tun.data;
384eee772ecSBrian Somers   struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2));
385af57ed9fSAtsushi Murai 
3866a6b4bbbSBrian Somers   tun_fill_header(tun, AF_INET);
3876a6b4bbbSBrian Somers   cp = tun.data;
388af57ed9fSAtsushi Murai   nb = 0;
389927145beSBrian Somers   for (wp = bp; wp; wp = wp->next) {	/* Copy to contiguous region */
390512db555SBrian Somers     if (sizeof tun.data - (cp - tun.data) < wp->cnt) {
391dd7e2610SBrian Somers       log_Printf(LogERROR, "ip_Input: Packet too large (%d) - dropped\n",
392dd7e2610SBrian Somers                 mbuf_Length(bp));
393dd7e2610SBrian Somers       mbuf_Free(bp);
394512db555SBrian Somers       return;
395512db555SBrian Somers     }
39675240ed1SBrian Somers     memcpy(cp, MBUF_CTOP(wp), wp->cnt);
397af57ed9fSAtsushi Murai     cp += wp->cnt;
398af57ed9fSAtsushi Murai     nb += wp->cnt;
399af57ed9fSAtsushi Murai   }
400af57ed9fSAtsushi Murai 
401b6e82f33SBrian Somers #ifndef NOALIAS
402eee772ecSBrian Somers   if (alias_IsEnabled() && pip->ip_p != IPPROTO_IGMP &&
403eee772ecSBrian Somers       (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) {
404b6e82f33SBrian Somers     struct tun_data *frag;
4056db75539SBrian Somers     int iresult;
4066db75539SBrian Somers     char *fptr;
4076db75539SBrian Somers 
4082764b86aSBrian Somers     iresult = (*PacketAlias.In)(tun.data, sizeof tun.data);
4096a6b4bbbSBrian Somers     nb = ntohs(((struct ip *) tun.data)->ip_len);
4106db75539SBrian Somers 
4116db75539SBrian Somers     if (nb > MAX_MRU) {
412dd7e2610SBrian Somers       log_Printf(LogERROR, "ip_Input: Problem with IP header length\n");
413dd7e2610SBrian Somers       mbuf_Free(bp);
4146db75539SBrian Somers       return;
415a9f484e5SJordan K. Hubbard     }
4166db75539SBrian Somers     if (iresult == PKT_ALIAS_OK
4176db75539SBrian Somers 	|| iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
4185ca5389aSBrian Somers       if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
419dd7e2610SBrian Somers 	mbuf_Free(bp);
420af57ed9fSAtsushi Murai 	return;
421af57ed9fSAtsushi Murai       }
4221e991daaSBrian Somers 
4231e991daaSBrian Somers       if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
4241e991daaSBrian Somers         bundle_StartIdleTimer(bundle);
4251e991daaSBrian Somers 
4265828db6dSBrian Somers       ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
4276db75539SBrian Somers 
4286a6b4bbbSBrian Somers       nb = ntohs(((struct ip *) tun.data)->ip_len);
42970ee81ffSBrian Somers       nb += sizeof tun - sizeof tun.data;
430faefde08SBrian Somers       nw = write(bundle->dev.fd, &tun, nb);
4316a596579SBrian Somers       if (nw != nb) {
43257fd05c4SBrian Somers         if (nw == -1)
433dd7e2610SBrian Somers 	  log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
43457fd05c4SBrian Somers                     strerror(errno));
43557fd05c4SBrian Somers         else
436dd7e2610SBrian Somers 	  log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
4376a596579SBrian Somers       }
4386db75539SBrian Somers 
4396db75539SBrian Somers       if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
4402764b86aSBrian Somers 	while ((fptr = (*PacketAlias.GetFragment)(tun.data)) != NULL) {
4412764b86aSBrian Somers 	  (*PacketAlias.FragmentIn)(tun.data, fptr);
4426db75539SBrian Somers 	  nb = ntohs(((struct ip *) fptr)->ip_len);
44370ee81ffSBrian Somers           frag = (struct tun_data *)
44470ee81ffSBrian Somers 	    ((char *)fptr - sizeof tun + sizeof tun.data);
44570ee81ffSBrian Somers           nb += sizeof tun - sizeof tun.data;
446faefde08SBrian Somers 	  nw = write(bundle->dev.fd, frag, nb);
4476a596579SBrian Somers 	  if (nw != nb) {
44857fd05c4SBrian Somers             if (nw == -1)
449dd7e2610SBrian Somers 	      log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
45057fd05c4SBrian Somers                         strerror(errno));
45157fd05c4SBrian Somers             else
452dd7e2610SBrian Somers 	      log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
4536a596579SBrian Somers           }
4546a6b4bbbSBrian Somers 	  free(frag);
4556db75539SBrian Somers 	}
4566db75539SBrian Somers       }
457944f7098SBrian Somers     } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) {
4586a6b4bbbSBrian Somers       nb = ntohs(((struct ip *) tun.data)->ip_len);
45970ee81ffSBrian Somers       nb += sizeof tun - sizeof tun.data;
4606a6b4bbbSBrian Somers       frag = (struct tun_data *)malloc(nb);
4616a6b4bbbSBrian Somers       if (frag == NULL)
462dd7e2610SBrian Somers 	log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n");
4636db75539SBrian Somers       else {
4646a6b4bbbSBrian Somers         tun_fill_header(*frag, AF_INET);
46570ee81ffSBrian Somers 	memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data);
4662764b86aSBrian Somers 	(*PacketAlias.SaveFragment)(frag->data);
4676db75539SBrian Somers       }
4686db75539SBrian Somers     }
469b6e82f33SBrian Somers   } else
470b6e82f33SBrian Somers #endif /* #ifndef NOALIAS */
471b6e82f33SBrian Somers   {			/* no aliasing */
4725ca5389aSBrian Somers     if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
473dd7e2610SBrian Somers       mbuf_Free(bp);
4746db75539SBrian Somers       return;
4756db75539SBrian Somers     }
4761e991daaSBrian Somers 
4771e991daaSBrian Somers     if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
4781e991daaSBrian Somers       bundle_StartIdleTimer(bundle);
4791e991daaSBrian Somers 
4805828db6dSBrian Somers     ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
4811e991daaSBrian Somers 
48270ee81ffSBrian Somers     nb += sizeof tun - sizeof tun.data;
483faefde08SBrian Somers     nw = write(bundle->dev.fd, &tun, nb);
484c4c4aaacSBrian Somers     if (nw != nb) {
48557fd05c4SBrian Somers       if (nw == -1)
486dd7e2610SBrian Somers 	log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno));
48757fd05c4SBrian Somers       else
488dd7e2610SBrian Somers         log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
4896db75539SBrian Somers     }
490c4c4aaacSBrian Somers   }
491dd7e2610SBrian Somers   mbuf_Free(bp);
492af57ed9fSAtsushi Murai }
493af57ed9fSAtsushi Murai 
49476bd0c0aSDoug Rabson static struct mqueue IpOutputQueues[PRI_FAST + 1];
495af57ed9fSAtsushi Murai 
496af57ed9fSAtsushi Murai void
497dd7e2610SBrian Somers ip_Enqueue(int pri, char *ptr, int count)
498af57ed9fSAtsushi Murai {
499af57ed9fSAtsushi Murai   struct mbuf *bp;
500af57ed9fSAtsushi Murai 
501dd7e2610SBrian Somers   bp = mbuf_Alloc(count, MB_IPQ);
50275240ed1SBrian Somers   memcpy(MBUF_CTOP(bp), ptr, count);
503dd7e2610SBrian Somers   mbuf_Enqueue(&IpOutputQueues[pri], bp);
504af57ed9fSAtsushi Murai }
505af57ed9fSAtsushi Murai 
50684b8a6ebSAtsushi Murai int
507f4768038SBrian Somers ip_QueueLen()
50884b8a6ebSAtsushi Murai {
50984b8a6ebSAtsushi Murai   struct mqueue *queue;
510f4768038SBrian Somers   int result = 0;
511944f7098SBrian Somers 
512f4768038SBrian Somers   for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--)
513f4768038SBrian Somers     result += queue->qlen;
51484b8a6ebSAtsushi Murai 
515f4768038SBrian Somers   return result;
5161ae349f5Scvs2svn }
5171ae349f5Scvs2svn 
5183b0f8d2eSBrian Somers int
519dd7e2610SBrian Somers ip_FlushPacket(struct link *l, struct bundle *bundle)
520af57ed9fSAtsushi Murai {
521af57ed9fSAtsushi Murai   struct mqueue *queue;
522af57ed9fSAtsushi Murai   struct mbuf *bp;
523274e766cSBrian Somers   int cnt;
524af57ed9fSAtsushi Murai 
5255828db6dSBrian Somers   if (bundle->ncp.ipcp.fsm.state != ST_OPENED)
5263b0f8d2eSBrian Somers     return 0;
5271e991daaSBrian Somers 
5281e991daaSBrian Somers   for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--)
529af57ed9fSAtsushi Murai     if (queue->top) {
530dd7e2610SBrian Somers       bp = mbuf_Dequeue(queue);
531af57ed9fSAtsushi Murai       if (bp) {
5321e991daaSBrian Somers         struct ip *pip = (struct ip *)MBUF_CTOP(bp);
5331e991daaSBrian Somers 
534dd7e2610SBrian Somers 	cnt = mbuf_Length(bp);
535dd7e2610SBrian Somers 	vj_SendFrame(l, bp, bundle);
5361e991daaSBrian Somers         if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
537ab886ad0SBrian Somers           bundle_StartIdleTimer(bundle);
5385828db6dSBrian Somers         ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt);
5393b0f8d2eSBrian Somers 	return 1;
540af57ed9fSAtsushi Murai       }
541af57ed9fSAtsushi Murai     }
5421e991daaSBrian Somers 
5433b0f8d2eSBrian Somers   return 0;
544af57ed9fSAtsushi Murai }
545