1145554Sdarrenr/* $FreeBSD: stable/10/contrib/ipfilter/ip_fil.c 341804 2018-12-11 01:49:06Z cy $ */ 2145554Sdarrenr 3145554Sdarrenr/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5145554Sdarrenr * 6145554Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7255332Scy * 8255332Scy * $Id$ 9145554Sdarrenr */ 10145554Sdarrenr#if !defined(lint) 11145554Sdarrenrstatic const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 12255332Scystatic const char rcsid[] = "@(#)$Id$"; 13145554Sdarrenr#endif 14145554Sdarrenr 15255332Scy#include "ipf.h" 16145554Sdarrenr#include "md5.h" 17255332Scy#include "ipt.h" 18145554Sdarrenr 19255332Scyipf_main_softc_t ipfmain; 20145554Sdarrenr 21145554Sdarrenrstatic struct ifnet **ifneta = NULL; 22145554Sdarrenrstatic int nifs = 0; 23145554Sdarrenr 24255332Scystruct rtentry; 25255332Scy 26255332Scystatic void ipf_setifpaddr __P((struct ifnet *, char *)); 27145554Sdarrenrvoid init_ifp __P((void)); 28145554Sdarrenr#if defined(__sgi) && (IRIX < 60500) 29145554Sdarrenrstatic int no_output __P((struct ifnet *, struct mbuf *, 30145554Sdarrenr struct sockaddr *)); 31145554Sdarrenrstatic int write_output __P((struct ifnet *, struct mbuf *, 32145554Sdarrenr struct sockaddr *)); 33145554Sdarrenr#else 34145554Sdarrenr# if TRU64 >= 1885 35145554Sdarrenrstatic int no_output __P((struct ifnet *, struct mbuf *, 36145554Sdarrenr struct sockaddr *, struct rtentry *, char *)); 37145554Sdarrenrstatic int write_output __P((struct ifnet *, struct mbuf *, 38145554Sdarrenr struct sockaddr *, struct rtentry *, char *)); 39145554Sdarrenr# else 40145554Sdarrenrstatic int no_output __P((struct ifnet *, struct mbuf *, 41145554Sdarrenr struct sockaddr *, struct rtentry *)); 42145554Sdarrenrstatic int write_output __P((struct ifnet *, struct mbuf *, 43145554Sdarrenr struct sockaddr *, struct rtentry *)); 44145554Sdarrenr# endif 45145554Sdarrenr#endif 46145554Sdarrenr 47145554Sdarrenr 48255332Scyint 49255332Scyipfattach(softc) 50255332Scy ipf_main_softc_t *softc; 51145554Sdarrenr{ 52145554Sdarrenr return 0; 53145554Sdarrenr} 54145554Sdarrenr 55145554Sdarrenr 56255332Scyint 57255332Scyipfdetach(softc) 58255332Scy ipf_main_softc_t *softc; 59145554Sdarrenr{ 60145554Sdarrenr return 0; 61145554Sdarrenr} 62145554Sdarrenr 63145554Sdarrenr 64145554Sdarrenr/* 65145554Sdarrenr * Filter ioctl interface. 66145554Sdarrenr */ 67255332Scyint 68255332Scyipfioctl(softc, dev, cmd, data, mode) 69255332Scy ipf_main_softc_t *softc; 70255332Scy int dev; 71255332Scy ioctlcmd_t cmd; 72255332Scy caddr_t data; 73255332Scy int mode; 74145554Sdarrenr{ 75170268Sdarrenr int error = 0, unit = 0, uid; 76145554Sdarrenr 77170268Sdarrenr uid = getuid(); 78145554Sdarrenr unit = dev; 79145554Sdarrenr 80145554Sdarrenr SPL_NET(s); 81145554Sdarrenr 82255332Scy error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL); 83170268Sdarrenr if (error != -1) { 84145554Sdarrenr SPL_X(s); 85145554Sdarrenr return error; 86145554Sdarrenr } 87145554Sdarrenr SPL_X(s); 88145554Sdarrenr return error; 89145554Sdarrenr} 90145554Sdarrenr 91145554Sdarrenr 92255332Scyvoid 93255332Scyipf_forgetifp(softc, ifp) 94255332Scy ipf_main_softc_t *softc; 95255332Scy void *ifp; 96145554Sdarrenr{ 97145554Sdarrenr register frentry_t *f; 98145554Sdarrenr 99255332Scy WRITE_ENTER(&softc->ipf_mutex); 100255332Scy for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL); 101255332Scy f = f->fr_next) 102145554Sdarrenr if (f->fr_ifa == ifp) 103145554Sdarrenr f->fr_ifa = (void *)-1; 104255332Scy for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL); 105255332Scy f = f->fr_next) 106145554Sdarrenr if (f->fr_ifa == ifp) 107145554Sdarrenr f->fr_ifa = (void *)-1; 108255332Scy for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL); 109255332Scy f = f->fr_next) 110145554Sdarrenr if (f->fr_ifa == ifp) 111145554Sdarrenr f->fr_ifa = (void *)-1; 112255332Scy for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL); 113255332Scy f = f->fr_next) 114145554Sdarrenr if (f->fr_ifa == ifp) 115145554Sdarrenr f->fr_ifa = (void *)-1; 116255332Scy RWLOCK_EXIT(&softc->ipf_mutex); 117255332Scy ipf_nat_sync(softc, ifp); 118255332Scy ipf_lookup_sync(softc, ifp); 119145554Sdarrenr} 120145554Sdarrenr 121145554Sdarrenr 122255332Scystatic int 123145554Sdarrenr#if defined(__sgi) && (IRIX < 60500) 124255332Scyno_output(ifp, m, s) 125145554Sdarrenr#else 126145554Sdarrenr# if TRU64 >= 1885 127255332Scyno_output (ifp, m, s, rt, cp) 128255332Scy char *cp; 129145554Sdarrenr# else 130255332Scyno_output(ifp, m, s, rt) 131145554Sdarrenr# endif 132255332Scy struct rtentry *rt; 133145554Sdarrenr#endif 134255332Scy struct ifnet *ifp; 135255332Scy struct mbuf *m; 136255332Scy struct sockaddr *s; 137145554Sdarrenr{ 138145554Sdarrenr return 0; 139145554Sdarrenr} 140145554Sdarrenr 141145554Sdarrenr 142255332Scystatic int 143145554Sdarrenr#if defined(__sgi) && (IRIX < 60500) 144255332Scywrite_output(ifp, m, s) 145145554Sdarrenr#else 146145554Sdarrenr# if TRU64 >= 1885 147255332Scywrite_output (ifp, m, s, rt, cp) 148255332Scy char *cp; 149145554Sdarrenr# else 150255332Scywrite_output(ifp, m, s, rt) 151145554Sdarrenr# endif 152255332Scy struct rtentry *rt; 153145554Sdarrenr#endif 154255332Scy struct ifnet *ifp; 155255332Scy struct mbuf *m; 156255332Scy struct sockaddr *s; 157145554Sdarrenr{ 158145554Sdarrenr char fname[32]; 159145554Sdarrenr mb_t *mb; 160145554Sdarrenr ip_t *ip; 161145554Sdarrenr int fd; 162145554Sdarrenr 163145554Sdarrenr mb = (mb_t *)m; 164145554Sdarrenr ip = MTOD(mb, ip_t *); 165145554Sdarrenr 166145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 167145554Sdarrenr (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 168145554Sdarrenr (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 169145554Sdarrenr sprintf(fname, "/tmp/%s", ifp->if_xname); 170145554Sdarrenr#else 171145554Sdarrenr sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 172145554Sdarrenr#endif 173145554Sdarrenr fd = open(fname, O_WRONLY|O_APPEND); 174145554Sdarrenr if (fd == -1) { 175145554Sdarrenr perror("open"); 176145554Sdarrenr return -1; 177145554Sdarrenr } 178145554Sdarrenr write(fd, (char *)ip, ntohs(ip->ip_len)); 179145554Sdarrenr close(fd); 180145554Sdarrenr return 0; 181145554Sdarrenr} 182145554Sdarrenr 183145554Sdarrenr 184255332Scystatic void 185255332Scyipf_setifpaddr(ifp, addr) 186255332Scy struct ifnet *ifp; 187255332Scy char *addr; 188145554Sdarrenr{ 189145554Sdarrenr#ifdef __sgi 190145554Sdarrenr struct in_ifaddr *ifa; 191145554Sdarrenr#else 192145554Sdarrenr struct ifaddr *ifa; 193145554Sdarrenr#endif 194145554Sdarrenr 195145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 196145554Sdarrenr if (ifp->if_addrlist.tqh_first != NULL) 197145554Sdarrenr#else 198145554Sdarrenr# ifdef __sgi 199145554Sdarrenr if (ifp->in_ifaddr != NULL) 200145554Sdarrenr# else 201145554Sdarrenr if (ifp->if_addrlist != NULL) 202145554Sdarrenr# endif 203145554Sdarrenr#endif 204145554Sdarrenr return; 205145554Sdarrenr 206145554Sdarrenr ifa = (struct ifaddr *)malloc(sizeof(*ifa)); 207145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 208145554Sdarrenr ifp->if_addrlist.tqh_first = ifa; 209145554Sdarrenr#else 210145554Sdarrenr# ifdef __sgi 211145554Sdarrenr ifp->in_ifaddr = ifa; 212145554Sdarrenr# else 213145554Sdarrenr ifp->if_addrlist = ifa; 214145554Sdarrenr# endif 215145554Sdarrenr#endif 216145554Sdarrenr 217145554Sdarrenr if (ifa != NULL) { 218145554Sdarrenr struct sockaddr_in *sin; 219145554Sdarrenr 220145554Sdarrenr#ifdef __sgi 221145554Sdarrenr sin = (struct sockaddr_in *)&ifa->ia_addr; 222145554Sdarrenr#else 223145554Sdarrenr sin = (struct sockaddr_in *)&ifa->ifa_addr; 224145554Sdarrenr#endif 225255332Scy#ifdef USE_INET6 226255332Scy if (index(addr, ':') != NULL) { 227255332Scy struct sockaddr_in6 *sin6; 228255332Scy 229255332Scy sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; 230255332Scy sin6->sin6_family = AF_INET6; 231255761Scy /* Abort if bad address. */ 232255761Scy switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr)) 233255761Scy { 234255761Scy case 1: 235255761Scy break; 236255761Scy case -1: 237255761Scy perror("inet_pton"); 238255761Scy abort(); 239255761Scy break; 240255761Scy default: 241255761Scy abort(); 242255761Scy break; 243255761Scy } 244255332Scy } else 245255332Scy#endif 246255332Scy { 247255332Scy sin->sin_family = AF_INET; 248255332Scy sin->sin_addr.s_addr = inet_addr(addr); 249255332Scy if (sin->sin_addr.s_addr == 0) 250255332Scy abort(); 251255332Scy } 252145554Sdarrenr } 253145554Sdarrenr} 254145554Sdarrenr 255255332Scystruct ifnet * 256255332Scyget_unit(name, family) 257255332Scy char *name; 258255332Scy int family; 259145554Sdarrenr{ 260145554Sdarrenr struct ifnet *ifp, **ifpp, **old_ifneta; 261145554Sdarrenr char *addr; 262145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 263145554Sdarrenr (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 264145554Sdarrenr (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 265145554Sdarrenr 266255332Scy if (!*name) 267255332Scy return NULL; 268255332Scy 269145554Sdarrenr if (name == NULL) 270145554Sdarrenr name = "anon0"; 271145554Sdarrenr 272145554Sdarrenr addr = strchr(name, '='); 273145554Sdarrenr if (addr != NULL) 274145554Sdarrenr *addr++ = '\0'; 275145554Sdarrenr 276145554Sdarrenr for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 277145554Sdarrenr if (!strcmp(name, ifp->if_xname)) { 278145554Sdarrenr if (addr != NULL) 279255332Scy ipf_setifpaddr(ifp, addr); 280145554Sdarrenr return ifp; 281145554Sdarrenr } 282145554Sdarrenr } 283145554Sdarrenr#else 284145554Sdarrenr char *s, ifname[LIFNAMSIZ+1]; 285145554Sdarrenr 286145554Sdarrenr if (name == NULL) 287145554Sdarrenr name = "anon0"; 288145554Sdarrenr 289145554Sdarrenr addr = strchr(name, '='); 290145554Sdarrenr if (addr != NULL) 291145554Sdarrenr *addr++ = '\0'; 292145554Sdarrenr 293145554Sdarrenr for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 294255332Scy COPYIFNAME(family, ifp, ifname); 295145554Sdarrenr if (!strcmp(name, ifname)) { 296145554Sdarrenr if (addr != NULL) 297255332Scy ipf_setifpaddr(ifp, addr); 298145554Sdarrenr return ifp; 299145554Sdarrenr } 300145554Sdarrenr } 301145554Sdarrenr#endif 302145554Sdarrenr 303145554Sdarrenr if (!ifneta) { 304145554Sdarrenr ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); 305145554Sdarrenr if (!ifneta) 306145554Sdarrenr return NULL; 307145554Sdarrenr ifneta[1] = NULL; 308145554Sdarrenr ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); 309145554Sdarrenr if (!ifneta[0]) { 310145554Sdarrenr free(ifneta); 311145554Sdarrenr return NULL; 312145554Sdarrenr } 313145554Sdarrenr nifs = 1; 314145554Sdarrenr } else { 315145554Sdarrenr old_ifneta = ifneta; 316145554Sdarrenr nifs++; 317145554Sdarrenr ifneta = (struct ifnet **)realloc(ifneta, 318145554Sdarrenr (nifs + 1) * sizeof(ifp)); 319145554Sdarrenr if (!ifneta) { 320145554Sdarrenr free(old_ifneta); 321145554Sdarrenr nifs = 0; 322145554Sdarrenr return NULL; 323145554Sdarrenr } 324145554Sdarrenr ifneta[nifs] = NULL; 325145554Sdarrenr ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); 326145554Sdarrenr if (!ifneta[nifs - 1]) { 327145554Sdarrenr nifs--; 328145554Sdarrenr return NULL; 329145554Sdarrenr } 330145554Sdarrenr } 331145554Sdarrenr ifp = ifneta[nifs - 1]; 332145554Sdarrenr 333172776Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 334172776Sdarrenr TAILQ_INIT(&ifp->if_addrlist); 335172776Sdarrenr#endif 336145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 337145554Sdarrenr (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 338145554Sdarrenr (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 339145554Sdarrenr (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); 340145554Sdarrenr#else 341255332Scy s = name + strlen(name) - 1; 342255332Scy for (; s > name; s--) { 343255332Scy if (!ISDIGIT(*s)) { 344255332Scy s++; 345255332Scy break; 346255332Scy } 347255332Scy } 348255332Scy 349255332Scy if ((s > name) && (*s != 0) && ISDIGIT(*s)) { 350145554Sdarrenr ifp->if_unit = atoi(s); 351145554Sdarrenr ifp->if_name = (char *)malloc(s - name + 1); 352145554Sdarrenr (void) strncpy(ifp->if_name, name, s - name); 353145554Sdarrenr ifp->if_name[s - name] = '\0'; 354145554Sdarrenr } else { 355145554Sdarrenr ifp->if_name = strdup(name); 356145554Sdarrenr ifp->if_unit = -1; 357145554Sdarrenr } 358145554Sdarrenr#endif 359170268Sdarrenr ifp->if_output = (void *)no_output; 360145554Sdarrenr 361145554Sdarrenr if (addr != NULL) { 362255332Scy ipf_setifpaddr(ifp, addr); 363145554Sdarrenr } 364145554Sdarrenr 365145554Sdarrenr return ifp; 366145554Sdarrenr} 367145554Sdarrenr 368145554Sdarrenr 369255332Scychar * 370255332Scyget_ifname(ifp) 371255332Scy struct ifnet *ifp; 372145554Sdarrenr{ 373145554Sdarrenr static char ifname[LIFNAMSIZ]; 374145554Sdarrenr 375145554Sdarrenr#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ 376145554Sdarrenr (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 377145554Sdarrenr sprintf(ifname, "%s", ifp->if_xname); 378145554Sdarrenr#else 379255332Scy if (ifp->if_unit != -1) 380255332Scy sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); 381255332Scy else 382255332Scy strcpy(ifname, ifp->if_name); 383145554Sdarrenr#endif 384145554Sdarrenr return ifname; 385145554Sdarrenr} 386145554Sdarrenr 387145554Sdarrenr 388145554Sdarrenr 389255332Scyvoid 390255332Scyinit_ifp() 391145554Sdarrenr{ 392145554Sdarrenr struct ifnet *ifp, **ifpp; 393145554Sdarrenr char fname[32]; 394145554Sdarrenr int fd; 395145554Sdarrenr 396145554Sdarrenr#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 397145554Sdarrenr (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 398145554Sdarrenr (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 399145554Sdarrenr for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 400170268Sdarrenr ifp->if_output = (void *)write_output; 401145554Sdarrenr sprintf(fname, "/tmp/%s", ifp->if_xname); 402145554Sdarrenr fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 403145554Sdarrenr if (fd == -1) 404145554Sdarrenr perror("open"); 405145554Sdarrenr else 406145554Sdarrenr close(fd); 407145554Sdarrenr } 408145554Sdarrenr#else 409145554Sdarrenr 410145554Sdarrenr for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 411255332Scy ifp->if_output = (void *)write_output; 412145554Sdarrenr sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 413145554Sdarrenr fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 414145554Sdarrenr if (fd == -1) 415145554Sdarrenr perror("open"); 416145554Sdarrenr else 417145554Sdarrenr close(fd); 418145554Sdarrenr } 419145554Sdarrenr#endif 420145554Sdarrenr} 421145554Sdarrenr 422145554Sdarrenr 423255332Scyint 424255332Scyipf_fastroute(m, mpp, fin, fdp) 425255332Scy mb_t *m, **mpp; 426255332Scy fr_info_t *fin; 427255332Scy frdest_t *fdp; 428145554Sdarrenr{ 429255332Scy struct ifnet *ifp; 430145554Sdarrenr ip_t *ip = fin->fin_ip; 431255332Scy frdest_t node; 432161357Sguido int error = 0; 433161357Sguido frentry_t *fr; 434161357Sguido void *sifp; 435255332Scy int sout; 436145554Sdarrenr 437255332Scy sifp = fin->fin_ifp; 438255332Scy sout = fin->fin_out; 439161357Sguido fr = fin->fin_fr; 440145554Sdarrenr ip->ip_sum = 0; 441161357Sguido 442255332Scy if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && 443255332Scy (fdp->fd_type == FRD_DSTLIST)) { 444255332Scy bzero(&node, sizeof(node)); 445255332Scy ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node); 446255332Scy fdp = &node; 447255332Scy } 448255332Scy ifp = fdp->fd_ptr; 449255332Scy 450255332Scy if (ifp == NULL) 451255332Scy return 0; /* no routing table out here */ 452255332Scy 453161357Sguido if (fin->fin_out == 0) { 454161357Sguido fin->fin_ifp = ifp; 455161357Sguido fin->fin_out = 1; 456255332Scy (void) ipf_acctpkt(fin, NULL); 457161357Sguido fin->fin_fr = NULL; 458161357Sguido if (!fr || !(fr->fr_flags & FR_RETMASK)) { 459161357Sguido u_32_t pass; 460161357Sguido 461255332Scy (void) ipf_state_check(fin, &pass); 462161357Sguido } 463161357Sguido 464255332Scy switch (ipf_nat_checkout(fin, NULL)) 465161357Sguido { 466161357Sguido case 0 : 467161357Sguido break; 468161357Sguido case 1 : 469161357Sguido ip->ip_sum = 0; 470161357Sguido break; 471161357Sguido case -1 : 472161357Sguido error = -1; 473161357Sguido goto done; 474161357Sguido break; 475161357Sguido } 476161357Sguido 477161357Sguido } 478161357Sguido 479255332Scy m->mb_ifp = ifp; 480255332Scy printpacket(fin->fin_out, m); 481255332Scy 482145554Sdarrenr (*ifp->if_output)(ifp, (void *)m, NULL, 0); 483161357Sguidodone: 484255332Scy fin->fin_ifp = sifp; 485255332Scy fin->fin_out = sout; 486161357Sguido return error; 487145554Sdarrenr} 488145554Sdarrenr 489145554Sdarrenr 490255332Scyint 491255332Scyipf_send_reset(fin) 492255332Scy fr_info_t *fin; 493145554Sdarrenr{ 494255332Scy ipfkverbose("- TCP RST sent\n"); 495145554Sdarrenr return 0; 496145554Sdarrenr} 497145554Sdarrenr 498145554Sdarrenr 499255332Scyint 500255332Scyipf_send_icmp_err(type, fin, dst) 501255332Scy int type; 502255332Scy fr_info_t *fin; 503255332Scy int dst; 504145554Sdarrenr{ 505255332Scy ipfkverbose("- ICMP unreachable sent\n"); 506145554Sdarrenr return 0; 507145554Sdarrenr} 508145554Sdarrenr 509145554Sdarrenr 510255332Scyvoid 511255332Scym_freem(m) 512255332Scy mb_t *m; 513145554Sdarrenr{ 514145554Sdarrenr return; 515145554Sdarrenr} 516145554Sdarrenr 517145554Sdarrenr 518255332Scyvoid 519255332Scym_copydata(m, off, len, cp) 520255332Scy mb_t *m; 521255332Scy int off, len; 522255332Scy caddr_t cp; 523145554Sdarrenr{ 524145554Sdarrenr bcopy((char *)m + off, cp, len); 525145554Sdarrenr} 526145554Sdarrenr 527145554Sdarrenr 528255332Scyint 529255332Scyipfuiomove(buf, len, rwflag, uio) 530255332Scy caddr_t buf; 531255332Scy int len, rwflag; 532255332Scy struct uio *uio; 533145554Sdarrenr{ 534145554Sdarrenr int left, ioc, num, offset; 535145554Sdarrenr struct iovec *io; 536145554Sdarrenr char *start; 537145554Sdarrenr 538145554Sdarrenr if (rwflag == UIO_READ) { 539145554Sdarrenr left = len; 540145554Sdarrenr ioc = 0; 541145554Sdarrenr 542145554Sdarrenr offset = uio->uio_offset; 543145554Sdarrenr 544145554Sdarrenr while ((left > 0) && (ioc < uio->uio_iovcnt)) { 545145554Sdarrenr io = uio->uio_iov + ioc; 546145554Sdarrenr num = io->iov_len; 547145554Sdarrenr if (num > left) 548145554Sdarrenr num = left; 549145554Sdarrenr start = (char *)io->iov_base + offset; 550145554Sdarrenr if (start > (char *)io->iov_base + io->iov_len) { 551145554Sdarrenr offset -= io->iov_len; 552145554Sdarrenr ioc++; 553145554Sdarrenr continue; 554145554Sdarrenr } 555145554Sdarrenr bcopy(buf, start, num); 556145554Sdarrenr uio->uio_resid -= num; 557145554Sdarrenr uio->uio_offset += num; 558145554Sdarrenr left -= num; 559145554Sdarrenr if (left > 0) 560145554Sdarrenr ioc++; 561145554Sdarrenr } 562145554Sdarrenr if (left > 0) 563145554Sdarrenr return EFAULT; 564145554Sdarrenr } 565145554Sdarrenr return 0; 566145554Sdarrenr} 567145554Sdarrenr 568145554Sdarrenr 569255332Scyu_32_t 570255332Scyipf_newisn(fin) 571255332Scy fr_info_t *fin; 572145554Sdarrenr{ 573145554Sdarrenr static int iss_seq_off = 0; 574145554Sdarrenr u_char hash[16]; 575145554Sdarrenr u_32_t newiss; 576145554Sdarrenr MD5_CTX ctx; 577145554Sdarrenr 578145554Sdarrenr /* 579145554Sdarrenr * Compute the base value of the ISS. It is a hash 580145554Sdarrenr * of (saddr, sport, daddr, dport, secret). 581145554Sdarrenr */ 582145554Sdarrenr MD5Init(&ctx); 583145554Sdarrenr 584145554Sdarrenr MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 585145554Sdarrenr sizeof(fin->fin_fi.fi_src)); 586145554Sdarrenr MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 587145554Sdarrenr sizeof(fin->fin_fi.fi_dst)); 588145554Sdarrenr MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 589145554Sdarrenr 590145554Sdarrenr /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ 591145554Sdarrenr 592145554Sdarrenr MD5Final(hash, &ctx); 593145554Sdarrenr 594145554Sdarrenr memcpy(&newiss, hash, sizeof(newiss)); 595145554Sdarrenr 596145554Sdarrenr /* 597145554Sdarrenr * Now increment our "timer", and add it in to 598145554Sdarrenr * the computed value. 599145554Sdarrenr * 600145554Sdarrenr * XXX Use `addin'? 601145554Sdarrenr * XXX TCP_ISSINCR too large to use? 602145554Sdarrenr */ 603145554Sdarrenr iss_seq_off += 0x00010000; 604145554Sdarrenr newiss += iss_seq_off; 605145554Sdarrenr return newiss; 606145554Sdarrenr} 607145554Sdarrenr 608145554Sdarrenr 609145554Sdarrenr/* ------------------------------------------------------------------------ */ 610255332Scy/* Function: ipf_nextipid */ 611145554Sdarrenr/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 612145554Sdarrenr/* Parameters: fin(I) - pointer to packet information */ 613145554Sdarrenr/* */ 614145554Sdarrenr/* Returns the next IPv4 ID to use for this packet. */ 615145554Sdarrenr/* ------------------------------------------------------------------------ */ 616255332ScyINLINE u_short 617255332Scyipf_nextipid(fin) 618255332Scy fr_info_t *fin; 619145554Sdarrenr{ 620145554Sdarrenr static u_short ipid = 0; 621255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 622145554Sdarrenr u_short id; 623145554Sdarrenr 624255332Scy MUTEX_ENTER(&softc->ipf_rw); 625255332Scy if (fin->fin_pktnum != 0) { 626255332Scy /* 627255332Scy * The -1 is for aligned test results. 628255332Scy */ 629255332Scy id = (fin->fin_pktnum - 1) & 0xffff; 630255332Scy } else { 631255332Scy } 632255332Scy id = ipid++; 633255332Scy MUTEX_EXIT(&softc->ipf_rw); 634145554Sdarrenr 635145554Sdarrenr return id; 636145554Sdarrenr} 637145554Sdarrenr 638145554Sdarrenr 639255332ScyINLINE int 640255332Scyipf_checkv4sum(fin) 641255332Scy fr_info_t *fin; 642145554Sdarrenr{ 643255332Scy 644255332Scy if (fin->fin_flx & FI_SHORT) 645255332Scy return 1; 646255332Scy 647255332Scy if (ipf_checkl4sum(fin) == -1) { 648145554Sdarrenr fin->fin_flx |= FI_BAD; 649255332Scy return -1; 650255332Scy } 651255332Scy return 0; 652145554Sdarrenr} 653145554Sdarrenr 654145554Sdarrenr 655145554Sdarrenr#ifdef USE_INET6 656255332ScyINLINE int 657255332Scyipf_checkv6sum(fin) 658255332Scy fr_info_t *fin; 659145554Sdarrenr{ 660255332Scy if (fin->fin_flx & FI_SHORT) 661255332Scy return 1; 662255332Scy 663255332Scy if (ipf_checkl4sum(fin) == -1) { 664145554Sdarrenr fin->fin_flx |= FI_BAD; 665255332Scy return -1; 666255332Scy } 667255332Scy return 0; 668145554Sdarrenr} 669145554Sdarrenr#endif 670145554Sdarrenr 671145554Sdarrenr 672255332Scy#if 0 673145554Sdarrenr/* 674145554Sdarrenr * See above for description, except that all addressing is in user space. 675145554Sdarrenr */ 676255332Scyint 677255332Scycopyoutptr(softc, src, dst, size) 678255332Scy void *src, *dst; 679255332Scy size_t size; 680145554Sdarrenr{ 681145554Sdarrenr caddr_t ca; 682145554Sdarrenr 683145554Sdarrenr bcopy(dst, (char *)&ca, sizeof(ca)); 684145554Sdarrenr bcopy(src, ca, size); 685145554Sdarrenr return 0; 686145554Sdarrenr} 687145554Sdarrenr 688145554Sdarrenr 689145554Sdarrenr/* 690145554Sdarrenr * See above for description, except that all addressing is in user space. 691145554Sdarrenr */ 692255332Scyint 693255332Scycopyinptr(src, dst, size) 694255332Scy void *src, *dst; 695255332Scy size_t size; 696145554Sdarrenr{ 697145554Sdarrenr caddr_t ca; 698145554Sdarrenr 699145554Sdarrenr bcopy(src, (char *)&ca, sizeof(ca)); 700145554Sdarrenr bcopy(ca, dst, size); 701145554Sdarrenr return 0; 702145554Sdarrenr} 703255332Scy#endif 704145554Sdarrenr 705145554Sdarrenr 706145554Sdarrenr/* 707145554Sdarrenr * return the first IP Address associated with an interface 708145554Sdarrenr */ 709255332Scyint 710255332Scyipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) 711255332Scy ipf_main_softc_t *softc; 712255332Scy int v, atype; 713255332Scy void *ifptr; 714255332Scy i6addr_t *inp, *inpmask; 715145554Sdarrenr{ 716145554Sdarrenr struct ifnet *ifp = ifptr; 717145554Sdarrenr#ifdef __sgi 718145554Sdarrenr struct in_ifaddr *ifa; 719145554Sdarrenr#else 720145554Sdarrenr struct ifaddr *ifa; 721145554Sdarrenr#endif 722145554Sdarrenr 723145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 724145554Sdarrenr ifa = ifp->if_addrlist.tqh_first; 725145554Sdarrenr#else 726145554Sdarrenr# ifdef __sgi 727145554Sdarrenr ifa = (struct in_ifaddr *)ifp->in_ifaddr; 728145554Sdarrenr# else 729145554Sdarrenr ifa = ifp->if_addrlist; 730145554Sdarrenr# endif 731145554Sdarrenr#endif 732145554Sdarrenr if (ifa != NULL) { 733255332Scy if (v == 4) { 734255332Scy struct sockaddr_in *sin, mask; 735145554Sdarrenr 736255332Scy mask.sin_addr.s_addr = 0xffffffff; 737145554Sdarrenr 738145554Sdarrenr#ifdef __sgi 739255332Scy sin = (struct sockaddr_in *)&ifa->ia_addr; 740145554Sdarrenr#else 741255332Scy sin = (struct sockaddr_in *)&ifa->ifa_addr; 742145554Sdarrenr#endif 743145554Sdarrenr 744255332Scy return ipf_ifpfillv4addr(atype, sin, &mask, 745255332Scy &inp->in4, &inpmask->in4); 746255332Scy } 747255332Scy#ifdef USE_INET6 748255332Scy if (v == 6) { 749255332Scy struct sockaddr_in6 *sin6, mask; 750255332Scy 751255332Scy sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; 752255332Scy ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff; 753255332Scy ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff; 754255332Scy ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff; 755255332Scy ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff; 756255332Scy return ipf_ifpfillv6addr(atype, sin6, &mask, 757255332Scy inp, inpmask); 758255332Scy } 759255332Scy#endif 760145554Sdarrenr } 761145554Sdarrenr return 0; 762145554Sdarrenr} 763170268Sdarrenr 764170268Sdarrenr 765255332Scy/* 766255332Scy * This function is not meant to be random, rather just produce a 767255332Scy * sequence of numbers that isn't linear to show "randomness". 768255332Scy */ 769255332Scyu_32_t 770255332Scyipf_random() 771170268Sdarrenr{ 772255332Scy static unsigned int last = 0xa5a5a5a5; 773255332Scy static int calls = 0; 774255332Scy int number; 775255332Scy 776255332Scy calls++; 777255332Scy 778255332Scy /* 779255332Scy * These are deliberately chosen to ensure that there is some 780255332Scy * attempt to test whether the output covers the range in test n18. 781255332Scy */ 782255332Scy switch (calls) 783255332Scy { 784255332Scy case 1 : 785255332Scy number = 0; 786255332Scy break; 787255332Scy case 2 : 788255332Scy number = 4; 789255332Scy break; 790255332Scy case 3 : 791255332Scy number = 3999; 792255332Scy break; 793255332Scy case 4 : 794255332Scy number = 4000; 795255332Scy break; 796255332Scy case 5 : 797255332Scy number = 48999; 798255332Scy break; 799255332Scy case 6 : 800255332Scy number = 49000; 801255332Scy break; 802255332Scy default : 803255332Scy number = last; 804255332Scy last *= calls; 805255332Scy last++; 806255332Scy number ^= last; 807255332Scy break; 808255332Scy } 809255332Scy return number; 810255332Scy} 811255332Scy 812255332Scy 813255332Scyint 814255332Scyipf_verifysrc(fin) 815255332Scy fr_info_t *fin; 816255332Scy{ 817255332Scy return 1; 818255332Scy} 819255332Scy 820255332Scy 821255332Scyint 822255332Scyipf_inject(fin, m) 823255332Scy fr_info_t *fin; 824255332Scy mb_t *m; 825255332Scy{ 826255332Scy FREE_MB_T(m); 827255332Scy 828170268Sdarrenr return 0; 829170268Sdarrenr} 830180778Sdarrenr 831180778Sdarrenr 832255332Scyu_int 833255332Scyipf_pcksum(fin, hlen, sum) 834255332Scy fr_info_t *fin; 835255332Scy int hlen; 836255332Scy u_int sum; 837180778Sdarrenr{ 838255332Scy u_short *sp; 839255332Scy u_int sum2; 840255332Scy int slen; 841180778Sdarrenr 842255332Scy slen = fin->fin_plen - hlen; 843255332Scy sp = (u_short *)((u_char *)fin->fin_ip + hlen); 844255332Scy 845255332Scy for (; slen > 1; slen -= 2) 846255332Scy sum += *sp++; 847255332Scy if (slen) 848255332Scy sum += ntohs(*(u_char *)sp << 8); 849255332Scy while (sum > 0xffff) 850255332Scy sum = (sum & 0xffff) + (sum >> 16); 851255332Scy sum2 = (u_short)(~sum & 0xffff); 852255332Scy 853255332Scy return sum2; 854255332Scy} 855255332Scy 856255332Scy 857255332Scyvoid * 858255332Scyipf_pullup(m, fin, plen) 859255332Scy mb_t *m; 860255332Scy fr_info_t *fin; 861255332Scy int plen; 862255332Scy{ 863255332Scy if (M_LEN(m) >= plen) 864255332Scy return fin->fin_ip; 865255332Scy 866180778Sdarrenr /* 867255332Scy * Fake ipf_pullup failing 868180778Sdarrenr */ 869255332Scy fin->fin_reason = FRB_PULLUP; 870255332Scy *fin->fin_mp = NULL; 871255332Scy fin->fin_m = NULL; 872255332Scy fin->fin_ip = NULL; 873255332Scy return NULL; 874180778Sdarrenr} 875