ip.c revision 49472
131567Ssef/* 231899Ssef * PPP IP Protocol Interface 331899Ssef * 431899Ssef * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 531899Ssef * 631899Ssef * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 731899Ssef * 831899Ssef * Redistribution and use in source and binary forms are permitted 931899Ssef * provided that the above copyright notice and this paragraph are 1031899Ssef * duplicated in all such forms and that any documentation, 1131899Ssef * advertising materials, and other materials related to such 1231899Ssef * distribution and use acknowledge that the software was developed 1331899Ssef * by the Internet Initiative Japan. The name of the 1431899Ssef * IIJ may not be used to endorse or promote products derived 1531899Ssef * from this software without specific prior written permission. 1631899Ssef * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1731899Ssef * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1831899Ssef * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1931899Ssef * 2031899Ssef * $Id: ip.c,v 1.67 1999/08/02 15:29:19 brian Exp $ 2131899Ssef * 2231899Ssef * TODO: 2331899Ssef * o Return ICMP message for filterd packet 2431899Ssef * and optionaly record it into log. 2531899Ssef */ 2631899Ssef#include <sys/param.h> 2731899Ssef#if defined(__OpenBSD__) || defined(__NetBSD__) 2831899Ssef#include <sys/socket.h> 2931899Ssef#endif 3031899Ssef#include <netinet/in.h> 3131899Ssef#include <netinet/in_systm.h> 3232275Scharnier#include <netinet/ip.h> 3332275Scharnier#include <netinet/ip_icmp.h> 3438897Ssef#include <netinet/udp.h> 3532275Scharnier#include <netinet/tcp.h> 3632275Scharnier#include <arpa/inet.h> 3731899Ssef#include <sys/un.h> 3831567Ssef 3931567Ssef#include <errno.h> 4031567Ssef#include <stdio.h> 4131567Ssef#include <string.h> 4231567Ssef#include <termios.h> 4332275Scharnier#include <unistd.h> 4432275Scharnier 4532275Scharnier#include "layer.h" 4632275Scharnier#include "proto.h" 4731567Ssef#include "mbuf.h" 4831567Ssef#include "log.h" 4931567Ssef#include "defs.h" 5031579Speter#include "timer.h" 5131567Ssef#include "fsm.h" 5231567Ssef#include "lqr.h" 5331567Ssef#include "hdlc.h" 5431567Ssef#include "throughput.h" 5531567Ssef#include "iplist.h" 5631567Ssef#include "slcompress.h" 5731567Ssef#include "ipcp.h" 5831567Ssef#include "filter.h" 5931567Ssef#include "descriptor.h" 6031567Ssef#include "lcp.h" 6131567Ssef#include "ccp.h" 6231567Ssef#include "link.h" 6331567Ssef#include "mp.h" 6431567Ssef#ifndef NORADIUS 6531567Ssef#include "radius.h" 6631567Ssef#endif 6731567Ssef#include "bundle.h" 6831567Ssef#include "tun.h" 6931567Ssef#include "ip.h" 7031567Ssef 7131567Ssefstatic const u_short interactive_ports[32] = { 7231567Ssef 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7332275Scharnier 80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 7432275Scharnier}; 7532275Scharnier 7632275Scharnier#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 7732275Scharnier 7831567Ssefstatic const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 7931567Ssef 8031567Ssefstatic __inline int 8138897SsefPortMatch(int op, u_short pport, u_short rport) 8238897Ssef{ 8338897Ssef switch (op) { 8438897Ssef case OP_EQ: 8531567Ssef return (pport == rport); 8631567Ssef case OP_GT: 8731567Ssef return (pport > rport); 8831567Ssef case OP_LT: 8931567Ssef return (pport < rport); 9031567Ssef default: 9131580Speter return (0); 9231567Ssef } 9331567Ssef} 9431567Ssef 9531567Ssef/* 9631567Ssef * Check a packet against a defined filter 9731567Ssef * Returns 0 to accept the packet, non-zero to drop the packet 9831567Ssef * 9931567Ssef * If filtering is enabled, the initial fragment of a datagram must 10031567Ssef * contain the complete protocol header, and subsequent fragments 10131567Ssef * must not attempt to over-write it. 10231567Ssef */ 10331567Ssefstatic int 10431567SsefFilterCheck(const struct ip *pip, const struct filter *filter) 10531567Ssef{ 10631567Ssef int gotinfo; /* true if IP payload decoded */ 10731567Ssef int cproto; /* P_* protocol type if (gotinfo) */ 10831567Ssef int estab, syn, finrst; /* TCP state flags if (gotinfo) */ 10931567Ssef u_short sport, dport; /* src, dest port from packet if (gotinfo) */ 11031567Ssef int n; /* filter rule to process */ 11131567Ssef int len; /* bytes used in dbuff */ 11231567Ssef int didname; /* true if filter header printed */ 11331567Ssef int match; /* true if condition matched */ 11431567Ssef const struct filterent *fp = filter->rule; 11531580Speter char dbuff[100]; 11631567Ssef 11731567Ssef if (fp->f_action == A_NONE) 11831567Ssef return (0); /* No rule is given. Permit this packet */ 11931567Ssef 12031567Ssef /* Deny any packet fragment that tries to over-write the header. 12131567Ssef * Since we no longer have the real header available, punt on the 12238897Ssef * largest normal header - 20 bytes for TCP without options, rounded 12338897Ssef * up to the next possible fragment boundary. Since the smallest 12438897Ssef * `legal' MTU is 576, and the smallest recommended MTU is 296, any 12538897Ssef * fragmentation within this range is dubious at best */ 12638897Ssef len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */ 12731567Ssef if (len > 0) { /* Not first fragment within datagram */ 12831567Ssef if (len < (24 >> 3)) /* don't allow fragment to over-write header */ 12931567Ssef return (1); 13032275Scharnier /* permit fragments on in and out filter */ 13131567Ssef return (filter->fragok); 13231567Ssef } 13331567Ssef 13431567Ssef cproto = gotinfo = estab = syn = finrst = didname = 0; 13531567Ssef sport = dport = 0; 13631567Ssef for (n = 0; n < MAXFILTERS; ) { 13731567Ssef if (fp->f_action == A_NONE) { 13832275Scharnier n++; 13938520Scracauer fp++; 14031567Ssef continue; 14132306Sjmg } 14231567Ssef 14331567Ssef if (!didname) { 14431567Ssef log_Printf(LogDEBUG, "%s filter:\n", filter->name); 14531567Ssef didname = 1; 14631567Ssef } 14732275Scharnier 14831567Ssef match = 0; 14931567Ssef if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) & 15031567Ssef fp->f_src.mask.s_addr) && 15131567Ssef !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) & 15231567Ssef fp->f_dst.mask.s_addr)) { 15331567Ssef if (fp->f_proto != P_NONE) { 15431567Ssef if (!gotinfo) { 15531567Ssef const char *ptop = (const char *) pip + (pip->ip_hl << 2); 15631567Ssef const struct tcphdr *th; 15731567Ssef const struct udphdr *uh; 15831582Ssef const struct icmp *ih; 15931567Ssef int datalen; /* IP datagram length */ 16031567Ssef 16132275Scharnier datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 16232275Scharnier switch (pip->ip_p) { 16332275Scharnier case IPPROTO_ICMP: 16432275Scharnier cproto = P_ICMP; 16532275Scharnier if (datalen < 8) /* ICMP must be at least 8 octets */ 16631567Ssef return (1); 16731567Ssef ih = (const struct icmp *) ptop; 16831567Ssef sport = ih->icmp_type; 16931567Ssef estab = syn = finrst = -1; 17031567Ssef if (log_IsKept(LogDEBUG)) 17131567Ssef snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 17231567Ssef break; 17331567Ssef case IPPROTO_IGMP: 17431567Ssef cproto = P_IGMP; 17531567Ssef if (datalen < 8) /* IGMP uses 8-octet messages */ 17631567Ssef return (1); 17731567Ssef estab = syn = finrst = -1; 17831567Ssef sport = ntohs(0); 17931567Ssef break; 18031567Ssef#ifdef IPPROTO_OSPFIGP 18131567Ssef case IPPROTO_OSPFIGP: 18231567Ssef cproto = P_OSPF; 18331567Ssef if (datalen < 8) /* IGMP uses 8-octet messages */ 18431567Ssef return (1); 18531567Ssef estab = syn = finrst = -1; 18631567Ssef sport = ntohs(0); 18731567Ssef break; 18831567Ssef#endif 18931567Ssef case IPPROTO_UDP: 19031567Ssef case IPPROTO_IPIP: 19131567Ssef cproto = P_UDP; 19231567Ssef if (datalen < 8) /* UDP header is 8 octets */ 19331567Ssef return (1); 19431567Ssef uh = (const struct udphdr *) ptop; 19531567Ssef sport = ntohs(uh->uh_sport); 19631567Ssef dport = ntohs(uh->uh_dport); 19731567Ssef estab = syn = finrst = -1; 19831567Ssef if (log_IsKept(LogDEBUG)) 19931567Ssef snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 20031567Ssef sport, dport); 20131567Ssef break; 20231567Ssef case IPPROTO_TCP: 20331567Ssef cproto = P_TCP; 20431567Ssef th = (const struct tcphdr *) ptop; 20531567Ssef /* TCP headers are variable length. The following code 20631567Ssef * ensures that the TCP header length isn't de-referenced if 20732275Scharnier * the datagram is too short 20831567Ssef */ 20931567Ssef if (datalen < 20 || datalen < (th->th_off << 2)) 21031567Ssef return (1); 21131567Ssef sport = ntohs(th->th_sport); 21231567Ssef dport = ntohs(th->th_dport); 21331567Ssef estab = (th->th_flags & TH_ACK); 21431567Ssef syn = (th->th_flags & TH_SYN); 21531567Ssef finrst = (th->th_flags & (TH_FIN|TH_RST)); 21631567Ssef if (log_IsKept(LogDEBUG)) { 21731567Ssef if (!estab) 21831567Ssef snprintf(dbuff, sizeof dbuff, 21931567Ssef "flags = %02x, sport = %d, dport = %d", 22031567Ssef th->th_flags, sport, dport); 22131567Ssef else 22231567Ssef *dbuff = '\0'; 22331567Ssef } 22431567Ssef break; 22531567Ssef default: 22631567Ssef return (1); /* We'll block unknown type of packet */ 22731567Ssef } 22837453Sbde 22938520Scracauer if (log_IsKept(LogDEBUG)) { 23031567Ssef if (estab != -1) { 23131567Ssef len = strlen(dbuff); 23237453Sbde snprintf(dbuff + len, sizeof dbuff - len, 23331567Ssef ", estab = %d, syn = %d, finrst = %d", 23431567Ssef estab, syn, finrst); 23531567Ssef } 23631567Ssef log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 23731567Ssef filter_Proto2Nam(cproto), dbuff); 23831567Ssef } 23931567Ssef gotinfo = 1; 24031567Ssef } 24131567Ssef if (log_IsKept(LogDEBUG)) { 24231567Ssef if (fp->f_srcop != OP_NONE) { 24331691Ssef snprintf(dbuff, sizeof dbuff, ", src %s %d", 24432275Scharnier filter_Op2Nam(fp->f_srcop), fp->f_srcport); 24531567Ssef len = strlen(dbuff); 24638520Scracauer } else 24738520Scracauer len = 0; 24838520Scracauer if (fp->f_dstop != OP_NONE) { 24938520Scracauer snprintf(dbuff + len, sizeof dbuff - len, 25038520Scracauer ", dst %s %d", filter_Op2Nam(fp->f_dstop), 25138520Scracauer fp->f_dstport); 25231567Ssef } else if (!len) 25331567Ssef *dbuff = '\0'; 254 255 log_Printf(LogDEBUG, " rule = %d: Address match, " 256 "check against proto %s%s, action = %s\n", 257 n, filter_Proto2Nam(fp->f_proto), 258 dbuff, filter_Action2Nam(fp->f_action)); 259 } 260 261 if (cproto == fp->f_proto) { 262 if ((fp->f_srcop == OP_NONE || 263 PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 264 (fp->f_dstop == OP_NONE || 265 PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 266 (fp->f_estab == 0 || estab) && 267 (fp->f_syn == 0 || syn) && 268 (fp->f_finrst == 0 || finrst)) { 269 match = 1; 270 } 271 } 272 } else { 273 /* Address is matched and no protocol specified. Make a decision. */ 274 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 275 filter_Action2Nam(fp->f_action)); 276 match = 1; 277 } 278 } else 279 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 280 281 if (match != fp->f_invert) { 282 /* Take specified action */ 283 if (fp->f_action < A_NONE) 284 fp = &filter->rule[n = fp->f_action]; 285 else 286 return (fp->f_action != A_PERMIT); 287 } else { 288 n++; 289 fp++; 290 } 291 } 292 return (1); /* No rule is mached. Deny this packet */ 293} 294 295#ifdef notdef 296static void 297IcmpError(struct ip *pip, int code) 298{ 299 struct mbuf *bp; 300 301 if (pip->ip_p != IPPROTO_ICMP) { 302 bp = mbuf_Alloc(cnt, MB_IPIN); 303 memcpy(MBUF_CTOP(bp), ptr, cnt); 304 vj_SendFrame(bp); 305 ipcp_AddOutOctets(cnt); 306 } 307} 308#endif 309 310/* 311 * For debugging aid. 312 */ 313int 314PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 315{ 316 struct ip *pip; 317 struct tcphdr *th; 318 struct udphdr *uh; 319 struct icmp *icmph; 320 char *ptop; 321 int mask, len, n; 322 int pri = PRI_NORMAL; 323 int logit, loglen; 324 char logbuf[200]; 325 326 logit = log_IsKept(LogTCPIP) && filter->logok; 327 loglen = 0; 328 329 pip = (struct ip *) cp; 330 331 if (logit && loglen < sizeof logbuf) { 332 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 333 loglen += strlen(logbuf + loglen); 334 } 335 ptop = (cp + (pip->ip_hl << 2)); 336 337 switch (pip->ip_p) { 338 case IPPROTO_ICMP: 339 if (logit && loglen < sizeof logbuf) { 340 icmph = (struct icmp *) ptop; 341 snprintf(logbuf + loglen, sizeof logbuf - loglen, 342 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 343 loglen += strlen(logbuf + loglen); 344 snprintf(logbuf + loglen, sizeof logbuf - loglen, 345 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 346 loglen += strlen(logbuf + loglen); 347 } 348 break; 349 case IPPROTO_UDP: 350 if (logit && loglen < sizeof logbuf) { 351 uh = (struct udphdr *) ptop; 352 snprintf(logbuf + loglen, sizeof logbuf - loglen, 353 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 354 loglen += strlen(logbuf + loglen); 355 snprintf(logbuf + loglen, sizeof logbuf - loglen, 356 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 357 loglen += strlen(logbuf + loglen); 358 } 359 break; 360#ifdef IPPROTO_OSPFIGP 361 case IPPROTO_OSPFIGP: 362 if (logit && loglen < sizeof logbuf) { 363 snprintf(logbuf + loglen, sizeof logbuf - loglen, 364 "OSPF: %s ---> ", inet_ntoa(pip->ip_src)); 365 loglen += strlen(logbuf + loglen); 366 snprintf(logbuf + loglen, sizeof logbuf - loglen, 367 "%s", inet_ntoa(pip->ip_dst)); 368 loglen += strlen(logbuf + loglen); 369 } 370 break; 371#endif 372 case IPPROTO_IPIP: 373 if (logit && loglen < sizeof logbuf) { 374 uh = (struct udphdr *) ptop; 375 snprintf(logbuf + loglen, sizeof logbuf - loglen, 376 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 377 loglen += strlen(logbuf + loglen); 378 snprintf(logbuf + loglen, sizeof logbuf - loglen, 379 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 380 loglen += strlen(logbuf + loglen); 381 } 382 break; 383 case IPPROTO_IGMP: 384 if (logit && loglen < sizeof logbuf) { 385 uh = (struct udphdr *) ptop; 386 snprintf(logbuf + loglen, sizeof logbuf - loglen, 387 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 388 loglen += strlen(logbuf + loglen); 389 snprintf(logbuf + loglen, sizeof logbuf - loglen, 390 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 391 loglen += strlen(logbuf + loglen); 392 } 393 break; 394 case IPPROTO_TCP: 395 th = (struct tcphdr *) ptop; 396 if (pip->ip_tos == IPTOS_LOWDELAY) 397 pri = PRI_FAST; 398 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 399 if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 400 pri = PRI_FAST; 401 } 402 if (logit && loglen < sizeof logbuf) { 403 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 404 snprintf(logbuf + loglen, sizeof logbuf - loglen, 405 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 406 loglen += strlen(logbuf + loglen); 407 snprintf(logbuf + loglen, sizeof logbuf - loglen, 408 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 409 loglen += strlen(logbuf + loglen); 410 n = 0; 411 for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 412 if (th->th_flags & mask) { 413 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 414 loglen += strlen(logbuf + loglen); 415 } 416 n++; 417 } 418 snprintf(logbuf + loglen, sizeof logbuf - loglen, 419 " seq:%lx ack:%lx (%d/%d)", 420 (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 421 loglen += strlen(logbuf + loglen); 422 if ((th->th_flags & TH_SYN) && nb > 40) { 423 u_short *sp; 424 425 ptop += 20; 426 sp = (u_short *) ptop; 427 if (ntohs(sp[0]) == 0x0204) { 428 snprintf(logbuf + loglen, sizeof logbuf - loglen, 429 " MSS = %d", ntohs(sp[1])); 430 loglen += strlen(logbuf + loglen); 431 } 432 } 433 } 434 break; 435 } 436 437 if (FilterCheck(pip, filter)) { 438 if (logit) 439 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 440#ifdef notdef 441 if (direction == 0) 442 IcmpError(pip, pri); 443#endif 444 return (-1); 445 } else { 446 /* Check Keep Alive filter */ 447 if (logit) { 448 if (FilterCheck(pip, &bundle->filter.alive)) 449 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 450 else 451 log_Printf(LogTCPIP, "%s\n", logbuf); 452 } 453 return (pri); 454 } 455} 456 457struct mbuf * 458ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 459{ 460 int nb, nw; 461 struct tun_data tun; 462 struct ip *pip; 463 464 if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 465 log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 466 mbuf_Free(bp); 467 return NULL; 468 } 469 470 mbuf_SetType(bp, MB_IPIN); 471 tun_fill_header(tun, AF_INET); 472 nb = mbuf_Length(bp); 473 if (nb > sizeof tun.data) { 474 log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 475 l->name, nb, (int)(sizeof tun.data)); 476 mbuf_Free(bp); 477 return NULL; 478 } 479 mbuf_Read(bp, tun.data, nb); 480 481 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) 482 return NULL; 483 484 pip = (struct ip *)tun.data; 485 if (!FilterCheck(pip, &bundle->filter.alive)) 486 bundle_StartIdleTimer(bundle); 487 488 ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 489 490 nb += sizeof tun - sizeof tun.data; 491 nw = write(bundle->dev.fd, &tun, nb); 492 if (nw != nb) { 493 if (nw == -1) 494 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 495 l->name, nb, strerror(errno)); 496 else 497 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 498 } 499 500 return NULL; 501} 502 503void 504ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 505{ 506 struct mbuf *bp; 507 508 if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0]) 509 log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 510 else { 511 /* 512 * We allocate an extra 6 bytes, four at the front and two at the end. 513 * This is an optimisation so that we need to do less work in 514 * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and 515 * appending in hdlc_LayerPush(). 516 */ 517 bp = mbuf_Alloc(count + 6, MB_IPOUT); 518 bp->offset += 4; 519 bp->cnt -= 6; 520 memcpy(MBUF_CTOP(bp), ptr, count); 521 mbuf_Enqueue(&ipcp->Queue[pri], bp); 522 } 523} 524 525void 526ip_DeleteQueue(struct ipcp *ipcp) 527{ 528 struct mqueue *queue; 529 530 for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 531 while (queue->top) 532 mbuf_Free(mbuf_Dequeue(queue)); 533} 534 535int 536ip_QueueLen(struct ipcp *ipcp) 537{ 538 struct mqueue *queue; 539 int result = 0; 540 541 for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 542 result += queue->qlen; 543 544 return result; 545} 546 547int 548ip_PushPacket(struct link *l, struct bundle *bundle) 549{ 550 struct ipcp *ipcp = &bundle->ncp.ipcp; 551 struct mqueue *queue; 552 struct mbuf *bp; 553 struct ip *pip; 554 int cnt; 555 556 if (ipcp->fsm.state != ST_OPENED) 557 return 0; 558 559 for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--) 560 if (queue->top) { 561 bp = mbuf_Contiguous(mbuf_Dequeue(queue)); 562 cnt = mbuf_Length(bp); 563 pip = (struct ip *)MBUF_CTOP(bp); 564 if (!FilterCheck(pip, &bundle->filter.alive)) 565 bundle_StartIdleTimer(bundle); 566 link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP); 567 ipcp_AddOutOctets(ipcp, cnt); 568 return 1; 569 } 570 571 return 0; 572} 573