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