ip.c revision 36961
16059Samurai/* 26059Samurai * PPP IP Protocol Interface 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 198857Srgrimes * 2036961Sbrian * $Id: ip.c,v 1.41 1998/05/21 21:45:37 brian Exp $ 218857Srgrimes * 226059Samurai * TODO: 236059Samurai * o Return ICMP message for filterd packet 246059Samurai * and optionaly record it into log. 256059Samurai */ 2636285Sbrian#include <sys/types.h> 2731195Sbrian#include <sys/socket.h> 2830715Sbrian#include <netinet/in.h> 296059Samurai#include <netinet/in_systm.h> 306059Samurai#include <netinet/ip.h> 316059Samurai#include <netinet/ip_icmp.h> 326059Samurai#include <netinet/udp.h> 336059Samurai#include <netinet/tcp.h> 3413389Sphk#include <arpa/inet.h> 3536285Sbrian#include <net/if_tun.h> 3636285Sbrian#include <sys/un.h> 3730715Sbrian 3831343Sbrian#ifndef NOALIAS 3926031Sbrian#include <alias.h> 4031343Sbrian#endif 4130092Sbrian#include <errno.h> 4230715Sbrian#include <stdio.h> 4330715Sbrian#include <stdlib.h> 4430715Sbrian#include <string.h> 4530715Sbrian#include <unistd.h> 4630715Sbrian 4730715Sbrian#include "mbuf.h" 4830715Sbrian#include "log.h" 4930715Sbrian#include "defs.h" 5030715Sbrian#include "timer.h" 5130715Sbrian#include "fsm.h" 5236285Sbrian#include "lqr.h" 5330715Sbrian#include "hdlc.h" 5426142Sbrian#include "loadalias.h" 5536285Sbrian#include "throughput.h" 5636285Sbrian#include "iplist.h" 5736285Sbrian#include "slcompress.h" 5836285Sbrian#include "ipcp.h" 596059Samurai#include "filter.h" 6036285Sbrian#include "descriptor.h" 6136285Sbrian#include "lcp.h" 6236285Sbrian#include "ccp.h" 6336285Sbrian#include "link.h" 6436285Sbrian#include "mp.h" 6536285Sbrian#include "bundle.h" 6630715Sbrian#include "vjcomp.h" 6731195Sbrian#include "tun.h" 6830715Sbrian#include "ip.h" 696059Samurai 7031343Sbrianstatic const u_short interactive_ports[32] = { 7128679Sbrian 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7228679Sbrian 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 736059Samurai}; 746059Samurai 7513733Sdfr#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 766059Samurai 7731343Sbrianstatic const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 786059Samurai 796059Samuraistatic int 8028679SbrianPortMatch(int op, u_short pport, u_short rport) 816059Samurai{ 826059Samurai switch (op) { 8328679Sbrian case OP_EQ: 8428679Sbrian return (pport == rport); 856059Samurai case OP_GT: 8628679Sbrian return (pport > rport); 876059Samurai case OP_LT: 8828679Sbrian return (pport < rport); 896059Samurai default: 9028679Sbrian return (0); 916059Samurai } 926059Samurai} 936059Samurai 946059Samurai/* 956059Samurai * Check a packet against with defined filters 966059Samurai */ 976059Samuraistatic int 9836285SbrianFilterCheck(struct ip *pip, struct filter *filter) 996059Samurai{ 10036285Sbrian int gotinfo, cproto, estab, syn, finrst, n, len, didname; 1016059Samurai struct tcphdr *th; 1026059Samurai struct udphdr *uh; 1036059Samurai struct icmp *ih; 1046059Samurai char *ptop; 1056059Samurai u_short sport, dport; 10636285Sbrian struct filterent *fp = filter->rule; 10736285Sbrian char dbuff[100]; 1086059Samurai 1096059Samurai if (fp->action) { 11036285Sbrian cproto = gotinfo = estab = syn = finrst = didname = 0; 1116059Samurai sport = dport = 0; 1126059Samurai for (n = 0; n < MAXFILTERS; n++) { 1136059Samurai if (fp->action) { 11428679Sbrian /* permit fragments on in and out filter */ 11536285Sbrian if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 11628679Sbrian return (A_PERMIT); 11736285Sbrian 11836285Sbrian if (!didname) 11936285Sbrian log_Printf(LogDEBUG, "%s filter:\n", filter->name); 12036285Sbrian didname = 1; 12136285Sbrian 12231143Sbrian if ((pip->ip_src.s_addr & fp->smask.s_addr) == 12331143Sbrian (fp->saddr.s_addr & fp->smask.s_addr) && 12431143Sbrian (pip->ip_dst.s_addr & fp->dmask.s_addr) == 12531143Sbrian (fp->daddr.s_addr & fp->dmask.s_addr)) { 1266059Samurai if (fp->proto) { 1276059Samurai if (!gotinfo) { 12828679Sbrian ptop = (char *) pip + (pip->ip_hl << 2); 1296059Samurai 1306059Samurai switch (pip->ip_p) { 1316059Samurai case IPPROTO_ICMP: 13228679Sbrian cproto = P_ICMP; 13328679Sbrian ih = (struct icmp *) ptop; 13428679Sbrian sport = ih->icmp_type; 13536285Sbrian estab = syn = finrst = -1; 13636285Sbrian if (log_IsKept(LogDEBUG)) 13736285Sbrian snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 1386059Samurai break; 1396059Samurai case IPPROTO_UDP: 14036961Sbrian case IPPROTO_IGMP: 14136961Sbrian case IPPROTO_IPIP: 14228679Sbrian cproto = P_UDP; 14328679Sbrian uh = (struct udphdr *) ptop; 14428679Sbrian sport = ntohs(uh->uh_sport); 14528679Sbrian dport = ntohs(uh->uh_dport); 14636285Sbrian estab = syn = finrst = -1; 14736285Sbrian if (log_IsKept(LogDEBUG)) 14836285Sbrian snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 14936285Sbrian sport, dport); 1506059Samurai break; 1516059Samurai case IPPROTO_TCP: 15228679Sbrian cproto = P_TCP; 15328679Sbrian th = (struct tcphdr *) ptop; 15428679Sbrian sport = ntohs(th->th_sport); 15528679Sbrian dport = ntohs(th->th_dport); 1566059Samurai estab = (th->th_flags & TH_ACK); 15736285Sbrian syn = (th->th_flags & TH_SYN); 15836285Sbrian finrst = (th->th_flags & (TH_FIN|TH_RST)); 15936285Sbrian if (log_IsKept(LogDEBUG) && !estab) 16036285Sbrian snprintf(dbuff, sizeof dbuff, 16136285Sbrian "flags = %02x, sport = %d, dport = %d", 16236285Sbrian th->th_flags, sport, dport); 1636059Samurai break; 1646059Samurai default: 16536285Sbrian return (A_DENY); /* We'll block unknown type of packet */ 1666059Samurai } 16736285Sbrian if (log_IsKept(LogDEBUG)) { 16836285Sbrian if (estab != -1) { 16936285Sbrian len = strlen(dbuff); 17036285Sbrian snprintf(dbuff + len, sizeof dbuff - len, 17136285Sbrian ", estab = %d, syn = %d, finrst = %d", 17236285Sbrian estab, syn, finrst); 17336285Sbrian } 17436285Sbrian log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 17536285Sbrian filter_Proto2Nam(cproto), dbuff); 17636285Sbrian } 1776059Samurai gotinfo = 1; 1786059Samurai } 17936285Sbrian if (log_IsKept(LogDEBUG)) { 18036285Sbrian if (fp->opt.srcop != OP_NONE) { 18136285Sbrian snprintf(dbuff, sizeof dbuff, ", src %s %d", 18236285Sbrian filter_Op2Nam(fp->opt.srcop), fp->opt.srcport); 18336285Sbrian len = strlen(dbuff); 18436285Sbrian } else 18536285Sbrian len = 0; 18636285Sbrian if (fp->opt.dstop != OP_NONE) { 18736285Sbrian snprintf(dbuff + len, sizeof dbuff - len, 18836285Sbrian ", dst %s %d", filter_Op2Nam(fp->opt.dstop), 18936285Sbrian fp->opt.dstport); 19036285Sbrian } else if (!len) 19136285Sbrian *dbuff = '\0'; 19226516Sbrian 19336285Sbrian log_Printf(LogDEBUG, " rule = %d: Address match, " 19436285Sbrian "check against proto %s%s, action = %s\n", 19536285Sbrian n, filter_Proto2Nam(fp->proto), 19636285Sbrian dbuff, filter_Action2Nam(fp->action)); 19736285Sbrian } 19836285Sbrian 1996059Samurai if (cproto == fp->proto) { 2006059Samurai if ((fp->opt.srcop == OP_NONE || 20136285Sbrian PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && 2026059Samurai (fp->opt.dstop == OP_NONE || 20336285Sbrian PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && 20436285Sbrian (fp->opt.estab == 0 || estab) && 20536285Sbrian (fp->opt.syn == 0 || syn) && 20636285Sbrian (fp->opt.finrst == 0 || finrst)) { 20728679Sbrian return (fp->action); 2086059Samurai } 2096059Samurai } 2106059Samurai } else { 2116059Samurai /* Address is mached. Make a decision. */ 21236285Sbrian log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 21336285Sbrian filter_Action2Nam(fp->action)); 21428679Sbrian return (fp->action); 2156059Samurai } 21636285Sbrian } else 21736285Sbrian log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 2186059Samurai } 2196059Samurai fp++; 2206059Samurai } 22128679Sbrian return (A_DENY); /* No rule is mached. Deny this packet */ 2226059Samurai } 22328679Sbrian return (A_PERMIT); /* No rule is given. Permit this packet */ 2246059Samurai} 2256059Samurai 22636285Sbrian#ifdef notdef 2276059Samuraistatic void 22828679SbrianIcmpError(struct ip * pip, int code) 2296059Samurai{ 2306059Samurai struct mbuf *bp; 2316059Samurai 2326059Samurai if (pip->ip_p != IPPROTO_ICMP) { 23336285Sbrian bp = mbuf_Alloc(cnt, MB_IPIN); 23430715Sbrian memcpy(MBUF_CTOP(bp), ptr, cnt); 23536285Sbrian vj_SendFrame(bp); 23636285Sbrian ipcp_AddOutOctets(cnt); 2376059Samurai } 23836285Sbrian} 2396059Samurai#endif 2406059Samurai 2416059Samurai/* 2426059Samurai * For debugging aid. 2436059Samurai */ 2446059Samuraiint 24536285SbrianPacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 2466059Samurai{ 2476059Samurai struct ip *pip; 2486059Samurai struct tcphdr *th; 2496059Samurai struct udphdr *uh; 2506059Samurai struct icmp *icmph; 2516059Samurai char *ptop; 2526059Samurai int mask, len, n; 2536059Samurai int pri = PRI_NORMAL; 25426692Sbrian int logit, loglen; 25526692Sbrian static char logbuf[200]; 2566059Samurai 25736285Sbrian logit = log_IsKept(LogTCPIP) && filter->logok; 25826692Sbrian loglen = 0; 2596059Samurai 26028679Sbrian pip = (struct ip *) cp; 2618857Srgrimes 26226692Sbrian if (logit && loglen < sizeof logbuf) { 26336285Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 26428679Sbrian loglen += strlen(logbuf + loglen); 26526692Sbrian } 2666059Samurai ptop = (cp + (pip->ip_hl << 2)); 2676059Samurai 2686059Samurai switch (pip->ip_p) { 2696059Samurai case IPPROTO_ICMP: 27026692Sbrian if (logit && loglen < sizeof logbuf) { 27128679Sbrian icmph = (struct icmp *) ptop; 27228679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 27328679Sbrian "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 27428679Sbrian loglen += strlen(logbuf + loglen); 27528679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 27628679Sbrian "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 27728679Sbrian loglen += strlen(logbuf + loglen); 2786059Samurai } 2796059Samurai break; 2806059Samurai case IPPROTO_UDP: 28126692Sbrian if (logit && loglen < sizeof logbuf) { 28228679Sbrian uh = (struct udphdr *) ptop; 28328679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 28428679Sbrian "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 28528679Sbrian loglen += strlen(logbuf + loglen); 28628679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 28728679Sbrian "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 28828679Sbrian loglen += strlen(logbuf + loglen); 2896059Samurai } 2906059Samurai break; 29136961Sbrian case IPPROTO_IPIP: 29236961Sbrian if (logit && loglen < sizeof logbuf) { 29336961Sbrian uh = (struct udphdr *) ptop; 29436961Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 29536961Sbrian "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 29636961Sbrian loglen += strlen(logbuf + loglen); 29736961Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 29836961Sbrian "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 29936961Sbrian loglen += strlen(logbuf + loglen); 30036961Sbrian } 30136961Sbrian break; 30236961Sbrian case IPPROTO_IGMP: 30336961Sbrian if (logit && loglen < sizeof logbuf) { 30436961Sbrian uh = (struct udphdr *) ptop; 30536961Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 30636961Sbrian "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 30736961Sbrian loglen += strlen(logbuf + loglen); 30836961Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 30936961Sbrian "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 31036961Sbrian loglen += strlen(logbuf + loglen); 31136961Sbrian } 31236961Sbrian break; 3136059Samurai case IPPROTO_TCP: 31428679Sbrian th = (struct tcphdr *) ptop; 3156059Samurai if (pip->ip_tos == IPTOS_LOWDELAY) 3166059Samurai pri = PRI_FAST; 31713733Sdfr else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 3186059Samurai if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 31928679Sbrian pri = PRI_FAST; 3206059Samurai } 32126692Sbrian if (logit && loglen < sizeof logbuf) { 3226059Samurai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 32328679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 32428679Sbrian "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 32528679Sbrian loglen += strlen(logbuf + loglen); 32628679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 32728679Sbrian "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 32828679Sbrian loglen += strlen(logbuf + loglen); 3296059Samurai n = 0; 3306059Samurai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 33126692Sbrian if (th->th_flags & mask) { 33228679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 33328679Sbrian loglen += strlen(logbuf + loglen); 33428679Sbrian } 3356059Samurai n++; 3366059Samurai } 33728679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 33828679Sbrian " seq:%x ack:%x (%d/%d)", 33928679Sbrian ntohl(th->th_seq), ntohl(th->th_ack), len, nb); 34028679Sbrian loglen += strlen(logbuf + loglen); 3416059Samurai if ((th->th_flags & TH_SYN) && nb > 40) { 34228679Sbrian u_short *sp; 3436059Samurai 3446059Samurai ptop += 20; 34528679Sbrian sp = (u_short *) ptop; 34626692Sbrian if (ntohs(sp[0]) == 0x0204) { 34728679Sbrian snprintf(logbuf + loglen, sizeof logbuf - loglen, 34828679Sbrian " MSS = %d", ntohs(sp[1])); 34928679Sbrian loglen += strlen(logbuf + loglen); 35028679Sbrian } 3516059Samurai } 3526059Samurai } 3536059Samurai break; 3546059Samurai } 35526692Sbrian 35636285Sbrian if ((FilterCheck(pip, filter) & A_DENY)) { 35731142Sbrian if (logit) 35836285Sbrian log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 35936285Sbrian#ifdef notdef 36028679Sbrian if (direction == 0) 36128679Sbrian IcmpError(pip, pri); 36236285Sbrian#endif 36328679Sbrian return (-1); 3646059Samurai } else { 36536285Sbrian /* Check Keep Alive filter */ 36636285Sbrian if (logit) { 36736285Sbrian if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) 36836285Sbrian log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 36936285Sbrian else 37036285Sbrian log_Printf(LogTCPIP, "%s\n", logbuf); 3716735Samurai } 37228679Sbrian return (pri); 3736059Samurai } 3746059Samurai} 3756059Samurai 3766059Samuraivoid 37736285Sbrianip_Input(struct bundle *bundle, struct mbuf * bp) 37836285Sbrian{ 3796059Samurai u_char *cp; 3806059Samurai struct mbuf *wp; 3816059Samurai int nb, nw; 38231343Sbrian struct tun_data tun; 38336285Sbrian struct ip *pip = (struct ip *)tun.data; 38436961Sbrian struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2)); 3856059Samurai 38631195Sbrian tun_fill_header(tun, AF_INET); 38731195Sbrian cp = tun.data; 3886059Samurai nb = 0; 38928679Sbrian for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 39032247Sbrian if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 39136285Sbrian log_Printf(LogERROR, "ip_Input: Packet too large (%d) - dropped\n", 39236285Sbrian mbuf_Length(bp)); 39336285Sbrian mbuf_Free(bp); 39432247Sbrian return; 39532247Sbrian } 39630715Sbrian memcpy(cp, MBUF_CTOP(wp), wp->cnt); 3976059Samurai cp += wp->cnt; 3986059Samurai nb += wp->cnt; 3996059Samurai } 4006059Samurai 40131343Sbrian#ifndef NOALIAS 40236961Sbrian if (alias_IsEnabled() && pip->ip_p != IPPROTO_IGMP && 40336961Sbrian (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) { 40431343Sbrian struct tun_data *frag; 40526031Sbrian int iresult; 40626031Sbrian char *fptr; 40726031Sbrian 40836285Sbrian iresult = (*PacketAlias.In)(tun.data, sizeof tun.data); 40931195Sbrian nb = ntohs(((struct ip *) tun.data)->ip_len); 41026031Sbrian 41126031Sbrian if (nb > MAX_MRU) { 41236285Sbrian log_Printf(LogERROR, "ip_Input: Problem with IP header length\n"); 41336285Sbrian mbuf_Free(bp); 41426031Sbrian return; 41526031Sbrian } 41626031Sbrian if (iresult == PKT_ALIAS_OK 41728679Sbrian || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 41836285Sbrian if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 41936285Sbrian mbuf_Free(bp); 42028679Sbrian return; 42126031Sbrian } 42226031Sbrian 42336285Sbrian if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 42436285Sbrian bundle_StartIdleTimer(bundle); 42536285Sbrian 42636285Sbrian ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 42736285Sbrian 42831195Sbrian nb = ntohs(((struct ip *) tun.data)->ip_len); 42931962Sbrian nb += sizeof tun - sizeof tun.data; 43036285Sbrian nw = write(bundle->dev.fd, &tun, nb); 43135449Sbrian if (nw != nb) { 43230092Sbrian if (nw == -1) 43336285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 43430092Sbrian strerror(errno)); 43530092Sbrian else 43636285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 43735449Sbrian } 43826031Sbrian 43926031Sbrian if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 44036285Sbrian while ((fptr = (*PacketAlias.GetFragment)(tun.data)) != NULL) { 44136285Sbrian (*PacketAlias.FragmentIn)(tun.data, fptr); 44228679Sbrian nb = ntohs(((struct ip *) fptr)->ip_len); 44331962Sbrian frag = (struct tun_data *) 44431962Sbrian ((char *)fptr - sizeof tun + sizeof tun.data); 44531962Sbrian nb += sizeof tun - sizeof tun.data; 44636285Sbrian nw = write(bundle->dev.fd, frag, nb); 44735449Sbrian if (nw != nb) { 44830092Sbrian if (nw == -1) 44936285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 45030092Sbrian strerror(errno)); 45130092Sbrian else 45236285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 45335449Sbrian } 45431195Sbrian free(frag); 45528679Sbrian } 45626031Sbrian } 45728679Sbrian } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 45831195Sbrian nb = ntohs(((struct ip *) tun.data)->ip_len); 45931962Sbrian nb += sizeof tun - sizeof tun.data; 46031195Sbrian frag = (struct tun_data *)malloc(nb); 46131195Sbrian if (frag == NULL) 46236285Sbrian log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n"); 46326031Sbrian else { 46431195Sbrian tun_fill_header(*frag, AF_INET); 46531962Sbrian memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 46636285Sbrian (*PacketAlias.SaveFragment)(frag->data); 46726031Sbrian } 46826031Sbrian } 46931343Sbrian } else 47031343Sbrian#endif /* #ifndef NOALIAS */ 47131343Sbrian { /* no aliasing */ 47236285Sbrian if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 47336285Sbrian mbuf_Free(bp); 47426031Sbrian return; 47526031Sbrian } 47636285Sbrian 47736285Sbrian if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 47836285Sbrian bundle_StartIdleTimer(bundle); 47936285Sbrian 48036285Sbrian ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 48136285Sbrian 48231962Sbrian nb += sizeof tun - sizeof tun.data; 48336285Sbrian nw = write(bundle->dev.fd, &tun, nb); 48434536Sbrian if (nw != nb) { 48530092Sbrian if (nw == -1) 48636285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno)); 48730092Sbrian else 48836285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 48934536Sbrian } 4906059Samurai } 49136285Sbrian mbuf_Free(bp); 4926059Samurai} 4936059Samurai 49428679Sbrianstatic struct mqueue IpOutputQueues[PRI_FAST + 1]; 4956059Samurai 4966059Samuraivoid 49736285Sbrianip_Enqueue(int pri, char *ptr, int count) 4986059Samurai{ 4996059Samurai struct mbuf *bp; 5006059Samurai 50136285Sbrian bp = mbuf_Alloc(count, MB_IPQ); 50230715Sbrian memcpy(MBUF_CTOP(bp), ptr, count); 50336285Sbrian mbuf_Enqueue(&IpOutputQueues[pri], bp); 5046059Samurai} 5056059Samurai 5068857Srgrimesint 50736285Sbrianip_QueueLen() 5087001Samurai{ 5097001Samurai struct mqueue *queue; 51036285Sbrian int result = 0; 51128679Sbrian 51236285Sbrian for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--) 51336285Sbrian result += queue->qlen; 51436285Sbrian 51536285Sbrian return result; 5167001Samurai} 5177001Samurai 51836285Sbrianint 51936285Sbrianip_FlushPacket(struct link *l, struct bundle *bundle) 5206059Samurai{ 5216059Samurai struct mqueue *queue; 5226059Samurai struct mbuf *bp; 52325630Sbrian int cnt; 5246059Samurai 52536285Sbrian if (bundle->ncp.ipcp.fsm.state != ST_OPENED) 52636285Sbrian return 0; 52736285Sbrian 52836285Sbrian for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) 5296059Samurai if (queue->top) { 53036285Sbrian bp = mbuf_Dequeue(queue); 5316059Samurai if (bp) { 53236285Sbrian struct ip *pip = (struct ip *)MBUF_CTOP(bp); 53336285Sbrian 53436285Sbrian cnt = mbuf_Length(bp); 53536285Sbrian vj_SendFrame(l, bp, bundle); 53636285Sbrian if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 53736285Sbrian bundle_StartIdleTimer(bundle); 53836285Sbrian ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt); 53936285Sbrian return 1; 54028679Sbrian } 5416059Samurai } 54236285Sbrian 54336285Sbrian return 0; 5446059Samurai} 545