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 * 20af57ed9fSAtsushi Murai * $Id:$ 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> 34af57ed9fSAtsushi Murai #include "vars.h" 35af57ed9fSAtsushi Murai #include "filter.h" 36af57ed9fSAtsushi Murai 3753c9f6c0SAtsushi Murai extern void SendPppFrame(); 38af57ed9fSAtsushi Murai extern int PacketCheck(); 39af57ed9fSAtsushi Murai extern void LcpClose(); 40af57ed9fSAtsushi Murai 41af57ed9fSAtsushi Murai static struct pppTimer IdleTimer; 42af57ed9fSAtsushi Murai 43af57ed9fSAtsushi Murai static void IdleTimeout() 44af57ed9fSAtsushi Murai { 45af57ed9fSAtsushi Murai LogPrintf(LOG_PHASE, "Idle timer expired.\n"); 46af57ed9fSAtsushi Murai LcpClose(); 47af57ed9fSAtsushi Murai } 48af57ed9fSAtsushi Murai 49af57ed9fSAtsushi Murai /* 50af57ed9fSAtsushi Murai * Start Idle timer. If timeout is reached, we call LcpClose() to 51af57ed9fSAtsushi Murai * close LCP and link. 52af57ed9fSAtsushi Murai */ 53af57ed9fSAtsushi Murai void 54af57ed9fSAtsushi Murai StartIdleTimer() 55af57ed9fSAtsushi Murai { 56af57ed9fSAtsushi Murai if (!(mode & MODE_DEDICATED)) { 57af57ed9fSAtsushi Murai StopTimer(&IdleTimer); 58af57ed9fSAtsushi Murai IdleTimer.func = IdleTimeout; 59af57ed9fSAtsushi Murai IdleTimer.load = VarIdleTimeout * SECTICKS; 60af57ed9fSAtsushi Murai IdleTimer.state = TIMER_STOPPED; 61af57ed9fSAtsushi Murai StartTimer(&IdleTimer); 62af57ed9fSAtsushi Murai } 63af57ed9fSAtsushi Murai } 64af57ed9fSAtsushi Murai 65af57ed9fSAtsushi Murai void 66af57ed9fSAtsushi Murai StopIdleTimer() 67af57ed9fSAtsushi Murai { 68af57ed9fSAtsushi Murai StopTimer(&IdleTimer); 69af57ed9fSAtsushi Murai } 70af57ed9fSAtsushi Murai 71af57ed9fSAtsushi Murai /* 72af57ed9fSAtsushi Murai * If any IP layer traffic is detected, refresh IdleTimer. 73af57ed9fSAtsushi Murai */ 74af57ed9fSAtsushi Murai static void 75af57ed9fSAtsushi Murai RestartIdleTimer() 76af57ed9fSAtsushi Murai { 7753c9f6c0SAtsushi Murai if (!(mode & MODE_DEDICATED) && ipKeepAlive ) { 7853c9f6c0SAtsushi Murai /* StopTimer(&IdleTimer); */ 79af57ed9fSAtsushi Murai StartTimer(&IdleTimer); 80af57ed9fSAtsushi Murai ipIdleSecs = 0; 81af57ed9fSAtsushi Murai } 82af57ed9fSAtsushi Murai } 83af57ed9fSAtsushi Murai 84af57ed9fSAtsushi Murai static u_short interactive_ports[8] = { 85af57ed9fSAtsushi Murai 0, 513, 0, 0, 0, 21, 0, 23, 86af57ed9fSAtsushi Murai }; 87af57ed9fSAtsushi Murai 88af57ed9fSAtsushi Murai #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p)) 89af57ed9fSAtsushi Murai 90af57ed9fSAtsushi Murai static char *TcpFlags[] = { 91af57ed9fSAtsushi Murai "FIN", "SYN", "RST", "PSH", "ACK", "URG", 92af57ed9fSAtsushi Murai }; 93af57ed9fSAtsushi Murai 9453c9f6c0SAtsushi Murai static char *Direction[] = { "INP", "OUT", "OUT", "IN/OUT" }; 9553c9f6c0SAtsushi Murai static struct filterent *Filters[] = { ifilters, ofilters, dfilters, afilters }; 96af57ed9fSAtsushi Murai 97af57ed9fSAtsushi Murai static int 98af57ed9fSAtsushi Murai PortMatch(op, pport, rport) 99af57ed9fSAtsushi Murai int op; 100af57ed9fSAtsushi Murai u_short pport, rport; 101af57ed9fSAtsushi Murai { 102af57ed9fSAtsushi Murai switch (op) { 103af57ed9fSAtsushi Murai case OP_EQ: 104af57ed9fSAtsushi Murai return(pport == rport); 105af57ed9fSAtsushi Murai case OP_GT: 106af57ed9fSAtsushi Murai return(pport > rport); 107af57ed9fSAtsushi Murai case OP_LT: 108af57ed9fSAtsushi Murai return(pport < rport); 109af57ed9fSAtsushi Murai default: 110af57ed9fSAtsushi Murai return(0); 111af57ed9fSAtsushi Murai } 112af57ed9fSAtsushi Murai } 113af57ed9fSAtsushi Murai 114af57ed9fSAtsushi Murai /* 115af57ed9fSAtsushi Murai * Check a packet against with defined filters 116af57ed9fSAtsushi Murai */ 117af57ed9fSAtsushi Murai static int 118af57ed9fSAtsushi Murai FilterCheck(pip, direction) 119af57ed9fSAtsushi Murai struct ip *pip; 120af57ed9fSAtsushi Murai int direction; 121af57ed9fSAtsushi Murai { 122af57ed9fSAtsushi Murai struct filterent *fp = Filters[direction]; 123af57ed9fSAtsushi Murai int gotinfo, cproto, estab, n; 124af57ed9fSAtsushi Murai struct tcphdr *th; 125af57ed9fSAtsushi Murai struct udphdr *uh; 126af57ed9fSAtsushi Murai struct icmp *ih; 127af57ed9fSAtsushi Murai char *ptop; 128af57ed9fSAtsushi Murai u_short sport, dport; 129af57ed9fSAtsushi Murai 130af57ed9fSAtsushi Murai if (fp->action) { 131af57ed9fSAtsushi Murai cproto = gotinfo = estab = 0; 132af57ed9fSAtsushi Murai sport = dport = 0; 133af57ed9fSAtsushi Murai for (n = 0; n < MAXFILTERS; n++) { 134af57ed9fSAtsushi Murai if (fp->action) { 135af57ed9fSAtsushi Murai #ifdef DEBUG 136af57ed9fSAtsushi Murai logprintf("rule = %d\n", n); 137af57ed9fSAtsushi Murai #endif 138af57ed9fSAtsushi Murai if ((pip->ip_src.s_addr & fp->smask.s_addr) == fp->saddr.s_addr 139af57ed9fSAtsushi Murai && (pip->ip_dst.s_addr & fp->dmask.s_addr) == fp->daddr.s_addr) { 140af57ed9fSAtsushi Murai if (fp->proto) { 141af57ed9fSAtsushi Murai if (!gotinfo) { 142af57ed9fSAtsushi Murai ptop = (char *)pip + (pip->ip_hl << 2); 143af57ed9fSAtsushi Murai 144af57ed9fSAtsushi Murai switch (pip->ip_p) { 145af57ed9fSAtsushi Murai case IPPROTO_ICMP: 146af57ed9fSAtsushi Murai cproto = P_ICMP; ih = (struct icmp *)ptop; 147af57ed9fSAtsushi Murai sport = ih->icmp_type; estab = 1; 148af57ed9fSAtsushi Murai break; 149af57ed9fSAtsushi Murai case IPPROTO_UDP: 150af57ed9fSAtsushi Murai cproto = P_UDP; uh = (struct udphdr *)ptop; 151af57ed9fSAtsushi Murai sport = ntohs(uh->uh_sport); dport = ntohs(uh->uh_dport); 152af57ed9fSAtsushi Murai estab = 1; 153af57ed9fSAtsushi Murai break; 154af57ed9fSAtsushi Murai case IPPROTO_TCP: 155af57ed9fSAtsushi Murai cproto = P_TCP; th = (struct tcphdr *)ptop; 156af57ed9fSAtsushi Murai sport = ntohs(th->th_sport); dport = ntohs(th->th_dport); 157af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 15853c9f6c0SAtsushi Murai #ifdef DEBUG 15953c9f6c0SAtsushi Murai if (estab == 0) 16053c9f6c0SAtsushi Murai logprintf("flag = %02x, sport = %d, dport = %d\n", th->th_flags, sport, dport); 16153c9f6c0SAtsushi Murai #endif 162af57ed9fSAtsushi Murai break; 163af57ed9fSAtsushi Murai default: 164af57ed9fSAtsushi Murai return(A_DENY); /* We'll block unknown type of packet */ 165af57ed9fSAtsushi Murai } 166af57ed9fSAtsushi Murai gotinfo = 1; 167af57ed9fSAtsushi Murai #ifdef DEBUG 168af57ed9fSAtsushi Murai logprintf("dir = %d, proto = %d, srcop = %d, dstop = %d, estab = %d\n", 169af57ed9fSAtsushi Murai direction, cproto, fp->opt.srcop, fp->opt.dstop, estab); 170af57ed9fSAtsushi Murai #endif 171af57ed9fSAtsushi Murai } 172af57ed9fSAtsushi Murai #ifdef DEBUG 173af57ed9fSAtsushi Murai logprintf("check0: rule = %d, proto = %d, sport = %d, dport = %d\n", 174af57ed9fSAtsushi Murai n, cproto, sport, dport); 175af57ed9fSAtsushi Murai logprintf("check0: action = %d\n", fp->action); 176af57ed9fSAtsushi Murai #endif 177af57ed9fSAtsushi Murai if (cproto == fp->proto) { 178af57ed9fSAtsushi Murai if ((fp->opt.srcop == OP_NONE || 179af57ed9fSAtsushi Murai PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) 180af57ed9fSAtsushi Murai && 181af57ed9fSAtsushi Murai (fp->opt.dstop == OP_NONE || 182af57ed9fSAtsushi Murai PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) 183af57ed9fSAtsushi Murai && 184af57ed9fSAtsushi Murai (fp->opt.estab == 0 || estab)) { 185af57ed9fSAtsushi Murai return(fp->action); 186af57ed9fSAtsushi Murai } 187af57ed9fSAtsushi Murai } 188af57ed9fSAtsushi Murai } else { 189af57ed9fSAtsushi Murai /* Address is mached. Make a decision. */ 190af57ed9fSAtsushi Murai #ifdef DEBUG 191af57ed9fSAtsushi Murai logprintf("check1: action = %d\n", fp->action); 192af57ed9fSAtsushi Murai #endif 193af57ed9fSAtsushi Murai return(fp->action); 194af57ed9fSAtsushi Murai } 195af57ed9fSAtsushi Murai } 196af57ed9fSAtsushi Murai } 197af57ed9fSAtsushi Murai fp++; 198af57ed9fSAtsushi Murai } 199af57ed9fSAtsushi Murai drop: 200af57ed9fSAtsushi Murai return(A_DENY); /* No rule is mached. Deny this packet */ 201af57ed9fSAtsushi Murai } 202af57ed9fSAtsushi Murai return(A_PERMIT); /* No rule is given. Permit this packet */ 203af57ed9fSAtsushi Murai } 204af57ed9fSAtsushi Murai 205af57ed9fSAtsushi Murai static void 206af57ed9fSAtsushi Murai IcmpError(pip, code) 207af57ed9fSAtsushi Murai struct ip *pip; 208af57ed9fSAtsushi Murai int code; 209af57ed9fSAtsushi Murai { 210af57ed9fSAtsushi Murai #ifdef notdef 211af57ed9fSAtsushi Murai struct mbuf *bp; 212af57ed9fSAtsushi Murai 213af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 214af57ed9fSAtsushi Murai bp = mballoc(cnt, MB_IPIN); 215af57ed9fSAtsushi Murai bcopy(ptr, MBUF_CTOP(bp), cnt); 21653c9f6c0SAtsushi Murai SendPppFrame(PRI_URGENT, bp); 217af57ed9fSAtsushi Murai RestartIdleTimer(); 218af57ed9fSAtsushi Murai ipOutOctets += cnt; 219af57ed9fSAtsushi Murai } 220af57ed9fSAtsushi Murai #endif 221af57ed9fSAtsushi Murai } 222af57ed9fSAtsushi Murai 223af57ed9fSAtsushi Murai /* 224af57ed9fSAtsushi Murai * For debugging aid. 225af57ed9fSAtsushi Murai */ 226af57ed9fSAtsushi Murai int 227af57ed9fSAtsushi Murai PacketCheck(cp, nb, direction) 228af57ed9fSAtsushi Murai char *cp; 229af57ed9fSAtsushi Murai int nb; 230af57ed9fSAtsushi Murai int direction; 231af57ed9fSAtsushi Murai { 232af57ed9fSAtsushi Murai struct ip *pip; 233af57ed9fSAtsushi Murai struct tcphdr *th; 234af57ed9fSAtsushi Murai struct udphdr *uh; 235af57ed9fSAtsushi Murai struct icmp *icmph; 236af57ed9fSAtsushi Murai char *ptop; 237af57ed9fSAtsushi Murai int mask, len, n; 238af57ed9fSAtsushi Murai int logit; 239af57ed9fSAtsushi Murai int pri = PRI_NORMAL; 240af57ed9fSAtsushi Murai 241af57ed9fSAtsushi Murai logit = (loglevel & (1 << LOG_TCPIP)); 242af57ed9fSAtsushi Murai 243af57ed9fSAtsushi Murai pip = (struct ip *)cp; 244af57ed9fSAtsushi Murai 245af57ed9fSAtsushi Murai if (logit) logprintf("%s ", Direction[direction]); 246af57ed9fSAtsushi Murai 247af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 248af57ed9fSAtsushi Murai 249af57ed9fSAtsushi Murai switch (pip->ip_p) { 250af57ed9fSAtsushi Murai case IPPROTO_ICMP: 251af57ed9fSAtsushi Murai if (logit) { 252af57ed9fSAtsushi Murai icmph = (struct icmp *)ptop; 253af57ed9fSAtsushi Murai logprintf("ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 254af57ed9fSAtsushi Murai logprintf("%s:%d\n", inet_ntoa(pip->ip_dst), icmph->icmp_type); 255af57ed9fSAtsushi Murai } 256af57ed9fSAtsushi Murai break; 257af57ed9fSAtsushi Murai case IPPROTO_UDP: 258af57ed9fSAtsushi Murai if (logit) { 259af57ed9fSAtsushi Murai uh = (struct udphdr *)ptop; 260af57ed9fSAtsushi Murai logprintf("UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 261af57ed9fSAtsushi Murai logprintf("%s:%d\n", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 262af57ed9fSAtsushi Murai } 263af57ed9fSAtsushi Murai break; 264af57ed9fSAtsushi Murai case IPPROTO_TCP: 265af57ed9fSAtsushi Murai th = (struct tcphdr *)ptop; 266af57ed9fSAtsushi Murai if (pip->ip_tos == IPTOS_LOWDELAY) 267af57ed9fSAtsushi Murai pri = PRI_FAST; 268af57ed9fSAtsushi Murai else if (pip->ip_off == 0) { 269af57ed9fSAtsushi Murai if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 270af57ed9fSAtsushi Murai pri = PRI_FAST; 271af57ed9fSAtsushi Murai } 272af57ed9fSAtsushi Murai 273af57ed9fSAtsushi Murai if (logit) { 274af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 275af57ed9fSAtsushi Murai logprintf("TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 276af57ed9fSAtsushi Murai logprintf("%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 277af57ed9fSAtsushi Murai n = 0; 278af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 279af57ed9fSAtsushi Murai if (th->th_flags & mask) 280af57ed9fSAtsushi Murai logprintf(" %s", TcpFlags[n]); 281af57ed9fSAtsushi Murai n++; 282af57ed9fSAtsushi Murai } 283af57ed9fSAtsushi Murai logprintf(" seq:%x ack:%x (%d/%d)\n", 284af57ed9fSAtsushi Murai ntohl(th->th_seq), ntohl(th->th_ack), len, nb); 285af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 286af57ed9fSAtsushi Murai u_short *sp; 287af57ed9fSAtsushi Murai 288af57ed9fSAtsushi Murai ptop += 20; 289af57ed9fSAtsushi Murai sp = (u_short *)ptop; 290af57ed9fSAtsushi Murai if (ntohs(sp[0]) == 0x0204) 291af57ed9fSAtsushi Murai logprintf(" MSS = %d\n", ntohs(sp[1])); 292af57ed9fSAtsushi Murai } 293af57ed9fSAtsushi Murai } 294af57ed9fSAtsushi Murai break; 295af57ed9fSAtsushi Murai } 296af57ed9fSAtsushi Murai pri = FilterCheck(pip, direction); 297af57ed9fSAtsushi Murai if (pri & A_DENY) { 298af57ed9fSAtsushi Murai #ifdef DEBUG 299af57ed9fSAtsushi Murai logprintf("blocked.\n"); 300af57ed9fSAtsushi Murai #endif 301af57ed9fSAtsushi Murai if (direction == 0) IcmpError(pip, pri); 302af57ed9fSAtsushi Murai return(-1); 303af57ed9fSAtsushi Murai } else { 30453c9f6c0SAtsushi Murai if ( FilterCheck(pip, 3) & A_DENY ) { /* Check Keep Alive filter */ 30553c9f6c0SAtsushi Murai ipKeepAlive = FALSE; 30653c9f6c0SAtsushi Murai } else { 30753c9f6c0SAtsushi Murai ipKeepAlive = TRUE; 30853c9f6c0SAtsushi Murai } 309af57ed9fSAtsushi Murai return(pri); 310af57ed9fSAtsushi Murai } 311af57ed9fSAtsushi Murai } 312af57ed9fSAtsushi Murai 313af57ed9fSAtsushi Murai void 314af57ed9fSAtsushi Murai IpInput(bp) 315af57ed9fSAtsushi Murai struct mbuf *bp; /* IN: Pointer to IP pakcet */ 316af57ed9fSAtsushi Murai { 317af57ed9fSAtsushi Murai u_char *cp; 318af57ed9fSAtsushi Murai struct mbuf *wp; 319af57ed9fSAtsushi Murai int nb, nw; 320af57ed9fSAtsushi Murai u_char tunbuff[MAX_MRU]; 321af57ed9fSAtsushi Murai 322af57ed9fSAtsushi Murai cp = tunbuff; 323af57ed9fSAtsushi Murai nb = 0; 324af57ed9fSAtsushi Murai for (wp = bp; wp; wp = wp->next) { /* Copy to continuois region */ 325af57ed9fSAtsushi Murai bcopy(MBUF_CTOP(wp), cp, wp->cnt); 326af57ed9fSAtsushi Murai cp += wp->cnt; 327af57ed9fSAtsushi Murai nb += wp->cnt; 328af57ed9fSAtsushi Murai } 329af57ed9fSAtsushi Murai 330af57ed9fSAtsushi Murai if (PacketCheck(tunbuff, nb, 0) < 0) { 331af57ed9fSAtsushi Murai pfree(bp); 332af57ed9fSAtsushi Murai return; 333af57ed9fSAtsushi Murai } 334af57ed9fSAtsushi Murai 335af57ed9fSAtsushi Murai ipInOctets += nb; 336af57ed9fSAtsushi Murai /* 337af57ed9fSAtsushi Murai * Pass it to tunnel device 338af57ed9fSAtsushi Murai */ 339af57ed9fSAtsushi Murai nw = write(tun_out, tunbuff, nb); 340af57ed9fSAtsushi Murai if (nw != nb) 341af57ed9fSAtsushi Murai fprintf(stderr, "wrote %d, got %d\r\n"); 342af57ed9fSAtsushi Murai pfree(bp); 343af57ed9fSAtsushi Murai 344af57ed9fSAtsushi Murai RestartIdleTimer(); 345af57ed9fSAtsushi Murai } 346af57ed9fSAtsushi Murai 347af57ed9fSAtsushi Murai void 348af57ed9fSAtsushi Murai IpOutput(ptr, cnt) 349af57ed9fSAtsushi Murai u_char *ptr; /* IN: Pointer to IP packet */ 350af57ed9fSAtsushi Murai int cnt; /* IN: Length of packet */ 351af57ed9fSAtsushi Murai { 352af57ed9fSAtsushi Murai struct mbuf *bp; 353af57ed9fSAtsushi Murai int pri; 354af57ed9fSAtsushi Murai 355af57ed9fSAtsushi Murai if (IpcpFsm.state != ST_OPENED) 356af57ed9fSAtsushi Murai return; 357af57ed9fSAtsushi Murai 358af57ed9fSAtsushi Murai pri = PacketCheck(ptr, cnt, 1); 359af57ed9fSAtsushi Murai if (pri >= 0) { 360af57ed9fSAtsushi Murai bp = mballoc(cnt, MB_IPIN); 361af57ed9fSAtsushi Murai bcopy(ptr, MBUF_CTOP(bp), cnt); 36253c9f6c0SAtsushi Murai SendPppFrame(pri, bp); 363af57ed9fSAtsushi Murai RestartIdleTimer(); 364af57ed9fSAtsushi Murai ipOutOctets += cnt; 365af57ed9fSAtsushi Murai } 366af57ed9fSAtsushi Murai } 367af57ed9fSAtsushi Murai 368af57ed9fSAtsushi Murai static struct mqueue IpOutputQueues[PRI_URGENT+1]; 369af57ed9fSAtsushi Murai 370af57ed9fSAtsushi Murai void 371af57ed9fSAtsushi Murai IpEnqueue(pri, ptr, count) 372af57ed9fSAtsushi Murai int pri; 373af57ed9fSAtsushi Murai char *ptr; 374af57ed9fSAtsushi Murai int count; 375af57ed9fSAtsushi Murai { 376af57ed9fSAtsushi Murai struct mbuf *bp; 377af57ed9fSAtsushi Murai 378af57ed9fSAtsushi Murai bp = mballoc(count, MB_IPQ); 379af57ed9fSAtsushi Murai bcopy(ptr, MBUF_CTOP(bp), count); 380af57ed9fSAtsushi Murai Enqueue(&IpOutputQueues[pri], bp); 381af57ed9fSAtsushi Murai } 382af57ed9fSAtsushi Murai 383af57ed9fSAtsushi Murai void 384af57ed9fSAtsushi Murai IpStartOutput() 385af57ed9fSAtsushi Murai { 386af57ed9fSAtsushi Murai struct mqueue *queue; 387af57ed9fSAtsushi Murai struct mbuf *bp; 388af57ed9fSAtsushi Murai int pri, cnt; 389af57ed9fSAtsushi Murai 390af57ed9fSAtsushi Murai if (IpcpFsm.state != ST_OPENED) 391af57ed9fSAtsushi Murai return; 392af57ed9fSAtsushi Murai pri = PRI_URGENT; 393af57ed9fSAtsushi Murai for (queue = &IpOutputQueues[PRI_URGENT]; queue >= IpOutputQueues; queue--) { 394af57ed9fSAtsushi Murai if (queue->top) { 395af57ed9fSAtsushi Murai bp = Dequeue(queue); 396af57ed9fSAtsushi Murai if (bp) { 397af57ed9fSAtsushi Murai cnt = plength(bp); 39853c9f6c0SAtsushi Murai SendPppFrame(pri, bp); 399af57ed9fSAtsushi Murai RestartIdleTimer(); 400af57ed9fSAtsushi Murai ipOutOctets += cnt; 401af57ed9fSAtsushi Murai } 402af57ed9fSAtsushi Murai } 403af57ed9fSAtsushi Murai pri--; 404af57ed9fSAtsushi Murai } 405af57ed9fSAtsushi Murai } 406