ip.c revision 37192
169783Smsmith/* 2281887Sjhb * PPP IP Protocol Interface 3223520Sjhb * 469783Smsmith * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 569783Smsmith * 669783Smsmith * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 769783Smsmith * 869783Smsmith * Redistribution and use in source and binary forms are permitted 969783Smsmith * provided that the above copyright notice and this paragraph are 1069783Smsmith * duplicated in all such forms and that any documentation, 1169783Smsmith * advertising materials, and other materials related to such 1269783Smsmith * distribution and use acknowledge that the software was developed 1369783Smsmith * by the Internet Initiative Japan. The name of the 1469783Smsmith * IIJ may not be used to endorse or promote products derived 1569783Smsmith * from this software without specific prior written permission. 1669783Smsmith * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1769783Smsmith * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1869783Smsmith * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1969783Smsmith * 2069783Smsmith * $Id: ip.c,v 1.46 1998/06/27 14:17:26 brian Exp $ 2169783Smsmith * 2269783Smsmith * TODO: 2369783Smsmith * o Return ICMP message for filterd packet 2469783Smsmith * and optionaly record it into log. 2569783Smsmith */ 2669783Smsmith#include <sys/types.h> 2769783Smsmith#include <sys/socket.h> 28119418Sobrien#include <netinet/in.h> 29119418Sobrien#include <netinet/in_systm.h> 30119418Sobrien#include <netinet/ip.h> 3169783Smsmith#include <netinet/ip_icmp.h> 32223520Sjhb#include <netinet/udp.h> 33223520Sjhb#include <netinet/tcp.h> 3469783Smsmith#include <arpa/inet.h> 3569783Smsmith#include <sys/un.h> 36224069Sjhb 37221393Sjhb#ifndef NOALIAS 38261790Sjhb#include <alias.h> 39107546Simp#endif 40224069Sjhb#include <errno.h> 4169783Smsmith#include <stdio.h> 42223520Sjhb#include <stdlib.h> 43119285Simp#include <string.h> 44119285Simp#include <unistd.h> 4569783Smsmith 4669783Smsmith#include "mbuf.h" 47107172Sjhb#include "log.h" 48107172Sjhb#include "defs.h" 49107172Sjhb#include "timer.h" 50107172Sjhb#include "fsm.h" 51107172Sjhb#include "lqr.h" 52119266Simp#include "hdlc.h" 53107172Sjhb#include "throughput.h" 54119266Simp#include "iplist.h" 55107172Sjhb#include "slcompress.h" 56107172Sjhb#include "ipcp.h" 57107248Sjhb#include "filter.h" 58107172Sjhb#include "descriptor.h" 59107172Sjhb#include "lcp.h" 60107172Sjhb#include "ccp.h" 61107172Sjhb#include "link.h" 62107172Sjhb#include "mp.h" 63107172Sjhb#include "bundle.h" 64107172Sjhb#include "vjcomp.h" 65107172Sjhb#include "tun.h" 66107172Sjhb#include "ip.h" 67107172Sjhb 68107172Sjhbstatic const u_short interactive_ports[32] = { 69107172Sjhb 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70107172Sjhb 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 71107172Sjhb}; 72107172Sjhb 73107172Sjhb#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 74107172Sjhb 75107172Sjhbstatic const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 76107172Sjhb 77107172Sjhbstatic int 78107172SjhbPortMatch(int op, u_short pport, u_short rport) 79107172Sjhb{ 80107172Sjhb switch (op) { 81107172Sjhb case OP_EQ: 82107172Sjhb return (pport == rport); 83107172Sjhb case OP_GT: 84107172Sjhb return (pport > rport); 85107172Sjhb case OP_LT: 86107172Sjhb return (pport < rport); 87107172Sjhb default: 88107248Sjhb return (0); 89107172Sjhb } 90107172Sjhb} 91107172Sjhb 92107248Sjhb/* 93107172Sjhb * Check a packet against with defined filters 94107172Sjhb */ 95107172Sjhbstatic int 96107248SjhbFilterCheck(struct ip *pip, struct filter *filter) 97107172Sjhb{ 98107172Sjhb int gotinfo, cproto, estab, syn, finrst, n, len, didname; 99107172Sjhb struct tcphdr *th; 100107248Sjhb struct udphdr *uh; 101107172Sjhb struct icmp *ih; 102107172Sjhb char *ptop; 103107172Sjhb u_short sport, dport; 104107172Sjhb struct filterent *fp = filter->rule; 105107172Sjhb char dbuff[100]; 106107172Sjhb 107107172Sjhb if (fp->action) { 108107172Sjhb cproto = gotinfo = estab = syn = finrst = didname = 0; 109107172Sjhb sport = dport = 0; 110107172Sjhb for (n = 0; n < MAXFILTERS; n++) { 111107172Sjhb if (fp->action) { 112107172Sjhb /* permit fragments on in and out filter */ 113107172Sjhb if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 114107172Sjhb return (A_PERMIT); 115215820Sjhb 116107172Sjhb if (!didname) 117215820Sjhb log_Printf(LogDEBUG, "%s filter:\n", filter->name); 118107172Sjhb didname = 1; 119107172Sjhb 120107172Sjhb if ((pip->ip_src.s_addr & fp->smask.s_addr) == 121144110Sjhb (fp->saddr.s_addr & fp->smask.s_addr) && 122144110Sjhb (pip->ip_dst.s_addr & fp->dmask.s_addr) == 123144110Sjhb (fp->daddr.s_addr & fp->dmask.s_addr)) { 124144110Sjhb if (fp->proto) { 125144110Sjhb if (!gotinfo) { 126107172Sjhb ptop = (char *) pip + (pip->ip_hl << 2); 127107172Sjhb 128107172Sjhb switch (pip->ip_p) { 129107172Sjhb case IPPROTO_ICMP: 130107172Sjhb cproto = P_ICMP; 131107172Sjhb ih = (struct icmp *) ptop; 132107172Sjhb sport = ih->icmp_type; 133224069Sjhb estab = syn = finrst = -1; 134224069Sjhb if (log_IsKept(LogDEBUG)) 135224069Sjhb snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 136224069Sjhb break; 137224069Sjhb case IPPROTO_UDP: 138224069Sjhb case IPPROTO_IGMP: 139224069Sjhb case IPPROTO_IPIP: 140224069Sjhb cproto = P_UDP; 141224069Sjhb uh = (struct udphdr *) ptop; 142224069Sjhb sport = ntohs(uh->uh_sport); 143224069Sjhb dport = ntohs(uh->uh_dport); 144224069Sjhb estab = syn = finrst = -1; 145224069Sjhb if (log_IsKept(LogDEBUG)) 146224069Sjhb snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 147224069Sjhb sport, dport); 148224069Sjhb break; 149224069Sjhb case IPPROTO_TCP: 150224069Sjhb cproto = P_TCP; 151224069Sjhb th = (struct tcphdr *) ptop; 152224069Sjhb sport = ntohs(th->th_sport); 153224069Sjhb dport = ntohs(th->th_dport); 154224069Sjhb estab = (th->th_flags & TH_ACK); 155261523Sjhb syn = (th->th_flags & TH_SYN); 156224069Sjhb finrst = (th->th_flags & (TH_FIN|TH_RST)); 157224069Sjhb if (log_IsKept(LogDEBUG) && !estab) 158224069Sjhb snprintf(dbuff, sizeof dbuff, 159224069Sjhb "flags = %02x, sport = %d, dport = %d", 160224069Sjhb th->th_flags, sport, dport); 161224069Sjhb break; 162224069Sjhb default: 163224069Sjhb return (A_DENY); /* We'll block unknown type of packet */ 164224069Sjhb } 165224069Sjhb if (log_IsKept(LogDEBUG)) { 166224069Sjhb if (estab != -1) { 167224069Sjhb len = strlen(dbuff); 168224069Sjhb snprintf(dbuff + len, sizeof dbuff - len, 169224069Sjhb ", estab = %d, syn = %d, finrst = %d", 170224069Sjhb estab, syn, finrst); 171224069Sjhb } 172224069Sjhb log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 173224069Sjhb filter_Proto2Nam(cproto), dbuff); 174224069Sjhb } 175224069Sjhb gotinfo = 1; 176224069Sjhb } 177224069Sjhb if (log_IsKept(LogDEBUG)) { 178224069Sjhb if (fp->opt.srcop != OP_NONE) { 179224069Sjhb snprintf(dbuff, sizeof dbuff, ", src %s %d", 180224069Sjhb filter_Op2Nam(fp->opt.srcop), fp->opt.srcport); 181224069Sjhb len = strlen(dbuff); 182224069Sjhb } else 183224069Sjhb len = 0; 184224069Sjhb if (fp->opt.dstop != OP_NONE) { 185224069Sjhb snprintf(dbuff + len, sizeof dbuff - len, 186224069Sjhb ", dst %s %d", filter_Op2Nam(fp->opt.dstop), 187224069Sjhb fp->opt.dstport); 188224069Sjhb } else if (!len) 189224069Sjhb *dbuff = '\0'; 190224069Sjhb 191224069Sjhb log_Printf(LogDEBUG, " rule = %d: Address match, " 192224069Sjhb "check against proto %s%s, action = %s\n", 193224069Sjhb n, filter_Proto2Nam(fp->proto), 194224069Sjhb dbuff, filter_Action2Nam(fp->action)); 195224069Sjhb } 196224069Sjhb 197224069Sjhb if (cproto == fp->proto) { 198224069Sjhb if ((fp->opt.srcop == OP_NONE || 199224069Sjhb PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && 200224069Sjhb (fp->opt.dstop == OP_NONE || 201224069Sjhb PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && 202224069Sjhb (fp->opt.estab == 0 || estab) && 203224069Sjhb (fp->opt.syn == 0 || syn) && 204224069Sjhb (fp->opt.finrst == 0 || finrst)) { 205224069Sjhb return (fp->action); 206224069Sjhb } 207224069Sjhb } 208224069Sjhb } else { 209224069Sjhb /* Address is mached. Make a decision. */ 210224069Sjhb log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 211224069Sjhb filter_Action2Nam(fp->action)); 212224069Sjhb return (fp->action); 213224069Sjhb } 214224069Sjhb } else 215224069Sjhb log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 216224069Sjhb } 217224069Sjhb fp++; 218224069Sjhb } 219224069Sjhb return (A_DENY); /* No rule is mached. Deny this packet */ 220224069Sjhb } 221224069Sjhb return (A_PERMIT); /* No rule is given. Permit this packet */ 222224069Sjhb} 223224069Sjhb 224224069Sjhb#ifdef notdef 225224069Sjhbstatic void 226224069SjhbIcmpError(struct ip * pip, int code) 227224069Sjhb{ 228224069Sjhb struct mbuf *bp; 229224069Sjhb 230224069Sjhb if (pip->ip_p != IPPROTO_ICMP) { 231224069Sjhb bp = mbuf_Alloc(cnt, MB_IPIN); 232224069Sjhb memcpy(MBUF_CTOP(bp), ptr, cnt); 233224069Sjhb vj_SendFrame(bp); 234224069Sjhb ipcp_AddOutOctets(cnt); 235224069Sjhb } 236224069Sjhb} 237224069Sjhb#endif 238224069Sjhb 239224069Sjhb/* 240224069Sjhb * For debugging aid. 241224069Sjhb */ 242224069Sjhbint 243224069SjhbPacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 244224069Sjhb{ 245224069Sjhb struct ip *pip; 246224069Sjhb struct tcphdr *th; 247224069Sjhb struct udphdr *uh; 248224069Sjhb struct icmp *icmph; 249224069Sjhb char *ptop; 250224069Sjhb int mask, len, n; 251224069Sjhb int pri = PRI_NORMAL; 252224069Sjhb int logit, loglen; 253224069Sjhb char logbuf[200]; 254224069Sjhb 255224069Sjhb logit = log_IsKept(LogTCPIP) && filter->logok; 256224069Sjhb loglen = 0; 257224069Sjhb 258224069Sjhb pip = (struct ip *) cp; 259224069Sjhb 260224069Sjhb if (logit && loglen < sizeof logbuf) { 261224069Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 262224069Sjhb loglen += strlen(logbuf + loglen); 263224069Sjhb } 264224069Sjhb ptop = (cp + (pip->ip_hl << 2)); 265224069Sjhb 266224069Sjhb switch (pip->ip_p) { 267224069Sjhb case IPPROTO_ICMP: 268224069Sjhb if (logit && loglen < sizeof logbuf) { 269224069Sjhb icmph = (struct icmp *) ptop; 270224069Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 271224069Sjhb "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 272224069Sjhb loglen += strlen(logbuf + loglen); 273224069Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 274224069Sjhb "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 275224069Sjhb loglen += strlen(logbuf + loglen); 276224069Sjhb } 277224069Sjhb break; 278224069Sjhb case IPPROTO_UDP: 279224069Sjhb if (logit && loglen < sizeof logbuf) { 280224069Sjhb uh = (struct udphdr *) ptop; 281224069Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 282224069Sjhb "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 283224069Sjhb loglen += strlen(logbuf + loglen); 284224069Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 285224069Sjhb "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 286261790Sjhb loglen += strlen(logbuf + loglen); 287261790Sjhb } 288261790Sjhb break; 289261790Sjhb case IPPROTO_IPIP: 290261790Sjhb if (logit && loglen < sizeof logbuf) { 291261790Sjhb uh = (struct udphdr *) ptop; 292261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 293261790Sjhb "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 294261790Sjhb loglen += strlen(logbuf + loglen); 295261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 296261790Sjhb "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 297261790Sjhb loglen += strlen(logbuf + loglen); 298261790Sjhb } 299261790Sjhb break; 300261790Sjhb case IPPROTO_IGMP: 301261790Sjhb if (logit && loglen < sizeof logbuf) { 302261790Sjhb uh = (struct udphdr *) ptop; 303261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 304261790Sjhb "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 305261790Sjhb loglen += strlen(logbuf + loglen); 306261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 307261790Sjhb "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 308261790Sjhb loglen += strlen(logbuf + loglen); 309261790Sjhb } 310261790Sjhb break; 311261790Sjhb case IPPROTO_TCP: 312261790Sjhb th = (struct tcphdr *) ptop; 313261790Sjhb if (pip->ip_tos == IPTOS_LOWDELAY) 314261790Sjhb pri = PRI_FAST; 315261790Sjhb else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 316261790Sjhb if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 317261790Sjhb pri = PRI_FAST; 318261790Sjhb } 319261790Sjhb if (logit && loglen < sizeof logbuf) { 320261790Sjhb len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 321261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 322261790Sjhb "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 323261790Sjhb loglen += strlen(logbuf + loglen); 324261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 325261790Sjhb "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 326261790Sjhb loglen += strlen(logbuf + loglen); 327261790Sjhb n = 0; 328261790Sjhb for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 329261790Sjhb if (th->th_flags & mask) { 330261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 331261790Sjhb loglen += strlen(logbuf + loglen); 332261790Sjhb } 333261790Sjhb n++; 334261790Sjhb } 335261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 336261790Sjhb " seq:%x ack:%x (%d/%d)", 337261790Sjhb ntohl(th->th_seq), ntohl(th->th_ack), len, nb); 338261790Sjhb loglen += strlen(logbuf + loglen); 339261790Sjhb if ((th->th_flags & TH_SYN) && nb > 40) { 340261790Sjhb u_short *sp; 341261790Sjhb 342261790Sjhb ptop += 20; 343261790Sjhb sp = (u_short *) ptop; 344261790Sjhb if (ntohs(sp[0]) == 0x0204) { 345261790Sjhb snprintf(logbuf + loglen, sizeof logbuf - loglen, 346261790Sjhb " MSS = %d", ntohs(sp[1])); 347261790Sjhb loglen += strlen(logbuf + loglen); 348261790Sjhb } 349261790Sjhb } 350261790Sjhb } 351261790Sjhb break; 352261790Sjhb } 353261790Sjhb 354261790Sjhb if ((FilterCheck(pip, filter) & A_DENY)) { 355261790Sjhb if (logit) 356261790Sjhb log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 357261790Sjhb#ifdef notdef 358261790Sjhb if (direction == 0) 359261790Sjhb IcmpError(pip, pri); 360261790Sjhb#endif 361261790Sjhb return (-1); 362261790Sjhb } else { 363261790Sjhb /* Check Keep Alive filter */ 364261790Sjhb if (logit) { 365261790Sjhb if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) 366261790Sjhb log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 367261790Sjhb else 368261790Sjhb log_Printf(LogTCPIP, "%s\n", logbuf); 369261790Sjhb } 370261790Sjhb return (pri); 371261790Sjhb } 372261790Sjhb} 373261790Sjhb 374261790Sjhbvoid 375261790Sjhbip_Input(struct bundle *bundle, struct mbuf * bp) 376261790Sjhb{ 377261790Sjhb u_char *cp; 378261790Sjhb struct mbuf *wp; 379261790Sjhb int nb, nw; 380261790Sjhb struct tun_data tun; 381261790Sjhb struct ip *pip = (struct ip *)tun.data; 382261790Sjhb struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2)); 383261790Sjhb 384224069Sjhb tun_fill_header(tun, AF_INET); 385 cp = tun.data; 386 nb = 0; 387 for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 388 if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 389 log_Printf(LogWARN, "ip_Input: Packet too large (%d) - dropped\n", 390 mbuf_Length(bp)); 391 mbuf_Free(bp); 392 return; 393 } 394 memcpy(cp, MBUF_CTOP(wp), wp->cnt); 395 cp += wp->cnt; 396 nb += wp->cnt; 397 } 398 399#ifndef NOALIAS 400 if (bundle->AliasEnabled && pip->ip_p != IPPROTO_IGMP && 401 (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) { 402 struct tun_data *frag; 403 int iresult; 404 char *fptr; 405 406 iresult = PacketAliasIn(tun.data, sizeof tun.data); 407 nb = ntohs(((struct ip *) tun.data)->ip_len); 408 409 if (nb > MAX_MRU) { 410 log_Printf(LogWARN, "ip_Input: Problem with IP header length\n"); 411 mbuf_Free(bp); 412 return; 413 } 414 if (iresult == PKT_ALIAS_OK 415 || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 416 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 417 mbuf_Free(bp); 418 return; 419 } 420 421 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 422 bundle_StartIdleTimer(bundle); 423 424 ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 425 426 nb = ntohs(((struct ip *) tun.data)->ip_len); 427 nb += sizeof tun - sizeof tun.data; 428 nw = write(bundle->dev.fd, &tun, nb); 429 if (nw != nb) { 430 if (nw == -1) 431 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 432 strerror(errno)); 433 else 434 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 435 } 436 437 if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 438 while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) { 439 PacketAliasFragmentIn(tun.data, fptr); 440 nb = ntohs(((struct ip *) fptr)->ip_len); 441 frag = (struct tun_data *) 442 ((char *)fptr - sizeof tun + sizeof tun.data); 443 nb += sizeof tun - sizeof tun.data; 444 nw = write(bundle->dev.fd, frag, nb); 445 if (nw != nb) { 446 if (nw == -1) 447 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 448 strerror(errno)); 449 else 450 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 451 } 452 free(frag); 453 } 454 } 455 } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 456 nb = ntohs(((struct ip *) tun.data)->ip_len); 457 nb += sizeof tun - sizeof tun.data; 458 frag = (struct tun_data *)malloc(nb); 459 if (frag == NULL) 460 log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n"); 461 else { 462 tun_fill_header(*frag, AF_INET); 463 memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 464 PacketAliasSaveFragment(frag->data); 465 } 466 } 467 } else 468#endif /* #ifndef NOALIAS */ 469 { /* no aliasing */ 470 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 471 mbuf_Free(bp); 472 return; 473 } 474 475 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 476 bundle_StartIdleTimer(bundle); 477 478 ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 479 480 nb += sizeof tun - sizeof tun.data; 481 nw = write(bundle->dev.fd, &tun, nb); 482 if (nw != nb) { 483 if (nw == -1) 484 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno)); 485 else 486 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 487 } 488 } 489 mbuf_Free(bp); 490} 491 492static struct mqueue IpOutputQueues[PRI_FAST + 1]; 493 494void 495ip_Enqueue(int pri, char *ptr, int count) 496{ 497 struct mbuf *bp; 498 499 bp = mbuf_Alloc(count, MB_IPQ); 500 memcpy(MBUF_CTOP(bp), ptr, count); 501 mbuf_Enqueue(&IpOutputQueues[pri], bp); 502} 503 504int 505ip_QueueLen() 506{ 507 struct mqueue *queue; 508 int result = 0; 509 510 for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--) 511 result += queue->qlen; 512 513 return result; 514} 515 516int 517ip_FlushPacket(struct link *l, struct bundle *bundle) 518{ 519 struct mqueue *queue; 520 struct mbuf *bp; 521 int cnt; 522 523 if (bundle->ncp.ipcp.fsm.state != ST_OPENED) 524 return 0; 525 526 for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) 527 if (queue->top) { 528 bp = mbuf_Dequeue(queue); 529 if (bp) { 530 struct ip *pip = (struct ip *)MBUF_CTOP(bp); 531 532 cnt = mbuf_Length(bp); 533 vj_SendFrame(l, bp, bundle); 534 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 535 bundle_StartIdleTimer(bundle); 536 ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt); 537 return 1; 538 } 539 } 540 541 return 0; 542} 543