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 * 20972a1bcfSBrian Somers * $Id: ip.c,v 1.54 1998/11/10 00:32:39 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> 2792b09558SBrian Somers #ifdef __OpenBSD__ 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> 4375240ed1SBrian Somers #include <unistd.h> 4475240ed1SBrian Somers 451595bacdSBrian Somers #ifndef NOALIAS 461595bacdSBrian Somers #ifdef __OpenBSD__ 471595bacdSBrian Somers #include "alias.h" 481595bacdSBrian Somers #else 491595bacdSBrian Somers #include <alias.h> 501595bacdSBrian Somers #endif 511595bacdSBrian Somers #endif 52927145beSBrian Somers #include "mbuf.h" 53927145beSBrian Somers #include "log.h" 5475240ed1SBrian Somers #include "defs.h" 5575240ed1SBrian Somers #include "timer.h" 5675240ed1SBrian Somers #include "fsm.h" 57879ed6faSBrian Somers #include "lqr.h" 5875240ed1SBrian Somers #include "hdlc.h" 595828db6dSBrian Somers #include "throughput.h" 605828db6dSBrian Somers #include "iplist.h" 61eaa4df37SBrian Somers #include "slcompress.h" 6275240ed1SBrian Somers #include "ipcp.h" 631ae349f5Scvs2svn #include "filter.h" 642f786681SBrian Somers #include "descriptor.h" 6575240ed1SBrian Somers #include "lcp.h" 663b0f8d2eSBrian Somers #include "ccp.h" 673b0f8d2eSBrian Somers #include "link.h" 683b0f8d2eSBrian Somers #include "mp.h" 69972a1bcfSBrian Somers #ifndef NORADIUS 70972a1bcfSBrian Somers #include "radius.h" 71972a1bcfSBrian Somers #endif 727a6f8720SBrian Somers #include "bundle.h" 731ae349f5Scvs2svn #include "vjcomp.h" 746a6b4bbbSBrian Somers #include "tun.h" 7575240ed1SBrian Somers #include "ip.h" 76af57ed9fSAtsushi Murai 77b6e82f33SBrian Somers static const u_short interactive_ports[32] = { 7876bd0c0aSDoug Rabson 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7976bd0c0aSDoug Rabson 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 80af57ed9fSAtsushi Murai }; 81af57ed9fSAtsushi Murai 8276bd0c0aSDoug Rabson #define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 83af57ed9fSAtsushi Murai 84b6e82f33SBrian Somers static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 85af57ed9fSAtsushi Murai 86af57ed9fSAtsushi Murai static int 87944f7098SBrian Somers PortMatch(int op, u_short pport, u_short rport) 88af57ed9fSAtsushi Murai { 89af57ed9fSAtsushi Murai switch (op) { 90af57ed9fSAtsushi Murai case OP_EQ: 91af57ed9fSAtsushi Murai return (pport == rport); 92af57ed9fSAtsushi Murai case OP_GT: 93af57ed9fSAtsushi Murai return (pport > rport); 94af57ed9fSAtsushi Murai case OP_LT: 95af57ed9fSAtsushi Murai return (pport < rport); 96af57ed9fSAtsushi Murai default: 97af57ed9fSAtsushi Murai return (0); 98af57ed9fSAtsushi Murai } 99af57ed9fSAtsushi Murai } 100af57ed9fSAtsushi Murai 101af57ed9fSAtsushi Murai /* 102af57ed9fSAtsushi Murai * Check a packet against with defined filters 103af57ed9fSAtsushi Murai */ 104af57ed9fSAtsushi Murai static int 1055ca5389aSBrian Somers FilterCheck(struct ip *pip, struct filter *filter) 106af57ed9fSAtsushi Murai { 10763f98b41SBrian Somers int gotinfo, cproto, estab, syn, finrst, n, len, didname; 108af57ed9fSAtsushi Murai struct tcphdr *th; 109af57ed9fSAtsushi Murai struct udphdr *uh; 110af57ed9fSAtsushi Murai struct icmp *ih; 111af57ed9fSAtsushi Murai char *ptop; 112af57ed9fSAtsushi Murai u_short sport, dport; 1135ca5389aSBrian Somers struct filterent *fp = filter->rule; 1148390b576SBrian Somers char dbuff[100]; 115af57ed9fSAtsushi Murai 116af57ed9fSAtsushi Murai if (fp->action) { 11763f98b41SBrian Somers cproto = gotinfo = estab = syn = finrst = didname = 0; 118af57ed9fSAtsushi Murai sport = dport = 0; 119af57ed9fSAtsushi Murai for (n = 0; n < MAXFILTERS; n++) { 120af57ed9fSAtsushi Murai if (fp->action) { 121f1884650SAtsushi Murai /* permit fragments on in and out filter */ 1225ca5389aSBrian Somers if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 123f1884650SAtsushi Murai return (A_PERMIT); 1245ca5389aSBrian Somers 1258390b576SBrian Somers if (!didname) 126dd7e2610SBrian Somers log_Printf(LogDEBUG, "%s filter:\n", filter->name); 1278390b576SBrian Somers didname = 1; 1288390b576SBrian Somers 129a272e47dSBrian Somers if ((pip->ip_src.s_addr & fp->smask.s_addr) == 130a272e47dSBrian Somers (fp->saddr.s_addr & fp->smask.s_addr) && 131a272e47dSBrian Somers (pip->ip_dst.s_addr & fp->dmask.s_addr) == 132a272e47dSBrian Somers (fp->daddr.s_addr & fp->dmask.s_addr)) { 133af57ed9fSAtsushi Murai if (fp->proto) { 134af57ed9fSAtsushi Murai if (!gotinfo) { 135af57ed9fSAtsushi Murai ptop = (char *) pip + (pip->ip_hl << 2); 136af57ed9fSAtsushi Murai 137af57ed9fSAtsushi Murai switch (pip->ip_p) { 138af57ed9fSAtsushi Murai case IPPROTO_ICMP: 139944f7098SBrian Somers cproto = P_ICMP; 140944f7098SBrian Somers ih = (struct icmp *) ptop; 141944f7098SBrian Somers sport = ih->icmp_type; 14263f98b41SBrian Somers estab = syn = finrst = -1; 143dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1448390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 145af57ed9fSAtsushi Murai break; 146af57ed9fSAtsushi Murai case IPPROTO_UDP: 147eee772ecSBrian Somers case IPPROTO_IGMP: 148eee772ecSBrian Somers case IPPROTO_IPIP: 149944f7098SBrian Somers cproto = P_UDP; 150944f7098SBrian Somers uh = (struct udphdr *) ptop; 151944f7098SBrian Somers sport = ntohs(uh->uh_sport); 152944f7098SBrian Somers dport = ntohs(uh->uh_dport); 15363f98b41SBrian Somers estab = syn = finrst = -1; 154dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) 1558390b576SBrian Somers snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 1568390b576SBrian Somers sport, dport); 157af57ed9fSAtsushi Murai break; 158af57ed9fSAtsushi Murai case IPPROTO_TCP: 159944f7098SBrian Somers cproto = P_TCP; 160944f7098SBrian Somers th = (struct tcphdr *) ptop; 161944f7098SBrian Somers sport = ntohs(th->th_sport); 162944f7098SBrian Somers dport = ntohs(th->th_dport); 163af57ed9fSAtsushi Murai estab = (th->th_flags & TH_ACK); 16463f98b41SBrian Somers syn = (th->th_flags & TH_SYN); 16563f98b41SBrian Somers finrst = (th->th_flags & (TH_FIN|TH_RST)); 1662b81c773SBrian Somers if (log_IsKept(LogDEBUG)) { 1672b81c773SBrian Somers if (!estab) 1688390b576SBrian Somers snprintf(dbuff, sizeof dbuff, 1698390b576SBrian Somers "flags = %02x, sport = %d, dport = %d", 170927145beSBrian Somers th->th_flags, sport, dport); 1712b81c773SBrian Somers else 1722b81c773SBrian Somers *dbuff = '\0'; 1732b81c773SBrian Somers } 174af57ed9fSAtsushi Murai break; 175af57ed9fSAtsushi Murai default: 176af57ed9fSAtsushi Murai return (A_DENY); /* We'll block unknown type of packet */ 177af57ed9fSAtsushi Murai } 178dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 1798390b576SBrian Somers if (estab != -1) { 1808390b576SBrian Somers len = strlen(dbuff); 18163f98b41SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 18263f98b41SBrian Somers ", estab = %d, syn = %d, finrst = %d", 18363f98b41SBrian Somers estab, syn, finrst); 184af57ed9fSAtsushi Murai } 185dd7e2610SBrian Somers log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 1868390b576SBrian Somers filter_Proto2Nam(cproto), dbuff); 1878390b576SBrian Somers } 1888390b576SBrian Somers gotinfo = 1; 1898390b576SBrian Somers } 190dd7e2610SBrian Somers if (log_IsKept(LogDEBUG)) { 1918390b576SBrian Somers if (fp->opt.srcop != OP_NONE) { 1928390b576SBrian Somers snprintf(dbuff, sizeof dbuff, ", src %s %d", 1938390b576SBrian Somers filter_Op2Nam(fp->opt.srcop), fp->opt.srcport); 1948390b576SBrian Somers len = strlen(dbuff); 1958390b576SBrian Somers } else 1968390b576SBrian Somers len = 0; 1978390b576SBrian Somers if (fp->opt.dstop != OP_NONE) { 1988390b576SBrian Somers snprintf(dbuff + len, sizeof dbuff - len, 1998390b576SBrian Somers ", dst %s %d", filter_Op2Nam(fp->opt.dstop), 2008390b576SBrian Somers fp->opt.dstport); 2018390b576SBrian Somers } else if (!len) 2028390b576SBrian Somers *dbuff = '\0'; 2038390b576SBrian Somers 204dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, " 2058390b576SBrian Somers "check against proto %s%s, action = %s\n", 2068390b576SBrian Somers n, filter_Proto2Nam(fp->proto), 2078390b576SBrian Somers dbuff, filter_Action2Nam(fp->action)); 2088390b576SBrian Somers } 209927145beSBrian Somers 210af57ed9fSAtsushi Murai if (cproto == fp->proto) { 211af57ed9fSAtsushi Murai if ((fp->opt.srcop == OP_NONE || 21263f98b41SBrian Somers PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && 213af57ed9fSAtsushi Murai (fp->opt.dstop == OP_NONE || 21463f98b41SBrian Somers PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && 21563f98b41SBrian Somers (fp->opt.estab == 0 || estab) && 21663f98b41SBrian Somers (fp->opt.syn == 0 || syn) && 21763f98b41SBrian Somers (fp->opt.finrst == 0 || finrst)) { 218af57ed9fSAtsushi Murai return (fp->action); 219af57ed9fSAtsushi Murai } 220af57ed9fSAtsushi Murai } 221af57ed9fSAtsushi Murai } else { 222af57ed9fSAtsushi Murai /* Address is mached. Make a decision. */ 223dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 2248390b576SBrian Somers filter_Action2Nam(fp->action)); 225af57ed9fSAtsushi Murai return (fp->action); 226af57ed9fSAtsushi Murai } 2278390b576SBrian Somers } else 228dd7e2610SBrian Somers log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 229af57ed9fSAtsushi Murai } 230af57ed9fSAtsushi Murai fp++; 231af57ed9fSAtsushi Murai } 232af57ed9fSAtsushi Murai return (A_DENY); /* No rule is mached. Deny this packet */ 233af57ed9fSAtsushi Murai } 234af57ed9fSAtsushi Murai return (A_PERMIT); /* No rule is given. Permit this packet */ 235af57ed9fSAtsushi Murai } 236af57ed9fSAtsushi Murai 2375ca5389aSBrian Somers #ifdef notdef 238af57ed9fSAtsushi Murai static void 239944f7098SBrian Somers IcmpError(struct ip * pip, int code) 240af57ed9fSAtsushi Murai { 241af57ed9fSAtsushi Murai struct mbuf *bp; 242af57ed9fSAtsushi Murai 243af57ed9fSAtsushi Murai if (pip->ip_p != IPPROTO_ICMP) { 244dd7e2610SBrian Somers bp = mbuf_Alloc(cnt, MB_IPIN); 24575240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, cnt); 246dd7e2610SBrian Somers vj_SendFrame(bp); 2475828db6dSBrian Somers ipcp_AddOutOctets(cnt); 2481ae349f5Scvs2svn } 249af57ed9fSAtsushi Murai } 250af57ed9fSAtsushi Murai #endif 251af57ed9fSAtsushi Murai 252af57ed9fSAtsushi Murai /* 253af57ed9fSAtsushi Murai * For debugging aid. 254af57ed9fSAtsushi Murai */ 255af57ed9fSAtsushi Murai int 2565ca5389aSBrian Somers PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 257af57ed9fSAtsushi Murai { 258af57ed9fSAtsushi Murai struct ip *pip; 259af57ed9fSAtsushi Murai struct tcphdr *th; 260af57ed9fSAtsushi Murai struct udphdr *uh; 261af57ed9fSAtsushi Murai struct icmp *icmph; 262af57ed9fSAtsushi Murai char *ptop; 263af57ed9fSAtsushi Murai int mask, len, n; 264af57ed9fSAtsushi Murai int pri = PRI_NORMAL; 26555a8cdeaSBrian Somers int logit, loglen; 266d93d3a9cSBrian Somers char logbuf[200]; 267af57ed9fSAtsushi Murai 268dd7e2610SBrian Somers logit = log_IsKept(LogTCPIP) && filter->logok; 26955a8cdeaSBrian Somers loglen = 0; 270af57ed9fSAtsushi Murai 271af57ed9fSAtsushi Murai pip = (struct ip *) cp; 272af57ed9fSAtsushi Murai 27355a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 2745ca5389aSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 27555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 27655a8cdeaSBrian Somers } 277af57ed9fSAtsushi Murai ptop = (cp + (pip->ip_hl << 2)); 278af57ed9fSAtsushi Murai 279af57ed9fSAtsushi Murai switch (pip->ip_p) { 280af57ed9fSAtsushi Murai case IPPROTO_ICMP: 28155a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 282af57ed9fSAtsushi Murai icmph = (struct icmp *) ptop; 28355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 28455a8cdeaSBrian Somers "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 28555a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 28655a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 28755a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 28855a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 289af57ed9fSAtsushi Murai } 290af57ed9fSAtsushi Murai break; 291af57ed9fSAtsushi Murai case IPPROTO_UDP: 29255a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 293af57ed9fSAtsushi Murai uh = (struct udphdr *) ptop; 29455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 29555a8cdeaSBrian Somers "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 29655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 29755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 29855a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 29955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 300af57ed9fSAtsushi Murai } 301af57ed9fSAtsushi Murai break; 302eee772ecSBrian Somers case IPPROTO_IPIP: 303eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 304eee772ecSBrian Somers uh = (struct udphdr *) ptop; 305eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 306eee772ecSBrian Somers "IPIP: %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; 313eee772ecSBrian Somers case IPPROTO_IGMP: 314eee772ecSBrian Somers if (logit && loglen < sizeof logbuf) { 315eee772ecSBrian Somers uh = (struct udphdr *) ptop; 316eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 317eee772ecSBrian Somers "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 318eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 319eee772ecSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 320eee772ecSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 321eee772ecSBrian Somers loglen += strlen(logbuf + loglen); 322eee772ecSBrian Somers } 323eee772ecSBrian Somers break; 324af57ed9fSAtsushi Murai case IPPROTO_TCP: 325af57ed9fSAtsushi Murai th = (struct tcphdr *) ptop; 326af57ed9fSAtsushi Murai if (pip->ip_tos == IPTOS_LOWDELAY) 327af57ed9fSAtsushi Murai pri = PRI_FAST; 32876bd0c0aSDoug Rabson else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 329af57ed9fSAtsushi Murai if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 330af57ed9fSAtsushi Murai pri = PRI_FAST; 331af57ed9fSAtsushi Murai } 33255a8cdeaSBrian Somers if (logit && loglen < sizeof logbuf) { 333af57ed9fSAtsushi Murai len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 33455a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 33555a8cdeaSBrian Somers "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 33655a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 33755a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 33855a8cdeaSBrian Somers "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 33955a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 340af57ed9fSAtsushi Murai n = 0; 341af57ed9fSAtsushi Murai for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 34255a8cdeaSBrian Somers if (th->th_flags & mask) { 34355a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 34455a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 34555a8cdeaSBrian Somers } 346af57ed9fSAtsushi Murai n++; 347af57ed9fSAtsushi Murai } 34855a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 3493a2e4f62SBrian Somers " seq:%lx ack:%lx (%d/%d)", 3503a2e4f62SBrian Somers (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 35155a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 352af57ed9fSAtsushi Murai if ((th->th_flags & TH_SYN) && nb > 40) { 353af57ed9fSAtsushi Murai u_short *sp; 354af57ed9fSAtsushi Murai 355af57ed9fSAtsushi Murai ptop += 20; 356af57ed9fSAtsushi Murai sp = (u_short *) ptop; 35755a8cdeaSBrian Somers if (ntohs(sp[0]) == 0x0204) { 35855a8cdeaSBrian Somers snprintf(logbuf + loglen, sizeof logbuf - loglen, 35955a8cdeaSBrian Somers " MSS = %d", ntohs(sp[1])); 36055a8cdeaSBrian Somers loglen += strlen(logbuf + loglen); 36155a8cdeaSBrian Somers } 362af57ed9fSAtsushi Murai } 363af57ed9fSAtsushi Murai } 364af57ed9fSAtsushi Murai break; 365af57ed9fSAtsushi Murai } 36676bd0c0aSDoug Rabson 3675ca5389aSBrian Somers if ((FilterCheck(pip, filter) & A_DENY)) { 368710e9c29SBrian Somers if (logit) 369dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 3705ca5389aSBrian Somers #ifdef notdef 371944f7098SBrian Somers if (direction == 0) 372944f7098SBrian Somers IcmpError(pip, pri); 3735ca5389aSBrian Somers #endif 374af57ed9fSAtsushi Murai return (-1); 375af57ed9fSAtsushi Murai } else { 3765ca5389aSBrian Somers /* Check Keep Alive filter */ 377e43ebac1SBrian Somers if (logit) { 3781e991daaSBrian Somers if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) 379dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 3801e991daaSBrian Somers else 381dd7e2610SBrian Somers log_Printf(LogTCPIP, "%s\n", logbuf); 38253c9f6c0SAtsushi Murai } 383af57ed9fSAtsushi Murai return (pri); 384af57ed9fSAtsushi Murai } 385af57ed9fSAtsushi Murai } 386af57ed9fSAtsushi Murai 387af57ed9fSAtsushi Murai void 388dd7e2610SBrian Somers ip_Input(struct bundle *bundle, struct mbuf * bp) 3897a6f8720SBrian Somers { 390af57ed9fSAtsushi Murai u_char *cp; 391af57ed9fSAtsushi Murai struct mbuf *wp; 392af57ed9fSAtsushi Murai int nb, nw; 393b6e82f33SBrian Somers struct tun_data tun; 3941e991daaSBrian Somers struct ip *pip = (struct ip *)tun.data; 3953a2e4f62SBrian Somers #ifndef NOALIAS 396eee772ecSBrian Somers struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2)); 3973a2e4f62SBrian Somers #endif 398af57ed9fSAtsushi Murai 3996a6b4bbbSBrian Somers tun_fill_header(tun, AF_INET); 4006a6b4bbbSBrian Somers cp = tun.data; 401af57ed9fSAtsushi Murai nb = 0; 402927145beSBrian Somers for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 403512db555SBrian Somers if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 404a33b2ef7SBrian Somers log_Printf(LogWARN, "ip_Input: Packet too large (%d) - dropped\n", 405dd7e2610SBrian Somers mbuf_Length(bp)); 406dd7e2610SBrian Somers mbuf_Free(bp); 407512db555SBrian Somers return; 408512db555SBrian Somers } 40975240ed1SBrian Somers memcpy(cp, MBUF_CTOP(wp), wp->cnt); 410af57ed9fSAtsushi Murai cp += wp->cnt; 411af57ed9fSAtsushi Murai nb += wp->cnt; 412af57ed9fSAtsushi Murai } 413af57ed9fSAtsushi Murai 414b6e82f33SBrian Somers #ifndef NOALIAS 415615ad4f9SBrian Somers if (bundle->AliasEnabled && pip->ip_p != IPPROTO_IGMP && 416eee772ecSBrian Somers (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) { 417b6e82f33SBrian Somers struct tun_data *frag; 4186db75539SBrian Somers int iresult; 4196db75539SBrian Somers char *fptr; 4206db75539SBrian Somers 421615ad4f9SBrian Somers iresult = PacketAliasIn(tun.data, sizeof tun.data); 4226a6b4bbbSBrian Somers nb = ntohs(((struct ip *) tun.data)->ip_len); 4236db75539SBrian Somers 4246db75539SBrian Somers if (nb > MAX_MRU) { 425a33b2ef7SBrian Somers log_Printf(LogWARN, "ip_Input: Problem with IP header length\n"); 426dd7e2610SBrian Somers mbuf_Free(bp); 4276db75539SBrian Somers return; 428a9f484e5SJordan K. Hubbard } 4296db75539SBrian Somers if (iresult == PKT_ALIAS_OK 4306db75539SBrian Somers || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 4315ca5389aSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 432dd7e2610SBrian Somers mbuf_Free(bp); 433af57ed9fSAtsushi Murai return; 434af57ed9fSAtsushi Murai } 4351e991daaSBrian Somers 4361e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 4371e991daaSBrian Somers bundle_StartIdleTimer(bundle); 4381e991daaSBrian Somers 4395828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4406db75539SBrian Somers 4416a6b4bbbSBrian Somers nb = ntohs(((struct ip *) tun.data)->ip_len); 44270ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 443faefde08SBrian Somers nw = write(bundle->dev.fd, &tun, nb); 4446a596579SBrian Somers if (nw != nb) { 44557fd05c4SBrian Somers if (nw == -1) 446dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 44757fd05c4SBrian Somers strerror(errno)); 44857fd05c4SBrian Somers else 449dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 4506a596579SBrian Somers } 4516db75539SBrian Somers 4526db75539SBrian Somers if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 453615ad4f9SBrian Somers while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) { 454615ad4f9SBrian Somers PacketAliasFragmentIn(tun.data, fptr); 4556db75539SBrian Somers nb = ntohs(((struct ip *) fptr)->ip_len); 45670ee81ffSBrian Somers frag = (struct tun_data *) 45770ee81ffSBrian Somers ((char *)fptr - sizeof tun + sizeof tun.data); 45870ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 459faefde08SBrian Somers nw = write(bundle->dev.fd, frag, nb); 4606a596579SBrian Somers if (nw != nb) { 46157fd05c4SBrian Somers if (nw == -1) 462dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 46357fd05c4SBrian Somers strerror(errno)); 46457fd05c4SBrian Somers else 465dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 4666a596579SBrian Somers } 4676a6b4bbbSBrian Somers free(frag); 4686db75539SBrian Somers } 4696db75539SBrian Somers } 470944f7098SBrian Somers } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 4716a6b4bbbSBrian Somers nb = ntohs(((struct ip *) tun.data)->ip_len); 47270ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 4736a6b4bbbSBrian Somers frag = (struct tun_data *)malloc(nb); 4746a6b4bbbSBrian Somers if (frag == NULL) 475dd7e2610SBrian Somers log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n"); 4766db75539SBrian Somers else { 4776a6b4bbbSBrian Somers tun_fill_header(*frag, AF_INET); 47870ee81ffSBrian Somers memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 479615ad4f9SBrian Somers PacketAliasSaveFragment(frag->data); 4806db75539SBrian Somers } 4816db75539SBrian Somers } 482b6e82f33SBrian Somers } else 483b6e82f33SBrian Somers #endif /* #ifndef NOALIAS */ 484b6e82f33SBrian Somers { /* no aliasing */ 4855ca5389aSBrian Somers if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 486dd7e2610SBrian Somers mbuf_Free(bp); 4876db75539SBrian Somers return; 4886db75539SBrian Somers } 4891e991daaSBrian Somers 4901e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 4911e991daaSBrian Somers bundle_StartIdleTimer(bundle); 4921e991daaSBrian Somers 4935828db6dSBrian Somers ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 4941e991daaSBrian Somers 49570ee81ffSBrian Somers nb += sizeof tun - sizeof tun.data; 496faefde08SBrian Somers nw = write(bundle->dev.fd, &tun, nb); 497c4c4aaacSBrian Somers if (nw != nb) { 49857fd05c4SBrian Somers if (nw == -1) 499dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno)); 50057fd05c4SBrian Somers else 501dd7e2610SBrian Somers log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 5026db75539SBrian Somers } 503c4c4aaacSBrian Somers } 504dd7e2610SBrian Somers mbuf_Free(bp); 505af57ed9fSAtsushi Murai } 506af57ed9fSAtsushi Murai 507af57ed9fSAtsushi Murai void 5085a72b6edSBrian Somers ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 509af57ed9fSAtsushi Murai { 510af57ed9fSAtsushi Murai struct mbuf *bp; 511af57ed9fSAtsushi Murai 5125a72b6edSBrian Somers if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0]) 5135a72b6edSBrian Somers log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 5145a72b6edSBrian Somers else { 515dd7e2610SBrian Somers bp = mbuf_Alloc(count, MB_IPQ); 51675240ed1SBrian Somers memcpy(MBUF_CTOP(bp), ptr, count); 5175a72b6edSBrian Somers mbuf_Enqueue(&ipcp->Queue[pri], bp); 5185a72b6edSBrian Somers } 519af57ed9fSAtsushi Murai } 520af57ed9fSAtsushi Murai 5216f8e9f0aSBrian Somers void 5225a72b6edSBrian Somers ip_DeleteQueue(struct ipcp *ipcp) 5236f8e9f0aSBrian Somers { 5246f8e9f0aSBrian Somers struct mqueue *queue; 5256f8e9f0aSBrian Somers 5265a72b6edSBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 5276f8e9f0aSBrian Somers while (queue->top) 5286f8e9f0aSBrian Somers mbuf_Free(mbuf_Dequeue(queue)); 5296f8e9f0aSBrian Somers } 5306f8e9f0aSBrian Somers 53184b8a6ebSAtsushi Murai int 5325a72b6edSBrian Somers ip_QueueLen(struct ipcp *ipcp) 53384b8a6ebSAtsushi Murai { 53484b8a6ebSAtsushi Murai struct mqueue *queue; 535f4768038SBrian Somers int result = 0; 536944f7098SBrian Somers 5375a72b6edSBrian Somers for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 538f4768038SBrian Somers result += queue->qlen; 53984b8a6ebSAtsushi Murai 540f4768038SBrian Somers return result; 5411ae349f5Scvs2svn } 5421ae349f5Scvs2svn 5433b0f8d2eSBrian Somers int 544dd7e2610SBrian Somers ip_FlushPacket(struct link *l, struct bundle *bundle) 545af57ed9fSAtsushi Murai { 5465a72b6edSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 547af57ed9fSAtsushi Murai struct mqueue *queue; 548af57ed9fSAtsushi Murai struct mbuf *bp; 549274e766cSBrian Somers int cnt; 550af57ed9fSAtsushi Murai 5515a72b6edSBrian Somers if (ipcp->fsm.state != ST_OPENED) 5523b0f8d2eSBrian Somers return 0; 5531e991daaSBrian Somers 5545a72b6edSBrian Somers for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--) 555af57ed9fSAtsushi Murai if (queue->top) { 556dd7e2610SBrian Somers bp = mbuf_Dequeue(queue); 557af57ed9fSAtsushi Murai if (bp) { 5581e991daaSBrian Somers struct ip *pip = (struct ip *)MBUF_CTOP(bp); 5591e991daaSBrian Somers 560dd7e2610SBrian Somers cnt = mbuf_Length(bp); 5611e991daaSBrian Somers if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 562ab886ad0SBrian Somers bundle_StartIdleTimer(bundle); 5637d797fa7SBrian Somers vj_SendFrame(l, bp, bundle); 5645a72b6edSBrian Somers ipcp_AddOutOctets(ipcp, cnt); 5653b0f8d2eSBrian Somers return 1; 566af57ed9fSAtsushi Murai } 567af57ed9fSAtsushi Murai } 5681e991daaSBrian Somers 5693b0f8d2eSBrian Somers return 0; 570af57ed9fSAtsushi Murai } 571