1 /* 2 * Copyright (C) 1993-2001, 2003 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 7 * Use is subject to license terms. 8 */ 9 10 #pragma ident "%Z%%M% %I% %E% SMI" 11 12 #if !defined(lint) 13 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 14 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.9 2005/01/08 14:22:18 darrenr Exp $"; 15 #endif 16 17 #ifndef SOLARIS 18 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) 19 #endif 20 21 #include <sys/param.h> 22 #if defined(__FreeBSD__) && !defined(__FreeBSD_version) 23 # if defined(IPFILTER_LKM) 24 # ifndef __FreeBSD_cc_version 25 # include <osreldate.h> 26 # else 27 # if __FreeBSD_cc_version < 430000 28 # include <osreldate.h> 29 # endif 30 # endif 31 # endif 32 #endif 33 #include <sys/errno.h> 34 #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL) 35 # include <sys/kern_svcs.h> 36 #endif 37 #include <sys/types.h> 38 #define _KERNEL 39 #define KERNEL 40 #ifdef __OpenBSD__ 41 struct file; 42 #endif 43 #include <sys/uio.h> 44 #undef _KERNEL 45 #undef KERNEL 46 #include <sys/file.h> 47 #include <sys/ioctl.h> 48 #ifdef __sgi 49 # include <sys/ptimers.h> 50 #endif 51 #include <sys/time.h> 52 #if !SOLARIS 53 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) 54 # include <sys/dirent.h> 55 # else 56 # include <sys/dir.h> 57 # endif 58 #else 59 # include <sys/filio.h> 60 #endif 61 #ifndef linux 62 # include <sys/protosw.h> 63 #endif 64 #include <sys/socket.h> 65 66 #include <stdio.h> 67 #include <string.h> 68 #include <stdlib.h> 69 #include <ctype.h> 70 #include <fcntl.h> 71 #include <arpa/inet.h> 72 73 #ifdef __hpux 74 # define _NET_ROUTE_INCLUDED 75 #endif 76 #include <net/if.h> 77 #ifdef sun 78 # include <net/af.h> 79 #endif 80 #if __FreeBSD_version >= 300000 81 # include <net/if_var.h> 82 #endif 83 #ifdef __sgi 84 #include <sys/debug.h> 85 # ifdef IFF_DRVRLOCK /* IRIX6 */ 86 #include <sys/hashing.h> 87 # endif 88 #endif 89 #if defined(__FreeBSD__) 90 # include "radix_ipf.h" 91 #endif 92 #include <net/route.h> 93 #include <netinet/in.h> 94 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \ 95 !defined(__hpux) && !defined(linux) 96 # include <netinet/in_var.h> 97 #endif 98 #include <netinet/in_systm.h> 99 #include <netinet/ip.h> 100 #if !defined(linux) 101 # include <netinet/ip_var.h> 102 #endif 103 #include <netinet/tcp.h> 104 #if defined(__osf__) 105 # include <netinet/tcp_timer.h> 106 #endif 107 #if defined(__osf__) || defined(__hpux) || defined(__sgi) 108 # include "radix_ipf_local.h" 109 # define _RADIX_H_ 110 #endif 111 #include <netinet/udp.h> 112 #include <netinet/tcpip.h> 113 #include <netinet/ip_icmp.h> 114 #include <unistd.h> 115 #include <syslog.h> 116 #ifdef __hpux 117 # undef _NET_ROUTE_INCLUDED 118 #endif 119 #include "netinet/ip_compat.h" 120 #include "netinet/ip_fil.h" 121 #include "netinet/ip_nat.h" 122 #include "netinet/ip_frag.h" 123 #include "netinet/ip_state.h" 124 #include "netinet/ip_proxy.h" 125 #include "netinet/ip_auth.h" 126 #ifdef IPFILTER_SYNC 127 #include "netinet/ip_sync.h" 128 #endif 129 #ifdef IPFILTER_SCAN 130 #include "netinet/ip_scan.h" 131 #endif 132 #include "netinet/ip_pool.h" 133 #ifdef IPFILTER_COMPILED 134 # include "netinet/ip_rules.h" 135 #endif 136 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 137 # include <sys/malloc.h> 138 #endif 139 #ifdef __hpux 140 struct rtentry; 141 #endif 142 #include "md5.h" 143 144 145 #if !defined(__osf__) 146 extern struct protosw inetsw[]; 147 #endif 148 149 #include "ipt.h" 150 static struct ifnet **ifneta = NULL; 151 static int nifs = 0; 152 153 static int frzerostats __P((caddr_t)); 154 static void fr_setifpaddr __P((struct ifnet *, char *)); 155 void init_ifp __P((void)); 156 #if defined(__sgi) && (IRIX < 60500) 157 static int no_output __P((struct ifnet *, struct mbuf *, 158 struct sockaddr *)); 159 static int write_output __P((struct ifnet *, struct mbuf *, 160 struct sockaddr *)); 161 #else 162 # if TRU64 >= 1885 163 static int no_output __P((struct ifnet *, struct mbuf *, 164 struct sockaddr *, struct rtentry *, char *)); 165 static int write_output __P((struct ifnet *, struct mbuf *, 166 struct sockaddr *, struct rtentry *, char *)); 167 # else 168 static int no_output __P((struct ifnet *, struct mbuf *, 169 struct sockaddr *, struct rtentry *)); 170 static int write_output __P((struct ifnet *, struct mbuf *, 171 struct sockaddr *, struct rtentry *)); 172 # endif 173 #endif 174 175 176 int iplattach() 177 { 178 fr_running = 1; 179 return 0; 180 } 181 182 183 int ipldetach() 184 { 185 fr_running = -1; 186 return 0; 187 } 188 189 190 static int frzerostats(data) 191 caddr_t data; 192 { 193 friostat_t fio; 194 int error; 195 196 fr_getstat(&fio); 197 error = copyoutptr(&fio, data, sizeof(fio)); 198 if (error) 199 return EFAULT; 200 201 bzero((char *)frstats, sizeof(*frstats) * 2); 202 203 return 0; 204 } 205 206 207 /* 208 * Filter ioctl interface. 209 */ 210 int iplioctl(dev, cmd, data, mode) 211 int dev; 212 ioctlcmd_t cmd; 213 caddr_t data; 214 int mode; 215 { 216 int error = 0, unit = 0, tmp; 217 friostat_t fio; 218 219 unit = dev; 220 221 SPL_NET(s); 222 223 if (unit == IPL_LOGNAT) { 224 if (fr_running > 0) 225 error = fr_nat_ioctl(data, cmd, mode); 226 else 227 error = EIO; 228 SPL_X(s); 229 return error; 230 } 231 if (unit == IPL_LOGSTATE) { 232 if (fr_running > 0) 233 error = fr_state_ioctl(data, cmd, mode); 234 else 235 error = EIO; 236 SPL_X(s); 237 return error; 238 } 239 if (unit == IPL_LOGAUTH) { 240 if (fr_running > 0) { 241 if ((cmd == (ioctlcmd_t)SIOCADAFR) || 242 (cmd == (ioctlcmd_t)SIOCRMAFR)) { 243 if (!(mode & FWRITE)) { 244 error = EPERM; 245 } else { 246 error = frrequest(unit, cmd, data, 247 fr_active, 1); 248 } 249 } else { 250 error = fr_auth_ioctl(data, mode, cmd); 251 } 252 } else 253 error = EIO; 254 SPL_X(s); 255 return error; 256 } 257 if (unit == IPL_LOGSYNC) { 258 #ifdef IPFILTER_SYNC 259 if (fr_running > 0) 260 error = fr_sync_ioctl(data, cmd, mode); 261 else 262 #endif 263 error = EIO; 264 SPL_X(s); 265 return error; 266 } 267 if (unit == IPL_LOGSCAN) { 268 #ifdef IPFILTER_SCAN 269 if (fr_running > 0) 270 error = fr_scan_ioctl(data, cmd, mode); 271 else 272 #endif 273 error = EIO; 274 SPL_X(s); 275 return error; 276 } 277 if (unit == IPL_LOGLOOKUP) { 278 if (fr_running > 0) 279 error = ip_lookup_ioctl(data, cmd, mode); 280 else 281 error = EIO; 282 SPL_X(s); 283 return error; 284 } 285 286 switch (cmd) 287 { 288 case FIONREAD : 289 #ifdef IPFILTER_LOG 290 error = COPYOUT(&iplused[IPL_LOGIPF], (caddr_t)data, 291 sizeof(iplused[IPL_LOGIPF])); 292 #endif 293 break; 294 case SIOCFRENB : 295 if (!(mode & FWRITE)) 296 error = EPERM; 297 else { 298 error = COPYIN(data, &tmp, sizeof(tmp)); 299 if (error) 300 break; 301 if (tmp) 302 error = iplattach(); 303 else 304 error = ipldetach(); 305 } 306 break; 307 case SIOCIPFSET : 308 if (!(mode & FWRITE)) { 309 error = EPERM; 310 break; 311 } 312 case SIOCIPFGETNEXT : 313 case SIOCIPFGET : 314 error = fr_ipftune(cmd, (void *)data); 315 break; 316 case SIOCSETFF : 317 if (!(mode & FWRITE)) 318 error = EPERM; 319 else 320 error = COPYIN(data, &fr_flags, sizeof(fr_flags)); 321 break; 322 case SIOCGETFF : 323 error = COPYOUT(&fr_flags, data, sizeof(fr_flags)); 324 break; 325 case SIOCFUNCL : 326 error = fr_resolvefunc(data); 327 break; 328 case SIOCINAFR : 329 case SIOCRMAFR : 330 case SIOCADAFR : 331 case SIOCZRLST : 332 if (!(mode & FWRITE)) 333 error = EPERM; 334 else 335 error = frrequest(unit, cmd, data, fr_active, 1); 336 break; 337 case SIOCINIFR : 338 case SIOCRMIFR : 339 case SIOCADIFR : 340 if (!(mode & FWRITE)) 341 error = EPERM; 342 else 343 error = frrequest(unit, cmd, data, 1 - fr_active, 1); 344 break; 345 case SIOCSWAPA : 346 if (!(mode & FWRITE)) 347 error = EPERM; 348 else { 349 bzero((char *)frcache, sizeof(frcache[0]) * 2); 350 *(u_int *)data = fr_active; 351 fr_active = 1 - fr_active; 352 } 353 break; 354 case SIOCGETFS : 355 fr_getstat(&fio); 356 error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT); 357 break; 358 case SIOCFRZST : 359 if (!(mode & FWRITE)) 360 error = EPERM; 361 else 362 error = frzerostats(data); 363 break; 364 case SIOCIPFFL : 365 if (!(mode & FWRITE)) 366 error = EPERM; 367 else { 368 error = COPYIN(data, &tmp, sizeof(tmp)); 369 if (!error) { 370 tmp = frflush(unit, 4, tmp); 371 error = COPYOUT(&tmp, data, sizeof(tmp)); 372 } 373 } 374 break; 375 #ifdef USE_INET6 376 case SIOCIPFL6 : 377 if (!(mode & FWRITE)) 378 error = EPERM; 379 else { 380 error = COPYIN(data, &tmp, sizeof(tmp)); 381 if (!error) { 382 tmp = frflush(unit, 6, tmp); 383 error = COPYOUT(&tmp, data, sizeof(tmp)); 384 } 385 } 386 break; 387 #endif 388 case SIOCSTLCK : 389 error = COPYIN(data, &tmp, sizeof(tmp)); 390 if (error == 0) { 391 fr_state_lock = tmp; 392 fr_nat_lock = tmp; 393 fr_frag_lock = tmp; 394 fr_auth_lock = tmp; 395 } else 396 error = EFAULT; 397 break; 398 #ifdef IPFILTER_LOG 399 case SIOCIPFFB : 400 if (!(mode & FWRITE)) 401 error = EPERM; 402 else 403 *(int *)data = ipflog_clear(unit); 404 break; 405 #endif /* IPFILTER_LOG */ 406 case SIOCGFRST : 407 error = fr_outobj(data, fr_fragstats(), IPFOBJ_FRAGSTAT); 408 break; 409 case SIOCFRSYN : 410 if (!(mode & FWRITE)) 411 error = EPERM; 412 else { 413 frsync(NULL); 414 } 415 break; 416 default : 417 error = EINVAL; 418 break; 419 } 420 SPL_X(s); 421 return error; 422 } 423 424 425 void fr_forgetifp(ifp) 426 void *ifp; 427 { 428 register frentry_t *f; 429 430 WRITE_ENTER(&ipf_mutex); 431 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next) 432 if (f->fr_ifa == ifp) 433 f->fr_ifa = (void *)-1; 434 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next) 435 if (f->fr_ifa == ifp) 436 f->fr_ifa = (void *)-1; 437 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next) 438 if (f->fr_ifa == ifp) 439 f->fr_ifa = (void *)-1; 440 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next) 441 if (f->fr_ifa == ifp) 442 f->fr_ifa = (void *)-1; 443 #ifdef USE_INET6 444 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next) 445 if (f->fr_ifa == ifp) 446 f->fr_ifa = (void *)-1; 447 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next) 448 if (f->fr_ifa == ifp) 449 f->fr_ifa = (void *)-1; 450 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next) 451 if (f->fr_ifa == ifp) 452 f->fr_ifa = (void *)-1; 453 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next) 454 if (f->fr_ifa == ifp) 455 f->fr_ifa = (void *)-1; 456 #endif 457 RWLOCK_EXIT(&ipf_mutex); 458 fr_natsync(ifp); 459 } 460 461 462 void fr_resolvedest(fdp, v) 463 frdest_t *fdp; 464 int v; 465 { 466 fdp->fd_ifp = NULL; 467 468 if (*fdp->fd_ifname) { 469 fdp->fd_ifp = GETIFP(fdp->fd_ifname, v); 470 if (!fdp->fd_ifp) 471 fdp->fd_ifp = (struct ifnet *)-1; 472 } 473 } 474 475 476 #if defined(__sgi) && (IRIX < 60500) 477 static int no_output(ifp, m, s) 478 #else 479 # if TRU64 >= 1885 480 static int no_output (ifp, m, s, rt, cp) 481 char *cp; 482 # else 483 static int no_output(ifp, m, s, rt) 484 # endif 485 struct rtentry *rt; 486 #endif 487 struct ifnet *ifp; 488 struct mbuf *m; 489 struct sockaddr *s; 490 { 491 return 0; 492 } 493 494 495 #if defined(__sgi) && (IRIX < 60500) 496 static int write_output(ifp, m, s) 497 #else 498 # if TRU64 >= 1885 499 static int write_output (ifp, m, s, rt, cp) 500 char *cp; 501 # else 502 static int write_output(ifp, m, s, rt) 503 # endif 504 struct rtentry *rt; 505 #endif 506 struct ifnet *ifp; 507 struct mbuf *m; 508 struct sockaddr *s; 509 { 510 char fname[32]; 511 mb_t *mb; 512 ip_t *ip; 513 int fd; 514 515 mb = (mb_t *)m; 516 ip = MTOD(mb, ip_t *); 517 518 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 519 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 520 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 521 sprintf(fname, "/tmp/%s", ifp->if_xname); 522 #else 523 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 524 #endif 525 fd = open(fname, O_WRONLY|O_APPEND); 526 if (fd == -1) { 527 perror("open"); 528 return -1; 529 } 530 write(fd, (char *)ip, ntohs(ip->ip_len)); 531 close(fd); 532 return 0; 533 } 534 535 536 static void fr_setifpaddr(ifp, addr) 537 struct ifnet *ifp; 538 char *addr; 539 { 540 #ifdef __sgi 541 struct in_ifaddr *ifa; 542 #else 543 struct ifaddr *ifa; 544 #endif 545 546 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 547 if (ifp->if_addrlist.tqh_first != NULL) 548 #else 549 # ifdef __sgi 550 if (ifp->in_ifaddr != NULL) 551 # else 552 if (ifp->if_addrlist != NULL) 553 # endif 554 #endif 555 return; 556 557 ifa = (struct ifaddr *)malloc(sizeof(*ifa)); 558 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 559 ifp->if_addrlist.tqh_first = ifa; 560 #else 561 # ifdef __sgi 562 ifp->in_ifaddr = ifa; 563 # else 564 ifp->if_addrlist = ifa; 565 # endif 566 #endif 567 568 if (ifa != NULL) { 569 struct sockaddr_in *sin; 570 571 #ifdef __sgi 572 sin = (struct sockaddr_in *)&ifa->ia_addr; 573 #else 574 sin = (struct sockaddr_in *)&ifa->ifa_addr; 575 #endif 576 sin->sin_addr.s_addr = inet_addr(addr); 577 if (sin->sin_addr.s_addr == 0) 578 abort(); 579 } 580 } 581 582 struct ifnet *get_unit(name, v) 583 char *name; 584 int v; 585 { 586 struct ifnet *ifp, **ifpp, **old_ifneta; 587 char *addr; 588 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 589 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 590 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 591 592 if (name == NULL) 593 name = "anon0"; 594 595 addr = strchr(name, '='); 596 if (addr != NULL) 597 *addr++ = '\0'; 598 599 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 600 if (!strcmp(name, ifp->if_xname)) { 601 if (addr != NULL) 602 fr_setifpaddr(ifp, addr); 603 return ifp; 604 } 605 } 606 #else 607 char *s, ifname[LIFNAMSIZ+1]; 608 609 if (name == NULL) 610 name = "anon0"; 611 612 addr = strchr(name, '='); 613 if (addr != NULL) 614 *addr++ = '\0'; 615 616 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 617 COPYIFNAME(ifp, ifname); 618 if (!strcmp(name, ifname)) { 619 if (addr != NULL) 620 fr_setifpaddr(ifp, addr); 621 return ifp; 622 } 623 } 624 #endif 625 626 if (!ifneta) { 627 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); 628 if (!ifneta) 629 return NULL; 630 ifneta[1] = NULL; 631 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); 632 if (!ifneta[0]) { 633 free(ifneta); 634 return NULL; 635 } 636 nifs = 1; 637 } else { 638 old_ifneta = ifneta; 639 nifs++; 640 ifneta = (struct ifnet **)realloc(ifneta, 641 (nifs + 1) * sizeof(ifp)); 642 if (!ifneta) { 643 free(old_ifneta); 644 nifs = 0; 645 return NULL; 646 } 647 ifneta[nifs] = NULL; 648 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); 649 if (!ifneta[nifs - 1]) { 650 nifs--; 651 return NULL; 652 } 653 } 654 ifp = ifneta[nifs - 1]; 655 656 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 657 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 658 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 659 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); 660 #else 661 for (s = name; *s && !ISDIGIT(*s); s++) 662 ; 663 if (*s && ISDIGIT(*s)) { 664 ifp->if_unit = atoi(s); 665 ifp->if_name = (char *)malloc(s - name + 1); 666 if (ifp->if_name == NULL) { 667 /* 668 * XXX do it more elegantly: free up mem, 669 * return NULL 670 */ 671 perror("malloc"); 672 exit(1); 673 } 674 (void) strncpy(ifp->if_name, name, s - name); 675 ifp->if_name[s - name] = '\0'; 676 } else { 677 ifp->if_name = strdup(name); 678 ifp->if_unit = -1; 679 } 680 #endif 681 ifp->if_output = no_output; 682 683 if (addr != NULL) { 684 fr_setifpaddr(ifp, addr); 685 } 686 687 return ifp; 688 } 689 690 691 char *get_ifname(ifp) 692 struct ifnet *ifp; 693 { 694 static char ifname[LIFNAMSIZ]; 695 696 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ 697 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 698 sprintf(ifname, "%s", ifp->if_xname); 699 #else 700 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); 701 #endif 702 return ifname; 703 } 704 705 706 707 void init_ifp() 708 { 709 struct ifnet *ifp, **ifpp; 710 char fname[32]; 711 int fd; 712 713 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 714 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 715 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 716 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 717 ifp->if_output = write_output; 718 sprintf(fname, "/tmp/%s", ifp->if_xname); 719 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 720 if (fd == -1) 721 perror("open"); 722 else 723 close(fd); 724 } 725 #else 726 727 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 728 ifp->if_output = write_output; 729 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 730 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 731 if (fd == -1) 732 perror("open"); 733 else 734 close(fd); 735 } 736 #endif 737 } 738 739 740 int fr_fastroute(m, mpp, fin, fdp) 741 mb_t *m, **mpp; 742 fr_info_t *fin; 743 frdest_t *fdp; 744 { 745 struct ifnet *ifp = fdp->fd_ifp; 746 ip_t *ip = fin->fin_ip; 747 748 if (!ifp) 749 return 0; /* no routing table out here */ 750 751 ip->ip_len = htons((u_short)ip->ip_len); 752 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); 753 ip->ip_sum = 0; 754 #if defined(__sgi) && (IRIX < 60500) 755 (*ifp->if_output)(ifp, (void *)ip, NULL); 756 # if TRU64 >= 1885 757 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); 758 # else 759 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 760 # endif 761 #endif 762 return 0; 763 } 764 765 766 int fr_send_reset(fin) 767 fr_info_t *fin; 768 { 769 verbose("- TCP RST sent\n"); 770 return 0; 771 } 772 773 774 int fr_send_icmp_err(type, fin, dst) 775 int type; 776 fr_info_t *fin; 777 int dst; 778 { 779 verbose("- ICMP unreachable sent\n"); 780 return 0; 781 } 782 783 784 void frsync(ifp) 785 void *ifp; 786 { 787 return; 788 } 789 790 791 void m_freem(m) 792 mb_t *m; 793 { 794 return; 795 } 796 797 798 void m_copydata(m, off, len, cp) 799 mb_t *m; 800 int off, len; 801 caddr_t cp; 802 { 803 bcopy((char *)m + off, cp, len); 804 } 805 806 807 int ipfuiomove(buf, len, rwflag, uio) 808 caddr_t buf; 809 int len, rwflag; 810 struct uio *uio; 811 { 812 int left, ioc, num, offset; 813 struct iovec *io; 814 char *start; 815 816 if (rwflag == UIO_READ) { 817 left = len; 818 ioc = 0; 819 820 offset = uio->uio_offset; 821 822 while ((left > 0) && (ioc < uio->uio_iovcnt)) { 823 io = uio->uio_iov + ioc; 824 num = io->iov_len; 825 if (num > left) 826 num = left; 827 start = (char *)io->iov_base + offset; 828 if (start > (char *)io->iov_base + io->iov_len) { 829 offset -= io->iov_len; 830 ioc++; 831 continue; 832 } 833 bcopy(buf, start, num); 834 uio->uio_resid -= num; 835 uio->uio_offset += num; 836 left -= num; 837 if (left > 0) 838 ioc++; 839 } 840 if (left > 0) 841 return EFAULT; 842 } 843 return 0; 844 } 845 846 847 u_32_t fr_newisn(fin) 848 fr_info_t *fin; 849 { 850 static int iss_seq_off = 0; 851 u_char hash[16]; 852 u_32_t newiss; 853 MD5_CTX ctx; 854 855 /* 856 * Compute the base value of the ISS. It is a hash 857 * of (saddr, sport, daddr, dport, secret). 858 */ 859 MD5Init(&ctx); 860 861 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 862 sizeof(fin->fin_fi.fi_src)); 863 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 864 sizeof(fin->fin_fi.fi_dst)); 865 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 866 867 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ 868 869 MD5Final(hash, &ctx); 870 871 memcpy(&newiss, hash, sizeof(newiss)); 872 873 /* 874 * Now increment our "timer", and add it in to 875 * the computed value. 876 * 877 * XXX Use `addin'? 878 * XXX TCP_ISSINCR too large to use? 879 */ 880 iss_seq_off += 0x00010000; 881 newiss += iss_seq_off; 882 return newiss; 883 } 884 885 886 /* ------------------------------------------------------------------------ */ 887 /* Function: fr_nextipid */ 888 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 889 /* Parameters: fin(I) - pointer to packet information */ 890 /* */ 891 /* Returns the next IPv4 ID to use for this packet. */ 892 /* ------------------------------------------------------------------------ */ 893 INLINE u_short fr_nextipid(fin) 894 fr_info_t *fin; 895 { 896 static u_short ipid = 0; 897 u_short id; 898 899 MUTEX_ENTER(&ipf_rw); 900 id = ipid++; 901 MUTEX_EXIT(&ipf_rw); 902 903 return id; 904 } 905 906 907 INLINE void fr_checkv4sum(fin) 908 fr_info_t *fin; 909 { 910 if (fr_checkl4sum(fin) == -1) 911 fin->fin_flx |= FI_BAD; 912 } 913 914 915 #ifdef USE_INET6 916 INLINE void fr_checkv6sum(fin) 917 fr_info_t *fin; 918 { 919 if (fr_checkl4sum(fin) == -1) 920 fin->fin_flx |= FI_BAD; 921 } 922 #endif 923 924 925 /* 926 * See above for description, except that all addressing is in user space. 927 */ 928 int copyoutptr(src, dst, size) 929 void *src, *dst; 930 size_t size; 931 { 932 caddr_t ca; 933 934 bcopy(dst, (char *)&ca, sizeof(ca)); 935 bcopy(src, ca, size); 936 return 0; 937 } 938 939 940 /* 941 * See above for description, except that all addressing is in user space. 942 */ 943 int copyinptr(src, dst, size) 944 void *src, *dst; 945 size_t size; 946 { 947 caddr_t ca; 948 949 bcopy(src, (char *)&ca, sizeof(ca)); 950 bcopy(ca, dst, size); 951 return 0; 952 } 953 954 955 /* 956 * return the first IP Address associated with an interface 957 */ 958 int fr_ifpaddr(v, atype, ifptr, inp, inpmask) 959 int v, atype; 960 void *ifptr; 961 struct in_addr *inp, *inpmask; 962 { 963 struct ifnet *ifp = ifptr; 964 #ifdef __sgi 965 struct in_ifaddr *ifa; 966 #else 967 struct ifaddr *ifa; 968 #endif 969 970 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 971 ifa = ifp->if_addrlist.tqh_first; 972 #else 973 # ifdef __sgi 974 ifa = (struct in_ifaddr *)ifp->in_ifaddr; 975 # else 976 ifa = ifp->if_addrlist; 977 # endif 978 #endif 979 if (ifa != NULL) { 980 struct sockaddr_in *sin, mask; 981 982 mask.sin_addr.s_addr = 0xffffffff; 983 984 #ifdef __sgi 985 sin = (struct sockaddr_in *)&ifa->ia_addr; 986 #else 987 sin = (struct sockaddr_in *)&ifa->ifa_addr; 988 #endif 989 990 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask); 991 } 992 return 0; 993 } 994