diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 32a13f20f896..a2b76b3c9a89 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -72,31 +72,23 @@ #define DIVSNDQ (65536 + 100) #define DIVRCVQ (65536 + 100) -/* Global variables */ - /* - * ip_input() and ip_output() set this secret value before calling us to - * let us know which divert port to divert a packet to; this is done so - * we can use the existing prototype for struct protosw's pr_input(). - * This is stored in host order. - */ -u_short ip_divert_port; - -/* - * A 16 bit cookie is passed to the user process. - * The user process can send it back to help the caller know something - * about where the packet came from. + * A 16 bit cookie is passed to and from the user process. + * The user process can send it back to help the caller know + * something about where the packet originally came from. * - * If IPFW is the caller then the cookie is the rule that sent + * In the case of ipfw, then the cookie is the rule that sent * us here. On reinjection is is the rule after which processing * should continue. Leaving it the same will make processing start * at the rule number after that which sent it here. Setting it to * 0 will restart processing at the beginning. + * + * For divert_packet(), ip_divert_cookie is an input value only. + * For div_output(), ip_divert_cookie is an output value only. */ u_int16_t ip_divert_cookie; /* Internal variables */ - static struct inpcbhead divcb; static struct inpcbinfo divcbinfo; @@ -107,7 +99,6 @@ static u_long div_recvspace = DIVRCVQ; /* XXX sysctl ? */ static struct sockaddr_in divsrc = { sizeof(divsrc), AF_INET }; /* Internal functions */ - static int div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr, struct mbuf *control); @@ -131,23 +122,36 @@ div_init(void) } /* - * Setup generic address and protocol structures - * for div_input routine, then pass them along with - * mbuf chain. ip->ip_len is assumed to have had - * the header length (hlen) subtracted out already. - * We tell whether the packet was incoming or outgoing - * by seeing if hlen == 0, which is a hack. + * IPPROTO_DIVERT is not a real IP protocol; don't allow any packets + * with that protocol number to enter the system from the outside. */ void div_input(struct mbuf *m, int hlen) +{ + ipstat.ips_noproto++; + m_freem(m); +} + +/* + * Divert a packet by passing it up to the divert socket at port 'port'. + * + * Setup generic address and protocol structures for div_input routine, + * then pass them along with mbuf chain. + */ +void +divert_packet(struct mbuf *m, int incoming, int port) { struct ip *ip; struct inpcb *inp; struct socket *sa; + u_int16_t nport; /* Sanity check */ - if (ip_divert_port == 0) - panic("div_input: port is 0"); + KASSERT(port != 0, ("%s: port=0", __FUNCTION__)); + + /* Record and reset divert cookie */ + divsrc.sin_port = ip_divert_cookie; + ip_divert_cookie = 0; /* Assure header */ if (m->m_len < sizeof(struct ip) && @@ -156,31 +160,16 @@ div_input(struct mbuf *m, int hlen) } ip = mtod(m, struct ip *); - /* Record divert cookie */ - divsrc.sin_port = ip_divert_cookie; - ip_divert_cookie = 0; - - /* Restore packet header fields */ - ip->ip_len += hlen; - HTONS(ip->ip_len); - HTONS(ip->ip_off); - /* - * Record receive interface address, if any + * Record receive interface address, if any. * But only for incoming packets. */ divsrc.sin_addr.s_addr = 0; - if (hlen) { + if (incoming) { struct ifaddr *ifa; -#ifdef DIAGNOSTIC /* Sanity check */ - if (!(m->m_flags & M_PKTHDR)) - panic("div_input: no pkt hdr"); -#endif - - /* More fields affected by ip_input() */ - HTONS(ip->ip_id); + KASSERT((m->m_flags & M_PKTHDR), ("%s: !PKTHDR", __FUNCTION__)); /* Find IP address for receive interface */ for (ifa = m->m_pkthdr.rcvif->if_addrhead.tqh_first; @@ -224,11 +213,11 @@ div_input(struct mbuf *m, int hlen) /* Put packet on socket queue, if any */ sa = NULL; + nport = htons((u_int16_t)port); for (inp = divcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { - if (inp->inp_lport == htons(ip_divert_port)) + if (inp->inp_lport == nport) sa = inp->inp_socket; } - ip_divert_port = 0; if (sa) { if (sbappendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m, (struct mbuf *)0) == 0) @@ -338,8 +327,8 @@ div_output(so, m, addr, control) return error; cantsend: - ip_divert_cookie = 0; m_freem(m); + ip_divert_cookie = 0; return error; } diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index 46c7d5403b76..a70822ebcd75 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -478,6 +478,7 @@ lookup_next_rule(struct ip_fw_chain *me) * hlen Packet header length * oif Outgoing interface, or NULL if packet is incoming * *cookie Skip up to the first rule past this rule number; + * upon return, non-zero port number for divert or tee * *m The packet; we set to NULL when/if we nuke it. * *flow_id pointer to the last matching rule (in/out) * *next_hop socket we are forwarding to (in/out). @@ -487,7 +488,13 @@ lookup_next_rule(struct ip_fw_chain *me) * 0 The packet is to be accepted and routed normally OR * the packet was denied/rejected and has been dropped; * in the latter case, *m is equal to NULL upon return. - * port Divert the packet to port. + * port Divert the packet to port, with these caveats: + * + * - If IP_FW_PORT_TEE_FLAG is set, tee the packet instead + * of diverting it (ie, 'ipfw tee'). + * + * - If IP_FW_PORT_DYNT_FLAG is set, interpret the lower + * 16 bits as a dummynet pipe number instead of diverting */ static int @@ -502,7 +509,11 @@ ip_fw_chk(struct ip **pip, int hlen, struct ifnet *const rif = (*m)->m_pkthdr.rcvif; u_short offset = 0 ; u_short src_port, dst_port; - u_int16_t skipto = *cookie; + u_int16_t skipto; + + /* Grab and reset cookie */ + skipto = *cookie; + *cookie = 0; if (pip) { /* normal ip packet */ ip = *pip; @@ -532,34 +543,37 @@ non_ip: ip = NULL ; } if (*flow_id) { - if (fw_one_pass) - return 0 ; /* accept if passed first test */ - /* - * pkt has already been tagged. Look for the next rule - * to restart processing - */ - chain = LIST_NEXT( *flow_id, chain); - if ( (chain = (*flow_id)->rule->next_rule_ptr) == NULL ) - chain = (*flow_id)->rule->next_rule_ptr = - lookup_next_rule(*flow_id) ; - if (! chain) goto dropit; - } else { - /* - * Go down the chain, looking for enlightment - * If we've been asked to start at a given rule immediatly, do so. - */ - chain = LIST_FIRST(&ip_fw_chain); - if ( skipto ) { - if (skipto >= IPFW_DEFAULT_RULE) + /* Accept if passed first test */ + if (fw_one_pass) + return 0; + + /* + * Packet has already been tagged. Look for the next rule + * to restart processing. + */ + chain = LIST_NEXT(*flow_id, chain); + + if ((chain = (*flow_id)->rule->next_rule_ptr) == NULL) + chain = (*flow_id)->rule->next_rule_ptr = + lookup_next_rule(*flow_id); + if (chain == NULL) goto dropit; - while (chain && (chain->rule->fw_number <= skipto)) { - chain = LIST_NEXT(chain, chain); + } else { + /* + * Go down the chain, looking for enlightment. + * If we've been asked to start at a given rule, do so + */ + chain = LIST_FIRST(&ip_fw_chain); + if (skipto != 0) { + if (skipto >= IPFW_DEFAULT_RULE) + goto dropit; + while (chain && chain->rule->fw_number <= skipto) + chain = LIST_NEXT(chain, chain); + if (chain == NULL) + goto dropit; } - if (! chain) goto dropit; } - } - *cookie = 0; for (; chain; chain = LIST_NEXT(chain, chain)) { register struct ip_fw * f ; again: @@ -661,8 +675,8 @@ non_ip: ip = NULL ; * here, pip==NULL for bridged pkts -- they include the ethernet * header so i have to adjust lengths accordingly */ -#define PULLUP_TO(l) do { \ - int len = (pip ? l : l + 14 ) ; \ +#define PULLUP_TO(l) do { \ + int len = (pip ? (l) : (l) + 14 ); \ if ((*m)->m_len < (len) ) { \ if ( (*m = m_pullup(*m, (len))) == 0) \ goto bogusfrag; \ @@ -706,8 +720,8 @@ non_ip: ip = NULL ; } else if (!groupmember(f->fw_gid, P->inp_socket->so_cred)) continue; - } else continue; - + } else + continue; break; } @@ -737,24 +751,14 @@ non_ip: ip = NULL ; } else if (!groupmember(f->fw_gid, P->inp_socket->so_cred)) continue; - } else continue; - + } else + continue; break; } - default: - continue; -/* - * XXX Shouldn't GCC be allowing two bogusfrag labels if they're both inside - * separate blocks? Hmm.... It seems it's got incorrect behavior here. - */ -#if 0 -bogusfrag: - if (fw_verbose) - ipfw_report(NULL, ip, rif, oif); - goto dropit; -#endif - } + default: + continue; + } } /* Protocol specific checks */ @@ -831,10 +835,14 @@ non_ip: ip = NULL ; } #undef PULLUP_TO + default: + break; + bogusfrag: - if (fw_verbose) - ipfw_report(NULL, ip, rif, oif); - goto dropit; + if (fw_verbose) + ipfw_report(NULL, ip, rif, oif); + goto dropit; + } rnd_then_got_match: @@ -865,15 +873,8 @@ non_ip: ip = NULL ; *cookie = f->fw_number; return(f->fw_divert_port); case IP_FW_F_TEE: - /* - * XXX someday tee packet here, but beware that you - * can't use m_copym() or m_copypacket() because - * the divert input routine modifies the mbuf - * (and these routines only increment reference - * counts in the case of mbuf clusters), so need - * to write custom routine. - */ - continue; + *cookie = f->fw_number; + return(f->fw_divert_port | IP_FW_PORT_TEE_FLAG); #endif case IP_FW_F_SKIPTO: /* XXX check */ if ( f->next_rule_ptr ) @@ -884,7 +885,7 @@ non_ip: ip = NULL ; goto again ; #ifdef DUMMYNET case IP_FW_F_PIPE: - return(f->fw_pipe_nr | 0x10000 ); + return(f->fw_pipe_nr | IP_FW_PORT_DYNT_FLAG); #endif #ifdef IPFIREWALL_FORWARD case IP_FW_F_FWD: @@ -968,7 +969,6 @@ non_ip: ip = NULL ; /* * Finally, drop the packet. */ - /* *cookie = 0; */ /* XXX is this necessary ? */ if (*m) { m_freem(*m); *m = NULL; diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 07ac1bb8fb6d..eb4a999d604d 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -212,6 +212,9 @@ struct ip_fw_chain { */ #ifdef KERNEL +#define IP_FW_PORT_DYNT_FLAG 0x10000 +#define IP_FW_PORT_TEE_FLAG 0x20000 + /* * Function definitions. */ diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 68d7594dedce..feb35a53f44a 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -175,26 +175,21 @@ static struct ip_srcrt { struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; } ip_srcrt; -#ifdef IPDIVERT -/* - * Shared variable between ip_input() and ip_reass() to communicate - * about which packets, once assembled from fragments, get diverted, - * and to which port. - */ -static u_short frag_divert_port; -#endif - struct sockaddr_in *ip_fw_fwd_addr; -static void save_rte __P((u_char *, struct in_addr)); -static int ip_dooptions __P((struct mbuf *)); -static void ip_forward __P((struct mbuf *, int)); -static void ip_freef __P((struct ipq *)); -static struct ip * - ip_reass __P((struct mbuf *, struct ipq *, struct ipq *)); -static struct in_ifaddr * - ip_rtaddr __P((struct in_addr)); +static void save_rte __P((u_char *, struct in_addr)); +static int ip_dooptions __P((struct mbuf *)); +static void ip_forward __P((struct mbuf *, int)); +static void ip_freef __P((struct ipq *)); +#ifdef IPDIVERT +static struct ip *ip_reass __P((struct mbuf *, + struct ipq *, struct ipq *, u_int32_t *, u_int16_t *)); +#else +static struct ip *ip_reass __P((struct mbuf *, struct ipq *, struct ipq *)); +#endif +static struct in_ifaddr *ip_rtaddr __P((struct in_addr)); static void ipintr __P((void)); + /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. @@ -245,10 +240,19 @@ ip_input(struct mbuf *m) struct in_ifaddr *ia; int i, hlen, mff; u_short sum; -#ifndef IPDIVERT /* dummy variable for the firewall code to play with */ - u_short ip_divert_cookie = 0 ; + u_int16_t divert_cookie; /* firewall cookie */ +#ifdef IPDIVERT + u_int32_t divert_info = 0; /* packet divert/tee info */ +#endif + struct ip_fw_chain *rule = NULL; + +#ifdef IPDIVERT + /* Get and reset firewall cookie */ + divert_cookie = ip_divert_cookie; + ip_divert_cookie = 0; +#else + divert_cookie = 0; #endif - struct ip_fw_chain *rule = NULL ; #if defined(IPFIREWALL) && defined(DUMMYNET) /* @@ -375,39 +379,39 @@ ip_input(struct mbuf *m) if (ip_fw_fwd_addr) goto ours; #endif /* IPFIREWALL_FORWARD */ - i = (*ip_fw_chk_ptr)(&ip, hlen, NULL, &ip_divert_cookie, - &m, &rule, &ip_fw_fwd_addr); /* - * see the comment in ip_output for the return values + * See the comment in ip_output for the return values * produced by the firewall. */ - if (!m) /* packet discarded by firewall */ - return ; - if (i == 0 && ip_fw_fwd_addr == NULL) /* common case */ - goto pass ; + i = (*ip_fw_chk_ptr)(&ip, + hlen, NULL, &divert_cookie, &m, &rule, &ip_fw_fwd_addr); + if (m == NULL) /* Packet discarded by firewall */ + return; + if (i == 0 && ip_fw_fwd_addr == NULL) /* common case */ + goto pass; #ifdef DUMMYNET - if (i & 0x10000) { - /* send packet to the appropriate pipe */ + if ((i & IP_FW_PORT_DYNT_FLAG) != 0) { + /* Send packet to the appropriate pipe */ dummynet_io(i&0xffff,DN_TO_IP_IN,m,NULL,NULL,0, rule); - return ; + return; } #endif #ifdef IPDIVERT - if (i > 0 && i < 0x10000) { - /* Divert packet */ - frag_divert_port = i & 0xffff ; + if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) { + /* Divert or tee packet */ + divert_info = i; goto ours; } #endif #ifdef IPFIREWALL_FORWARD if (i == 0 && ip_fw_fwd_addr != NULL) - goto pass ; + goto pass; #endif /* * if we get here, the packet must be dropped */ - m_freem(m); - return; + m_freem(m); + return; } pass: @@ -550,10 +554,6 @@ ip_input(struct mbuf *m) if (m->m_flags & M_EXT) { /* XXX */ if ((m = m_pullup(m, hlen)) == 0) { ipstat.ips_toosmall++; -#ifdef IPDIVERT - frag_divert_port = 0; - ip_divert_cookie = 0; -#endif #ifdef IPFIREWALL_FORWARD ip_fw_fwd_addr = NULL; #endif @@ -620,9 +620,14 @@ ip_input(struct mbuf *m) if (mff || ip->ip_off) { ipstat.ips_fragments++; m->m_pkthdr.header = ip; +#ifdef IPDIVERT + ip = ip_reass(m, + fp, &ipq[sum], &divert_info, &divert_cookie); +#else ip = ip_reass(m, fp, &ipq[sum]); +#endif if (ip == 0) { -#ifdef IPFIREWALL_FORWARD +#ifdef IPFIREWALL_FORWARD ip_fw_fwd_addr = NULL; #endif return; @@ -632,7 +637,8 @@ ip_input(struct mbuf *m) ipstat.ips_reassembled++; m = dtom(ip); #ifdef IPDIVERT - if (frag_divert_port) { + /* Restore original checksum before diverting packet */ + if (divert_info != 0) { ip->ip_len += hlen; HTONS(ip->ip_len); HTONS(ip->ip_off); @@ -653,24 +659,35 @@ ip_input(struct mbuf *m) #ifdef IPDIVERT /* - * Divert reassembled packets to the divert protocol if required - * If divert port is null then cookie should be too, - * so we shouldn't need to clear them here. Assume ip_divert does so. + * Divert or tee packet to the divert protocol if required. + * + * If divert_info is zero then cookie should be too, so we shouldn't + * need to clear them here. Assume divert_packet() does so also. */ - if (frag_divert_port) { + if (divert_info != 0) { + struct mbuf *clone = NULL; + + /* Clone packet if we're doing a 'tee' */ + if ((divert_info & IP_FW_PORT_TEE_FLAG) != 0) + clone = m_dup(m, M_DONTWAIT); + + /* Restore packet header fields to original values */ + ip->ip_len += hlen; + HTONS(ip->ip_len); + HTONS(ip->ip_off); + HTONS(ip->ip_id); + + /* Deliver packet to divert input routine */ + ip_divert_cookie = divert_cookie; + divert_packet(m, 1, divert_info & 0xffff); ipstat.ips_delivered++; - ip_divert_port = frag_divert_port; - frag_divert_port = 0; - (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, hlen); - return; - } - /* Don't let packets divert themselves */ - if (ip->ip_p == IPPROTO_DIVERT) { - ipstat.ips_noproto++; - goto bad; + /* If 'tee', continue with original packet */ + if (clone == NULL) + return; + m = clone; + ip = mtod(m, struct ip *); } - #endif /* @@ -711,16 +728,27 @@ ipintr(void) NETISR_SET(NETISR_IP, ipintr); /* - * Take incoming datagram fragment and try to - * reassemble it into whole datagram. If a chain for - * reassembly of this datagram already exists, then it - * is given as fp; otherwise have to make a chain. + * Take incoming datagram fragment and try to reassemble it into + * whole datagram. If a chain for reassembly of this datagram already + * exists, then it is given as fp; otherwise have to make a chain. + * + * When IPDIVERT enabled, keep additional state with each packet that + * tells us if we need to divert or tee the packet we're building. */ + static struct ip * +#ifdef IPDIVERT +ip_reass(m, fp, where, divinfo, divcookie) +#else ip_reass(m, fp, where) +#endif register struct mbuf *m; register struct ipq *fp; struct ipq *where; +#ifdef IPDIVERT + u_int32_t *divinfo; + u_int16_t *divcookie; +#endif { struct ip *ip = mtod(m, struct ip *); register struct mbuf *p = 0, *q, *nq; @@ -752,7 +780,7 @@ ip_reass(m, fp, where) fp->ipq_frags = m; m->m_nextpkt = NULL; #ifdef IPDIVERT - fp->ipq_divert = 0; + fp->ipq_div_info = 0; fp->ipq_div_cookie = 0; #endif goto inserted; @@ -812,14 +840,13 @@ ip_reass(m, fp, where) #ifdef IPDIVERT /* - * Any fragment diverting causes the whole packet to divert + * Transfer firewall instructions to the fragment structure. + * Any fragment diverting causes the whole packet to divert. */ - if (frag_divert_port) { - fp->ipq_divert = frag_divert_port; - fp->ipq_div_cookie = ip_divert_cookie; - } - frag_divert_port = 0; - ip_divert_cookie = 0; + fp->ipq_div_info = *divinfo; + fp->ipq_div_cookie = *divcookie; + *divinfo = 0; + *divcookie = 0; #endif /* @@ -863,10 +890,10 @@ ip_reass(m, fp, where) #ifdef IPDIVERT /* - * extract divert port for packet, if any + * Extract firewall instructions from the fragment structure. */ - frag_divert_port = fp->ipq_divert; - ip_divert_cookie = fp->ipq_div_cookie; + *divinfo = fp->ipq_div_info; + *divcookie = fp->ipq_div_cookie; #endif /* @@ -894,8 +921,8 @@ ip_reass(m, fp, where) dropfrag: #ifdef IPDIVERT - frag_divert_port = 0; - ip_divert_cookie = 0; + *divinfo = 0; + *divcookie = 0; #endif ipstat.ips_fragdropped++; m_freem(m); diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 32200c1e1186..2ed22e6ba8c4 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -123,15 +123,20 @@ ip_output(m0, opt, ro, flags, imo) struct sockaddr_in *dst; struct in_ifaddr *ia; int isbroadcast; + u_int16_t divert_cookie; /* firewall cookie */ #ifdef IPFIREWALL_FORWARD int fwd_rewrite_src = 0; #endif - -#ifndef IPDIVERT /* dummy variable for the firewall code to play with */ - u_short ip_divert_cookie = 0 ; + struct ip_fw_chain *rule = NULL; + +#ifdef IPDIVERT + /* Get and reset firewall cookie */ + divert_cookie = ip_divert_cookie; + ip_divert_cookie = 0; +#else + divert_cookie = 0; #endif - struct ip_fw_chain *rule = NULL ; - + #if defined(IPFIREWALL) && defined(DUMMYNET) /* * dummynet packet are prepended a vestigial mbuf with @@ -418,12 +423,13 @@ ip_output(m0, opt, ro, flags, imo) struct sockaddr_in *old = dst; off = (*ip_fw_chk_ptr)(&ip, - hlen, ifp, &ip_divert_cookie, &m, &rule, &dst); + hlen, ifp, &divert_cookie, &m, &rule, &dst); /* * On return we must do the following: * m == NULL -> drop the pkt * 1<=off<= 0xffff -> DIVERT * (off & 0x10000) -> send to a DUMMYNET pipe + * (off & 0x20000) -> TEE the packet * dst != old -> IPFIREWALL_FORWARD * off==0, dst==old -> accept * If some of the above modules is not compiled in, then @@ -439,7 +445,7 @@ ip_output(m0, opt, ro, flags, imo) if (off == 0 && dst == old) /* common case */ goto pass ; #ifdef DUMMYNET - if (off & 0x10000) { + if ((off & IP_FW_PORT_DYNT_FLAG) != 0) { /* * pass the pkt to dummynet. Need to include * pipe number, m, ifp, ro, dst because these are @@ -454,9 +460,27 @@ ip_output(m0, opt, ro, flags, imo) } #endif #ifdef IPDIVERT - if (off > 0 && off < 0x10000) { /* Divert packet */ - ip_divert_port = off & 0xffff ; - (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, 0); + if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) { + struct mbuf *clone = NULL; + + /* Clone packet if we're doing a 'tee' */ + if ((off & IP_FW_PORT_TEE_FLAG) != 0) + clone = m_dup(m, M_DONTWAIT); + + /* Restore packet header fields to original values */ + HTONS(ip->ip_len); + HTONS(ip->ip_off); + + /* Deliver packet to divert input routine */ + ip_divert_cookie = divert_cookie; + divert_packet(m, 0, off & 0xffff); + + /* If 'tee', continue with original packet */ + if (clone != NULL) { + m = clone; + ip = mtod(m, struct ip *); + goto pass; + } goto done; } #endif diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 1b69ec24847b..c56a34090bad 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -62,8 +62,8 @@ struct ipq { struct mbuf *ipq_frags; /* to ip headers of fragments */ struct in_addr ipq_src,ipq_dst; #ifdef IPDIVERT - u_short ipq_divert; /* divert protocol port */ - u_short ipq_div_cookie; /* divert protocol cookie */ + u_int32_t ipq_div_info; /* ipfw divert port & flags */ + u_int16_t ipq_div_cookie; /* ipfw divert cookie */ #endif }; @@ -179,9 +179,9 @@ void ip_rsvp_force_done __P((struct socket *)); #ifdef IPDIVERT void div_init __P((void)); void div_input __P((struct mbuf *, int)); +void divert_packet __P((struct mbuf *, int, int)); extern struct pr_usrreqs div_usrreqs; -extern u_short ip_divert_port; -extern u_short ip_divert_cookie; +extern u_int16_t ip_divert_cookie; #endif extern struct sockaddr_in *ip_fw_fwd_addr;