1 /* 2 * Copyright (c) 1982, 1986, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD: src/sys/netinet/ip_divert.c,v 1.42.2.6 2003/01/23 21:06:45 sam Exp $ 34 * $DragonFly: src/sys/netinet/ip_divert.c,v 1.40 2008/10/21 13:51:01 sephe Exp $ 35 */ 36 37 #define _IP_VHL 38 39 #include "opt_inet.h" 40 #include "opt_ipfw.h" 41 #include "opt_ipdivert.h" 42 #include "opt_ipsec.h" 43 44 #ifndef INET 45 #error "IPDIVERT requires INET." 46 #endif 47 48 #include <sys/param.h> 49 #include <sys/kernel.h> 50 #include <sys/malloc.h> 51 #include <sys/mbuf.h> 52 #include <sys/socket.h> 53 #include <sys/protosw.h> 54 #include <sys/socketvar.h> 55 #include <sys/sysctl.h> 56 #include <sys/systm.h> 57 #include <sys/proc.h> 58 #include <sys/thread2.h> 59 #include <sys/in_cksum.h> 60 #include <sys/lock.h> 61 #ifdef SMP 62 #include <sys/msgport.h> 63 #endif 64 65 #include <vm/vm_zone.h> 66 67 #include <net/if.h> 68 #include <net/route.h> 69 #ifdef SMP 70 #include <net/netmsg2.h> 71 #endif 72 73 #include <netinet/in.h> 74 #include <netinet/in_systm.h> 75 #include <netinet/ip.h> 76 #include <netinet/in_pcb.h> 77 #include <netinet/in_var.h> 78 #include <netinet/ip_var.h> 79 #include <netinet/ip_divert.h> 80 81 /* 82 * Divert sockets 83 */ 84 85 /* 86 * Allocate enough space to hold a full IP packet 87 */ 88 #define DIVSNDQ (65536 + 100) 89 #define DIVRCVQ (65536 + 100) 90 91 #define DIV_IS_OUTPUT(sin) ((sin) == NULL || (sin)->sin_addr.s_addr == 0) 92 93 #define DIV_OUTPUT 0x10000 94 #define DIV_INPUT 0x20000 95 96 /* 97 * Divert sockets work in conjunction with ipfw, see the divert(4) 98 * manpage for features. 99 * Internally, packets selected by ipfw in ip_input() or ip_output(), 100 * and never diverted before, are passed to the input queue of the 101 * divert socket with a given 'divert_port' number (as specified in 102 * the matching ipfw rule), and they are tagged with a 16 bit cookie 103 * (representing the rule number of the matching ipfw rule), which 104 * is passed to process reading from the socket. 105 * 106 * Packets written to the divert socket are again tagged with a cookie 107 * (usually the same as above) and a destination address. 108 * If the destination address is INADDR_ANY then the packet is 109 * treated as outgoing and sent to ip_output(), otherwise it is 110 * treated as incoming and sent to ip_input(). 111 * In both cases, the packet is tagged with the cookie. 112 * 113 * On reinjection, processing in ip_input() and ip_output() 114 * will be exactly the same as for the original packet, except that 115 * ipfw processing will start at the rule number after the one 116 * written in the cookie (so, tagging a packet with a cookie of 0 117 * will cause it to be effectively considered as a standard packet). 118 */ 119 120 /* Internal variables */ 121 static struct inpcbinfo divcbinfo; 122 123 static u_long div_sendspace = DIVSNDQ; /* XXX sysctl ? */ 124 static u_long div_recvspace = DIVRCVQ; /* XXX sysctl ? */ 125 126 static struct mbuf *ip_divert(struct mbuf *, int, int); 127 128 /* 129 * Initialize divert connection block queue. 130 */ 131 void 132 div_init(void) 133 { 134 in_pcbinfo_init(&divcbinfo); 135 /* 136 * XXX We don't use the hash list for divert IP, but it's easier 137 * to allocate a one entry hash list than it is to check all 138 * over the place for hashbase == NULL. 139 */ 140 divcbinfo.hashbase = hashinit(1, M_PCB, &divcbinfo.hashmask); 141 divcbinfo.porthashbase = hashinit(1, M_PCB, &divcbinfo.porthashmask); 142 divcbinfo.wildcardhashbase = hashinit(1, M_PCB, 143 &divcbinfo.wildcardhashmask); 144 divcbinfo.ipi_zone = zinit("divcb", sizeof(struct inpcb), 145 maxsockets, ZONE_INTERRUPT, 0); 146 ip_divert_p = ip_divert; 147 } 148 149 /* 150 * IPPROTO_DIVERT is not a real IP protocol; don't allow any packets 151 * with that protocol number to enter the system from the outside. 152 */ 153 void 154 div_input(struct mbuf *m, ...) 155 { 156 ipstat.ips_noproto++; 157 m_freem(m); 158 } 159 160 struct lwkt_port * 161 div_soport(struct socket *so, struct sockaddr *nam, 162 struct mbuf **mptr, int req) 163 { 164 struct sockaddr_in *sin; 165 struct mbuf *m; 166 int dir; 167 168 /* Except for send(), everything happens on CPU0 */ 169 if (req != PRU_SEND) 170 return cpu0_soport(so, nam, mptr, req); 171 172 sin = (struct sockaddr_in *)nam; 173 m = *mptr; 174 M_ASSERTPKTHDR(m); 175 176 m->m_pkthdr.rcvif = NULL; 177 dir = DIV_IS_OUTPUT(sin) ? IP_MPORT_OUT : IP_MPORT_IN; 178 179 if (sin != NULL) { 180 int i; 181 182 /* 183 * Try locating the interface, if we originally had one. 184 * This is done even for outgoing packets, since for a 185 * forwarded packet, there must be an interface attached. 186 * 187 * Find receive interface with the given name, stuffed 188 * (if it exists) in the sin_zero[] field. 189 * The name is user supplied data so don't trust its size 190 * or that it is zero terminated. 191 */ 192 for (i = 0; sin->sin_zero[i] && i < sizeof(sin->sin_zero); i++) 193 ; 194 if (i > 0 && i < sizeof(sin->sin_zero)) 195 m->m_pkthdr.rcvif = ifunit(sin->sin_zero); 196 } 197 198 if (dir == IP_MPORT_IN && m->m_pkthdr.rcvif == NULL) { 199 /* 200 * No luck with the name, check by IP address. 201 * Clear the port and the ifname to make sure 202 * there are no distractions for ifa_ifwithaddr. 203 * 204 * Be careful not to trash sin->sin_port; it will 205 * be used later in div_output(). 206 */ 207 struct ifaddr *ifa; 208 u_short sin_port; 209 210 bzero(sin->sin_zero, sizeof(sin->sin_zero)); 211 sin_port = sin->sin_port; /* save */ 212 sin->sin_port = 0; 213 ifa = ifa_ifwithaddr((struct sockaddr *)sin); 214 if (ifa == NULL) { 215 m_freem(m); 216 *mptr = NULL; 217 return NULL; 218 } 219 sin->sin_port = sin_port; /* restore */ 220 m->m_pkthdr.rcvif = ifa->ifa_ifp; 221 } 222 223 return ip_mport(mptr, dir); 224 } 225 226 /* 227 * Divert a packet by passing it up to the divert socket at port 'port'. 228 * 229 * Setup generic address and protocol structures for div_input routine, 230 * then pass them along with mbuf chain. 231 */ 232 static void 233 div_packet(struct mbuf *m, int incoming, int port) 234 { 235 struct sockaddr_in divsrc = { sizeof divsrc, AF_INET }; 236 struct inpcb *inp; 237 struct socket *sa; 238 struct m_tag *mtag; 239 struct divert_info *divinfo; 240 u_int16_t nport; 241 242 /* Locate the divert info */ 243 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL); 244 divinfo = m_tag_data(mtag); 245 divsrc.sin_port = divinfo->skipto; 246 247 /* 248 * Record receive interface address, if any. 249 * But only for incoming packets. 250 */ 251 divsrc.sin_addr.s_addr = 0; 252 if (incoming) { 253 struct ifaddr_container *ifac; 254 255 /* Find IP address for receive interface */ 256 TAILQ_FOREACH(ifac, &m->m_pkthdr.rcvif->if_addrheads[mycpuid], 257 ifa_link) { 258 struct ifaddr *ifa = ifac->ifa; 259 260 if (ifa->ifa_addr == NULL) 261 continue; 262 if (ifa->ifa_addr->sa_family != AF_INET) 263 continue; 264 divsrc.sin_addr = 265 ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; 266 break; 267 } 268 } 269 /* 270 * Record the incoming interface name whenever we have one. 271 */ 272 if (m->m_pkthdr.rcvif) { 273 /* 274 * Hide the actual interface name in there in the 275 * sin_zero array. XXX This needs to be moved to a 276 * different sockaddr type for divert, e.g. 277 * sockaddr_div with multiple fields like 278 * sockaddr_dl. Presently we have only 7 bytes 279 * but that will do for now as most interfaces 280 * are 4 or less + 2 or less bytes for unit. 281 * There is probably a faster way of doing this, 282 * possibly taking it from the sockaddr_dl on the iface. 283 * This solves the problem of a P2P link and a LAN interface 284 * having the same address, which can result in the wrong 285 * interface being assigned to the packet when fed back 286 * into the divert socket. Theoretically if the daemon saves 287 * and re-uses the sockaddr_in as suggested in the man pages, 288 * this iface name will come along for the ride. 289 * (see div_output for the other half of this.) 290 */ 291 ksnprintf(divsrc.sin_zero, sizeof divsrc.sin_zero, 292 m->m_pkthdr.rcvif->if_xname); 293 } 294 295 /* Put packet on socket queue, if any */ 296 sa = NULL; 297 nport = htons((u_int16_t)port); 298 299 /* 300 * XXX 301 * Following loop to locate the inpcb is MPSAFE since the inpcb 302 * insertion/removal happens on the same CPU (CPU0), however, 303 * saving/testing the socket pointer is not MPSAFE. So we still 304 * need to hold BGL here. 305 */ 306 get_mplock(); 307 LIST_FOREACH(inp, &divcbinfo.pcblisthead, inp_list) { 308 if (inp->inp_flags & INP_PLACEMARKER) 309 continue; 310 if (inp->inp_lport == nport) 311 sa = inp->inp_socket; 312 } 313 if (sa) { 314 if (ssb_appendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m, 315 (struct mbuf *)NULL) == 0) 316 m_freem(m); 317 else 318 sorwakeup(sa); 319 rel_mplock(); 320 } else { 321 rel_mplock(); 322 m_freem(m); 323 ipstat.ips_noproto++; 324 ipstat.ips_delivered--; 325 } 326 } 327 328 #ifdef SMP 329 static void 330 div_packet_handler(struct netmsg *nmsg) 331 { 332 struct netmsg_packet *nmp; 333 struct lwkt_msg *msg; 334 struct mbuf *m; 335 int port, incoming = 0; 336 337 nmp = (struct netmsg_packet *)nmsg; 338 m = nmp->nm_packet; 339 340 msg = &nmsg->nm_lmsg; 341 port = msg->u.ms_result32 & 0xffff; 342 if (msg->u.ms_result32 & DIV_INPUT) 343 incoming = 1; 344 345 div_packet(m, incoming, port); 346 } 347 #endif /* SMP */ 348 349 static void 350 divert_packet(struct mbuf *m, int incoming) 351 { 352 struct m_tag *mtag; 353 struct divert_info *divinfo; 354 int port; 355 356 M_ASSERTPKTHDR(m); 357 358 /* Assure header */ 359 if (m->m_len < sizeof(struct ip) && 360 (m = m_pullup(m, sizeof(struct ip))) == NULL) 361 return; 362 363 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL); 364 KASSERT(mtag != NULL, ("%s no divert tag!", __func__)); 365 divinfo = m_tag_data(mtag); 366 367 port = divinfo->port; 368 KASSERT(port != 0, ("%s: port=0", __func__)); 369 370 #ifdef SMP 371 if (mycpuid != 0) { 372 struct netmsg_packet *nmp; 373 struct lwkt_msg *msg; 374 375 nmp = &m->m_hdr.mh_netmsg; 376 netmsg_init(&nmp->nm_netmsg, &netisr_apanic_rport, MSGF_MPSAFE, 377 div_packet_handler); 378 nmp->nm_packet = m; 379 380 msg = &nmp->nm_netmsg.nm_lmsg; 381 msg->u.ms_result32 = port; /* port is 16bits */ 382 if (incoming) 383 msg->u.ms_result32 |= DIV_INPUT; 384 else 385 msg->u.ms_result32 |= DIV_OUTPUT; 386 387 lwkt_sendmsg(cpu_portfn(0), &nmp->nm_netmsg.nm_lmsg); 388 } else 389 #endif 390 div_packet(m, incoming, port); 391 } 392 393 /* 394 * Deliver packet back into the IP processing machinery. 395 * 396 * If no address specified, or address is 0.0.0.0, send to ip_output(); 397 * otherwise, send to ip_input() and mark as having been received on 398 * the interface with that address. 399 */ 400 static int 401 div_output(struct socket *so, struct mbuf *m, 402 struct sockaddr_in *sin, struct mbuf *control) 403 { 404 int error = 0; 405 struct m_tag *mtag; 406 struct divert_info *divinfo; 407 408 if (control) 409 m_freem(control); /* XXX */ 410 411 /* 412 * Prepare the tag for divert info. Note that a packet 413 * with a 0 tag in mh_data is effectively untagged, 414 * so we could optimize that case. 415 */ 416 mtag = m_tag_get(PACKET_TAG_IPFW_DIVERT, sizeof(*divinfo), MB_DONTWAIT); 417 if (mtag == NULL) { 418 error = ENOBUFS; 419 goto cantsend; 420 } 421 m_tag_prepend(m, mtag); 422 423 /* Loopback avoidance and state recovery */ 424 divinfo = m_tag_data(mtag); 425 if (sin) 426 divinfo->skipto = sin->sin_port; 427 else 428 divinfo->skipto = 0; 429 430 /* Reinject packet into the system as incoming or outgoing */ 431 if (DIV_IS_OUTPUT(sin)) { 432 struct ip *const ip = mtod(m, struct ip *); 433 434 /* Don't allow packet length sizes that will crash */ 435 if ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len) { 436 error = EINVAL; 437 goto cantsend; 438 } 439 440 /* Convert fields to host order for ip_output() */ 441 ip->ip_len = ntohs(ip->ip_len); 442 ip->ip_off = ntohs(ip->ip_off); 443 444 /* Send packet to output processing */ 445 ipstat.ips_rawout++; /* XXX */ 446 error = ip_output(m, NULL, NULL, 447 (so->so_options & SO_DONTROUTE) | 448 IP_ALLOWBROADCAST | IP_RAWOUTPUT, 449 NULL, NULL); 450 } else { 451 ip_input(m); 452 } 453 return error; 454 455 cantsend: 456 m_freem(m); 457 return error; 458 } 459 460 static int 461 div_attach(struct socket *so, int proto, struct pru_attach_info *ai) 462 { 463 struct inpcb *inp; 464 int error; 465 466 inp = so->so_pcb; 467 if (inp) 468 panic("div_attach"); 469 if ((error = suser_cred(ai->p_ucred, NULL_CRED_OKAY)) != 0) 470 return error; 471 472 error = soreserve(so, div_sendspace, div_recvspace, ai->sb_rlimit); 473 if (error) 474 return error; 475 error = in_pcballoc(so, &divcbinfo); 476 if (error) 477 return error; 478 inp = (struct inpcb *)so->so_pcb; 479 inp->inp_ip_p = proto; 480 inp->inp_vflag |= INP_IPV4; 481 inp->inp_flags |= INP_HDRINCL; 482 /* 483 * The socket is always "connected" because 484 * we always know "where" to send the packet. 485 */ 486 so->so_state |= SS_ISCONNECTED; 487 return 0; 488 } 489 490 static int 491 div_detach(struct socket *so) 492 { 493 struct inpcb *inp; 494 495 inp = so->so_pcb; 496 if (inp == NULL) 497 panic("div_detach"); 498 in_pcbdetach(inp); 499 return 0; 500 } 501 502 static int 503 div_abort(struct socket *so) 504 { 505 soisdisconnected(so); 506 return div_detach(so); 507 } 508 509 static int 510 div_disconnect(struct socket *so) 511 { 512 if (!(so->so_state & SS_ISCONNECTED)) 513 return ENOTCONN; 514 return div_abort(so); 515 } 516 517 static int 518 div_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 519 { 520 int error; 521 522 /* 523 * in_pcbbind assumes that nam is a sockaddr_in 524 * and in_pcbbind requires a valid address. Since divert 525 * sockets don't we need to make sure the address is 526 * filled in properly. 527 * XXX -- divert should not be abusing in_pcbind 528 * and should probably have its own family. 529 */ 530 if (nam->sa_family != AF_INET) { 531 error = EAFNOSUPPORT; 532 } else { 533 ((struct sockaddr_in *)nam)->sin_addr.s_addr = INADDR_ANY; 534 error = in_pcbbind(so->so_pcb, nam, td); 535 } 536 return error; 537 } 538 539 static int 540 div_shutdown(struct socket *so) 541 { 542 socantsendmore(so); 543 return 0; 544 } 545 546 static int 547 div_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 548 struct mbuf *control, struct thread *td) 549 { 550 /* Length check already done in ip_mport() */ 551 KASSERT(m->m_len >= sizeof(struct ip), ("IP header not in one mbuf")); 552 553 /* Send packet */ 554 return div_output(so, m, (struct sockaddr_in *)nam, control); 555 } 556 557 SYSCTL_DECL(_net_inet_divert); 558 SYSCTL_PROC(_net_inet_divert, OID_AUTO, pcblist, CTLFLAG_RD, &divcbinfo, 0, 559 in_pcblist_global, "S,xinpcb", "List of active divert sockets"); 560 561 struct pr_usrreqs div_usrreqs = { 562 .pru_abort = div_abort, 563 .pru_accept = pru_accept_notsupp, 564 .pru_attach = div_attach, 565 .pru_bind = div_bind, 566 .pru_connect = pru_connect_notsupp, 567 .pru_connect2 = pru_connect2_notsupp, 568 .pru_control = in_control, 569 .pru_detach = div_detach, 570 .pru_disconnect = div_disconnect, 571 .pru_listen = pru_listen_notsupp, 572 .pru_peeraddr = in_setpeeraddr, 573 .pru_rcvd = pru_rcvd_notsupp, 574 .pru_rcvoob = pru_rcvoob_notsupp, 575 .pru_send = div_send, 576 .pru_sense = pru_sense_null, 577 .pru_shutdown = div_shutdown, 578 .pru_sockaddr = in_setsockaddr, 579 .pru_sosend = sosend, 580 .pru_soreceive = soreceive, 581 .pru_sopoll = sopoll 582 }; 583 584 static struct mbuf * 585 ip_divert_out(struct mbuf *m, int tee) 586 { 587 struct mbuf *clone = NULL; 588 struct ip *ip = mtod(m, struct ip *); 589 590 /* Clone packet if we're doing a 'tee' */ 591 if (tee) 592 clone = m_dup(m, MB_DONTWAIT); 593 594 /* 595 * XXX 596 * delayed checksums are not currently compatible 597 * with divert sockets. 598 */ 599 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 600 in_delayed_cksum(m); 601 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 602 } 603 604 /* Restore packet header fields to original values */ 605 ip->ip_len = htons(ip->ip_len); 606 ip->ip_off = htons(ip->ip_off); 607 608 /* Deliver packet to divert input routine */ 609 divert_packet(m, 0); 610 611 /* If 'tee', continue with original packet */ 612 return clone; 613 } 614 615 static struct mbuf * 616 ip_divert_in(struct mbuf *m, int tee) 617 { 618 struct mbuf *clone = NULL; 619 struct ip *ip = mtod(m, struct ip *); 620 struct m_tag *mtag; 621 622 if (ip->ip_off & (IP_MF | IP_OFFMASK)) { 623 const struct divert_info *divinfo; 624 u_short frag_off; 625 int hlen; 626 627 /* 628 * Only trust divert info in the fragment 629 * at offset 0. 630 */ 631 frag_off = ip->ip_off << 3; 632 if (frag_off != 0) { 633 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL); 634 m_tag_delete(m, mtag); 635 } 636 637 /* 638 * Attempt reassembly; if it succeeds, proceed. 639 * ip_reass() will return a different mbuf. 640 */ 641 m = ip_reass(m); 642 if (m == NULL) 643 return NULL; 644 ip = mtod(m, struct ip *); 645 646 /* Caller need to redispatch the packet, if it is for us */ 647 m->m_pkthdr.fw_flags |= FW_MBUF_REDISPATCH; 648 649 /* 650 * Get the header length of the reassembled 651 * packet 652 */ 653 hlen = IP_VHL_HL(ip->ip_vhl) << 2; 654 655 /* 656 * Restore original checksum before diverting 657 * packet 658 */ 659 ip->ip_len += hlen; 660 ip->ip_len = htons(ip->ip_len); 661 ip->ip_off = htons(ip->ip_off); 662 ip->ip_sum = 0; 663 if (hlen == sizeof(struct ip)) 664 ip->ip_sum = in_cksum_hdr(ip); 665 else 666 ip->ip_sum = in_cksum(m, hlen); 667 ip->ip_off = ntohs(ip->ip_off); 668 ip->ip_len = ntohs(ip->ip_len); 669 670 /* 671 * Only use the saved divert info 672 */ 673 mtag = m_tag_find(m, PACKET_TAG_IPFW_DIVERT, NULL); 674 if (mtag == NULL) { 675 /* Wrongly configured ipfw */ 676 kprintf("ip_input no divert info\n"); 677 m_freem(m); 678 return NULL; 679 } 680 divinfo = m_tag_data(mtag); 681 tee = divinfo->tee; 682 } 683 684 /* 685 * Divert or tee packet to the divert protocol if 686 * required. 687 */ 688 689 /* Clone packet if we're doing a 'tee' */ 690 if (tee) 691 clone = m_dup(m, MB_DONTWAIT); 692 693 /* 694 * Restore packet header fields to original 695 * values 696 */ 697 ip->ip_len = htons(ip->ip_len); 698 ip->ip_off = htons(ip->ip_off); 699 700 /* Deliver packet to divert input routine */ 701 divert_packet(m, 1); 702 703 /* Catch invalid reference */ 704 m = NULL; 705 ip = NULL; 706 707 ipstat.ips_delivered++; 708 709 /* If 'tee', continue with original packet */ 710 if (clone != NULL) { 711 /* 712 * Complete processing of the packet. 713 * XXX Better safe than sorry, remove the DIVERT tag. 714 */ 715 mtag = m_tag_find(clone, PACKET_TAG_IPFW_DIVERT, NULL); 716 KKASSERT(mtag != NULL); 717 m_tag_delete(clone, mtag); 718 } 719 return clone; 720 } 721 722 static struct mbuf * 723 ip_divert(struct mbuf *m, int tee, int incoming) 724 { 725 struct mbuf *ret; 726 727 if (incoming) 728 ret = ip_divert_in(m, tee); 729 else 730 ret = ip_divert_out(m, tee); 731 return ret; 732 } 733