xref: /freebsd/usr.sbin/ppp/ip.c (revision 972a1bcf5db5ee4c5520a1d29d3c81e81bdec84f)
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  *
20972a1bcfSBrian Somers  * $Id: ip.c,v 1.54 1998/11/10 00:32:39 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>
2792b09558SBrian Somers #ifdef __OpenBSD__
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>
4375240ed1SBrian Somers #include <unistd.h>
4475240ed1SBrian Somers 
451595bacdSBrian Somers #ifndef NOALIAS
461595bacdSBrian Somers #ifdef __OpenBSD__
471595bacdSBrian Somers #include "alias.h"
481595bacdSBrian Somers #else
491595bacdSBrian Somers #include <alias.h>
501595bacdSBrian Somers #endif
511595bacdSBrian Somers #endif
52927145beSBrian Somers #include "mbuf.h"
53927145beSBrian Somers #include "log.h"
5475240ed1SBrian Somers #include "defs.h"
5575240ed1SBrian Somers #include "timer.h"
5675240ed1SBrian Somers #include "fsm.h"
57879ed6faSBrian Somers #include "lqr.h"
5875240ed1SBrian Somers #include "hdlc.h"
595828db6dSBrian Somers #include "throughput.h"
605828db6dSBrian Somers #include "iplist.h"
61eaa4df37SBrian Somers #include "slcompress.h"
6275240ed1SBrian Somers #include "ipcp.h"
631ae349f5Scvs2svn #include "filter.h"
642f786681SBrian Somers #include "descriptor.h"
6575240ed1SBrian Somers #include "lcp.h"
663b0f8d2eSBrian Somers #include "ccp.h"
673b0f8d2eSBrian Somers #include "link.h"
683b0f8d2eSBrian Somers #include "mp.h"
69972a1bcfSBrian Somers #ifndef NORADIUS
70972a1bcfSBrian Somers #include "radius.h"
71972a1bcfSBrian Somers #endif
727a6f8720SBrian Somers #include "bundle.h"
731ae349f5Scvs2svn #include "vjcomp.h"
746a6b4bbbSBrian Somers #include "tun.h"
7575240ed1SBrian Somers #include "ip.h"
76af57ed9fSAtsushi Murai 
77b6e82f33SBrian Somers static const u_short interactive_ports[32] = {
7876bd0c0aSDoug Rabson   544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7976bd0c0aSDoug Rabson   0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
80af57ed9fSAtsushi Murai };
81af57ed9fSAtsushi Murai 
8276bd0c0aSDoug Rabson #define	INTERACTIVE(p)	(interactive_ports[(p) & 0x1F] == (p))
83af57ed9fSAtsushi Murai 
84b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
85af57ed9fSAtsushi Murai 
86af57ed9fSAtsushi Murai static int
87944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport)
88af57ed9fSAtsushi Murai {
89af57ed9fSAtsushi Murai   switch (op) {
90af57ed9fSAtsushi Murai     case OP_EQ:
91af57ed9fSAtsushi Murai     return (pport == rport);
92af57ed9fSAtsushi Murai   case OP_GT:
93af57ed9fSAtsushi Murai     return (pport > rport);
94af57ed9fSAtsushi Murai   case OP_LT:
95af57ed9fSAtsushi Murai     return (pport < rport);
96af57ed9fSAtsushi Murai   default:
97af57ed9fSAtsushi Murai     return (0);
98af57ed9fSAtsushi Murai   }
99af57ed9fSAtsushi Murai }
100af57ed9fSAtsushi Murai 
101af57ed9fSAtsushi Murai /*
102af57ed9fSAtsushi Murai  *  Check a packet against with defined filters
103af57ed9fSAtsushi Murai  */
104af57ed9fSAtsushi Murai static int
1055ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter)
106af57ed9fSAtsushi Murai {
10763f98b41SBrian Somers   int gotinfo, cproto, estab, syn, finrst, n, len, didname;
108af57ed9fSAtsushi Murai   struct tcphdr *th;
109af57ed9fSAtsushi Murai   struct udphdr *uh;
110af57ed9fSAtsushi Murai   struct icmp *ih;
111af57ed9fSAtsushi Murai   char *ptop;
112af57ed9fSAtsushi Murai   u_short sport, dport;
1135ca5389aSBrian Somers   struct filterent *fp = filter->rule;
1148390b576SBrian Somers   char dbuff[100];
115af57ed9fSAtsushi Murai 
116af57ed9fSAtsushi Murai   if (fp->action) {
11763f98b41SBrian Somers     cproto = gotinfo = estab = syn = finrst = didname = 0;
118af57ed9fSAtsushi Murai     sport = dport = 0;
119af57ed9fSAtsushi Murai     for (n = 0; n < MAXFILTERS; n++) {
120af57ed9fSAtsushi Murai       if (fp->action) {
121f1884650SAtsushi Murai 	/* permit fragments on in and out filter */
1225ca5389aSBrian Somers         if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0)
123f1884650SAtsushi Murai 	  return (A_PERMIT);
1245ca5389aSBrian Somers 
1258390b576SBrian Somers         if (!didname)
126dd7e2610SBrian Somers           log_Printf(LogDEBUG, "%s filter:\n", filter->name);
1278390b576SBrian Somers         didname = 1;
1288390b576SBrian Somers 
129a272e47dSBrian Somers 	if ((pip->ip_src.s_addr & fp->smask.s_addr) ==
130a272e47dSBrian Somers 	    (fp->saddr.s_addr & fp->smask.s_addr) &&
131a272e47dSBrian Somers 	    (pip->ip_dst.s_addr & fp->dmask.s_addr) ==
132a272e47dSBrian Somers 	    (fp->daddr.s_addr & fp->dmask.s_addr)) {
133af57ed9fSAtsushi Murai 	  if (fp->proto) {
134af57ed9fSAtsushi Murai 	    if (!gotinfo) {
135af57ed9fSAtsushi Murai 	      ptop = (char *) pip + (pip->ip_hl << 2);
136af57ed9fSAtsushi Murai 
137af57ed9fSAtsushi Murai 	      switch (pip->ip_p) {
138af57ed9fSAtsushi Murai 	      case IPPROTO_ICMP:
139944f7098SBrian Somers 		cproto = P_ICMP;
140944f7098SBrian Somers 		ih = (struct icmp *) ptop;
141944f7098SBrian Somers 		sport = ih->icmp_type;
14263f98b41SBrian Somers 		estab = syn = finrst = -1;
143dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG))
1448390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
145af57ed9fSAtsushi Murai 		break;
146af57ed9fSAtsushi Murai 	      case IPPROTO_UDP:
147eee772ecSBrian Somers 	      case IPPROTO_IGMP:
148eee772ecSBrian Somers 	      case IPPROTO_IPIP:
149944f7098SBrian Somers 		cproto = P_UDP;
150944f7098SBrian Somers 		uh = (struct udphdr *) ptop;
151944f7098SBrian Somers 		sport = ntohs(uh->uh_sport);
152944f7098SBrian Somers 		dport = ntohs(uh->uh_dport);
15363f98b41SBrian Somers 		estab = syn = finrst = -1;
154dd7e2610SBrian Somers                 if (log_IsKept(LogDEBUG))
1558390b576SBrian Somers 		  snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
1568390b576SBrian Somers                            sport, dport);
157af57ed9fSAtsushi Murai 		break;
158af57ed9fSAtsushi Murai 	      case IPPROTO_TCP:
159944f7098SBrian Somers 		cproto = P_TCP;
160944f7098SBrian Somers 		th = (struct tcphdr *) ptop;
161944f7098SBrian Somers 		sport = ntohs(th->th_sport);
162944f7098SBrian Somers 		dport = ntohs(th->th_dport);
163af57ed9fSAtsushi Murai 		estab = (th->th_flags & TH_ACK);
16463f98b41SBrian Somers 		syn = (th->th_flags & TH_SYN);
16563f98b41SBrian Somers 		finrst = (th->th_flags & (TH_FIN|TH_RST));
1662b81c773SBrian Somers                 if (log_IsKept(LogDEBUG)) {
1672b81c773SBrian Somers                   if (!estab)
1688390b576SBrian Somers 		    snprintf(dbuff, sizeof dbuff,
1698390b576SBrian Somers                              "flags = %02x, sport = %d, dport = %d",
170927145beSBrian Somers                              th->th_flags, sport, dport);
1712b81c773SBrian Somers                   else
1722b81c773SBrian Somers                     *dbuff = '\0';
1732b81c773SBrian Somers                 }
174af57ed9fSAtsushi Murai 		break;
175af57ed9fSAtsushi Murai 	      default:
176af57ed9fSAtsushi Murai 		return (A_DENY);       /* We'll block unknown type of packet */
177af57ed9fSAtsushi Murai 	      }
178dd7e2610SBrian Somers               if (log_IsKept(LogDEBUG)) {
1798390b576SBrian Somers                 if (estab != -1) {
1808390b576SBrian Somers                   len = strlen(dbuff);
18163f98b41SBrian Somers                   snprintf(dbuff + len, sizeof dbuff - len,
18263f98b41SBrian Somers                            ", estab = %d, syn = %d, finrst = %d",
18363f98b41SBrian Somers                            estab, syn, finrst);
184af57ed9fSAtsushi Murai                 }
185dd7e2610SBrian Somers 	        log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
1868390b576SBrian Somers                           filter_Proto2Nam(cproto), dbuff);
1878390b576SBrian Somers               }
1888390b576SBrian Somers 	      gotinfo = 1;
1898390b576SBrian Somers 	    }
190dd7e2610SBrian Somers             if (log_IsKept(LogDEBUG)) {
1918390b576SBrian Somers 	      if (fp->opt.srcop != OP_NONE) {
1928390b576SBrian Somers                 snprintf(dbuff, sizeof dbuff, ", src %s %d",
1938390b576SBrian Somers                          filter_Op2Nam(fp->opt.srcop), fp->opt.srcport);
1948390b576SBrian Somers                 len = strlen(dbuff);
1958390b576SBrian Somers               } else
1968390b576SBrian Somers                 len = 0;
1978390b576SBrian Somers 	      if (fp->opt.dstop != OP_NONE) {
1988390b576SBrian Somers                 snprintf(dbuff + len, sizeof dbuff - len,
1998390b576SBrian Somers                          ", dst %s %d", filter_Op2Nam(fp->opt.dstop),
2008390b576SBrian Somers                          fp->opt.dstport);
2018390b576SBrian Somers               } else if (!len)
2028390b576SBrian Somers                 *dbuff = '\0';
2038390b576SBrian Somers 
204dd7e2610SBrian Somers 	      log_Printf(LogDEBUG, "  rule = %d: Address match, "
2058390b576SBrian Somers                         "check against proto %s%s, action = %s\n",
2068390b576SBrian Somers                         n, filter_Proto2Nam(fp->proto),
2078390b576SBrian Somers                         dbuff, filter_Action2Nam(fp->action));
2088390b576SBrian Somers             }
209927145beSBrian Somers 
210af57ed9fSAtsushi Murai 	    if (cproto == fp->proto) {
211af57ed9fSAtsushi Murai 	      if ((fp->opt.srcop == OP_NONE ||
21263f98b41SBrian Somers 		   PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) &&
213af57ed9fSAtsushi Murai 		  (fp->opt.dstop == OP_NONE ||
21463f98b41SBrian Somers 		   PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) &&
21563f98b41SBrian Somers 		  (fp->opt.estab == 0 || estab) &&
21663f98b41SBrian Somers 		  (fp->opt.syn == 0 || syn) &&
21763f98b41SBrian Somers 		  (fp->opt.finrst == 0 || finrst)) {
218af57ed9fSAtsushi Murai 		return (fp->action);
219af57ed9fSAtsushi Murai 	      }
220af57ed9fSAtsushi Murai 	    }
221af57ed9fSAtsushi Murai 	  } else {
222af57ed9fSAtsushi Murai 	    /* Address is mached. Make a decision. */
223dd7e2610SBrian Somers 	    log_Printf(LogDEBUG, "  rule = %d: Address match, action = %s\n", n,
2248390b576SBrian Somers                       filter_Action2Nam(fp->action));
225af57ed9fSAtsushi Murai 	    return (fp->action);
226af57ed9fSAtsushi Murai 	  }
2278390b576SBrian Somers 	} else
228dd7e2610SBrian Somers 	  log_Printf(LogDEBUG, "  rule = %d: Address mismatch\n", n);
229af57ed9fSAtsushi Murai       }
230af57ed9fSAtsushi Murai       fp++;
231af57ed9fSAtsushi Murai     }
232af57ed9fSAtsushi Murai     return (A_DENY);		/* No rule is mached. Deny this packet */
233af57ed9fSAtsushi Murai   }
234af57ed9fSAtsushi Murai   return (A_PERMIT);		/* No rule is given. Permit this packet */
235af57ed9fSAtsushi Murai }
236af57ed9fSAtsushi Murai 
2375ca5389aSBrian Somers #ifdef notdef
238af57ed9fSAtsushi Murai static void
239944f7098SBrian Somers IcmpError(struct ip * pip, int code)
240af57ed9fSAtsushi Murai {
241af57ed9fSAtsushi Murai   struct mbuf *bp;
242af57ed9fSAtsushi Murai 
243af57ed9fSAtsushi Murai   if (pip->ip_p != IPPROTO_ICMP) {
244dd7e2610SBrian Somers     bp = mbuf_Alloc(cnt, MB_IPIN);
24575240ed1SBrian Somers     memcpy(MBUF_CTOP(bp), ptr, cnt);
246dd7e2610SBrian Somers     vj_SendFrame(bp);
2475828db6dSBrian Somers     ipcp_AddOutOctets(cnt);
2481ae349f5Scvs2svn   }
249af57ed9fSAtsushi Murai }
250af57ed9fSAtsushi Murai #endif
251af57ed9fSAtsushi Murai 
252af57ed9fSAtsushi Murai /*
253af57ed9fSAtsushi Murai  *  For debugging aid.
254af57ed9fSAtsushi Murai  */
255af57ed9fSAtsushi Murai int
2565ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
257af57ed9fSAtsushi Murai {
258af57ed9fSAtsushi Murai   struct ip *pip;
259af57ed9fSAtsushi Murai   struct tcphdr *th;
260af57ed9fSAtsushi Murai   struct udphdr *uh;
261af57ed9fSAtsushi Murai   struct icmp *icmph;
262af57ed9fSAtsushi Murai   char *ptop;
263af57ed9fSAtsushi Murai   int mask, len, n;
264af57ed9fSAtsushi Murai   int pri = PRI_NORMAL;
26555a8cdeaSBrian Somers   int logit, loglen;
266d93d3a9cSBrian Somers   char logbuf[200];
267af57ed9fSAtsushi Murai 
268dd7e2610SBrian Somers   logit = log_IsKept(LogTCPIP) && filter->logok;
26955a8cdeaSBrian Somers   loglen = 0;
270af57ed9fSAtsushi Murai 
271af57ed9fSAtsushi Murai   pip = (struct ip *) cp;
272af57ed9fSAtsushi Murai 
27355a8cdeaSBrian Somers   if (logit && loglen < sizeof logbuf) {
2745ca5389aSBrian Somers     snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
27555a8cdeaSBrian Somers     loglen += strlen(logbuf + loglen);
27655a8cdeaSBrian Somers   }
277af57ed9fSAtsushi Murai   ptop = (cp + (pip->ip_hl << 2));
278af57ed9fSAtsushi Murai 
279af57ed9fSAtsushi Murai   switch (pip->ip_p) {
280af57ed9fSAtsushi Murai   case IPPROTO_ICMP:
28155a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
282af57ed9fSAtsushi Murai       icmph = (struct icmp *) ptop;
28355a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
28455a8cdeaSBrian Somers 	     "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
28555a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
28655a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
28755a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
28855a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
289af57ed9fSAtsushi Murai     }
290af57ed9fSAtsushi Murai     break;
291af57ed9fSAtsushi Murai   case IPPROTO_UDP:
29255a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
293af57ed9fSAtsushi Murai       uh = (struct udphdr *) ptop;
29455a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
29555a8cdeaSBrian Somers 	   "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
29655a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
29755a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
29855a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
29955a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
300af57ed9fSAtsushi Murai     }
301af57ed9fSAtsushi Murai     break;
302eee772ecSBrian Somers   case IPPROTO_IPIP:
303eee772ecSBrian Somers     if (logit && loglen < sizeof logbuf) {
304eee772ecSBrian Somers       uh = (struct udphdr *) ptop;
305eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
306eee772ecSBrian Somers 	   "IPIP: %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;
313eee772ecSBrian Somers   case IPPROTO_IGMP:
314eee772ecSBrian Somers     if (logit && loglen < sizeof logbuf) {
315eee772ecSBrian Somers       uh = (struct udphdr *) ptop;
316eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
317eee772ecSBrian Somers 	   "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
318eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
319eee772ecSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
320eee772ecSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
321eee772ecSBrian Somers       loglen += strlen(logbuf + loglen);
322eee772ecSBrian Somers     }
323eee772ecSBrian Somers     break;
324af57ed9fSAtsushi Murai   case IPPROTO_TCP:
325af57ed9fSAtsushi Murai     th = (struct tcphdr *) ptop;
326af57ed9fSAtsushi Murai     if (pip->ip_tos == IPTOS_LOWDELAY)
327af57ed9fSAtsushi Murai       pri = PRI_FAST;
32876bd0c0aSDoug Rabson     else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
329af57ed9fSAtsushi Murai       if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
330af57ed9fSAtsushi Murai 	pri = PRI_FAST;
331af57ed9fSAtsushi Murai     }
33255a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
333af57ed9fSAtsushi Murai       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
33455a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
33555a8cdeaSBrian Somers 	   "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
33655a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
33755a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
33855a8cdeaSBrian Somers 	       "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
33955a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
340af57ed9fSAtsushi Murai       n = 0;
341af57ed9fSAtsushi Murai       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
34255a8cdeaSBrian Somers 	if (th->th_flags & mask) {
34355a8cdeaSBrian Somers 	  snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
34455a8cdeaSBrian Somers 	  loglen += strlen(logbuf + loglen);
34555a8cdeaSBrian Somers 	}
346af57ed9fSAtsushi Murai 	n++;
347af57ed9fSAtsushi Murai       }
34855a8cdeaSBrian Somers       snprintf(logbuf + loglen, sizeof logbuf - loglen,
3493a2e4f62SBrian Somers 	       "  seq:%lx  ack:%lx (%d/%d)",
3503a2e4f62SBrian Somers 	       (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
35155a8cdeaSBrian Somers       loglen += strlen(logbuf + loglen);
352af57ed9fSAtsushi Murai       if ((th->th_flags & TH_SYN) && nb > 40) {
353af57ed9fSAtsushi Murai 	u_short *sp;
354af57ed9fSAtsushi Murai 
355af57ed9fSAtsushi Murai 	ptop += 20;
356af57ed9fSAtsushi Murai 	sp = (u_short *) ptop;
35755a8cdeaSBrian Somers 	if (ntohs(sp[0]) == 0x0204) {
35855a8cdeaSBrian Somers 	  snprintf(logbuf + loglen, sizeof logbuf - loglen,
35955a8cdeaSBrian Somers 		   " MSS = %d", ntohs(sp[1]));
36055a8cdeaSBrian Somers 	  loglen += strlen(logbuf + loglen);
36155a8cdeaSBrian Somers 	}
362af57ed9fSAtsushi Murai       }
363af57ed9fSAtsushi Murai     }
364af57ed9fSAtsushi Murai     break;
365af57ed9fSAtsushi Murai   }
36676bd0c0aSDoug Rabson 
3675ca5389aSBrian Somers   if ((FilterCheck(pip, filter) & A_DENY)) {
368710e9c29SBrian Somers     if (logit)
369dd7e2610SBrian Somers       log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
3705ca5389aSBrian Somers #ifdef notdef
371944f7098SBrian Somers     if (direction == 0)
372944f7098SBrian Somers       IcmpError(pip, pri);
3735ca5389aSBrian Somers #endif
374af57ed9fSAtsushi Murai     return (-1);
375af57ed9fSAtsushi Murai   } else {
3765ca5389aSBrian Somers     /* Check Keep Alive filter */
377e43ebac1SBrian Somers     if (logit) {
3781e991daaSBrian Somers       if (FilterCheck(pip, &bundle->filter.alive) & A_DENY)
379dd7e2610SBrian Somers         log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
3801e991daaSBrian Somers       else
381dd7e2610SBrian Somers         log_Printf(LogTCPIP, "%s\n", logbuf);
38253c9f6c0SAtsushi Murai     }
383af57ed9fSAtsushi Murai     return (pri);
384af57ed9fSAtsushi Murai   }
385af57ed9fSAtsushi Murai }
386af57ed9fSAtsushi Murai 
387af57ed9fSAtsushi Murai void
388dd7e2610SBrian Somers ip_Input(struct bundle *bundle, struct mbuf * bp)
3897a6f8720SBrian Somers {
390af57ed9fSAtsushi Murai   u_char *cp;
391af57ed9fSAtsushi Murai   struct mbuf *wp;
392af57ed9fSAtsushi Murai   int nb, nw;
393b6e82f33SBrian Somers   struct tun_data tun;
3941e991daaSBrian Somers   struct ip *pip = (struct ip *)tun.data;
3953a2e4f62SBrian Somers #ifndef NOALIAS
396eee772ecSBrian Somers   struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2));
3973a2e4f62SBrian Somers #endif
398af57ed9fSAtsushi Murai 
3996a6b4bbbSBrian Somers   tun_fill_header(tun, AF_INET);
4006a6b4bbbSBrian Somers   cp = tun.data;
401af57ed9fSAtsushi Murai   nb = 0;
402927145beSBrian Somers   for (wp = bp; wp; wp = wp->next) {	/* Copy to contiguous region */
403512db555SBrian Somers     if (sizeof tun.data - (cp - tun.data) < wp->cnt) {
404a33b2ef7SBrian Somers       log_Printf(LogWARN, "ip_Input: Packet too large (%d) - dropped\n",
405dd7e2610SBrian Somers                 mbuf_Length(bp));
406dd7e2610SBrian Somers       mbuf_Free(bp);
407512db555SBrian Somers       return;
408512db555SBrian Somers     }
40975240ed1SBrian Somers     memcpy(cp, MBUF_CTOP(wp), wp->cnt);
410af57ed9fSAtsushi Murai     cp += wp->cnt;
411af57ed9fSAtsushi Murai     nb += wp->cnt;
412af57ed9fSAtsushi Murai   }
413af57ed9fSAtsushi Murai 
414b6e82f33SBrian Somers #ifndef NOALIAS
415615ad4f9SBrian Somers   if (bundle->AliasEnabled && pip->ip_p != IPPROTO_IGMP &&
416eee772ecSBrian Somers       (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) {
417b6e82f33SBrian Somers     struct tun_data *frag;
4186db75539SBrian Somers     int iresult;
4196db75539SBrian Somers     char *fptr;
4206db75539SBrian Somers 
421615ad4f9SBrian Somers     iresult = PacketAliasIn(tun.data, sizeof tun.data);
4226a6b4bbbSBrian Somers     nb = ntohs(((struct ip *) tun.data)->ip_len);
4236db75539SBrian Somers 
4246db75539SBrian Somers     if (nb > MAX_MRU) {
425a33b2ef7SBrian Somers       log_Printf(LogWARN, "ip_Input: Problem with IP header length\n");
426dd7e2610SBrian Somers       mbuf_Free(bp);
4276db75539SBrian Somers       return;
428a9f484e5SJordan K. Hubbard     }
4296db75539SBrian Somers     if (iresult == PKT_ALIAS_OK
4306db75539SBrian Somers 	|| iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
4315ca5389aSBrian Somers       if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
432dd7e2610SBrian Somers 	mbuf_Free(bp);
433af57ed9fSAtsushi Murai 	return;
434af57ed9fSAtsushi Murai       }
4351e991daaSBrian Somers 
4361e991daaSBrian Somers       if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
4371e991daaSBrian Somers         bundle_StartIdleTimer(bundle);
4381e991daaSBrian Somers 
4395828db6dSBrian Somers       ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
4406db75539SBrian Somers 
4416a6b4bbbSBrian Somers       nb = ntohs(((struct ip *) tun.data)->ip_len);
44270ee81ffSBrian Somers       nb += sizeof tun - sizeof tun.data;
443faefde08SBrian Somers       nw = write(bundle->dev.fd, &tun, nb);
4446a596579SBrian Somers       if (nw != nb) {
44557fd05c4SBrian Somers         if (nw == -1)
446dd7e2610SBrian Somers 	  log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
44757fd05c4SBrian Somers                     strerror(errno));
44857fd05c4SBrian Somers         else
449dd7e2610SBrian Somers 	  log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
4506a596579SBrian Somers       }
4516db75539SBrian Somers 
4526db75539SBrian Somers       if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
453615ad4f9SBrian Somers 	while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) {
454615ad4f9SBrian Somers 	  PacketAliasFragmentIn(tun.data, fptr);
4556db75539SBrian Somers 	  nb = ntohs(((struct ip *) fptr)->ip_len);
45670ee81ffSBrian Somers           frag = (struct tun_data *)
45770ee81ffSBrian Somers 	    ((char *)fptr - sizeof tun + sizeof tun.data);
45870ee81ffSBrian Somers           nb += sizeof tun - sizeof tun.data;
459faefde08SBrian Somers 	  nw = write(bundle->dev.fd, frag, nb);
4606a596579SBrian Somers 	  if (nw != nb) {
46157fd05c4SBrian Somers             if (nw == -1)
462dd7e2610SBrian Somers 	      log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb,
46357fd05c4SBrian Somers                         strerror(errno));
46457fd05c4SBrian Somers             else
465dd7e2610SBrian Somers 	      log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
4666a596579SBrian Somers           }
4676a6b4bbbSBrian Somers 	  free(frag);
4686db75539SBrian Somers 	}
4696db75539SBrian Somers       }
470944f7098SBrian Somers     } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) {
4716a6b4bbbSBrian Somers       nb = ntohs(((struct ip *) tun.data)->ip_len);
47270ee81ffSBrian Somers       nb += sizeof tun - sizeof tun.data;
4736a6b4bbbSBrian Somers       frag = (struct tun_data *)malloc(nb);
4746a6b4bbbSBrian Somers       if (frag == NULL)
475dd7e2610SBrian Somers 	log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n");
4766db75539SBrian Somers       else {
4776a6b4bbbSBrian Somers         tun_fill_header(*frag, AF_INET);
47870ee81ffSBrian Somers 	memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data);
479615ad4f9SBrian Somers 	PacketAliasSaveFragment(frag->data);
4806db75539SBrian Somers       }
4816db75539SBrian Somers     }
482b6e82f33SBrian Somers   } else
483b6e82f33SBrian Somers #endif /* #ifndef NOALIAS */
484b6e82f33SBrian Somers   {			/* no aliasing */
4855ca5389aSBrian Somers     if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) {
486dd7e2610SBrian Somers       mbuf_Free(bp);
4876db75539SBrian Somers       return;
4886db75539SBrian Somers     }
4891e991daaSBrian Somers 
4901e991daaSBrian Somers     if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
4911e991daaSBrian Somers       bundle_StartIdleTimer(bundle);
4921e991daaSBrian Somers 
4935828db6dSBrian Somers     ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
4941e991daaSBrian Somers 
49570ee81ffSBrian Somers     nb += sizeof tun - sizeof tun.data;
496faefde08SBrian Somers     nw = write(bundle->dev.fd, &tun, nb);
497c4c4aaacSBrian Somers     if (nw != nb) {
49857fd05c4SBrian Somers       if (nw == -1)
499dd7e2610SBrian Somers 	log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno));
50057fd05c4SBrian Somers       else
501dd7e2610SBrian Somers         log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw);
5026db75539SBrian Somers     }
503c4c4aaacSBrian Somers   }
504dd7e2610SBrian Somers   mbuf_Free(bp);
505af57ed9fSAtsushi Murai }
506af57ed9fSAtsushi Murai 
507af57ed9fSAtsushi Murai void
5085a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
509af57ed9fSAtsushi Murai {
510af57ed9fSAtsushi Murai   struct mbuf *bp;
511af57ed9fSAtsushi Murai 
5125a72b6edSBrian Somers   if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0])
5135a72b6edSBrian Somers     log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
5145a72b6edSBrian Somers   else {
515dd7e2610SBrian Somers     bp = mbuf_Alloc(count, MB_IPQ);
51675240ed1SBrian Somers     memcpy(MBUF_CTOP(bp), ptr, count);
5175a72b6edSBrian Somers     mbuf_Enqueue(&ipcp->Queue[pri], bp);
5185a72b6edSBrian Somers   }
519af57ed9fSAtsushi Murai }
520af57ed9fSAtsushi Murai 
5216f8e9f0aSBrian Somers void
5225a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp)
5236f8e9f0aSBrian Somers {
5246f8e9f0aSBrian Somers   struct mqueue *queue;
5256f8e9f0aSBrian Somers 
5265a72b6edSBrian Somers   for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
5276f8e9f0aSBrian Somers     while (queue->top)
5286f8e9f0aSBrian Somers       mbuf_Free(mbuf_Dequeue(queue));
5296f8e9f0aSBrian Somers }
5306f8e9f0aSBrian Somers 
53184b8a6ebSAtsushi Murai int
5325a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp)
53384b8a6ebSAtsushi Murai {
53484b8a6ebSAtsushi Murai   struct mqueue *queue;
535f4768038SBrian Somers   int result = 0;
536944f7098SBrian Somers 
5375a72b6edSBrian Somers   for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
538f4768038SBrian Somers     result += queue->qlen;
53984b8a6ebSAtsushi Murai 
540f4768038SBrian Somers   return result;
5411ae349f5Scvs2svn }
5421ae349f5Scvs2svn 
5433b0f8d2eSBrian Somers int
544dd7e2610SBrian Somers ip_FlushPacket(struct link *l, struct bundle *bundle)
545af57ed9fSAtsushi Murai {
5465a72b6edSBrian Somers   struct ipcp *ipcp = &bundle->ncp.ipcp;
547af57ed9fSAtsushi Murai   struct mqueue *queue;
548af57ed9fSAtsushi Murai   struct mbuf *bp;
549274e766cSBrian Somers   int cnt;
550af57ed9fSAtsushi Murai 
5515a72b6edSBrian Somers   if (ipcp->fsm.state != ST_OPENED)
5523b0f8d2eSBrian Somers     return 0;
5531e991daaSBrian Somers 
5545a72b6edSBrian Somers   for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--)
555af57ed9fSAtsushi Murai     if (queue->top) {
556dd7e2610SBrian Somers       bp = mbuf_Dequeue(queue);
557af57ed9fSAtsushi Murai       if (bp) {
5581e991daaSBrian Somers         struct ip *pip = (struct ip *)MBUF_CTOP(bp);
5591e991daaSBrian Somers 
560dd7e2610SBrian Somers 	cnt = mbuf_Length(bp);
5611e991daaSBrian Somers         if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
562ab886ad0SBrian Somers           bundle_StartIdleTimer(bundle);
5637d797fa7SBrian Somers 	vj_SendFrame(l, bp, bundle);
5645a72b6edSBrian Somers         ipcp_AddOutOctets(ipcp, cnt);
5653b0f8d2eSBrian Somers 	return 1;
566af57ed9fSAtsushi Murai       }
567af57ed9fSAtsushi Murai     }
5681e991daaSBrian Somers 
5693b0f8d2eSBrian Somers   return 0;
570af57ed9fSAtsushi Murai }
571