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 * 203a2e4f62SBrian Somers * $Id: ip.c,v 1.47 1998/06/27 14:18:05 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23af57ed9fSAtsushi Murai * o Return ICMP message for filterd packet 24af57ed9fSAtsushi Murai * and optionaly record it into log. 25af57ed9fSAtsushi Murai */ 262764b86aSBrian Somers #include <sys/types.h> 276a6b4bbbSBrian Somers #include <sys/socket.h> 2875240ed1SBrian Somers #include <netinet/in.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> 34ed6a16c1SPoul-Henning Kamp #include <arpa/inet.h> 351fa665f5SBrian Somers #include <sys/un.h> 3675240ed1SBrian Somers 37b6e82f33SBrian Somers #ifndef NOALIAS 386db75539SBrian Somers #include <alias.h> 39b6e82f33SBrian Somers #endif 4057fd05c4SBrian Somers #include <errno.h> 4175240ed1SBrian Somers #include <stdio.h> 4275240ed1SBrian Somers #include <stdlib.h> 4375240ed1SBrian Somers #include <string.h> 4475240ed1SBrian Somers #include <unistd.h> 4575240ed1SBrian Somers 46927145beSBrian Somers #include "mbuf.h" 47927145beSBrian Somers #include "log.h" 4875240ed1SBrian Somers #include "defs.h" 4975240ed1SBrian Somers #include "timer.h" 5075240ed1SBrian Somers #include "fsm.h" 51879ed6faSBrian Somers #include "lqr.h" 5275240ed1SBrian Somers #include "hdlc.h" 535828db6dSBrian Somers #include "throughput.h" 545828db6dSBrian Somers #include "iplist.h" 55eaa4df37SBrian Somers #include "slcompress.h" 5675240ed1SBrian Somers #include "ipcp.h" 571ae349f5Scvs2svn #include "filter.h" 582f786681SBrian Somers #include "descriptor.h" 5975240ed1SBrian Somers #include "lcp.h" 603b0f8d2eSBrian Somers #include "ccp.h" 613b0f8d2eSBrian Somers #include "link.h" 623b0f8d2eSBrian Somers #include "mp.h" 637a6f8720SBrian Somers #include "bundle.h" 641ae349f5Scvs2svn #include "vjcomp.h" 656a6b4bbbSBrian Somers #include "tun.h" 6675240ed1SBrian Somers #include "ip.h" 67af57ed9fSAtsushi Murai 68b6e82f33SBrian Somers static const u_short interactive_ports[32] = { 6976bd0c0aSDoug Rabson 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7076bd0c0aSDoug Rabson 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 71af57ed9fSAtsushi Murai }; 72af57ed9fSAtsushi Murai 7376bd0c0aSDoug Rabson #define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 74af57ed9fSAtsushi Murai 75b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 76af57ed9fSAtsushi Murai 77af57ed9fSAtsushi Murai static int 78944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 79af57ed9fSAtsushi Murai { 80af57ed9fSAtsushi Murai switch (op) { 81af57ed9fSAtsushi Murai case OP_EQ: 82af57ed9fSAtsushi Murai return (pport == rport); 83af57ed9fSAtsushi Murai case OP_GT: 84af57ed9fSAtsushi Murai return (pport > rport); 85af57ed9fSAtsushi Murai case OP_LT: 86af57ed9fSAtsushi Murai return (pport < rport); 87af57ed9fSAtsushi Murai default: 88af57ed9fSAtsushi Murai return (0); 89af57ed9fSAtsushi Murai } 90af57ed9fSAtsushi Murai } 91af57ed9fSAtsushi Murai 92af57ed9fSAtsushi Murai /* 93af57ed9fSAtsushi Murai * Check a packet against with defined filters 94af57ed9fSAtsushi Murai */ 95af57ed9fSAtsushi Murai static int 965ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter) 97af57ed9fSAtsushi Murai { 9863f98b41SBrian Somers int gotinfo, cproto, estab, syn, finrst, n, len, didname; 99af57ed9fSAtsushi Murai struct tcphdr *th; 100af57ed9fSAtsushi Murai struct udphdr *uh; 101af57ed9fSAtsushi Murai struct icmp *ih; 102af57ed9fSAtsushi Murai char *ptop; 103af57ed9fSAtsushi Murai u_short sport, dport; 1045ca5389aSBrian Somers struct filterent *fp = filter->rule; 1058390b576SBrian Somers char dbuff[100]; 106af57ed9fSAtsushi Murai 107af57ed9fSAtsushi Murai if (fp->action) { 10863f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 109af57ed9fSAtsushi Murai sport = dport = 0; 110af57ed9fSAtsushi Murai for (n = 0; n < MAXFILTERS; n++) { 111af57ed9fSAtsushi Murai if (fp->action) { 112f1884650SAtsushi Murai /* permit fragments on in and out filter */ 1135ca5389aSBrian Somers if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 114f1884650SAtsushi Murai return (A_PERMIT); 1155ca5389aSBrian Somers 1168390b576SBrian Somers if (!didname) 117dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 1188390b576SBrian Somers didname = 1; 1198390b576SBrian Somers 120a272e47dSBrian Somers if ((pip->ip_src.s_addr & fp->smask.s_addr) == 121a272e47dSBrian Somers (fp->saddr.s_addr & fp->smask.s_addr) && 122a272e47dSBrian Somers (pip->ip_dst.s_addr & fp->dmask.s_addr) == 123a272e47dSBrian Somers (fp->daddr.s_addr & fp->dmask.s_addr)) { 124af57ed9fSAtsushi Murai if (fp->proto) { 125af57ed9fSAtsushi Murai if (!gotinfo) { 126af57ed9fSAtsushi Murai ptop = (char *) pip + (pip->ip_hl << 2); 127af57ed9fSAtsushi Murai 128af57ed9fSAtsushi Murai switch (pip->ip_p) { 129af57ed9fSAtsushi Murai case IPPROTO_ICMP: 130944f7098SBrian Somers cproto = P_ICMP; 131944f7098SBrian Somers ih = (struct icmp *) ptop; 132944f7098SBrian Somers sport = ih->icmp_type; 13363f98b41SBrian Somers estab = syn = finrst = -1; 134dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1358390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 136af57ed9fSAtsushi Murai break; 137af57ed9fSAtsushi Murai case IPPROTO_UDP: 138eee772ecSBrian Somers case IPPROTO_IGMP: 139eee772ecSBrian Somers case IPPROTO_IPIP: 140944f7098SBrian Somers cproto = P_UDP; 141944f7098SBrian Somers uh = (struct udphdr *) ptop; 142944f7098SBrian Somers sport = ntohs(uh->uh_sport); 143944f7098SBrian Somers dport = ntohs(uh->uh_dport); 14463f98b41SBrian Somers estab = syn = finrst = -1; 145dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1468390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 1478390b576SBrian Somers sport, dport); 148af57ed9fSAtsushi Murai break; 149af57ed9fSAtsushi Murai case IPPROTO_TCP: 150944f7098SBrian Somers cproto = P_TCP; 151944f7098SBrian Somers th = (struct tcphdr *) ptop; 152944f7098SBrian Somers sport = ntohs(th->th_sport); 153944f7098SBrian Somers dport = ntohs(th->th_dport); 154af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 15563f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 15663f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 157dd7e2610SBrian Somers if (log_IsKept(LogDEBUG) && !estab) 1588390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 1598390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 160927145beSBrian Somers th->th_flags, sport, dport); 161af57ed9fSAtsushi Murai break; 162af57ed9fSAtsushi Murai default: 163af57ed9fSAtsushi Murai return (A_DENY); /* We'll block unknown type of packet */ 164af57ed9fSAtsushi Murai } 165dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 1668390b576SBrian Somers if (estab != -1) { 1678390b576SBrian Somers len = strlen(dbuff); 16863f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 16963f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 17063f98b41SBrian Somers estab, syn, finrst); 171af57ed9fSAtsushi Murai } 172dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 1738390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 1748390b576SBrian Somers } 1758390b576SBrian Somers gotinfo = 1; 1768390b576SBrian Somers } 177dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 1788390b576SBrian Somers if (fp->opt.srcop != OP_NONE) { 1798390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 1808390b576SBrian Somers filter_Op2Nam(fp->opt.srcop), fp->opt.srcport); 1818390b576SBrian Somers len = strlen(dbuff); 1828390b576SBrian Somers } else 1838390b576SBrian Somers len = 0; 1848390b576SBrian Somers if (fp->opt.dstop != OP_NONE) { 1858390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 1868390b576SBrian Somers ", dst %s %d", filter_Op2Nam(fp->opt.dstop), 1878390b576SBrian Somers fp->opt.dstport); 1888390b576SBrian Somers } else if (!len) 1898390b576SBrian Somers *dbuff = '\0'; 1908390b576SBrian Somers 191dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 1928390b576SBrian Somers "check against proto %s%s, action = %s\n", 1938390b576SBrian Somers n, filter_Proto2Nam(fp->proto), 1948390b576SBrian Somers dbuff, filter_Action2Nam(fp->action)); 1958390b576SBrian Somers } 196927145beSBrian Somers 197af57ed9fSAtsushi Murai if (cproto == fp->proto) { 198af57ed9fSAtsushi Murai if ((fp->opt.srcop == OP_NONE || 19963f98b41SBrian Somers PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && 200af57ed9fSAtsushi Murai (fp->opt.dstop == OP_NONE || 20163f98b41SBrian Somers PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && 20263f98b41SBrian Somers (fp->opt.estab == 0 || estab) && 20363f98b41SBrian Somers (fp->opt.syn == 0 || syn) && 20463f98b41SBrian Somers (fp->opt.finrst == 0 || finrst)) { 205af57ed9fSAtsushi Murai return (fp->action); 206af57ed9fSAtsushi Murai } 207af57ed9fSAtsushi Murai } 208af57ed9fSAtsushi Murai } else { 209af57ed9fSAtsushi Murai /* Address is mached. Make a decision. */ 210dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 2118390b576SBrian Somers filter_Action2Nam(fp->action)); 212af57ed9fSAtsushi Murai return (fp->action); 213af57ed9fSAtsushi Murai } 2148390b576SBrian Somers } else 215dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 216af57ed9fSAtsushi Murai } 217af57ed9fSAtsushi Murai fp++; 218af57ed9fSAtsushi Murai } 219af57ed9fSAtsushi Murai return (A_DENY); /* No rule is mached. Deny this packet */ 220af57ed9fSAtsushi Murai } 221af57ed9fSAtsushi Murai return (A_PERMIT); /* No rule is given. Permit this packet */ 222af57ed9fSAtsushi Murai } 223af57ed9fSAtsushi Murai 2245ca5389aSBrian Somers #ifdef notdef 225af57ed9fSAtsushi Murai static void 226944f7098SBrian Somers IcmpError(struct ip * pip, int code) 227af57ed9fSAtsushi Murai { 228af57ed9fSAtsushi Murai struct mbuf *bp; 229af57ed9fSAtsushi Murai 230af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 231dd7e2610SBrian Somers bp = mbuf_Alloc(cnt, MB_IPIN); 23275240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, cnt); 233dd7e2610SBrian Somers vj_SendFrame(bp); 2345828db6dSBrian Somers ipcp_AddOutOctets(cnt); 2351ae349f5Scvs2svn } 236af57ed9fSAtsushi Murai } 237af57ed9fSAtsushi Murai #endif 238af57ed9fSAtsushi Murai 239af57ed9fSAtsushi Murai /* 240af57ed9fSAtsushi Murai * For debugging aid. 241af57ed9fSAtsushi Murai */ 242af57ed9fSAtsushi Murai int 2435ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 244af57ed9fSAtsushi Murai { 245af57ed9fSAtsushi Murai struct ip *pip; 246af57ed9fSAtsushi Murai struct tcphdr *th; 247af57ed9fSAtsushi Murai struct udphdr *uh; 248af57ed9fSAtsushi Murai struct icmp *icmph; 249af57ed9fSAtsushi Murai char *ptop; 250af57ed9fSAtsushi Murai int mask, len, n; 251af57ed9fSAtsushi Murai int pri = PRI_NORMAL; 25255a8cdeaSBrian Somers int logit, loglen; 253d93d3a9cSBrian Somers char logbuf[200]; 254af57ed9fSAtsushi Murai 255dd7e2610SBrian Somers logit = log_IsKept(LogTCPIP) && filter->logok; 25655a8cdeaSBrian Somers loglen = 0; 257af57ed9fSAtsushi Murai 258af57ed9fSAtsushi Murai pip = (struct ip *) cp; 259af57ed9fSAtsushi Murai 26055a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 2615ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 26255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 26355a8cdeaSBrian Somers } 264af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 265af57ed9fSAtsushi Murai 266af57ed9fSAtsushi Murai switch (pip->ip_p) { 267af57ed9fSAtsushi Murai case IPPROTO_ICMP: 26855a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 269af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 27055a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 27155a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 27255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 27355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 27455a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 27555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 276af57ed9fSAtsushi Murai } 277af57ed9fSAtsushi Murai break; 278af57ed9fSAtsushi Murai case IPPROTO_UDP: 27955a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 280af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 28155a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 28255a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 28355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 28455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 28555a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 28655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 287af57ed9fSAtsushi Murai } 288af57ed9fSAtsushi Murai break; 289eee772ecSBrian Somers case IPPROTO_IPIP: 290eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 291eee772ecSBrian Somers uh = (struct udphdr *) ptop; 292eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 293eee772ecSBrian Somers "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 294eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 295eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 296eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 297eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 298eee772ecSBrian Somers } 299eee772ecSBrian Somers break; 300eee772ecSBrian Somers case IPPROTO_IGMP: 301eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 302eee772ecSBrian Somers uh = (struct udphdr *) ptop; 303eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 304eee772ecSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 305eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 306eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 307eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 308eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 309eee772ecSBrian Somers } 310eee772ecSBrian Somers break; 311af57ed9fSAtsushi Murai case IPPROTO_TCP: 312af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 313af57ed9fSAtsushi Murai if (pip->ip_tos == IPTOS_LOWDELAY) 314af57ed9fSAtsushi Murai pri = PRI_FAST; 31576bd0c0aSDoug Rabson else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 316af57ed9fSAtsushi Murai if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 317af57ed9fSAtsushi Murai pri = PRI_FAST; 318af57ed9fSAtsushi Murai } 31955a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 320af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 32155a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 32255a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 32355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 32455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 32555a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 32655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 327af57ed9fSAtsushi Murai n = 0; 328af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 32955a8cdeaSBrian Somers if (th->th_flags & mask) { 33055a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 33155a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 33255a8cdeaSBrian Somers } 333af57ed9fSAtsushi Murai n++; 334af57ed9fSAtsushi Murai } 33555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3363a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 3373a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 33855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 339af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 340af57ed9fSAtsushi Murai u_short *sp; 341af57ed9fSAtsushi Murai 342af57ed9fSAtsushi Murai ptop += 20; 343af57ed9fSAtsushi Murai sp = (u_short *) ptop; 34455a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 34555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 34655a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 34755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 34855a8cdeaSBrian Somers } 349af57ed9fSAtsushi Murai } 350af57ed9fSAtsushi Murai } 351af57ed9fSAtsushi Murai break; 352af57ed9fSAtsushi Murai } 35376bd0c0aSDoug Rabson 3545ca5389aSBrian Somers if ((FilterCheck(pip, filter) & A_DENY)) { 355710e9c29SBrian Somers if (logit) 356dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 3575ca5389aSBrian Somers #ifdef notdef 358944f7098SBrian Somers if (direction == 0) 359944f7098SBrian Somers IcmpError(pip, pri); 3605ca5389aSBrian Somers #endif 361af57ed9fSAtsushi Murai return (-1); 362af57ed9fSAtsushi Murai } else { 3635ca5389aSBrian Somers /* Check Keep Alive filter */ 364e43ebac1SBrian Somers if (logit) { 3651e991daaSBrian Somers if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) 366dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 3671e991daaSBrian Somers else 368dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 36953c9f6c0SAtsushi Murai } 370af57ed9fSAtsushi Murai return (pri); 371af57ed9fSAtsushi Murai } 372af57ed9fSAtsushi Murai } 373af57ed9fSAtsushi Murai 374af57ed9fSAtsushi Murai void 375dd7e2610SBrian Somers ip_Input(struct bundle *bundle, struct mbuf * bp) 3767a6f8720SBrian Somers { 377af57ed9fSAtsushi Murai u_char *cp; 378af57ed9fSAtsushi Murai struct mbuf *wp; 379af57ed9fSAtsushi Murai int nb, nw; 380b6e82f33SBrian Somers struct tun_data tun; 3811e991daaSBrian Somers struct ip *pip = (struct ip *)tun.data; 3823a2e4f62SBrian Somers #ifndef NOALIAS 383eee772ecSBrian Somers struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2)); 3843a2e4f62SBrian Somers #endif 385af57ed9fSAtsushi Murai 3866a6b4bbbSBrian Somers tun_fill_header(tun, AF_INET); 3876a6b4bbbSBrian Somers cp = tun.data; 388af57ed9fSAtsushi Murai nb = 0; 389927145beSBrian Somers for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 390512db555SBrian Somers if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 391a33b2ef7SBrian Somers log_Printf(LogWARN, "ip_Input: Packet too large (%d) - dropped\n", 392dd7e2610SBrian Somers mbuf_Length(bp)); 393dd7e2610SBrian Somers mbuf_Free(bp); 394512db555SBrian Somers return; 395512db555SBrian Somers } 39675240ed1SBrian Somers memcpy(cp, MBUF_CTOP(wp), wp->cnt); 397af57ed9fSAtsushi Murai cp += wp->cnt; 398af57ed9fSAtsushi Murai nb += wp->cnt; 399af57ed9fSAtsushi Murai } 400af57ed9fSAtsushi Murai 401b6e82f33SBrian Somers #ifndef NOALIAS 402615ad4f9SBrian Somers if (bundle->AliasEnabled && pip->ip_p != IPPROTO_IGMP && 403eee772ecSBrian Somers (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) { 404b6e82f33SBrian Somers struct tun_data *frag; 4056db75539SBrian Somers int iresult; 4066db75539SBrian Somers char *fptr; 4076db75539SBrian Somers 408615ad4f9SBrian Somers iresult = PacketAliasIn(tun.data, sizeof tun.data); 4096a6b4bbbSBrian Somers nb = ntohs(((struct ip *) tun.data)->ip_len); 4106db75539SBrian Somers 4116db75539SBrian Somers if (nb > MAX_MRU) { 412a33b2ef7SBrian Somers log_Printf(LogWARN, "ip_Input: Problem with IP header length\n"); 413dd7e2610SBrian Somers mbuf_Free(bp); 4146db75539SBrian Somers return; 415a9f484e5SJordan K. Hubbard } 4166db75539SBrian Somers if (iresult == PKT_ALIAS_OK 4176db75539SBrian Somers || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 4185ca5389aSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 419dd7e2610SBrian Somers mbuf_Free(bp); 420af57ed9fSAtsushi Murai return; 421af57ed9fSAtsushi Murai } 4221e991daaSBrian Somers 4231e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 4241e991daaSBrian Somers bundle_StartIdleTimer(bundle); 4251e991daaSBrian Somers 4265828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4276db75539SBrian Somers 4286a6b4bbbSBrian Somers nb = ntohs(((struct ip *) tun.data)->ip_len); 42970ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 430faefde08SBrian Somers nw = write(bundle->dev.fd, &tun, nb); 4316a596579SBrian Somers if (nw != nb) { 43257fd05c4SBrian Somers if (nw == -1) 433dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 43457fd05c4SBrian Somers strerror(errno)); 43557fd05c4SBrian Somers else 436dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 4376a596579SBrian Somers } 4386db75539SBrian Somers 4396db75539SBrian Somers if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 440615ad4f9SBrian Somers while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) { 441615ad4f9SBrian Somers PacketAliasFragmentIn(tun.data, fptr); 4426db75539SBrian Somers nb = ntohs(((struct ip *) fptr)->ip_len); 44370ee81ffSBrian Somers frag = (struct tun_data *) 44470ee81ffSBrian Somers ((char *)fptr - sizeof tun + sizeof tun.data); 44570ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 446faefde08SBrian Somers nw = write(bundle->dev.fd, frag, nb); 4476a596579SBrian Somers if (nw != nb) { 44857fd05c4SBrian Somers if (nw == -1) 449dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 45057fd05c4SBrian Somers strerror(errno)); 45157fd05c4SBrian Somers else 452dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 4536a596579SBrian Somers } 4546a6b4bbbSBrian Somers free(frag); 4556db75539SBrian Somers } 4566db75539SBrian Somers } 457944f7098SBrian Somers } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 4586a6b4bbbSBrian Somers nb = ntohs(((struct ip *) tun.data)->ip_len); 45970ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 4606a6b4bbbSBrian Somers frag = (struct tun_data *)malloc(nb); 4616a6b4bbbSBrian Somers if (frag == NULL) 462dd7e2610SBrian Somers log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n"); 4636db75539SBrian Somers else { 4646a6b4bbbSBrian Somers tun_fill_header(*frag, AF_INET); 46570ee81ffSBrian Somers memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 466615ad4f9SBrian Somers PacketAliasSaveFragment(frag->data); 4676db75539SBrian Somers } 4686db75539SBrian Somers } 469b6e82f33SBrian Somers } else 470b6e82f33SBrian Somers #endif /* #ifndef NOALIAS */ 471b6e82f33SBrian Somers { /* no aliasing */ 4725ca5389aSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 473dd7e2610SBrian Somers mbuf_Free(bp); 4746db75539SBrian Somers return; 4756db75539SBrian Somers } 4761e991daaSBrian Somers 4771e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 4781e991daaSBrian Somers bundle_StartIdleTimer(bundle); 4791e991daaSBrian Somers 4805828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4811e991daaSBrian Somers 48270ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 483faefde08SBrian Somers nw = write(bundle->dev.fd, &tun, nb); 484c4c4aaacSBrian Somers if (nw != nb) { 48557fd05c4SBrian Somers if (nw == -1) 486dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno)); 48757fd05c4SBrian Somers else 488dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 4896db75539SBrian Somers } 490c4c4aaacSBrian Somers } 491dd7e2610SBrian Somers mbuf_Free(bp); 492af57ed9fSAtsushi Murai } 493af57ed9fSAtsushi Murai 49476bd0c0aSDoug Rabson static struct mqueue IpOutputQueues[PRI_FAST + 1]; 495af57ed9fSAtsushi Murai 496af57ed9fSAtsushi Murai void 497dd7e2610SBrian Somers ip_Enqueue(int pri, char *ptr, int count) 498af57ed9fSAtsushi Murai { 499af57ed9fSAtsushi Murai struct mbuf *bp; 500af57ed9fSAtsushi Murai 501dd7e2610SBrian Somers bp = mbuf_Alloc(count, MB_IPQ); 50275240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, count); 503dd7e2610SBrian Somers mbuf_Enqueue(&IpOutputQueues[pri], bp); 504af57ed9fSAtsushi Murai } 505af57ed9fSAtsushi Murai 50684b8a6ebSAtsushi Murai int 507f4768038SBrian Somers ip_QueueLen() 50884b8a6ebSAtsushi Murai { 50984b8a6ebSAtsushi Murai struct mqueue *queue; 510f4768038SBrian Somers int result = 0; 511944f7098SBrian Somers 512f4768038SBrian Somers for (queue = &IpOutputQueues[PRI_MAX]; queue >= IpOutputQueues; queue--) 513f4768038SBrian Somers result += queue->qlen; 51484b8a6ebSAtsushi Murai 515f4768038SBrian Somers return result; 5161ae349f5Scvs2svn } 5171ae349f5Scvs2svn 5183b0f8d2eSBrian Somers int 519dd7e2610SBrian Somers ip_FlushPacket(struct link *l, struct bundle *bundle) 520af57ed9fSAtsushi Murai { 521af57ed9fSAtsushi Murai struct mqueue *queue; 522af57ed9fSAtsushi Murai struct mbuf *bp; 523274e766cSBrian Somers int cnt; 524af57ed9fSAtsushi Murai 5255828db6dSBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) 5263b0f8d2eSBrian Somers return 0; 5271e991daaSBrian Somers 5281e991daaSBrian Somers for (queue = &IpOutputQueues[PRI_FAST]; queue >= IpOutputQueues; queue--) 529af57ed9fSAtsushi Murai if (queue->top) { 530dd7e2610SBrian Somers bp = mbuf_Dequeue(queue); 531af57ed9fSAtsushi Murai if (bp) { 5321e991daaSBrian Somers struct ip *pip = (struct ip *)MBUF_CTOP(bp); 5331e991daaSBrian Somers 534dd7e2610SBrian Somers cnt = mbuf_Length(bp); 535dd7e2610SBrian Somers vj_SendFrame(l, bp, bundle); 5361e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 537ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 5385828db6dSBrian Somers ipcp_AddOutOctets(&bundle->ncp.ipcp, cnt); 5393b0f8d2eSBrian Somers return 1; 540af57ed9fSAtsushi Murai } 541af57ed9fSAtsushi Murai } 5421e991daaSBrian Somers 5433b0f8d2eSBrian Somers return 0; 544af57ed9fSAtsushi Murai } 545