ip.c revision 38557
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 * 2038557Sbrian * $Id: ip.c,v 1.51 1998/08/25 17:48:42 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> 2738174Sbrian#ifdef __OpenBSD__ 2831195Sbrian#include <sys/socket.h> 2938174Sbrian#endif 3030715Sbrian#include <netinet/in.h> 316059Samurai#include <netinet/in_systm.h> 326059Samurai#include <netinet/ip.h> 336059Samurai#include <netinet/ip_icmp.h> 346059Samurai#include <netinet/udp.h> 356059Samurai#include <netinet/tcp.h> 3613389Sphk#include <arpa/inet.h> 3736285Sbrian#include <sys/un.h> 3830715Sbrian 3931343Sbrian#ifndef NOALIAS 4026031Sbrian#include <alias.h> 4131343Sbrian#endif 4230092Sbrian#include <errno.h> 4330715Sbrian#include <stdio.h> 4430715Sbrian#include <stdlib.h> 4530715Sbrian#include <string.h> 4630715Sbrian#include <unistd.h> 4730715Sbrian 4830715Sbrian#include "mbuf.h" 4930715Sbrian#include "log.h" 5030715Sbrian#include "defs.h" 5130715Sbrian#include "timer.h" 5230715Sbrian#include "fsm.h" 5336285Sbrian#include "lqr.h" 5430715Sbrian#include "hdlc.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; 25537010Sbrian 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, 33837210Sbrian " seq:%lx ack:%lx (%d/%d)", 33937210Sbrian (u_long)ntohl(th->th_seq), (u_long)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; 38437210Sbrian#ifndef NOALIAS 38536961Sbrian struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2)); 38637210Sbrian#endif 3876059Samurai 38831195Sbrian tun_fill_header(tun, AF_INET); 38931195Sbrian cp = tun.data; 3906059Samurai nb = 0; 39128679Sbrian for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 39232247Sbrian if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 39337019Sbrian log_Printf(LogWARN, "ip_Input: Packet too large (%d) - dropped\n", 39436285Sbrian mbuf_Length(bp)); 39536285Sbrian mbuf_Free(bp); 39632247Sbrian return; 39732247Sbrian } 39830715Sbrian memcpy(cp, MBUF_CTOP(wp), wp->cnt); 3996059Samurai cp += wp->cnt; 4006059Samurai nb += wp->cnt; 4016059Samurai } 4026059Samurai 40331343Sbrian#ifndef NOALIAS 40437191Sbrian if (bundle->AliasEnabled && pip->ip_p != IPPROTO_IGMP && 40536961Sbrian (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) { 40631343Sbrian struct tun_data *frag; 40726031Sbrian int iresult; 40826031Sbrian char *fptr; 40926031Sbrian 41037191Sbrian iresult = PacketAliasIn(tun.data, sizeof tun.data); 41131195Sbrian nb = ntohs(((struct ip *) tun.data)->ip_len); 41226031Sbrian 41326031Sbrian if (nb > MAX_MRU) { 41437019Sbrian log_Printf(LogWARN, "ip_Input: Problem with IP header length\n"); 41536285Sbrian mbuf_Free(bp); 41626031Sbrian return; 41726031Sbrian } 41826031Sbrian if (iresult == PKT_ALIAS_OK 41928679Sbrian || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 42036285Sbrian if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 42136285Sbrian mbuf_Free(bp); 42228679Sbrian return; 42326031Sbrian } 42426031Sbrian 42536285Sbrian if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 42636285Sbrian bundle_StartIdleTimer(bundle); 42736285Sbrian 42836285Sbrian ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 42936285Sbrian 43031195Sbrian nb = ntohs(((struct ip *) tun.data)->ip_len); 43131962Sbrian nb += sizeof tun - sizeof tun.data; 43236285Sbrian nw = write(bundle->dev.fd, &tun, nb); 43335449Sbrian if (nw != nb) { 43430092Sbrian if (nw == -1) 43536285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 43630092Sbrian strerror(errno)); 43730092Sbrian else 43836285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 43935449Sbrian } 44026031Sbrian 44126031Sbrian if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 44237191Sbrian while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) { 44337191Sbrian PacketAliasFragmentIn(tun.data, fptr); 44428679Sbrian nb = ntohs(((struct ip *) fptr)->ip_len); 44531962Sbrian frag = (struct tun_data *) 44631962Sbrian ((char *)fptr - sizeof tun + sizeof tun.data); 44731962Sbrian nb += sizeof tun - sizeof tun.data; 44836285Sbrian nw = write(bundle->dev.fd, frag, nb); 44935449Sbrian if (nw != nb) { 45030092Sbrian if (nw == -1) 45136285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 45230092Sbrian strerror(errno)); 45330092Sbrian else 45436285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 45535449Sbrian } 45631195Sbrian free(frag); 45728679Sbrian } 45826031Sbrian } 45928679Sbrian } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 46031195Sbrian nb = ntohs(((struct ip *) tun.data)->ip_len); 46131962Sbrian nb += sizeof tun - sizeof tun.data; 46231195Sbrian frag = (struct tun_data *)malloc(nb); 46331195Sbrian if (frag == NULL) 46436285Sbrian log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n"); 46526031Sbrian else { 46631195Sbrian tun_fill_header(*frag, AF_INET); 46731962Sbrian memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 46837191Sbrian PacketAliasSaveFragment(frag->data); 46926031Sbrian } 47026031Sbrian } 47131343Sbrian } else 47231343Sbrian#endif /* #ifndef NOALIAS */ 47331343Sbrian { /* no aliasing */ 47436285Sbrian if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 47536285Sbrian mbuf_Free(bp); 47626031Sbrian return; 47726031Sbrian } 47836285Sbrian 47936285Sbrian if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 48036285Sbrian bundle_StartIdleTimer(bundle); 48136285Sbrian 48236285Sbrian ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 48336285Sbrian 48431962Sbrian nb += sizeof tun - sizeof tun.data; 48536285Sbrian nw = write(bundle->dev.fd, &tun, nb); 48634536Sbrian if (nw != nb) { 48730092Sbrian if (nw == -1) 48836285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno)); 48930092Sbrian else 49036285Sbrian log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 49134536Sbrian } 4926059Samurai } 49336285Sbrian mbuf_Free(bp); 4946059Samurai} 4956059Samurai 4966059Samuraivoid 49738557Sbrianip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 4986059Samurai{ 4996059Samurai struct mbuf *bp; 5006059Samurai 50138557Sbrian if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0]) 50238557Sbrian log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 50338557Sbrian else { 50438557Sbrian bp = mbuf_Alloc(count, MB_IPQ); 50538557Sbrian memcpy(MBUF_CTOP(bp), ptr, count); 50638557Sbrian mbuf_Enqueue(&ipcp->Queue[pri], bp); 50738557Sbrian } 5086059Samurai} 5096059Samurai 51038544Sbrianvoid 51138557Sbrianip_DeleteQueue(struct ipcp *ipcp) 51238544Sbrian{ 51338544Sbrian struct mqueue *queue; 51438544Sbrian 51538557Sbrian for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 51638544Sbrian while (queue->top) 51738544Sbrian mbuf_Free(mbuf_Dequeue(queue)); 51838544Sbrian} 51938544Sbrian 5208857Srgrimesint 52138557Sbrianip_QueueLen(struct ipcp *ipcp) 5227001Samurai{ 5237001Samurai struct mqueue *queue; 52436285Sbrian int result = 0; 52528679Sbrian 52638557Sbrian for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 52736285Sbrian result += queue->qlen; 52836285Sbrian 52936285Sbrian return result; 5307001Samurai} 5317001Samurai 53236285Sbrianint 53336285Sbrianip_FlushPacket(struct link *l, struct bundle *bundle) 5346059Samurai{ 53538557Sbrian struct ipcp *ipcp = &bundle->ncp.ipcp; 5366059Samurai struct mqueue *queue; 5376059Samurai struct mbuf *bp; 53825630Sbrian int cnt; 5396059Samurai 54038557Sbrian if (ipcp->fsm.state != ST_OPENED) 54136285Sbrian return 0; 54236285Sbrian 54338557Sbrian for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--) 5446059Samurai if (queue->top) { 54536285Sbrian bp = mbuf_Dequeue(queue); 5466059Samurai if (bp) { 54736285Sbrian struct ip *pip = (struct ip *)MBUF_CTOP(bp); 54836285Sbrian 54936285Sbrian cnt = mbuf_Length(bp); 55036285Sbrian if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 55136285Sbrian bundle_StartIdleTimer(bundle); 55237572Sbrian vj_SendFrame(l, bp, bundle); 55338557Sbrian ipcp_AddOutOctets(ipcp, cnt); 55436285Sbrian return 1; 55528679Sbrian } 5566059Samurai } 55736285Sbrian 55836285Sbrian return 0; 5596059Samurai} 560