xref: /freebsd/usr.sbin/ppp/ip.c (revision 3a2e4f621c7f05e1f6148507e3e5ca55ff3a01f0)
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  *
203a2e4f62SBrian Somers  * $Id: ip.c,v 1.47 1998/06/27 14:18:05 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>
351fa665f5SBrian Somers #include <sys/un.h>
3675240ed1SBrian Somers 
37b6e82f33SBrian Somers #ifndef NOALIAS
386db75539SBrian Somers #include <alias.h>
39b6e82f33SBrian Somers #endif
4057fd05c4SBrian Somers #include <errno.h>
4175240ed1SBrian Somers #include <stdio.h>
4275240ed1SBrian Somers #include <stdlib.h>
4375240ed1SBrian Somers #include <string.h>
4475240ed1SBrian Somers #include <unistd.h>
4575240ed1SBrian Somers 
46927145beSBrian Somers #include "mbuf.h"
47927145beSBrian Somers #include "log.h"
4875240ed1SBrian Somers #include "defs.h"
4975240ed1SBrian Somers #include "timer.h"
5075240ed1SBrian Somers #include "fsm.h"
51879ed6faSBrian Somers #include "lqr.h"
5275240ed1SBrian Somers #include "hdlc.h"
535828db6dSBrian Somers #include "throughput.h"
545828db6dSBrian Somers #include "iplist.h"
55eaa4df37SBrian Somers #include "slcompress.h"
5675240ed1SBrian Somers #include "ipcp.h"
571ae349f5Scvs2svn #include "filter.h"
582f786681SBrian Somers #include "descriptor.h"
5975240ed1SBrian Somers #include "lcp.h"
603b0f8d2eSBrian Somers #include "ccp.h"
613b0f8d2eSBrian Somers #include "link.h"
623b0f8d2eSBrian Somers #include "mp.h"
637a6f8720SBrian Somers #include "bundle.h"
641ae349f5Scvs2svn #include "vjcomp.h"
656a6b4bbbSBrian Somers #include "tun.h"
6675240ed1SBrian Somers #include "ip.h"
67af57ed9fSAtsushi Murai 
68b6e82f33SBrian Somers static const u_short interactive_ports[32] = {
6976bd0c0aSDoug Rabson   544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7076bd0c0aSDoug Rabson   0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
71af57ed9fSAtsushi Murai };
72af57ed9fSAtsushi Murai 
7376bd0c0aSDoug Rabson #define	INTERACTIVE(p)	(interactive_ports[(p) & 0x1F] == (p))
74af57ed9fSAtsushi Murai 
75b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
76af57ed9fSAtsushi Murai 
77af57ed9fSAtsushi Murai static int
78944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport)
79af57ed9fSAtsushi Murai {
80af57ed9fSAtsushi Murai   switch (op) {
81af57ed9fSAtsushi Murai     case OP_EQ:
82af57ed9fSAtsushi Murai     return (pport == rport);
83af57ed9fSAtsushi Murai   case OP_GT:
84af57ed9fSAtsushi Murai     return (pport > rport);
85af57ed9fSAtsushi Murai   case OP_LT:
86af57ed9fSAtsushi Murai     return (pport < rport);
87af57ed9fSAtsushi Murai   default:
88af57ed9fSAtsushi Murai     return (0);
89af57ed9fSAtsushi Murai   }
90af57ed9fSAtsushi Murai }
91af57ed9fSAtsushi Murai 
92af57ed9fSAtsushi Murai /*
93af57ed9fSAtsushi Murai  *  Check a packet against with defined filters
94af57ed9fSAtsushi Murai  */
95af57ed9fSAtsushi Murai static int
965ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter)
97af57ed9fSAtsushi Murai {
9863f98b41SBrian Somers   int gotinfo, cproto, estab, syn, finrst, n, len, didname;
99af57ed9fSAtsushi Murai   struct tcphdr *th;
100af57ed9fSAtsushi Murai   struct udphdr *uh;
101af57ed9fSAtsushi Murai   struct icmp *ih;
102af57ed9fSAtsushi Murai   char *ptop;
103af57ed9fSAtsushi Murai   u_short sport, dport;
1045ca5389aSBrian Somers   struct filterent *fp = filter->rule;
1058390b576SBrian Somers   char dbuff[100];
106af57ed9fSAtsushi Murai 
107af57ed9fSAtsushi Murai   if (fp->action) {
10863f98b41SBrian Somers     cproto = gotinfo = estab = syn = finrst = didname = 0;
109af57ed9fSAtsushi Murai     sport = dport = 0;
110af57ed9fSAtsushi Murai     for (n = 0; n < MAXFILTERS; n++) {
111af57ed9fSAtsushi Murai       if (fp->action) {
112f1884650SAtsushi Murai 	/* permit fragments on in and out filter */
1135ca5389aSBrian Somers         if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0)
114f1884650SAtsushi Murai 	  return (A_PERMIT);
1155ca5389aSBrian Somers 
1168390b576SBrian Somers         if (!didname)
117dd7e2610SBrian Somers           log_Printf(LogDEBUG, "%s filter:\n", filter->name);
1188390b576SBrian Somers         didname = 1;
1198390b576SBrian Somers 
120a272e47dSBrian Somers 	if ((pip->ip_src.s_addr & fp->smask.s_addr) ==
121a272e47dSBrian Somers 	    (fp->saddr.s_addr & fp->smask.s_addr) &&
122a272e47dSBrian Somers 	    (pip->ip_dst.s_addr & fp->dmask.s_addr) ==
123a272e47dSBrian Somers 	    (fp->daddr.s_addr & fp->dmask.s_addr)) {
124af57ed9fSAtsushi Murai 	  if (fp->proto) {
125af57ed9fSAtsushi Murai 	    if (!gotinfo) {
126af57ed9fSAtsushi Murai 	      ptop = (char *) pip + (pip->ip_hl << 2);
127af57ed9fSAtsushi Murai 
128af57ed9fSAtsushi Murai 	      switch (pip->ip_p) {
129af57ed9fSAtsushi Murai 	      case IPPROTO_ICMP:
130944f7098SBrian Somers 		cproto = P_ICMP;
131944f7098SBrian Somers 		ih = (struct icmp *) ptop;
132944f7098SBrian Somers 		sport = ih->icmp_type;
13363f98b41SBrian Somers 		estab = syn = finrst = -1;
134dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG))
1358390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
136af57ed9fSAtsushi Murai 		break;
137af57ed9fSAtsushi Murai 	      case IPPROTO_UDP:
138eee772ecSBrian Somers 	      case IPPROTO_IGMP:
139eee772ecSBrian Somers 	      case IPPROTO_IPIP:
140944f7098SBrian Somers 		cproto = P_UDP;
141944f7098SBrian Somers 		uh = (struct udphdr *) ptop;
142944f7098SBrian Somers 		sport = ntohs(uh->uh_sport);
143944f7098SBrian Somers 		dport = ntohs(uh->uh_dport);
14463f98b41SBrian Somers 		estab = syn = finrst = -1;
145dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG))
1468390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
1478390b576SBrian Somers                            sport, dport);
148af57ed9fSAtsushi Murai 		break;
149af57ed9fSAtsushi Murai 	      case IPPROTO_TCP:
150944f7098SBrian Somers 		cproto = P_TCP;
151944f7098SBrian Somers 		th = (struct tcphdr *) ptop;
152944f7098SBrian Somers 		sport = ntohs(th->th_sport);
153944f7098SBrian Somers 		dport = ntohs(th->th_dport);
154af57ed9fSAtsushi Murai 		estab = (th->th_flags & TH_ACK);
15563f98b41SBrian Somers 		syn = (th->th_flags & TH_SYN);
15663f98b41SBrian Somers 		finrst = (th->th_flags & (TH_FIN|TH_RST));
157dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG) && !estab)
1588390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff,
1598390b576SBrian Somers                            "flags = %02x, sport = %d, dport = %d",
160927145beSBrian Somers                            th->th_flags, sport, dport);
161af57ed9fSAtsushi Murai 		break;
162af57ed9fSAtsushi Murai 	      default:
163af57ed9fSAtsushi Murai 		return (A_DENY);       /* We'll block unknown type of packet */
164af57ed9fSAtsushi Murai 	      }
165dd7e2610SBrian Somers               if (log_IsKept(LogDEBUG)) {
1668390b576SBrian Somers                 if (estab != -1) {
1678390b576SBrian Somers                   len = strlen(dbuff);
16863f98b41SBrian Somers                   snprintf(dbuff + len, sizeof dbuff - len,
16963f98b41SBrian Somers                            ", estab = %d, syn = %d, finrst = %d",
17063f98b41SBrian Somers                            estab, syn, finrst);
171af57ed9fSAtsushi Murai                 }
172dd7e2610SBrian Somers 	        log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
1738390b576SBrian Somers                           filter_Proto2Nam(cproto), dbuff);
1748390b576SBrian Somers               }
1758390b576SBrian Somers 	      gotinfo = 1;
1768390b576SBrian Somers 	    }
177dd7e2610SBrian Somers             if (log_IsKept(LogDEBUG)) {
1788390b576SBrian Somers 	      if (fp->opt.srcop != OP_NONE) {
1798390b576SBrian Somers                 snprintf(dbuff, sizeof dbuff, ", src %s %d",
1808390b576SBrian Somers                          filter_Op2Nam(fp->opt.srcop), fp->opt.srcport);
1818390b576SBrian Somers                 len = strlen(dbuff);
1828390b576SBrian Somers               } else
1838390b576SBrian Somers                 len = 0;
1848390b576SBrian Somers 	      if (fp->opt.dstop != OP_NONE) {
1858390b576SBrian Somers                 snprintf(dbuff + len, sizeof dbuff - len,
1868390b576SBrian Somers                          ", dst %s %d", filter_Op2Nam(fp->opt.dstop),
1878390b576SBrian Somers                          fp->opt.dstport);
1888390b576SBrian Somers               } else if (!len)
1898390b576SBrian Somers                 *dbuff = '\0';
1908390b576SBrian Somers 
191dd7e2610SBrian Somers 	      log_Printf(LogDEBUG, "  rule = %d: Address match, "
1928390b576SBrian Somers                         "check against proto %s%s, action = %s\n",
1938390b576SBrian Somers                         n, filter_Proto2Nam(fp->proto),
1948390b576SBrian Somers                         dbuff, filter_Action2Nam(fp->action));
1958390b576SBrian Somers             }
196927145beSBrian Somers 
197af57ed9fSAtsushi Murai 	    if (cproto == fp->proto) {
198af57ed9fSAtsushi Murai 	      if ((fp->opt.srcop == OP_NONE ||
19963f98b41SBrian Somers 		   PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) &&
200af57ed9fSAtsushi Murai 		  (fp->opt.dstop == OP_NONE ||
20163f98b41SBrian Somers 		   PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) &&
20263f98b41SBrian Somers 		  (fp->opt.estab == 0 || estab) &&
20363f98b41SBrian Somers 		  (fp->opt.syn == 0 || syn) &&
20463f98b41SBrian Somers 		  (fp->opt.finrst == 0 || finrst)) {
205af57ed9fSAtsushi Murai 		return (fp->action);
206af57ed9fSAtsushi Murai 	      }
207af57ed9fSAtsushi Murai 	    }
208af57ed9fSAtsushi Murai 	  } else {
209af57ed9fSAtsushi Murai 	    /* Address is mached. Make a decision. */
210dd7e2610SBrian Somers 	    log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
2118390b576SBrian Somers                       filter_Action2Nam(fp->action));
212af57ed9fSAtsushi Murai 	    return (fp->action);
213af57ed9fSAtsushi Murai 	  }
2148390b576SBrian Somers 	} else
215dd7e2610SBrian Somers 	  log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
216af57ed9fSAtsushi Murai       }
217af57ed9fSAtsushi Murai       fp++;
218af57ed9fSAtsushi Murai     }
219af57ed9fSAtsushi Murai     return (A_DENY);		/* No rule is mached. Deny this packet */
220af57ed9fSAtsushi Murai   }
221af57ed9fSAtsushi Murai   return (A_PERMIT);		/* No rule is given. Permit this packet */
222af57ed9fSAtsushi Murai }
223af57ed9fSAtsushi Murai 
2245ca5389aSBrian Somers #ifdef notdef
225af57ed9fSAtsushi Murai static void
226944f7098SBrian Somers IcmpError(struct ip * pip, int code)
227af57ed9fSAtsushi Murai {
228af57ed9fSAtsushi Murai   struct mbuf *bp;
229af57ed9fSAtsushi Murai 
230af57ed9fSAtsushi Murai   if (pip->ip_p != IPPROTO_ICMP) {
231dd7e2610SBrian Somers     bp = mbuf_Alloc(cnt, MB_IPIN);
23275240ed1SBrian Somers     memcpy(MBUF_CTOP(bp), ptr, cnt);
233dd7e2610SBrian Somers     vj_SendFrame(bp);
2345828db6dSBrian Somers     ipcp_AddOutOctets(cnt);
2351ae349f5Scvs2svn   }
236af57ed9fSAtsushi Murai }
237af57ed9fSAtsushi Murai #endif
238af57ed9fSAtsushi Murai 
239af57ed9fSAtsushi Murai /*
240af57ed9fSAtsushi Murai  *  For debugging aid.
241af57ed9fSAtsushi Murai  */
242af57ed9fSAtsushi Murai int
2435ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
244af57ed9fSAtsushi Murai {
245af57ed9fSAtsushi Murai   struct ip *pip;
246af57ed9fSAtsushi Murai   struct tcphdr *th;
247af57ed9fSAtsushi Murai   struct udphdr *uh;
248af57ed9fSAtsushi Murai   struct icmp *icmph;
249af57ed9fSAtsushi Murai   char *ptop;
250af57ed9fSAtsushi Murai   int mask, len, n;
251af57ed9fSAtsushi Murai   int pri = PRI_NORMAL;
25255a8cdeaSBrian Somers   int logit, loglen;
253d93d3a9cSBrian Somers   char logbuf[200];
254af57ed9fSAtsushi Murai 
255dd7e2610SBrian Somers   logit = log_IsKept(LogTCPIP) && filter->logok;
25655a8cdeaSBrian Somers   loglen = 0;
257af57ed9fSAtsushi Murai 
258af57ed9fSAtsushi Murai   pip = (struct ip *) cp;
259af57ed9fSAtsushi Murai 
26055a8cdeaSBrian Somers   if (logit && loglen < sizeof logbuf) {
2615ca5389aSBrian Somers     snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
26255a8cdeaSBrian Somers     loglen += strlen(logbuf + loglen);
26355a8cdeaSBrian Somers   }
264af57ed9fSAtsushi Murai   ptop = (cp + (pip->ip_hl << 2));
265af57ed9fSAtsushi Murai 
266af57ed9fSAtsushi Murai   switch (pip->ip_p) {
267af57ed9fSAtsushi Murai   case IPPROTO_ICMP:
26855a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
269af57ed9fSAtsushi Murai       icmph = (struct icmp *) ptop;
27055a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
27155a8cdeaSBrian Somers 	     "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
27255a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
27355a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
27455a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
27555a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
276af57ed9fSAtsushi Murai     }
277af57ed9fSAtsushi Murai     break;
278af57ed9fSAtsushi Murai   case IPPROTO_UDP:
27955a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
280af57ed9fSAtsushi Murai       uh = (struct udphdr *) ptop;
28155a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
28255a8cdeaSBrian Somers 	   "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
28355a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
28455a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
28555a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
28655a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
287af57ed9fSAtsushi Murai     }
288af57ed9fSAtsushi Murai     break;
289eee772ecSBrian Somers   case IPPROTO_IPIP:
290eee772ecSBrian Somers     if (logit && loglen < sizeof logbuf) {
291eee772ecSBrian Somers       uh = (struct udphdr *) ptop;
292eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
293eee772ecSBrian Somers 	   "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
294eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
295eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
296eee772ecSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
297eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
298eee772ecSBrian Somers     }
299eee772ecSBrian Somers     break;
300eee772ecSBrian Somers   case IPPROTO_IGMP:
301eee772ecSBrian Somers     if (logit && loglen < sizeof logbuf) {
302eee772ecSBrian Somers       uh = (struct udphdr *) ptop;
303eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
304eee772ecSBrian Somers 	   "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
305eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
306eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
307eee772ecSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
308eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
309eee772ecSBrian Somers     }
310eee772ecSBrian Somers     break;
311af57ed9fSAtsushi Murai   case IPPROTO_TCP:
312af57ed9fSAtsushi Murai     th = (struct tcphdr *) ptop;
313af57ed9fSAtsushi Murai     if (pip->ip_tos == IPTOS_LOWDELAY)
314af57ed9fSAtsushi Murai       pri = PRI_FAST;
31576bd0c0aSDoug Rabson     else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
316af57ed9fSAtsushi Murai       if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
317af57ed9fSAtsushi Murai 	pri = PRI_FAST;
318af57ed9fSAtsushi Murai     }
31955a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
320af57ed9fSAtsushi Murai       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
32155a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
32255a8cdeaSBrian Somers 	   "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
32355a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
32455a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
32555a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
32655a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
327af57ed9fSAtsushi Murai       n = 0;
328af57ed9fSAtsushi Murai       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
32955a8cdeaSBrian Somers 	if (th->th_flags & mask) {
33055a8cdeaSBrian Somers 	  snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
33155a8cdeaSBrian Somers 	  loglen += strlen(logbuf + loglen);
33255a8cdeaSBrian Somers 	}
333af57ed9fSAtsushi Murai 	n++;
334af57ed9fSAtsushi Murai       }
33555a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
3363a2e4f62SBrian Somers 	       "  seq:%lx  ack:%lx (%d/%d)",
3373a2e4f62SBrian Somers 	       (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
33855a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
339af57ed9fSAtsushi Murai       if ((th->th_flags & TH_SYN) && nb > 40) {
340af57ed9fSAtsushi Murai 	u_short *sp;
341af57ed9fSAtsushi Murai 
342af57ed9fSAtsushi Murai 	ptop += 20;
343af57ed9fSAtsushi Murai 	sp = (u_short *) ptop;
34455a8cdeaSBrian Somers 	if (ntohs(sp[0]) == 0x0204) {
34555a8cdeaSBrian Somers 	  snprintf(logbuf + loglen, sizeof logbuf - loglen,
34655a8cdeaSBrian Somers 		   " MSS = %d", ntohs(sp[1]));
34755a8cdeaSBrian Somers 	  loglen += strlen(logbuf + loglen);
34855a8cdeaSBrian Somers 	}
349af57ed9fSAtsushi Murai       }
350af57ed9fSAtsushi Murai     }
351af57ed9fSAtsushi Murai     break;
352af57ed9fSAtsushi Murai   }
35376bd0c0aSDoug Rabson 
3545ca5389aSBrian Somers   if ((FilterCheck(pip, filter) & A_DENY)) {
355710e9c29SBrian Somers     if (logit)
356dd7e2610SBrian Somers       log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
3575ca5389aSBrian Somers #ifdef notdef
358944f7098SBrian Somers     if (direction == 0)
359944f7098SBrian Somers       IcmpError(pip, pri);
3605ca5389aSBrian Somers #endif
361af57ed9fSAtsushi Murai     return (-1);
362af57ed9fSAtsushi Murai   } else {
3635ca5389aSBrian Somers     /* Check Keep Alive filter */
364e43ebac1SBrian Somers     if (logit) {
3651e991daaSBrian Somers       if (FilterCheck(pip, &bundle->filter.alive) & A_DENY)
366dd7e2610SBrian Somers         log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
3671e991daaSBrian Somers       else
368dd7e2610SBrian Somers         log_Printf(LogTCPIP, "%s\n", logbuf);
36953c9f6c0SAtsushi Murai     }
370af57ed9fSAtsushi Murai     return (pri);
371af57ed9fSAtsushi Murai   }
372af57ed9fSAtsushi Murai }
373af57ed9fSAtsushi Murai 
374af57ed9fSAtsushi Murai void
375dd7e2610SBrian Somers ip_Input(struct bundle *bundle, struct mbuf * bp)
3767a6f8720SBrian Somers {
377af57ed9fSAtsushi Murai   u_char *cp;
378af57ed9fSAtsushi Murai   struct mbuf *wp;
379af57ed9fSAtsushi Murai   int nb, nw;
380b6e82f33SBrian Somers   struct tun_data tun;
3811e991daaSBrian Somers   struct ip *pip = (struct ip *)tun.data;
3823a2e4f62SBrian Somers #ifndef NOALIAS
383eee772ecSBrian Somers   struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2));
3843a2e4f62SBrian Somers #endif
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) {
391a33b2ef7SBrian Somers       log_Printf(LogWARN, "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
402615ad4f9SBrian Somers   if (bundle->AliasEnabled && 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 
408615ad4f9SBrian Somers     iresult = PacketAliasIn(tun.data, sizeof tun.data);
4096a6b4bbbSBrian Somers     nb = ntohs(((struct ip *) tun.data)->ip_len);
4106db75539SBrian Somers 
4116db75539SBrian Somers     if (nb > MAX_MRU) {
412a33b2ef7SBrian Somers       log_Printf(LogWARN, "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) {
440615ad4f9SBrian Somers 	while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) {
441615ad4f9SBrian Somers 	  PacketAliasFragmentIn(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);
466615ad4f9SBrian Somers 	PacketAliasSaveFragment(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