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 * 205d9e6103SBrian Somers * $Id: ip.c,v 1.58 1999/05/01 11:31:29 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 */ 26972a1bcfSBrian Somers #include <sys/param.h> 277884358fSBrian Somers #if defined(__OpenBSD__) || defined(__NetBSD__) 286a6b4bbbSBrian Somers #include <sys/socket.h> 2992b09558SBrian Somers #endif 3075240ed1SBrian Somers #include <netinet/in.h> 31af57ed9fSAtsushi Murai #include <netinet/in_systm.h> 32af57ed9fSAtsushi Murai #include <netinet/ip.h> 33af57ed9fSAtsushi Murai #include <netinet/ip_icmp.h> 34af57ed9fSAtsushi Murai #include <netinet/udp.h> 35af57ed9fSAtsushi Murai #include <netinet/tcp.h> 36ed6a16c1SPoul-Henning Kamp #include <arpa/inet.h> 371fa665f5SBrian Somers #include <sys/un.h> 3875240ed1SBrian Somers 3957fd05c4SBrian Somers #include <errno.h> 4075240ed1SBrian Somers #include <stdio.h> 4175240ed1SBrian Somers #include <stdlib.h> 4275240ed1SBrian Somers #include <string.h> 435d9e6103SBrian Somers #include <termios.h> 4475240ed1SBrian Somers #include <unistd.h> 4575240ed1SBrian Somers 465d9e6103SBrian Somers #include "layer.h" 475d9e6103SBrian Somers #include "proto.h" 48927145beSBrian Somers #include "mbuf.h" 49927145beSBrian Somers #include "log.h" 5075240ed1SBrian Somers #include "defs.h" 5175240ed1SBrian Somers #include "timer.h" 5275240ed1SBrian Somers #include "fsm.h" 53879ed6faSBrian Somers #include "lqr.h" 5475240ed1SBrian Somers #include "hdlc.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" 65972a1bcfSBrian Somers #ifndef NORADIUS 66972a1bcfSBrian Somers #include "radius.h" 67972a1bcfSBrian Somers #endif 687a6f8720SBrian Somers #include "bundle.h" 691ae349f5Scvs2svn #include "vjcomp.h" 706a6b4bbbSBrian Somers #include "tun.h" 7175240ed1SBrian Somers #include "ip.h" 72af57ed9fSAtsushi Murai 73b6e82f33SBrian Somers static const u_short interactive_ports[32] = { 7476bd0c0aSDoug Rabson 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7522d1222bSBrian Somers 80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 76af57ed9fSAtsushi Murai }; 77af57ed9fSAtsushi Murai 7876bd0c0aSDoug Rabson #define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 79af57ed9fSAtsushi Murai 80b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 81af57ed9fSAtsushi Murai 82af57ed9fSAtsushi Murai static int 83944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 84af57ed9fSAtsushi Murai { 85af57ed9fSAtsushi Murai switch (op) { 86af57ed9fSAtsushi Murai case OP_EQ: 87af57ed9fSAtsushi Murai return (pport == rport); 88af57ed9fSAtsushi Murai case OP_GT: 89af57ed9fSAtsushi Murai return (pport > rport); 90af57ed9fSAtsushi Murai case OP_LT: 91af57ed9fSAtsushi Murai return (pport < rport); 92af57ed9fSAtsushi Murai default: 93af57ed9fSAtsushi Murai return (0); 94af57ed9fSAtsushi Murai } 95af57ed9fSAtsushi Murai } 96af57ed9fSAtsushi Murai 97af57ed9fSAtsushi Murai /* 985d9e6103SBrian Somers * Check a packet against a defined filter 99af57ed9fSAtsushi Murai */ 100af57ed9fSAtsushi Murai static int 1015ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter) 102af57ed9fSAtsushi Murai { 10363f98b41SBrian Somers int gotinfo, cproto, estab, syn, finrst, n, len, didname; 104af57ed9fSAtsushi Murai struct tcphdr *th; 105af57ed9fSAtsushi Murai struct udphdr *uh; 106af57ed9fSAtsushi Murai struct icmp *ih; 107af57ed9fSAtsushi Murai char *ptop; 108af57ed9fSAtsushi Murai u_short sport, dport; 1095ca5389aSBrian Somers struct filterent *fp = filter->rule; 1108390b576SBrian Somers char dbuff[100]; 111af57ed9fSAtsushi Murai 112af57ed9fSAtsushi Murai if (fp->action) { 11363f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 114af57ed9fSAtsushi Murai sport = dport = 0; 115af57ed9fSAtsushi Murai for (n = 0; n < MAXFILTERS; n++) { 116af57ed9fSAtsushi Murai if (fp->action) { 117f1884650SAtsushi Murai /* permit fragments on in and out filter */ 1185ca5389aSBrian Somers if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 119f1884650SAtsushi Murai return (A_PERMIT); 1205ca5389aSBrian Somers 1218390b576SBrian Somers if (!didname) 122dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 1238390b576SBrian Somers didname = 1; 1248390b576SBrian Somers 125a272e47dSBrian Somers if ((pip->ip_src.s_addr & fp->smask.s_addr) == 126a272e47dSBrian Somers (fp->saddr.s_addr & fp->smask.s_addr) && 127a272e47dSBrian Somers (pip->ip_dst.s_addr & fp->dmask.s_addr) == 128a272e47dSBrian Somers (fp->daddr.s_addr & fp->dmask.s_addr)) { 129af57ed9fSAtsushi Murai if (fp->proto) { 130af57ed9fSAtsushi Murai if (!gotinfo) { 131af57ed9fSAtsushi Murai ptop = (char *) pip + (pip->ip_hl << 2); 132af57ed9fSAtsushi Murai 133af57ed9fSAtsushi Murai switch (pip->ip_p) { 134af57ed9fSAtsushi Murai case IPPROTO_ICMP: 135944f7098SBrian Somers cproto = P_ICMP; 136944f7098SBrian Somers ih = (struct icmp *) ptop; 137944f7098SBrian Somers sport = ih->icmp_type; 13863f98b41SBrian Somers estab = syn = finrst = -1; 139dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1408390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 141af57ed9fSAtsushi Murai break; 142af57ed9fSAtsushi Murai case IPPROTO_UDP: 143eee772ecSBrian Somers case IPPROTO_IGMP: 144eee772ecSBrian Somers case IPPROTO_IPIP: 145944f7098SBrian Somers cproto = P_UDP; 146944f7098SBrian Somers uh = (struct udphdr *) ptop; 147944f7098SBrian Somers sport = ntohs(uh->uh_sport); 148944f7098SBrian Somers dport = ntohs(uh->uh_dport); 14963f98b41SBrian Somers estab = syn = finrst = -1; 150dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1518390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 1528390b576SBrian Somers sport, dport); 153af57ed9fSAtsushi Murai break; 154af57ed9fSAtsushi Murai case IPPROTO_TCP: 155944f7098SBrian Somers cproto = P_TCP; 156944f7098SBrian Somers th = (struct tcphdr *) ptop; 157944f7098SBrian Somers sport = ntohs(th->th_sport); 158944f7098SBrian Somers dport = ntohs(th->th_dport); 159af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 16063f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 16163f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 1622b81c773SBrian Somers if (log_IsKept(LogDEBUG)) { 1632b81c773SBrian Somers if (!estab) 1648390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 1658390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 166927145beSBrian Somers th->th_flags, sport, dport); 1672b81c773SBrian Somers else 1682b81c773SBrian Somers *dbuff = '\0'; 1692b81c773SBrian Somers } 170af57ed9fSAtsushi Murai break; 171af57ed9fSAtsushi Murai default: 172af57ed9fSAtsushi Murai return (A_DENY); /* We'll block unknown type of packet */ 173af57ed9fSAtsushi Murai } 174dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 1758390b576SBrian Somers if (estab != -1) { 1768390b576SBrian Somers len = strlen(dbuff); 17763f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 17863f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 17963f98b41SBrian Somers estab, syn, finrst); 180af57ed9fSAtsushi Murai } 181dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 1828390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 1838390b576SBrian Somers } 1848390b576SBrian Somers gotinfo = 1; 1858390b576SBrian Somers } 186dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 1878390b576SBrian Somers if (fp->opt.srcop != OP_NONE) { 1888390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 1898390b576SBrian Somers filter_Op2Nam(fp->opt.srcop), fp->opt.srcport); 1908390b576SBrian Somers len = strlen(dbuff); 1918390b576SBrian Somers } else 1928390b576SBrian Somers len = 0; 1938390b576SBrian Somers if (fp->opt.dstop != OP_NONE) { 1948390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 1958390b576SBrian Somers ", dst %s %d", filter_Op2Nam(fp->opt.dstop), 1968390b576SBrian Somers fp->opt.dstport); 1978390b576SBrian Somers } else if (!len) 1988390b576SBrian Somers *dbuff = '\0'; 1998390b576SBrian Somers 200dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 2018390b576SBrian Somers "check against proto %s%s, action = %s\n", 2028390b576SBrian Somers n, filter_Proto2Nam(fp->proto), 2038390b576SBrian Somers dbuff, filter_Action2Nam(fp->action)); 2048390b576SBrian Somers } 205927145beSBrian Somers 206af57ed9fSAtsushi Murai if (cproto == fp->proto) { 207af57ed9fSAtsushi Murai if ((fp->opt.srcop == OP_NONE || 20863f98b41SBrian Somers PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && 209af57ed9fSAtsushi Murai (fp->opt.dstop == OP_NONE || 21063f98b41SBrian Somers PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && 21163f98b41SBrian Somers (fp->opt.estab == 0 || estab) && 21263f98b41SBrian Somers (fp->opt.syn == 0 || syn) && 21363f98b41SBrian Somers (fp->opt.finrst == 0 || finrst)) { 214af57ed9fSAtsushi Murai return (fp->action); 215af57ed9fSAtsushi Murai } 216af57ed9fSAtsushi Murai } 217af57ed9fSAtsushi Murai } else { 218af57ed9fSAtsushi Murai /* Address is mached. Make a decision. */ 219dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 2208390b576SBrian Somers filter_Action2Nam(fp->action)); 221af57ed9fSAtsushi Murai return (fp->action); 222af57ed9fSAtsushi Murai } 2238390b576SBrian Somers } else 224dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 225af57ed9fSAtsushi Murai } 226af57ed9fSAtsushi Murai fp++; 227af57ed9fSAtsushi Murai } 228af57ed9fSAtsushi Murai return (A_DENY); /* No rule is mached. Deny this packet */ 229af57ed9fSAtsushi Murai } 230af57ed9fSAtsushi Murai return (A_PERMIT); /* No rule is given. Permit this packet */ 231af57ed9fSAtsushi Murai } 232af57ed9fSAtsushi Murai 2335ca5389aSBrian Somers #ifdef notdef 234af57ed9fSAtsushi Murai static void 235944f7098SBrian Somers IcmpError(struct ip * pip, int code) 236af57ed9fSAtsushi Murai { 237af57ed9fSAtsushi Murai struct mbuf *bp; 238af57ed9fSAtsushi Murai 239af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 240dd7e2610SBrian Somers bp = mbuf_Alloc(cnt, MB_IPIN); 24175240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, cnt); 242dd7e2610SBrian Somers vj_SendFrame(bp); 2435828db6dSBrian Somers ipcp_AddOutOctets(cnt); 2441ae349f5Scvs2svn } 245af57ed9fSAtsushi Murai } 246af57ed9fSAtsushi Murai #endif 247af57ed9fSAtsushi Murai 248af57ed9fSAtsushi Murai /* 249af57ed9fSAtsushi Murai * For debugging aid. 250af57ed9fSAtsushi Murai */ 251af57ed9fSAtsushi Murai int 2525ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 253af57ed9fSAtsushi Murai { 254af57ed9fSAtsushi Murai struct ip *pip; 255af57ed9fSAtsushi Murai struct tcphdr *th; 256af57ed9fSAtsushi Murai struct udphdr *uh; 257af57ed9fSAtsushi Murai struct icmp *icmph; 258af57ed9fSAtsushi Murai char *ptop; 259af57ed9fSAtsushi Murai int mask, len, n; 260af57ed9fSAtsushi Murai int pri = PRI_NORMAL; 26155a8cdeaSBrian Somers int logit, loglen; 262d93d3a9cSBrian Somers char logbuf[200]; 263af57ed9fSAtsushi Murai 264dd7e2610SBrian Somers logit = log_IsKept(LogTCPIP) && filter->logok; 26555a8cdeaSBrian Somers loglen = 0; 266af57ed9fSAtsushi Murai 267af57ed9fSAtsushi Murai pip = (struct ip *) cp; 268af57ed9fSAtsushi Murai 26955a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 2705ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 27155a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 27255a8cdeaSBrian Somers } 273af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 274af57ed9fSAtsushi Murai 275af57ed9fSAtsushi Murai switch (pip->ip_p) { 276af57ed9fSAtsushi Murai case IPPROTO_ICMP: 27755a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 278af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 27955a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 28055a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 28155a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 28255a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 28355a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 28455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 285af57ed9fSAtsushi Murai } 286af57ed9fSAtsushi Murai break; 287af57ed9fSAtsushi Murai case IPPROTO_UDP: 28855a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 289af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 29055a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 29155a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 29255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 29355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 29455a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 29555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 296af57ed9fSAtsushi Murai } 297af57ed9fSAtsushi Murai break; 298eee772ecSBrian Somers case IPPROTO_IPIP: 299eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 300eee772ecSBrian Somers uh = (struct udphdr *) ptop; 301eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 302eee772ecSBrian Somers "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 303eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 304eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 305eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 306eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 307eee772ecSBrian Somers } 308eee772ecSBrian Somers break; 309eee772ecSBrian Somers case IPPROTO_IGMP: 310eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 311eee772ecSBrian Somers uh = (struct udphdr *) ptop; 312eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 313eee772ecSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 314eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 315eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 316eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 317eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 318eee772ecSBrian Somers } 319eee772ecSBrian Somers break; 320af57ed9fSAtsushi Murai case IPPROTO_TCP: 321af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 322af57ed9fSAtsushi Murai if (pip->ip_tos == IPTOS_LOWDELAY) 323af57ed9fSAtsushi Murai pri = PRI_FAST; 32476bd0c0aSDoug Rabson else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 325af57ed9fSAtsushi Murai if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 326af57ed9fSAtsushi Murai pri = PRI_FAST; 327af57ed9fSAtsushi Murai } 32855a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 329af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 33055a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 33155a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 33255a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 33355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 33455a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 33555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 336af57ed9fSAtsushi Murai n = 0; 337af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 33855a8cdeaSBrian Somers if (th->th_flags & mask) { 33955a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 34055a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 34155a8cdeaSBrian Somers } 342af57ed9fSAtsushi Murai n++; 343af57ed9fSAtsushi Murai } 34455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3453a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 3463a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 34755a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 348af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 349af57ed9fSAtsushi Murai u_short *sp; 350af57ed9fSAtsushi Murai 351af57ed9fSAtsushi Murai ptop += 20; 352af57ed9fSAtsushi Murai sp = (u_short *) ptop; 35355a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 35455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 35555a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 35655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 35755a8cdeaSBrian Somers } 358af57ed9fSAtsushi Murai } 359af57ed9fSAtsushi Murai } 360af57ed9fSAtsushi Murai break; 361af57ed9fSAtsushi Murai } 36276bd0c0aSDoug Rabson 3635ca5389aSBrian Somers if ((FilterCheck(pip, filter) & A_DENY)) { 364710e9c29SBrian Somers if (logit) 365dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 3665ca5389aSBrian Somers #ifdef notdef 367944f7098SBrian Somers if (direction == 0) 368944f7098SBrian Somers IcmpError(pip, pri); 3695ca5389aSBrian Somers #endif 370af57ed9fSAtsushi Murai return (-1); 371af57ed9fSAtsushi Murai } else { 3725ca5389aSBrian Somers /* Check Keep Alive filter */ 373e43ebac1SBrian Somers if (logit) { 3741e991daaSBrian Somers if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) 375dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 3761e991daaSBrian Somers else 377dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 37853c9f6c0SAtsushi Murai } 379af57ed9fSAtsushi Murai return (pri); 380af57ed9fSAtsushi Murai } 381af57ed9fSAtsushi Murai } 382af57ed9fSAtsushi Murai 3835d9e6103SBrian Somers struct mbuf * 3845d9e6103SBrian Somers ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 3857a6f8720SBrian Somers { 386af57ed9fSAtsushi Murai int nb, nw; 387b6e82f33SBrian Somers struct tun_data tun; 3885d9e6103SBrian Somers struct ip *pip; 3895d9e6103SBrian Somers 3905d9e6103SBrian Somers if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 3915d9e6103SBrian Somers log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 3925d9e6103SBrian Somers mbuf_Free(bp); 3935d9e6103SBrian Somers return NULL; 3945d9e6103SBrian Somers } 395af57ed9fSAtsushi Murai 3966a6b4bbbSBrian Somers tun_fill_header(tun, AF_INET); 3975d9e6103SBrian Somers nb = mbuf_Length(bp); 3985d9e6103SBrian Somers mbuf_Read(bp, tun.data, nb); 399af57ed9fSAtsushi Murai 4005d9e6103SBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) 4015d9e6103SBrian Somers return NULL; 4026db75539SBrian Somers 4035d9e6103SBrian Somers pip = (struct ip *)tun.data; 4041e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 4051e991daaSBrian Somers bundle_StartIdleTimer(bundle); 4061e991daaSBrian Somers 4075828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4081e991daaSBrian Somers 40970ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 410faefde08SBrian Somers nw = write(bundle->dev.fd, &tun, nb); 411c4c4aaacSBrian Somers if (nw != nb) { 41257fd05c4SBrian Somers if (nw == -1) 413dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno)); 41457fd05c4SBrian Somers else 415dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 4166db75539SBrian Somers } 4175d9e6103SBrian Somers 4185d9e6103SBrian Somers return NULL; 419af57ed9fSAtsushi Murai } 420af57ed9fSAtsushi Murai 421af57ed9fSAtsushi Murai void 4225a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 423af57ed9fSAtsushi Murai { 424af57ed9fSAtsushi Murai struct mbuf *bp; 425af57ed9fSAtsushi Murai 4265a72b6edSBrian Somers if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0]) 4275a72b6edSBrian Somers log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 4285a72b6edSBrian Somers else { 4295d9e6103SBrian Somers /* 4305d9e6103SBrian Somers * We allocate an extra 6 bytes, four at the front and two at the end. 4315d9e6103SBrian Somers * This is an optimisation so that we need to do less work in 4325d9e6103SBrian Somers * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and 4335d9e6103SBrian Somers * appending in hdlc_LayerPush(). 4345d9e6103SBrian Somers */ 4355d9e6103SBrian Somers bp = mbuf_Alloc(count + 6, MB_IPQ); 4365d9e6103SBrian Somers bp->offset += 4; 4375d9e6103SBrian Somers bp->cnt -= 6; 43875240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, count); 4395a72b6edSBrian Somers mbuf_Enqueue(&ipcp->Queue[pri], bp); 4405a72b6edSBrian Somers } 441af57ed9fSAtsushi Murai } 442af57ed9fSAtsushi Murai 4436f8e9f0aSBrian Somers void 4445a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp) 4456f8e9f0aSBrian Somers { 4466f8e9f0aSBrian Somers struct mqueue *queue; 4476f8e9f0aSBrian Somers 4485a72b6edSBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 4496f8e9f0aSBrian Somers while (queue->top) 4506f8e9f0aSBrian Somers mbuf_Free(mbuf_Dequeue(queue)); 4516f8e9f0aSBrian Somers } 4526f8e9f0aSBrian Somers 45384b8a6ebSAtsushi Murai int 4545a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp) 45584b8a6ebSAtsushi Murai { 45684b8a6ebSAtsushi Murai struct mqueue *queue; 457f4768038SBrian Somers int result = 0; 458944f7098SBrian Somers 4595a72b6edSBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 460f4768038SBrian Somers result += queue->qlen; 46184b8a6ebSAtsushi Murai 462f4768038SBrian Somers return result; 4631ae349f5Scvs2svn } 4641ae349f5Scvs2svn 4653b0f8d2eSBrian Somers int 4665d9e6103SBrian Somers ip_PushPacket(struct link *l, struct bundle *bundle) 467af57ed9fSAtsushi Murai { 4685a72b6edSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 469af57ed9fSAtsushi Murai struct mqueue *queue; 470af57ed9fSAtsushi Murai struct mbuf *bp; 4715d9e6103SBrian Somers struct ip *pip; 472274e766cSBrian Somers int cnt; 473af57ed9fSAtsushi Murai 4745a72b6edSBrian Somers if (ipcp->fsm.state != ST_OPENED) 4753b0f8d2eSBrian Somers return 0; 4761e991daaSBrian Somers 4775a72b6edSBrian Somers for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--) 478af57ed9fSAtsushi Murai if (queue->top) { 479aad80d9fSBrian Somers bp = mbuf_Contiguous(mbuf_Dequeue(queue)); 480dd7e2610SBrian Somers cnt = mbuf_Length(bp); 4815d9e6103SBrian Somers pip = (struct ip *)MBUF_CTOP(bp); 4821e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 483ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 4845d9e6103SBrian Somers link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP); 4855a72b6edSBrian Somers ipcp_AddOutOctets(ipcp, cnt); 4863b0f8d2eSBrian Somers return 1; 487af57ed9fSAtsushi Murai } 4881e991daaSBrian Somers 4893b0f8d2eSBrian Somers return 0; 490af57ed9fSAtsushi Murai } 491