xref: /freebsd/usr.sbin/ppp/ip.c (revision 55a8cdea92c3ddefdceacb2045fd840f6f9e990b)
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  *
2055a8cdeaSBrian Somers  * $Id: ip.c,v 1.21 1997/06/09 03:27:23 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  */
26af57ed9fSAtsushi Murai #include "fsm.h"
27af57ed9fSAtsushi Murai #include "lcpproto.h"
28af57ed9fSAtsushi Murai #include "hdlc.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>
356db75539SBrian Somers #include <alias.h>
366ed9fb2fSBrian Somers #include "loadalias.h"
37af57ed9fSAtsushi Murai #include "vars.h"
38af57ed9fSAtsushi Murai #include "filter.h"
39927145beSBrian Somers #include "mbuf.h"
40927145beSBrian Somers #include "log.h"
41af57ed9fSAtsushi Murai 
4253c9f6c0SAtsushi Murai extern void SendPppFrame();
43af57ed9fSAtsushi Murai extern void LcpClose();
44af57ed9fSAtsushi Murai 
45af57ed9fSAtsushi Murai static struct pppTimer IdleTimer;
46af57ed9fSAtsushi Murai 
47af57ed9fSAtsushi Murai static void IdleTimeout()
48af57ed9fSAtsushi Murai {
49927145beSBrian Somers   LogPrintf(LogPHASE, "Idle timer expired.\n");
5025aa96acSBrian Somers   reconnect(RECON_FALSE);
51af57ed9fSAtsushi Murai   LcpClose();
52af57ed9fSAtsushi Murai }
53af57ed9fSAtsushi Murai 
54af57ed9fSAtsushi Murai /*
55af57ed9fSAtsushi Murai  *  Start Idle timer. If timeout is reached, we call LcpClose() to
56af57ed9fSAtsushi Murai  *  close LCP and link.
57af57ed9fSAtsushi Murai  */
58af57ed9fSAtsushi Murai void
59af57ed9fSAtsushi Murai StartIdleTimer()
60af57ed9fSAtsushi Murai {
61680026d6SNate Williams   if (!(mode & (MODE_DEDICATED|MODE_DDIAL))) {
62af57ed9fSAtsushi Murai     StopTimer(&IdleTimer);
63af57ed9fSAtsushi Murai     IdleTimer.func = IdleTimeout;
64af57ed9fSAtsushi Murai     IdleTimer.load = VarIdleTimeout * SECTICKS;
65af57ed9fSAtsushi Murai     IdleTimer.state = TIMER_STOPPED;
66af57ed9fSAtsushi Murai     StartTimer(&IdleTimer);
67af57ed9fSAtsushi Murai   }
68af57ed9fSAtsushi Murai }
69af57ed9fSAtsushi Murai 
70af57ed9fSAtsushi Murai void
71927145beSBrian Somers UpdateIdleTimer()
72927145beSBrian Somers {
73927145beSBrian Somers   if (IdleTimer.state == TIMER_RUNNING)
74927145beSBrian Somers     StartIdleTimer();
75927145beSBrian Somers }
76927145beSBrian Somers 
77927145beSBrian Somers void
78af57ed9fSAtsushi Murai StopIdleTimer()
79af57ed9fSAtsushi Murai {
80af57ed9fSAtsushi Murai   StopTimer(&IdleTimer);
81af57ed9fSAtsushi Murai }
82af57ed9fSAtsushi Murai 
83af57ed9fSAtsushi Murai /*
84af57ed9fSAtsushi Murai  *  If any IP layer traffic is detected, refresh IdleTimer.
85af57ed9fSAtsushi Murai  */
86af57ed9fSAtsushi Murai static void
87af57ed9fSAtsushi Murai RestartIdleTimer()
88af57ed9fSAtsushi Murai {
89680026d6SNate Williams   if (!(mode & (MODE_DEDICATED|MODE_DDIAL)) && ipKeepAlive ) {
90af57ed9fSAtsushi Murai     StartTimer(&IdleTimer);
91af57ed9fSAtsushi Murai     ipIdleSecs = 0;
92af57ed9fSAtsushi Murai   }
93af57ed9fSAtsushi Murai }
94af57ed9fSAtsushi Murai 
9576bd0c0aSDoug Rabson static u_short interactive_ports[32] = {
9676bd0c0aSDoug Rabson   544, 513, 514,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
9776bd0c0aSDoug Rabson     0,   0,   0,   0,   0,  21,  22,  23,   0,   0,   0,   0,   0,   0,   0, 543,
98af57ed9fSAtsushi Murai };
99af57ed9fSAtsushi Murai 
10076bd0c0aSDoug Rabson #define	INTERACTIVE(p)	(interactive_ports[(p) & 0x1F] == (p))
101af57ed9fSAtsushi Murai 
102af57ed9fSAtsushi Murai static char *TcpFlags[] = {
103af57ed9fSAtsushi Murai   "FIN", "SYN", "RST", "PSH", "ACK", "URG",
104af57ed9fSAtsushi Murai };
105af57ed9fSAtsushi Murai 
10653c9f6c0SAtsushi Murai static char *Direction[] = { "INP", "OUT", "OUT", "IN/OUT" };
10753c9f6c0SAtsushi Murai static struct filterent *Filters[] = { ifilters, ofilters, dfilters, afilters };
108af57ed9fSAtsushi Murai 
109af57ed9fSAtsushi Murai static int
110af57ed9fSAtsushi Murai PortMatch(op, pport, rport)
111af57ed9fSAtsushi Murai int op;
112af57ed9fSAtsushi Murai u_short pport, rport;
113af57ed9fSAtsushi Murai {
114af57ed9fSAtsushi Murai   switch (op) {
115af57ed9fSAtsushi Murai   case OP_EQ:
116af57ed9fSAtsushi Murai     return(pport == rport);
117af57ed9fSAtsushi Murai   case OP_GT:
118af57ed9fSAtsushi Murai     return(pport > rport);
119af57ed9fSAtsushi Murai   case OP_LT:
120af57ed9fSAtsushi Murai     return(pport < rport);
121af57ed9fSAtsushi Murai   default:
122af57ed9fSAtsushi Murai     return(0);
123af57ed9fSAtsushi Murai   }
124af57ed9fSAtsushi Murai }
125af57ed9fSAtsushi Murai 
126af57ed9fSAtsushi Murai /*
127af57ed9fSAtsushi Murai  *  Check a packet against with defined filters
128af57ed9fSAtsushi Murai  */
129af57ed9fSAtsushi Murai static int
130af57ed9fSAtsushi Murai FilterCheck(pip, direction)
131af57ed9fSAtsushi Murai struct ip *pip;
132af57ed9fSAtsushi Murai int direction;
133af57ed9fSAtsushi Murai {
134af57ed9fSAtsushi Murai   struct filterent *fp = Filters[direction];
135af57ed9fSAtsushi Murai   int gotinfo, cproto, estab, n;
136af57ed9fSAtsushi Murai   struct tcphdr *th;
137af57ed9fSAtsushi Murai   struct udphdr *uh;
138af57ed9fSAtsushi Murai   struct icmp *ih;
139af57ed9fSAtsushi Murai   char *ptop;
140af57ed9fSAtsushi Murai   u_short sport, dport;
141af57ed9fSAtsushi Murai 
142af57ed9fSAtsushi Murai   if (fp->action) {
143af57ed9fSAtsushi Murai     cproto = gotinfo = estab = 0;
144af57ed9fSAtsushi Murai     sport = dport = 0;
145af57ed9fSAtsushi Murai     for (n = 0; n < MAXFILTERS; n++) {
146af57ed9fSAtsushi Murai       if (fp->action) {
147f1884650SAtsushi Murai          /* permit fragments on in and out filter */
148f1884650SAtsushi Murai          if ((direction == FL_IN || direction == FL_OUT) &&
14976bd0c0aSDoug Rabson              (ntohs(pip->ip_off) & IP_OFFMASK) != 0) {
150f1884650SAtsushi Murai               return(A_PERMIT);
151f1884650SAtsushi Murai          }
152927145beSBrian Somers         LogPrintf(LogDEBUG, "rule = %d\n", n);
153af57ed9fSAtsushi Murai 	if ((pip->ip_src.s_addr & fp->smask.s_addr) == fp->saddr.s_addr
154af57ed9fSAtsushi Murai 	    && (pip->ip_dst.s_addr & fp->dmask.s_addr) == fp->daddr.s_addr) {
155af57ed9fSAtsushi Murai 	  if (fp->proto) {
156af57ed9fSAtsushi Murai 	    if (!gotinfo) {
157af57ed9fSAtsushi Murai 	      ptop = (char *)pip + (pip->ip_hl << 2);
158af57ed9fSAtsushi Murai 
159af57ed9fSAtsushi Murai 	      switch (pip->ip_p) {
160af57ed9fSAtsushi Murai 	      case IPPROTO_ICMP:
161af57ed9fSAtsushi Murai 		cproto = P_ICMP; ih = (struct icmp *)ptop;
162af57ed9fSAtsushi Murai 		sport = ih->icmp_type; estab = 1;
163af57ed9fSAtsushi Murai 		break;
164af57ed9fSAtsushi Murai 	      case IPPROTO_UDP:
165af57ed9fSAtsushi Murai 		cproto = P_UDP; uh = (struct udphdr *)ptop;
166af57ed9fSAtsushi Murai 		sport = ntohs(uh->uh_sport); dport = ntohs(uh->uh_dport);
167af57ed9fSAtsushi Murai 		estab = 1;
168af57ed9fSAtsushi Murai 		break;
169af57ed9fSAtsushi Murai 	      case IPPROTO_TCP:
170af57ed9fSAtsushi Murai 		cproto = P_TCP; th = (struct tcphdr *)ptop;
171af57ed9fSAtsushi Murai 		sport = ntohs(th->th_sport); dport = ntohs(th->th_dport);
172af57ed9fSAtsushi Murai 		estab = (th->th_flags & TH_ACK);
17353c9f6c0SAtsushi Murai                 if (estab == 0)
174927145beSBrian Somers                   LogPrintf(LogDEBUG, "flag = %02x, sport = %d, dport = %d\n",
175927145beSBrian Somers                             th->th_flags, sport, dport);
176af57ed9fSAtsushi Murai 		break;
177af57ed9fSAtsushi Murai 	      default:
178af57ed9fSAtsushi Murai 		return(A_DENY);	/* We'll block unknown type of packet */
179af57ed9fSAtsushi Murai 	      }
180af57ed9fSAtsushi Murai 	      gotinfo = 1;
181927145beSBrian Somers               LogPrintf(LogDEBUG, "dir = %d, proto = %d, srcop = %d,"
182927145beSBrian Somers                        " dstop = %d, estab = %d\n", direction, cproto,
183927145beSBrian Somers                        fp->opt.srcop, fp->opt.dstop, estab);
184af57ed9fSAtsushi Murai 	    }
185927145beSBrian Somers 
186927145beSBrian Somers 	    LogPrintf(LogDEBUG, "check0: rule = %d, proto = %d, sport = %d,"
187927145beSBrian Somers                       " dport = %d\n", n, cproto, sport, dport);
188927145beSBrian Somers 	    LogPrintf(LogDEBUG, "check0: action = %d\n", fp->action);
189927145beSBrian Somers 
190af57ed9fSAtsushi Murai 	    if (cproto == fp->proto) {
191af57ed9fSAtsushi Murai 	      if ((fp->opt.srcop == OP_NONE ||
192af57ed9fSAtsushi Murai 		  PortMatch(fp->opt.srcop, sport, fp->opt.srcport))
193af57ed9fSAtsushi Murai 	       &&
194af57ed9fSAtsushi Murai 		  (fp->opt.dstop == OP_NONE ||
195af57ed9fSAtsushi Murai 		  PortMatch(fp->opt.dstop, dport, fp->opt.dstport))
196af57ed9fSAtsushi Murai 	       &&
197af57ed9fSAtsushi Murai 		  (fp->opt.estab == 0 || estab)) {
198af57ed9fSAtsushi Murai 		return(fp->action);
199af57ed9fSAtsushi Murai 	      }
200af57ed9fSAtsushi Murai 	    }
201af57ed9fSAtsushi Murai 	  } else {
202af57ed9fSAtsushi Murai 	    /* Address is mached. Make a decision. */
203927145beSBrian Somers 	    LogPrintf(LogDEBUG, "check1: action = %d\n", fp->action);
204af57ed9fSAtsushi Murai 	    return(fp->action);
205af57ed9fSAtsushi Murai 	  }
206af57ed9fSAtsushi Murai 	}
207af57ed9fSAtsushi Murai       }
208af57ed9fSAtsushi Murai       fp++;
209af57ed9fSAtsushi Murai     }
210af57ed9fSAtsushi Murai     return(A_DENY);	/* No rule is mached. Deny this packet */
211af57ed9fSAtsushi Murai   }
212af57ed9fSAtsushi Murai   return(A_PERMIT);	/* No rule is given. Permit this packet */
213af57ed9fSAtsushi Murai }
214af57ed9fSAtsushi Murai 
215af57ed9fSAtsushi Murai static void
216af57ed9fSAtsushi Murai IcmpError(pip, code)
217af57ed9fSAtsushi Murai struct ip *pip;
218af57ed9fSAtsushi Murai int code;
219af57ed9fSAtsushi Murai {
220af57ed9fSAtsushi Murai #ifdef notdef
221af57ed9fSAtsushi Murai   struct mbuf *bp;
222af57ed9fSAtsushi Murai 
223af57ed9fSAtsushi Murai   if (pip->ip_p != IPPROTO_ICMP) {
224af57ed9fSAtsushi Murai     bp = mballoc(cnt, MB_IPIN);
225af57ed9fSAtsushi Murai     bcopy(ptr, MBUF_CTOP(bp), cnt);
22676bd0c0aSDoug Rabson     SendPppFrame(bp);
227af57ed9fSAtsushi Murai     RestartIdleTimer();
228af57ed9fSAtsushi Murai     ipOutOctets += cnt;
229af57ed9fSAtsushi Murai   }
230af57ed9fSAtsushi Murai #endif
231af57ed9fSAtsushi Murai }
232af57ed9fSAtsushi Murai 
233af57ed9fSAtsushi Murai /*
234af57ed9fSAtsushi Murai  *  For debugging aid.
235af57ed9fSAtsushi Murai  */
236af57ed9fSAtsushi Murai int
237af57ed9fSAtsushi Murai PacketCheck(cp, nb, direction)
238af57ed9fSAtsushi Murai char *cp;
239af57ed9fSAtsushi Murai int nb;
240af57ed9fSAtsushi Murai int direction;
241af57ed9fSAtsushi Murai {
242af57ed9fSAtsushi Murai   struct ip *pip;
243af57ed9fSAtsushi Murai   struct tcphdr *th;
244af57ed9fSAtsushi Murai   struct udphdr *uh;
245af57ed9fSAtsushi Murai   struct icmp *icmph;
246af57ed9fSAtsushi Murai   char *ptop;
247af57ed9fSAtsushi Murai   int mask, len, n;
248af57ed9fSAtsushi Murai   int pri = PRI_NORMAL;
24955a8cdeaSBrian Somers   int logit, loglen;
25055a8cdeaSBrian Somers   static char logbuf[200];
251af57ed9fSAtsushi Murai 
252927145beSBrian Somers   logit = LogIsKept(LogTCPIP);
25355a8cdeaSBrian Somers   loglen = 0;
254af57ed9fSAtsushi Murai 
255af57ed9fSAtsushi Murai   pip = (struct ip *)cp;
256af57ed9fSAtsushi Murai 
25755a8cdeaSBrian Somers   if (logit && loglen < sizeof logbuf) {
25855a8cdeaSBrian Somers     snprintf(logbuf+loglen, sizeof logbuf - loglen, "%s ",
25955a8cdeaSBrian Somers              Direction[direction]);
26055a8cdeaSBrian Somers     loglen += strlen(logbuf+loglen);
26155a8cdeaSBrian Somers   }
262af57ed9fSAtsushi Murai 
263af57ed9fSAtsushi Murai   ptop = (cp + (pip->ip_hl << 2));
264af57ed9fSAtsushi Murai 
265af57ed9fSAtsushi Murai   switch (pip->ip_p) {
266af57ed9fSAtsushi Murai   case IPPROTO_ICMP:
26755a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
268af57ed9fSAtsushi Murai       icmph = (struct icmp *)ptop;
26955a8cdeaSBrian Somers       snprintf(logbuf+loglen, sizeof logbuf - loglen,
27055a8cdeaSBrian Somers                "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
27155a8cdeaSBrian Somers       loglen += strlen(logbuf+loglen);
27255a8cdeaSBrian Somers       snprintf(logbuf+loglen, sizeof logbuf - loglen,
27355a8cdeaSBrian Somers                "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
27455a8cdeaSBrian Somers       loglen += strlen(logbuf+loglen);
275af57ed9fSAtsushi Murai     }
276af57ed9fSAtsushi Murai     break;
277af57ed9fSAtsushi Murai   case IPPROTO_UDP:
27855a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
279af57ed9fSAtsushi Murai       uh = (struct udphdr *)ptop;
28055a8cdeaSBrian Somers       snprintf(logbuf+loglen, sizeof logbuf - loglen,
28155a8cdeaSBrian Somers                "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
28255a8cdeaSBrian Somers       loglen += strlen(logbuf+loglen);
28355a8cdeaSBrian Somers       snprintf(logbuf+loglen, sizeof logbuf - loglen,
28455a8cdeaSBrian Somers                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
28555a8cdeaSBrian Somers       loglen += strlen(logbuf+loglen);
286af57ed9fSAtsushi Murai     }
287af57ed9fSAtsushi Murai     break;
288af57ed9fSAtsushi Murai   case IPPROTO_TCP:
289af57ed9fSAtsushi Murai     th = (struct tcphdr *)ptop;
290af57ed9fSAtsushi Murai     if (pip->ip_tos == IPTOS_LOWDELAY)
291af57ed9fSAtsushi Murai       pri = PRI_FAST;
29276bd0c0aSDoug Rabson     else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
293af57ed9fSAtsushi Murai       if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
294af57ed9fSAtsushi Murai 	 pri = PRI_FAST;
295af57ed9fSAtsushi Murai     }
296af57ed9fSAtsushi Murai 
29755a8cdeaSBrian Somers     if (logit && loglen < sizeof logbuf) {
298af57ed9fSAtsushi Murai       len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
29955a8cdeaSBrian Somers       snprintf(logbuf+loglen, sizeof logbuf - loglen,
30055a8cdeaSBrian Somers                "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
30155a8cdeaSBrian Somers       loglen += strlen(logbuf+loglen);
30255a8cdeaSBrian Somers       snprintf(logbuf+loglen, sizeof logbuf - loglen,
30355a8cdeaSBrian Somers                "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
30455a8cdeaSBrian Somers       loglen += strlen(logbuf+loglen);
305af57ed9fSAtsushi Murai       n = 0;
306af57ed9fSAtsushi Murai       for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
30755a8cdeaSBrian Somers 	if (th->th_flags & mask) {
30855a8cdeaSBrian Somers           snprintf(logbuf+loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
30955a8cdeaSBrian Somers           loglen += strlen(logbuf+loglen);
31055a8cdeaSBrian Somers         }
311af57ed9fSAtsushi Murai 	n++;
312af57ed9fSAtsushi Murai       }
31355a8cdeaSBrian Somers       snprintf(logbuf+loglen, sizeof logbuf - loglen,
31455a8cdeaSBrian Somers                "  seq:%x  ack:%x (%d/%d)",
315af57ed9fSAtsushi Murai                ntohl(th->th_seq), ntohl(th->th_ack), len, nb);
31655a8cdeaSBrian Somers       loglen += strlen(logbuf+loglen);
317af57ed9fSAtsushi Murai       if ((th->th_flags & TH_SYN) && nb > 40) {
318af57ed9fSAtsushi Murai         u_short *sp;
319af57ed9fSAtsushi Murai 
320af57ed9fSAtsushi Murai 	ptop += 20;
321af57ed9fSAtsushi Murai 	sp = (u_short *)ptop;
32255a8cdeaSBrian Somers 	if (ntohs(sp[0]) == 0x0204) {
32355a8cdeaSBrian Somers           snprintf(logbuf+loglen, sizeof logbuf - loglen,
32455a8cdeaSBrian Somers 	           " MSS = %d", ntohs(sp[1]));
32555a8cdeaSBrian Somers           loglen += strlen(logbuf+loglen);
32655a8cdeaSBrian Somers         }
327af57ed9fSAtsushi Murai       }
328af57ed9fSAtsushi Murai     }
329af57ed9fSAtsushi Murai     break;
330af57ed9fSAtsushi Murai   }
33176bd0c0aSDoug Rabson 
33255a8cdeaSBrian Somers   if (logit)
33355a8cdeaSBrian Somers     LogPrintf(LogTCPIP, "%s\n", logbuf);
33455a8cdeaSBrian Somers 
33576bd0c0aSDoug Rabson   if ((FilterCheck(pip, direction) & A_DENY)) {
336927145beSBrian Somers     LogPrintf(LogDEBUG, "blocked.\n");
337af57ed9fSAtsushi Murai     if (direction == 0) IcmpError(pip, pri);
338af57ed9fSAtsushi Murai     return(-1);
339af57ed9fSAtsushi Murai   } else {
34084b8a6ebSAtsushi Murai     if ( FilterCheck(pip, FL_KEEP ) & A_DENY ) {  /* Check Keep Alive filter */
34153c9f6c0SAtsushi Murai 	ipKeepAlive = FALSE;
34253c9f6c0SAtsushi Murai     } else {
34353c9f6c0SAtsushi Murai 	ipKeepAlive = TRUE;
34453c9f6c0SAtsushi Murai     }
345af57ed9fSAtsushi Murai     return(pri);
346af57ed9fSAtsushi Murai   }
347af57ed9fSAtsushi Murai }
348af57ed9fSAtsushi Murai 
349af57ed9fSAtsushi Murai void
350af57ed9fSAtsushi Murai IpInput(bp)
351af57ed9fSAtsushi Murai struct mbuf *bp;		/* IN: Pointer to IP pakcet */
352af57ed9fSAtsushi Murai {
353af57ed9fSAtsushi Murai   u_char *cp;
354af57ed9fSAtsushi Murai   struct mbuf *wp;
355af57ed9fSAtsushi Murai   int nb, nw;
356af57ed9fSAtsushi Murai   u_char tunbuff[MAX_MRU];
357af57ed9fSAtsushi Murai 
358af57ed9fSAtsushi Murai   cp = tunbuff;
359af57ed9fSAtsushi Murai   nb = 0;
360927145beSBrian Somers   for (wp = bp; wp; wp = wp->next) {		/* Copy to contiguous region */
361af57ed9fSAtsushi Murai     bcopy(MBUF_CTOP(wp), cp, wp->cnt);
362af57ed9fSAtsushi Murai     cp += wp->cnt;
363af57ed9fSAtsushi Murai     nb += wp->cnt;
364af57ed9fSAtsushi Murai   }
365af57ed9fSAtsushi Murai 
366a9f484e5SJordan K. Hubbard   if (mode & MODE_ALIAS) {
3676db75539SBrian Somers     int iresult;
3686db75539SBrian Somers     char *fptr;
3696db75539SBrian Somers 
3706ed9fb2fSBrian Somers     iresult = VarPacketAliasIn(tunbuff, sizeof tunbuff);
371a9f484e5SJordan K. Hubbard     nb = ntohs(((struct ip *) tunbuff)->ip_len);
3726db75539SBrian Somers 
3736db75539SBrian Somers     if (nb > MAX_MRU) {
374927145beSBrian Somers       LogPrintf(LogERROR, "IpInput: Problem with IP header length\n");
3756db75539SBrian Somers       pfree(bp);
3766db75539SBrian Somers       return;
377a9f484e5SJordan K. Hubbard     }
378a9f484e5SJordan K. Hubbard 
3796db75539SBrian Somers     if (iresult == PKT_ALIAS_OK
3806db75539SBrian Somers      || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
38184b8a6ebSAtsushi Murai       if ( PacketCheck(tunbuff, nb, FL_IN ) < 0) {
382af57ed9fSAtsushi Murai           pfree(bp);
383af57ed9fSAtsushi Murai           return;
384af57ed9fSAtsushi Murai       }
385af57ed9fSAtsushi Murai 
386af57ed9fSAtsushi Murai       ipInOctets += nb;
3876db75539SBrian Somers 
3886db75539SBrian Somers       nb = ntohs(((struct ip *) tunbuff)->ip_len);
389af57ed9fSAtsushi Murai       nw = write(tun_out, tunbuff, nb);
390af57ed9fSAtsushi Murai       if (nw != nb)
391927145beSBrian Somers         LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
3926db75539SBrian Somers 
3936db75539SBrian Somers       if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
3946ed9fb2fSBrian Somers         while ((fptr = VarGetNextFragmentPtr(tunbuff)) != NULL) {
3956ed9fb2fSBrian Somers           VarFragmentAliasIn(tunbuff, fptr);
3966db75539SBrian Somers           nb = ntohs(((struct ip *) fptr)->ip_len);
3976db75539SBrian Somers           nw = write(tun_out, fptr, nb);
3986db75539SBrian Somers           if (nw != nb)
399927145beSBrian Somers             LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
4006db75539SBrian Somers           free(fptr);
4016db75539SBrian Somers         }
4026db75539SBrian Somers       }
4036db75539SBrian Somers     }
4046db75539SBrian Somers     else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) {
4056db75539SBrian Somers       nb = ntohs(((struct ip *) tunbuff)->ip_len);
4066db75539SBrian Somers       fptr = malloc(nb);
407927145beSBrian Somers       if (fptr == NULL)
408927145beSBrian Somers         LogPrintf(LogALERT, "IpInput: Cannot allocate memory for fragment\n");
4096db75539SBrian Somers       else {
4106db75539SBrian Somers         memcpy(fptr, tunbuff, nb);
4116ed9fb2fSBrian Somers         VarSaveFragmentPtr(fptr);
4126db75539SBrian Somers       }
4136db75539SBrian Somers     }
4146db75539SBrian Somers   }
4156db75539SBrian Somers   else
4166db75539SBrian Somers   { /* no aliasing */
4176db75539SBrian Somers     if ( PacketCheck(tunbuff, nb, FL_IN ) < 0)
4186db75539SBrian Somers     {
4196db75539SBrian Somers       pfree(bp);
4206db75539SBrian Somers       return;
4216db75539SBrian Somers     }
4226db75539SBrian Somers 
4236db75539SBrian Somers     ipInOctets += nb;
4246db75539SBrian Somers     nw = write(tun_out, tunbuff, nb);
4256db75539SBrian Somers     if (nw != nb)
426927145beSBrian Somers       LogPrintf(LogERROR, "IpInput: wrote %d, got %d\n", nb, nw);
4276db75539SBrian Somers   }
428af57ed9fSAtsushi Murai   pfree(bp);
429af57ed9fSAtsushi Murai 
430af57ed9fSAtsushi Murai   RestartIdleTimer();
431af57ed9fSAtsushi Murai }
432af57ed9fSAtsushi Murai 
43376bd0c0aSDoug Rabson static struct mqueue IpOutputQueues[PRI_FAST+1];
434af57ed9fSAtsushi Murai 
435af57ed9fSAtsushi Murai void
436af57ed9fSAtsushi Murai IpEnqueue(pri, ptr, count)
437af57ed9fSAtsushi Murai int pri;
438af57ed9fSAtsushi Murai char *ptr;
439af57ed9fSAtsushi Murai int count;
440af57ed9fSAtsushi Murai {
441af57ed9fSAtsushi Murai   struct mbuf *bp;
442af57ed9fSAtsushi Murai 
443af57ed9fSAtsushi Murai   bp = mballoc(count, MB_IPQ);
444af57ed9fSAtsushi Murai   bcopy(ptr, MBUF_CTOP(bp), count);
445af57ed9fSAtsushi Murai   Enqueue(&IpOutputQueues[pri], bp);
446af57ed9fSAtsushi Murai }
447af57ed9fSAtsushi Murai 
44884b8a6ebSAtsushi Murai int
44984b8a6ebSAtsushi Murai IsIpEnqueued()
45084b8a6ebSAtsushi Murai {
45184b8a6ebSAtsushi Murai   struct mqueue *queue;
45284b8a6ebSAtsushi Murai   int    exist = FALSE;
45376bd0c0aSDoug Rabson   for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) {
45484b8a6ebSAtsushi Murai      if ( queue->qlen > 0 ) {
45584b8a6ebSAtsushi Murai        exist = TRUE;
45684b8a6ebSAtsushi Murai        break;
45784b8a6ebSAtsushi Murai      }
45884b8a6ebSAtsushi Murai   }
45984b8a6ebSAtsushi Murai   return( exist );
46084b8a6ebSAtsushi Murai }
46184b8a6ebSAtsushi Murai 
462af57ed9fSAtsushi Murai void
463af57ed9fSAtsushi Murai IpStartOutput()
464af57ed9fSAtsushi Murai {
465af57ed9fSAtsushi Murai   struct mqueue *queue;
466af57ed9fSAtsushi Murai   struct mbuf *bp;
467274e766cSBrian Somers   int cnt;
468af57ed9fSAtsushi Murai 
469af57ed9fSAtsushi Murai   if (IpcpFsm.state != ST_OPENED)
470af57ed9fSAtsushi Murai     return;
47176bd0c0aSDoug Rabson   for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) {
472af57ed9fSAtsushi Murai     if (queue->top) {
473af57ed9fSAtsushi Murai       bp = Dequeue(queue);
474af57ed9fSAtsushi Murai       if (bp) {
475af57ed9fSAtsushi Murai 	cnt = plength(bp);
47676bd0c0aSDoug Rabson 	SendPppFrame(bp);
477af57ed9fSAtsushi Murai 	RestartIdleTimer();
478af57ed9fSAtsushi Murai 	ipOutOctets += cnt;
47976bd0c0aSDoug Rabson 	break;
480af57ed9fSAtsushi Murai        }
481af57ed9fSAtsushi Murai     }
482af57ed9fSAtsushi Murai   }
483af57ed9fSAtsushi Murai }
484