1145554Sdarrenr/* $FreeBSD$ */ 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#if defined(__sgi) && (IRIX < 60500) 483145554Sdarrenr (*ifp->if_output)(ifp, (void *)ip, NULL); 484145554Sdarrenr# if TRU64 >= 1885 485145554Sdarrenr (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); 486145554Sdarrenr# else 487145554Sdarrenr (*ifp->if_output)(ifp, (void *)m, NULL, 0); 488145554Sdarrenr# endif 489145554Sdarrenr#endif 490161357Sguidodone: 491255332Scy fin->fin_ifp = sifp; 492255332Scy fin->fin_out = sout; 493161357Sguido return error; 494145554Sdarrenr} 495145554Sdarrenr 496145554Sdarrenr 497255332Scyint 498255332Scyipf_send_reset(fin) 499255332Scy fr_info_t *fin; 500145554Sdarrenr{ 501255332Scy ipfkverbose("- TCP RST sent\n"); 502145554Sdarrenr return 0; 503145554Sdarrenr} 504145554Sdarrenr 505145554Sdarrenr 506255332Scyint 507255332Scyipf_send_icmp_err(type, fin, dst) 508255332Scy int type; 509255332Scy fr_info_t *fin; 510255332Scy int dst; 511145554Sdarrenr{ 512255332Scy ipfkverbose("- ICMP unreachable sent\n"); 513145554Sdarrenr return 0; 514145554Sdarrenr} 515145554Sdarrenr 516145554Sdarrenr 517255332Scyvoid 518255332Scym_freem(m) 519255332Scy mb_t *m; 520145554Sdarrenr{ 521145554Sdarrenr return; 522145554Sdarrenr} 523145554Sdarrenr 524145554Sdarrenr 525255332Scyvoid 526255332Scym_copydata(m, off, len, cp) 527255332Scy mb_t *m; 528255332Scy int off, len; 529255332Scy caddr_t cp; 530145554Sdarrenr{ 531145554Sdarrenr bcopy((char *)m + off, cp, len); 532145554Sdarrenr} 533145554Sdarrenr 534145554Sdarrenr 535255332Scyint 536255332Scyipfuiomove(buf, len, rwflag, uio) 537255332Scy caddr_t buf; 538255332Scy int len, rwflag; 539255332Scy struct uio *uio; 540145554Sdarrenr{ 541145554Sdarrenr int left, ioc, num, offset; 542145554Sdarrenr struct iovec *io; 543145554Sdarrenr char *start; 544145554Sdarrenr 545145554Sdarrenr if (rwflag == UIO_READ) { 546145554Sdarrenr left = len; 547145554Sdarrenr ioc = 0; 548145554Sdarrenr 549145554Sdarrenr offset = uio->uio_offset; 550145554Sdarrenr 551145554Sdarrenr while ((left > 0) && (ioc < uio->uio_iovcnt)) { 552145554Sdarrenr io = uio->uio_iov + ioc; 553145554Sdarrenr num = io->iov_len; 554145554Sdarrenr if (num > left) 555145554Sdarrenr num = left; 556145554Sdarrenr start = (char *)io->iov_base + offset; 557145554Sdarrenr if (start > (char *)io->iov_base + io->iov_len) { 558145554Sdarrenr offset -= io->iov_len; 559145554Sdarrenr ioc++; 560145554Sdarrenr continue; 561145554Sdarrenr } 562145554Sdarrenr bcopy(buf, start, num); 563145554Sdarrenr uio->uio_resid -= num; 564145554Sdarrenr uio->uio_offset += num; 565145554Sdarrenr left -= num; 566145554Sdarrenr if (left > 0) 567145554Sdarrenr ioc++; 568145554Sdarrenr } 569145554Sdarrenr if (left > 0) 570145554Sdarrenr return EFAULT; 571145554Sdarrenr } 572145554Sdarrenr return 0; 573145554Sdarrenr} 574145554Sdarrenr 575145554Sdarrenr 576255332Scyu_32_t 577255332Scyipf_newisn(fin) 578255332Scy fr_info_t *fin; 579145554Sdarrenr{ 580145554Sdarrenr static int iss_seq_off = 0; 581145554Sdarrenr u_char hash[16]; 582145554Sdarrenr u_32_t newiss; 583145554Sdarrenr MD5_CTX ctx; 584145554Sdarrenr 585145554Sdarrenr /* 586145554Sdarrenr * Compute the base value of the ISS. It is a hash 587145554Sdarrenr * of (saddr, sport, daddr, dport, secret). 588145554Sdarrenr */ 589145554Sdarrenr MD5Init(&ctx); 590145554Sdarrenr 591145554Sdarrenr MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 592145554Sdarrenr sizeof(fin->fin_fi.fi_src)); 593145554Sdarrenr MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 594145554Sdarrenr sizeof(fin->fin_fi.fi_dst)); 595145554Sdarrenr MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 596145554Sdarrenr 597145554Sdarrenr /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ 598145554Sdarrenr 599145554Sdarrenr MD5Final(hash, &ctx); 600145554Sdarrenr 601145554Sdarrenr memcpy(&newiss, hash, sizeof(newiss)); 602145554Sdarrenr 603145554Sdarrenr /* 604145554Sdarrenr * Now increment our "timer", and add it in to 605145554Sdarrenr * the computed value. 606145554Sdarrenr * 607145554Sdarrenr * XXX Use `addin'? 608145554Sdarrenr * XXX TCP_ISSINCR too large to use? 609145554Sdarrenr */ 610145554Sdarrenr iss_seq_off += 0x00010000; 611145554Sdarrenr newiss += iss_seq_off; 612145554Sdarrenr return newiss; 613145554Sdarrenr} 614145554Sdarrenr 615145554Sdarrenr 616145554Sdarrenr/* ------------------------------------------------------------------------ */ 617255332Scy/* Function: ipf_nextipid */ 618145554Sdarrenr/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 619145554Sdarrenr/* Parameters: fin(I) - pointer to packet information */ 620145554Sdarrenr/* */ 621145554Sdarrenr/* Returns the next IPv4 ID to use for this packet. */ 622145554Sdarrenr/* ------------------------------------------------------------------------ */ 623255332ScyINLINE u_short 624255332Scyipf_nextipid(fin) 625255332Scy fr_info_t *fin; 626145554Sdarrenr{ 627145554Sdarrenr static u_short ipid = 0; 628255332Scy ipf_main_softc_t *softc = fin->fin_main_soft; 629145554Sdarrenr u_short id; 630145554Sdarrenr 631255332Scy MUTEX_ENTER(&softc->ipf_rw); 632255332Scy if (fin->fin_pktnum != 0) { 633255332Scy /* 634255332Scy * The -1 is for aligned test results. 635255332Scy */ 636255332Scy id = (fin->fin_pktnum - 1) & 0xffff; 637255332Scy } else { 638255332Scy } 639255332Scy id = ipid++; 640255332Scy MUTEX_EXIT(&softc->ipf_rw); 641145554Sdarrenr 642145554Sdarrenr return id; 643145554Sdarrenr} 644145554Sdarrenr 645145554Sdarrenr 646255332ScyINLINE int 647255332Scyipf_checkv4sum(fin) 648255332Scy fr_info_t *fin; 649145554Sdarrenr{ 650255332Scy 651255332Scy if (fin->fin_flx & FI_SHORT) 652255332Scy return 1; 653255332Scy 654255332Scy if (ipf_checkl4sum(fin) == -1) { 655145554Sdarrenr fin->fin_flx |= FI_BAD; 656255332Scy return -1; 657255332Scy } 658255332Scy return 0; 659145554Sdarrenr} 660145554Sdarrenr 661145554Sdarrenr 662145554Sdarrenr#ifdef USE_INET6 663255332ScyINLINE int 664255332Scyipf_checkv6sum(fin) 665255332Scy fr_info_t *fin; 666145554Sdarrenr{ 667255332Scy if (fin->fin_flx & FI_SHORT) 668255332Scy return 1; 669255332Scy 670255332Scy if (ipf_checkl4sum(fin) == -1) { 671145554Sdarrenr fin->fin_flx |= FI_BAD; 672255332Scy return -1; 673255332Scy } 674255332Scy return 0; 675145554Sdarrenr} 676145554Sdarrenr#endif 677145554Sdarrenr 678145554Sdarrenr 679255332Scy#if 0 680145554Sdarrenr/* 681145554Sdarrenr * See above for description, except that all addressing is in user space. 682145554Sdarrenr */ 683255332Scyint 684255332Scycopyoutptr(softc, src, dst, size) 685255332Scy void *src, *dst; 686255332Scy size_t size; 687145554Sdarrenr{ 688145554Sdarrenr caddr_t ca; 689145554Sdarrenr 690145554Sdarrenr bcopy(dst, (char *)&ca, sizeof(ca)); 691145554Sdarrenr bcopy(src, ca, size); 692145554Sdarrenr return 0; 693145554Sdarrenr} 694145554Sdarrenr 695145554Sdarrenr 696145554Sdarrenr/* 697145554Sdarrenr * See above for description, except that all addressing is in user space. 698145554Sdarrenr */ 699255332Scyint 700255332Scycopyinptr(src, dst, size) 701255332Scy void *src, *dst; 702255332Scy size_t size; 703145554Sdarrenr{ 704145554Sdarrenr caddr_t ca; 705145554Sdarrenr 706145554Sdarrenr bcopy(src, (char *)&ca, sizeof(ca)); 707145554Sdarrenr bcopy(ca, dst, size); 708145554Sdarrenr return 0; 709145554Sdarrenr} 710255332Scy#endif 711145554Sdarrenr 712145554Sdarrenr 713145554Sdarrenr/* 714145554Sdarrenr * return the first IP Address associated with an interface 715145554Sdarrenr */ 716255332Scyint 717255332Scyipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) 718255332Scy ipf_main_softc_t *softc; 719255332Scy int v, atype; 720255332Scy void *ifptr; 721255332Scy i6addr_t *inp, *inpmask; 722145554Sdarrenr{ 723145554Sdarrenr struct ifnet *ifp = ifptr; 724145554Sdarrenr#ifdef __sgi 725145554Sdarrenr struct in_ifaddr *ifa; 726145554Sdarrenr#else 727145554Sdarrenr struct ifaddr *ifa; 728145554Sdarrenr#endif 729145554Sdarrenr 730145554Sdarrenr#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 731145554Sdarrenr ifa = ifp->if_addrlist.tqh_first; 732145554Sdarrenr#else 733145554Sdarrenr# ifdef __sgi 734145554Sdarrenr ifa = (struct in_ifaddr *)ifp->in_ifaddr; 735145554Sdarrenr# else 736145554Sdarrenr ifa = ifp->if_addrlist; 737145554Sdarrenr# endif 738145554Sdarrenr#endif 739145554Sdarrenr if (ifa != NULL) { 740255332Scy if (v == 4) { 741255332Scy struct sockaddr_in *sin, mask; 742145554Sdarrenr 743255332Scy mask.sin_addr.s_addr = 0xffffffff; 744145554Sdarrenr 745145554Sdarrenr#ifdef __sgi 746255332Scy sin = (struct sockaddr_in *)&ifa->ia_addr; 747145554Sdarrenr#else 748255332Scy sin = (struct sockaddr_in *)&ifa->ifa_addr; 749145554Sdarrenr#endif 750145554Sdarrenr 751255332Scy return ipf_ifpfillv4addr(atype, sin, &mask, 752255332Scy &inp->in4, &inpmask->in4); 753255332Scy } 754255332Scy#ifdef USE_INET6 755255332Scy if (v == 6) { 756255332Scy struct sockaddr_in6 *sin6, mask; 757255332Scy 758255332Scy sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; 759255332Scy ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff; 760255332Scy ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff; 761255332Scy ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff; 762255332Scy ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff; 763255332Scy return ipf_ifpfillv6addr(atype, sin6, &mask, 764255332Scy inp, inpmask); 765255332Scy } 766255332Scy#endif 767145554Sdarrenr } 768145554Sdarrenr return 0; 769145554Sdarrenr} 770170268Sdarrenr 771170268Sdarrenr 772255332Scy/* 773255332Scy * This function is not meant to be random, rather just produce a 774255332Scy * sequence of numbers that isn't linear to show "randomness". 775255332Scy */ 776255332Scyu_32_t 777255332Scyipf_random() 778170268Sdarrenr{ 779255332Scy static unsigned int last = 0xa5a5a5a5; 780255332Scy static int calls = 0; 781255332Scy int number; 782255332Scy 783255332Scy calls++; 784255332Scy 785255332Scy /* 786255332Scy * These are deliberately chosen to ensure that there is some 787255332Scy * attempt to test whether the output covers the range in test n18. 788255332Scy */ 789255332Scy switch (calls) 790255332Scy { 791255332Scy case 1 : 792255332Scy number = 0; 793255332Scy break; 794255332Scy case 2 : 795255332Scy number = 4; 796255332Scy break; 797255332Scy case 3 : 798255332Scy number = 3999; 799255332Scy break; 800255332Scy case 4 : 801255332Scy number = 4000; 802255332Scy break; 803255332Scy case 5 : 804255332Scy number = 48999; 805255332Scy break; 806255332Scy case 6 : 807255332Scy number = 49000; 808255332Scy break; 809255332Scy default : 810255332Scy number = last; 811255332Scy last *= calls; 812255332Scy last++; 813255332Scy number ^= last; 814255332Scy break; 815255332Scy } 816255332Scy return number; 817255332Scy} 818255332Scy 819255332Scy 820255332Scyint 821255332Scyipf_verifysrc(fin) 822255332Scy fr_info_t *fin; 823255332Scy{ 824255332Scy return 1; 825255332Scy} 826255332Scy 827255332Scy 828255332Scyint 829255332Scyipf_inject(fin, m) 830255332Scy fr_info_t *fin; 831255332Scy mb_t *m; 832255332Scy{ 833255332Scy FREE_MB_T(m); 834255332Scy 835170268Sdarrenr return 0; 836170268Sdarrenr} 837180778Sdarrenr 838180778Sdarrenr 839255332Scyu_int 840255332Scyipf_pcksum(fin, hlen, sum) 841255332Scy fr_info_t *fin; 842255332Scy int hlen; 843255332Scy u_int sum; 844180778Sdarrenr{ 845255332Scy u_short *sp; 846255332Scy u_int sum2; 847255332Scy int slen; 848180778Sdarrenr 849255332Scy slen = fin->fin_plen - hlen; 850255332Scy sp = (u_short *)((u_char *)fin->fin_ip + hlen); 851255332Scy 852255332Scy for (; slen > 1; slen -= 2) 853255332Scy sum += *sp++; 854255332Scy if (slen) 855255332Scy sum += ntohs(*(u_char *)sp << 8); 856255332Scy while (sum > 0xffff) 857255332Scy sum = (sum & 0xffff) + (sum >> 16); 858255332Scy sum2 = (u_short)(~sum & 0xffff); 859255332Scy 860255332Scy return sum2; 861255332Scy} 862255332Scy 863255332Scy 864255332Scyvoid * 865255332Scyipf_pullup(m, fin, plen) 866255332Scy mb_t *m; 867255332Scy fr_info_t *fin; 868255332Scy int plen; 869255332Scy{ 870255332Scy if (M_LEN(m) >= plen) 871255332Scy return fin->fin_ip; 872255332Scy 873180778Sdarrenr /* 874255332Scy * Fake ipf_pullup failing 875180778Sdarrenr */ 876255332Scy fin->fin_reason = FRB_PULLUP; 877255332Scy *fin->fin_mp = NULL; 878255332Scy fin->fin_m = NULL; 879255332Scy fin->fin_ip = NULL; 880255332Scy return NULL; 881180778Sdarrenr} 882