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 * 20eee772ecSBrian Somers * $Id: ip.c,v 1.41 1998/05/21 21:45:37 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> 35e43ebac1SBrian Somers #include <net/if_tun.h> 361fa665f5SBrian Somers #include <sys/un.h> 3775240ed1SBrian Somers 38b6e82f33SBrian Somers #ifndef NOALIAS 396db75539SBrian Somers #include <alias.h> 40b6e82f33SBrian Somers #endif 4157fd05c4SBrian Somers #include <errno.h> 4275240ed1SBrian Somers #include <stdio.h> 4375240ed1SBrian Somers #include <stdlib.h> 4475240ed1SBrian Somers #include <string.h> 4575240ed1SBrian Somers #include <unistd.h> 4675240ed1SBrian Somers 47927145beSBrian Somers #include "mbuf.h" 48927145beSBrian Somers #include "log.h" 4975240ed1SBrian Somers #include "defs.h" 5075240ed1SBrian Somers #include "timer.h" 5175240ed1SBrian Somers #include "fsm.h" 52879ed6faSBrian Somers #include "lqr.h" 5375240ed1SBrian Somers #include "hdlc.h" 5475240ed1SBrian Somers #include "loadalias.h" 555828db6dSBrian Somers #include "throughput.h" 565828db6dSBrian Somers #include "iplist.h" 57eaa4df37SBrian Somers #include "slcompress.h" 5875240ed1SBrian Somers #include "ipcp.h" 591ae349f5Scvs2svn #include "filter.h" 602f786681SBrian Somers #include "descriptor.h" 6175240ed1SBrian Somers #include "lcp.h" 623b0f8d2eSBrian Somers #include "ccp.h" 633b0f8d2eSBrian Somers #include "link.h" 643b0f8d2eSBrian Somers #include "mp.h" 657a6f8720SBrian Somers #include "bundle.h" 661ae349f5Scvs2svn #include "vjcomp.h" 676a6b4bbbSBrian Somers #include "tun.h" 6875240ed1SBrian Somers #include "ip.h" 69af57ed9fSAtsushi Murai 70b6e82f33SBrian Somers static const u_short interactive_ports[32] = { 7176bd0c0aSDoug Rabson 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7276bd0c0aSDoug Rabson 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 73af57ed9fSAtsushi Murai }; 74af57ed9fSAtsushi Murai 7576bd0c0aSDoug Rabson #define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 76af57ed9fSAtsushi Murai 77b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 78af57ed9fSAtsushi Murai 79af57ed9fSAtsushi Murai static int 80944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 81af57ed9fSAtsushi Murai { 82af57ed9fSAtsushi Murai switch (op) { 83af57ed9fSAtsushi Murai case OP_EQ: 84af57ed9fSAtsushi Murai return (pport == rport); 85af57ed9fSAtsushi Murai case OP_GT: 86af57ed9fSAtsushi Murai return (pport > rport); 87af57ed9fSAtsushi Murai case OP_LT: 88af57ed9fSAtsushi Murai return (pport < rport); 89af57ed9fSAtsushi Murai default: 90af57ed9fSAtsushi Murai return (0); 91af57ed9fSAtsushi Murai } 92af57ed9fSAtsushi Murai } 93af57ed9fSAtsushi Murai 94af57ed9fSAtsushi Murai /* 95af57ed9fSAtsushi Murai * Check a packet against with defined filters 96af57ed9fSAtsushi Murai */ 97af57ed9fSAtsushi Murai static int 985ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter) 99af57ed9fSAtsushi Murai { 10063f98b41SBrian Somers int gotinfo, cproto, estab, syn, finrst, n, len, didname; 101af57ed9fSAtsushi Murai struct tcphdr *th; 102af57ed9fSAtsushi Murai struct udphdr *uh; 103af57ed9fSAtsushi Murai struct icmp *ih; 104af57ed9fSAtsushi Murai char *ptop; 105af57ed9fSAtsushi Murai u_short sport, dport; 1065ca5389aSBrian Somers struct filterent *fp = filter->rule; 1078390b576SBrian Somers char dbuff[100]; 108af57ed9fSAtsushi Murai 109af57ed9fSAtsushi Murai if (fp->action) { 11063f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 111af57ed9fSAtsushi Murai sport = dport = 0; 112af57ed9fSAtsushi Murai for (n = 0; n < MAXFILTERS; n++) { 113af57ed9fSAtsushi Murai if (fp->action) { 114f1884650SAtsushi Murai /* permit fragments on in and out filter */ 1155ca5389aSBrian Somers if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 116f1884650SAtsushi Murai return (A_PERMIT); 1175ca5389aSBrian Somers 1188390b576SBrian Somers if (!didname) 119dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 1208390b576SBrian Somers didname = 1; 1218390b576SBrian Somers 122a272e47dSBrian Somers if ((pip->ip_src.s_addr & fp->smask.s_addr) == 123a272e47dSBrian Somers (fp->saddr.s_addr & fp->smask.s_addr) && 124a272e47dSBrian Somers (pip->ip_dst.s_addr & fp->dmask.s_addr) == 125a272e47dSBrian Somers (fp->daddr.s_addr & fp->dmask.s_addr)) { 126af57ed9fSAtsushi Murai if (fp->proto) { 127af57ed9fSAtsushi Murai if (!gotinfo) { 128af57ed9fSAtsushi Murai ptop = (char *) pip + (pip->ip_hl << 2); 129af57ed9fSAtsushi Murai 130af57ed9fSAtsushi Murai switch (pip->ip_p) { 131af57ed9fSAtsushi Murai case IPPROTO_ICMP: 132944f7098SBrian Somers cproto = P_ICMP; 133944f7098SBrian Somers ih = (struct icmp *) ptop; 134944f7098SBrian Somers sport = ih->icmp_type; 13563f98b41SBrian Somers estab = syn = finrst = -1; 136dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1378390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 138af57ed9fSAtsushi Murai break; 139af57ed9fSAtsushi Murai case IPPROTO_UDP: 140eee772ecSBrian Somers case IPPROTO_IGMP: 141eee772ecSBrian Somers case IPPROTO_IPIP: 142944f7098SBrian Somers cproto = P_UDP; 143944f7098SBrian Somers uh = (struct udphdr *) ptop; 144944f7098SBrian Somers sport = ntohs(uh->uh_sport); 145944f7098SBrian Somers dport = ntohs(uh->uh_dport); 14663f98b41SBrian Somers estab = syn = finrst = -1; 147dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1488390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 1498390b576SBrian Somers sport, dport); 150af57ed9fSAtsushi Murai break; 151af57ed9fSAtsushi Murai case IPPROTO_TCP: 152944f7098SBrian Somers cproto = P_TCP; 153944f7098SBrian Somers th = (struct tcphdr *) ptop; 154944f7098SBrian Somers sport = ntohs(th->th_sport); 155944f7098SBrian Somers dport = ntohs(th->th_dport); 156af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 15763f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 15863f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 159dd7e2610SBrian Somers if (log_IsKept(LogDEBUG) && !estab) 1608390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 1618390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 162927145beSBrian Somers th->th_flags, sport, dport); 163af57ed9fSAtsushi Murai break; 164af57ed9fSAtsushi Murai default: 165af57ed9fSAtsushi Murai return (A_DENY); /* We'll block unknown type of packet */ 166af57ed9fSAtsushi Murai } 167dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 1688390b576SBrian Somers if (estab != -1) { 1698390b576SBrian Somers len = strlen(dbuff); 17063f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 17163f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 17263f98b41SBrian Somers estab, syn, finrst); 173af57ed9fSAtsushi Murai } 174dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 1758390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 1768390b576SBrian Somers } 1778390b576SBrian Somers gotinfo = 1; 1788390b576SBrian Somers } 179dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 1808390b576SBrian Somers if (fp->opt.srcop != OP_NONE) { 1818390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 1828390b576SBrian Somers filter_Op2Nam(fp->opt.srcop), fp->opt.srcport); 1838390b576SBrian Somers len = strlen(dbuff); 1848390b576SBrian Somers } else 1858390b576SBrian Somers len = 0; 1868390b576SBrian Somers if (fp->opt.dstop != OP_NONE) { 1878390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 1888390b576SBrian Somers ", dst %s %d", filter_Op2Nam(fp->opt.dstop), 1898390b576SBrian Somers fp->opt.dstport); 1908390b576SBrian Somers } else if (!len) 1918390b576SBrian Somers *dbuff = '\0'; 1928390b576SBrian Somers 193dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 1948390b576SBrian Somers "check against proto %s%s, action = %s\n", 1958390b576SBrian Somers n, filter_Proto2Nam(fp->proto), 1968390b576SBrian Somers dbuff, filter_Action2Nam(fp->action)); 1978390b576SBrian Somers } 198927145beSBrian Somers 199af57ed9fSAtsushi Murai if (cproto == fp->proto) { 200af57ed9fSAtsushi Murai if ((fp->opt.srcop == OP_NONE || 20163f98b41SBrian Somers PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && 202af57ed9fSAtsushi Murai (fp->opt.dstop == OP_NONE || 20363f98b41SBrian Somers PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && 20463f98b41SBrian Somers (fp->opt.estab == 0 || estab) && 20563f98b41SBrian Somers (fp->opt.syn == 0 || syn) && 20663f98b41SBrian Somers (fp->opt.finrst == 0 || finrst)) { 207af57ed9fSAtsushi Murai return (fp->action); 208af57ed9fSAtsushi Murai } 209af57ed9fSAtsushi Murai } 210af57ed9fSAtsushi Murai } else { 211af57ed9fSAtsushi Murai /* Address is mached. Make a decision. */ 212dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 2138390b576SBrian Somers filter_Action2Nam(fp->action)); 214af57ed9fSAtsushi Murai return (fp->action); 215af57ed9fSAtsushi Murai } 2168390b576SBrian Somers } else 217dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 218af57ed9fSAtsushi Murai } 219af57ed9fSAtsushi Murai fp++; 220af57ed9fSAtsushi Murai } 221af57ed9fSAtsushi Murai return (A_DENY); /* No rule is mached. Deny this packet */ 222af57ed9fSAtsushi Murai } 223af57ed9fSAtsushi Murai return (A_PERMIT); /* No rule is given. Permit this packet */ 224af57ed9fSAtsushi Murai } 225af57ed9fSAtsushi Murai 2265ca5389aSBrian Somers #ifdef notdef 227af57ed9fSAtsushi Murai static void 228944f7098SBrian Somers IcmpError(struct ip * pip, int code) 229af57ed9fSAtsushi Murai { 230af57ed9fSAtsushi Murai struct mbuf *bp; 231af57ed9fSAtsushi Murai 232af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 233dd7e2610SBrian Somers bp = mbuf_Alloc(cnt, MB_IPIN); 23475240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, cnt); 235dd7e2610SBrian Somers vj_SendFrame(bp); 2365828db6dSBrian Somers ipcp_AddOutOctets(cnt); 2371ae349f5Scvs2svn } 238af57ed9fSAtsushi Murai } 239af57ed9fSAtsushi Murai #endif 240af57ed9fSAtsushi Murai 241af57ed9fSAtsushi Murai /* 242af57ed9fSAtsushi Murai * For debugging aid. 243af57ed9fSAtsushi Murai */ 244af57ed9fSAtsushi Murai int 2455ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 246af57ed9fSAtsushi Murai { 247af57ed9fSAtsushi Murai struct ip *pip; 248af57ed9fSAtsushi Murai struct tcphdr *th; 249af57ed9fSAtsushi Murai struct udphdr *uh; 250af57ed9fSAtsushi Murai struct icmp *icmph; 251af57ed9fSAtsushi Murai char *ptop; 252af57ed9fSAtsushi Murai int mask, len, n; 253af57ed9fSAtsushi Murai int pri = PRI_NORMAL; 25455a8cdeaSBrian Somers int logit, loglen; 25555a8cdeaSBrian Somers static char logbuf[200]; 256af57ed9fSAtsushi Murai 257dd7e2610SBrian Somers logit = log_IsKept(LogTCPIP) && filter->logok; 25855a8cdeaSBrian Somers loglen = 0; 259af57ed9fSAtsushi Murai 260af57ed9fSAtsushi Murai pip = (struct ip *) cp; 261af57ed9fSAtsushi Murai 26255a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 2635ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 26455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 26555a8cdeaSBrian Somers } 266af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 267af57ed9fSAtsushi Murai 268af57ed9fSAtsushi Murai switch (pip->ip_p) { 269af57ed9fSAtsushi Murai case IPPROTO_ICMP: 27055a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 271af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 27255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 27355a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 27455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 27555a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 27655a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 27755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 278af57ed9fSAtsushi Murai } 279af57ed9fSAtsushi Murai break; 280af57ed9fSAtsushi Murai case IPPROTO_UDP: 28155a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 282af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 28355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 28455a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 28555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 28655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 28755a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 28855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 289af57ed9fSAtsushi Murai } 290af57ed9fSAtsushi Murai break; 291eee772ecSBrian Somers case IPPROTO_IPIP: 292eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 293eee772ecSBrian Somers uh = (struct udphdr *) ptop; 294eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 295eee772ecSBrian Somers "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 296eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 297eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 298eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 299eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 300eee772ecSBrian Somers } 301eee772ecSBrian Somers break; 302eee772ecSBrian Somers case IPPROTO_IGMP: 303eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 304eee772ecSBrian Somers uh = (struct udphdr *) ptop; 305eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 306eee772ecSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 307eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 308eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 309eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 310eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 311eee772ecSBrian Somers } 312eee772ecSBrian Somers break; 313af57ed9fSAtsushi Murai case IPPROTO_TCP: 314af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 315af57ed9fSAtsushi Murai if (pip->ip_tos == IPTOS_LOWDELAY) 316af57ed9fSAtsushi Murai pri = PRI_FAST; 31776bd0c0aSDoug Rabson else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 318af57ed9fSAtsushi Murai if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 319af57ed9fSAtsushi Murai pri = PRI_FAST; 320af57ed9fSAtsushi Murai } 32155a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 322af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 32355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 32455a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 32555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 32655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 32755a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 32855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 329af57ed9fSAtsushi Murai n = 0; 330af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 33155a8cdeaSBrian Somers if (th->th_flags & mask) { 33255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 33355a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 33455a8cdeaSBrian Somers } 335af57ed9fSAtsushi Murai n++; 336af57ed9fSAtsushi Murai } 33755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 33855a8cdeaSBrian Somers " seq:%x ack:%x (%d/%d)", 339af57ed9fSAtsushi Murai ntohl(th->th_seq), ntohl(th->th_ack), len, nb); 34055a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 341af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 342af57ed9fSAtsushi Murai u_short *sp; 343af57ed9fSAtsushi Murai 344af57ed9fSAtsushi Murai ptop += 20; 345af57ed9fSAtsushi Murai sp = (u_short *) ptop; 34655a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 34755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 34855a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 34955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 35055a8cdeaSBrian Somers } 351af57ed9fSAtsushi Murai } 352af57ed9fSAtsushi Murai } 353af57ed9fSAtsushi Murai break; 354af57ed9fSAtsushi Murai } 35576bd0c0aSDoug Rabson 3565ca5389aSBrian Somers if ((FilterCheck(pip, filter) & A_DENY)) { 357710e9c29SBrian Somers if (logit) 358dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 3595ca5389aSBrian Somers #ifdef notdef 360944f7098SBrian Somers if (direction == 0) 361944f7098SBrian Somers IcmpError(pip, pri); 3625ca5389aSBrian Somers #endif 363af57ed9fSAtsushi Murai return (-1); 364af57ed9fSAtsushi Murai } else { 3655ca5389aSBrian Somers /* Check Keep Alive filter */ 366e43ebac1SBrian Somers if (logit) { 3671e991daaSBrian Somers if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) 368dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 3691e991daaSBrian Somers else 370dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 37153c9f6c0SAtsushi Murai } 372af57ed9fSAtsushi Murai return (pri); 373af57ed9fSAtsushi Murai } 374af57ed9fSAtsushi Murai } 375af57ed9fSAtsushi Murai 376af57ed9fSAtsushi Murai void 377dd7e2610SBrian Somers ip_Input(struct bundle *bundle, struct mbuf * bp) 3787a6f8720SBrian Somers { 379af57ed9fSAtsushi Murai u_char *cp; 380af57ed9fSAtsushi Murai struct mbuf *wp; 381af57ed9fSAtsushi Murai int nb, nw; 382b6e82f33SBrian Somers struct tun_data tun; 3831e991daaSBrian Somers struct ip *pip = (struct ip *)tun.data; 384eee772ecSBrian Somers struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2)); 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) { 391dd7e2610SBrian Somers log_Printf(LogERROR, "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 402eee772ecSBrian Somers if (alias_IsEnabled() && 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 4082764b86aSBrian Somers iresult = (*PacketAlias.In)(tun.data, sizeof tun.data); 4096a6b4bbbSBrian Somers nb = ntohs(((struct ip *) tun.data)->ip_len); 4106db75539SBrian Somers 4116db75539SBrian Somers if (nb > MAX_MRU) { 412dd7e2610SBrian Somers log_Printf(LogERROR, "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) { 4402764b86aSBrian Somers while ((fptr = (*PacketAlias.GetFragment)(tun.data)) != NULL) { 4412764b86aSBrian Somers (*PacketAlias.FragmentIn)(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); 4662764b86aSBrian Somers (*PacketAlias.SaveFragment)(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