From owner-p4-projects@FreeBSD.ORG Mon Nov 24 16:38:04 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 5E04216A4D1; Mon, 24 Nov 2003 16:38:04 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3721B16A4CE for ; Mon, 24 Nov 2003 16:38:04 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2C5994400D for ; Mon, 24 Nov 2003 16:37:46 -0800 (PST) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.9/8.12.9) with ESMTP id hAP0bjXJ040786 for ; Mon, 24 Nov 2003 16:37:45 -0800 (PST) (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.9/8.12.9/Submit) id hAP0bjqu040783 for perforce@freebsd.org; Mon, 24 Nov 2003 16:37:45 -0800 (PST) (envelope-from sam@freebsd.org) Date: Mon, 24 Nov 2003 16:37:45 -0800 (PST) Message-Id: <200311250037.hAP0bjqu040783@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 43019 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Nov 2003 00:38:04 -0000 http://perforce.freebsd.org/chv.cgi?CH=43019 Change 43019 by sam@sam_ebb on 2003/11/24 16:37:31 replace MT_TAG mbufs by m_tag's for divert sockets; move divert-related definitions to a new ip_divert.h file Affected files ... .. //depot/projects/netperf/sys/net/if_ethersubr.c#13 edit .. //depot/projects/netperf/sys/netinet/in_proto.c#7 edit .. //depot/projects/netperf/sys/netinet/ip_divert.c#18 edit .. //depot/projects/netperf/sys/netinet/ip_divert.h#1 add .. //depot/projects/netperf/sys/netinet/ip_fastfwd.c#4 edit .. //depot/projects/netperf/sys/netinet/ip_fw.h#5 edit .. //depot/projects/netperf/sys/netinet/ip_fw2.c#19 edit .. //depot/projects/netperf/sys/netinet/ip_input.c#26 edit .. //depot/projects/netperf/sys/netinet/ip_output.c#19 edit .. //depot/projects/netperf/sys/netinet/ip_var.h#14 edit Differences ... ==== //depot/projects/netperf/sys/net/if_ethersubr.c#13 (text+ko) ==== @@ -393,7 +393,6 @@ args.m = m; /* the packet we are looking at */ args.oif = dst; /* destination, if any */ - args.divert_rule = 0; /* we do not support divert yet */ args.rule = *rule; /* matching rule to restart */ args.next_hop = NULL; /* we do not support forward yet */ args.eh = &save_eh; /* MAC header for bridged/MAC packets */ ==== //depot/projects/netperf/sys/netinet/in_proto.c#7 (text+ko) ==== @@ -57,6 +57,7 @@ #include #include #include +#include #include #ifdef PIM #include ==== //depot/projects/netperf/sys/netinet/ip_divert.c#18 (text+ko) ==== @@ -68,6 +68,7 @@ #include #include #include +#include #include /* @@ -150,17 +151,21 @@ * then pass them along with mbuf chain. */ void -divert_packet(struct mbuf *m, int incoming, int port, int rule) +divert_packet(struct mbuf *m, int incoming) { struct ip *ip; struct inpcb *inp; struct socket *sa; u_int16_t nport; struct sockaddr_in divsrc; + struct m_tag *mtag; - /* Sanity check */ - KASSERT(port != 0, ("%s: port=0", __func__)); - + mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); + if (mtag == NULL) { + printf("%s: no divert tag\n", __func__); + m_freem(m); + return; + } /* Assure header */ if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == 0) @@ -174,7 +179,7 @@ bzero(&divsrc, sizeof(divsrc)); divsrc.sin_len = sizeof(divsrc); divsrc.sin_family = AF_INET; - divsrc.sin_port = rule; /* record matching rule */ + divsrc.sin_port = divert_cookie(mtag); /* record matching rule */ if (incoming) { struct ifaddr *ifa; @@ -234,7 +239,7 @@ mtx_lock(&Giant); /* Put packet on socket queue, if any */ sa = NULL; - nport = htons((u_int16_t)port); + nport = htons((u_int16_t)divert_info(mtag)); INP_INFO_RLOCK(&divcbinfo); LIST_FOREACH(inp, &divcb, inp_list) { INP_LOCK(inp); @@ -273,19 +278,8 @@ struct sockaddr_in *sin, struct mbuf *control) { int error = 0; - struct m_hdr divert_tag; - /* - * Prepare the tag for divert info. Note that a packet - * with a 0 tag in mh_data is effectively untagged, - * so we could optimize that case. - */ - divert_tag.mh_type = MT_TAG; - divert_tag.mh_flags = PACKET_TAG_DIVERT; - divert_tag.mh_next = m; - divert_tag.mh_data = 0; /* the matching rule # */ - divert_tag.mh_nextpkt = NULL; - m->m_pkthdr.rcvif = NULL; /* XXX is it necessary ? */ + KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null")); #ifdef MAC mac_create_mbuf_from_socket(so, m); @@ -296,9 +290,21 @@ /* Loopback avoidance and state recovery */ if (sin) { + struct m_tag *mtag; + struct divert_tag *dt; int i; - divert_tag.mh_data = (caddr_t)(uintptr_t)sin->sin_port; + mtag = m_tag_get(PACKET_TAG_DIVERT, + sizeof(struct divert_tag), M_NOWAIT); + if (mtag == NULL) { + error = ENOBUFS; + goto cantsend; + } + dt = (struct divert_tag *)(mtag+1); + dt->info = 0; + dt->cookie = sin->sin_port; + m_tag_prepend(m, mtag); + /* * Find receive interface with the given name, stuffed * (if it exists) in the sin_zero[] field. @@ -335,7 +341,7 @@ /* Send packet to output processing */ ipstat.ips_rawout++; /* XXX */ - error = ip_output((struct mbuf *)&divert_tag, + error = ip_output(m, inp->inp_options, NULL, (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST | IP_RAWOUTPUT, @@ -362,7 +368,7 @@ m->m_pkthdr.rcvif = ifa->ifa_ifp; } /* Send packet to input processing */ - ip_input((struct mbuf *)&divert_tag); + ip_input(m); } return error; @@ -372,6 +378,27 @@ return error; } +/* + * Return a copy of the specified packet, but without + * the divert tag. This is used when packets are ``tee'd'' + * and we want the cloned copy to not have divert processing. + */ +struct mbuf * +divert_clone(struct mbuf *m) +{ + struct mbuf *clone; + struct m_tag *mtag; + + clone = m_dup(m, M_DONTWAIT); + if (clone != NULL) { + /* strip divert tag from copy */ + mtag = m_tag_find(clone, PACKET_TAG_DIVERT, NULL); + if (mtag != NULL) + m_tag_delete(clone, mtag); + } + return clone; +} + static int div_attach(struct socket *so, int proto, struct thread *td) { ==== //depot/projects/netperf/sys/netinet/ip_fastfwd.c#4 (text+ko) ==== @@ -110,6 +110,7 @@ #include #include +#include #include static int ipfastforward_active = 0; @@ -373,25 +374,13 @@ /* * See if this is a fragment */ - if (ip->ip_off & (IP_MF | IP_OFFMASK)) { - MGETHDR(tag, M_DONTWAIT, MT_TAG); - if (tag == NULL) - goto drop; - tag->m_flags = PACKET_TAG_DIVERT; - tag->m_data = (caddr_t)(intptr_t)args.divert_rule; - tag->m_next = m; - /* XXX: really bloody hack, see ip_input */ - tag->m_nextpkt = (struct mbuf *)1; - m = tag; - tag = NULL; - + if (ip->ip_off & (IP_MF | IP_OFFMASK)) goto droptoours; - } /* * Tee packet */ if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) - teem = m_dup(m, M_DONTWAIT); + teem = divert_clone(m); else teem = m; if (teem == NULL) @@ -413,7 +402,7 @@ /* * Deliver packet to divert input routine */ - divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule); + divert_packet(teem, 0); /* * If this was not tee, we are done */ @@ -560,27 +549,13 @@ /* * See if this is a fragment */ - if (ip->ip_off & (IP_MF | IP_OFFMASK)) { - MGETHDR(tag, M_DONTWAIT, MT_TAG); - if (tag == NULL) { - RTFREE(ro.ro_rt); - goto drop; - } - tag->m_flags = PACKET_TAG_DIVERT; - tag->m_data = (caddr_t)(intptr_t)args.divert_rule; - tag->m_next = m; - /* XXX: really bloody hack, see ip_input */ - tag->m_nextpkt = (struct mbuf *)1; - m = tag; - tag = NULL; - + if (ip->ip_off & (IP_MF | IP_OFFMASK)) goto droptoours; - } /* * Tee packet */ if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) - teem = m_dup(m, M_DONTWAIT); + teem = divert_clone(m); else teem = m; if (teem == NULL) @@ -602,7 +577,7 @@ /* * Deliver packet to divert input routine */ - divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule); + divert_packet(teem, 0); /* * If this was not tee, we are done */ ==== //depot/projects/netperf/sys/netinet/ip_fw.h#5 (text+ko) ==== @@ -400,7 +400,6 @@ int flags; /* for dummynet */ struct ipfw_flow_id f_id; /* grabbed from IP header */ - u_int16_t divert_rule; /* divert cookie */ u_int32_t retval; }; ==== //depot/projects/netperf/sys/netinet/ip_fw2.c#19 (text+ko) ==== @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -1462,6 +1463,7 @@ int dyn_dir = MATCH_UNKNOWN; ipfw_dyn_rule *q = NULL; struct ip_fw_chain *chain = &layer3_chain; + struct m_tag *mtag; if (m->m_flags & M_SKIP_FIREWALL) return 0; /* accept */ @@ -1550,6 +1552,7 @@ after_ip_checks: IPFW_LOCK(chain); /* XXX expensive? can we run lock free? */ + mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); if (args->rule) { /* * Packet has already been tagged. Look for the next rule @@ -1572,7 +1575,7 @@ * Find the starting rule. It can be either the first * one, or the one after divert_rule if asked so. */ - int skipto = args->divert_rule; + int skipto = mtag ? divert_cookie(mtag) : 0; f = chain->rules; if (args->eh == NULL && skipto != 0) { @@ -1588,7 +1591,9 @@ } } } - args->divert_rule = 0; /* reset to avoid confusion later */ + /* reset divert rule to avoid confusion later */ + if (mtag) + m_tag_delete(m, mtag); /* * Now scan the rules, and parse microinstructions for each rule. @@ -2023,14 +2028,29 @@ goto done; case O_DIVERT: - case O_TEE: + case O_TEE: { + struct divert_tag *dt; + if (args->eh) /* not on layer 2 */ break; - args->divert_rule = f->rulenum; - retval = (cmd->opcode == O_DIVERT) ? + mtag = m_tag_get(PACKET_TAG_DIVERT, + sizeof(struct divert_tag), + M_NOWAIT); + if (mtag == NULL) { + /* XXX statistic */ + /* drop packet */ + IPFW_UNLOCK(chain); + return IP_FW_PORT_DENY_FLAG; + } + dt = (struct divert_tag *)(mtag+1); + dt->cookie = f->rulenum; + dt->info = (cmd->opcode == O_DIVERT) ? cmd->arg1 : cmd->arg1 | IP_FW_PORT_TEE_FLAG; + m_tag_prepend(m, mtag); + retval = dt->info; goto done; + } case O_COUNT: case O_SKIPTO: ==== //depot/projects/netperf/sys/netinet/ip_input.c#26 (text+ko) ==== @@ -78,6 +78,7 @@ #include #include +#include #include #ifdef IPSEC @@ -239,8 +240,7 @@ static void ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop); static void ip_freef(struct ipqhead *, struct ipq *); -static struct mbuf *ip_reass(struct mbuf *, struct ipqhead *, - struct ipq *, u_int32_t *, u_int16_t *); +static struct mbuf *ip_reass(struct mbuf *, struct ipqhead *, struct ipq *); /* * IP initialization: fill in IP protocol switch table. @@ -303,7 +303,9 @@ int ours = 0; u_short sum; struct in_addr pkt_dst; - u_int32_t divert_info = 0; /* packet divert/tee info */ +#ifdef IPDIVERT + u_int32_t divert_info; /* packet divert/tee info */ +#endif struct ip_fw_args args; int dchg = 0; /* dest changed after fw */ #ifdef PFIL_HOOKS @@ -318,7 +320,6 @@ args.eh = NULL; args.oif = NULL; - args.divert_rule = 0; /* divert cookie */ args.next_hop = NULL; /* @@ -339,10 +340,6 @@ m->_m_tag_id); break; - case PACKET_TAG_DIVERT: - args.divert_rule = (intptr_t)m->m_hdr.mh_data & 0xffff; - break; - case PACKET_TAG_IPFORWARD: args.next_hop = (struct sockaddr_in *)m->m_hdr.mh_data; break; @@ -527,7 +524,6 @@ #ifdef IPDIVERT if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) { /* Divert or tee packet */ - divert_info = i; goto ours; } #endif @@ -835,13 +831,11 @@ /* * Attempt reassembly; if it succeeds, proceed. - * ip_reass() will return a different mbuf, and update - * the divert info in divert_info and args.divert_rule. + * ip_reass() will return a different mbuf. */ ipstat.ips_fragments++; m->m_pkthdr.header = ip; - m = ip_reass(m, - &ipq[sum], fp, &divert_info, &args.divert_rule); + m = ip_reass(m, &ipq[sum], fp); IPQ_UNLOCK(); if (m == 0) return; @@ -851,7 +845,7 @@ hlen = ip->ip_hl << 2; #ifdef IPDIVERT /* Restore original checksum before diverting packet */ - if (divert_info != 0) { + if (divert_find_info(m) != 0) { ip->ip_len += hlen; ip->ip_len = htons(ip->ip_len); ip->ip_off = htons(ip->ip_off); @@ -872,12 +866,15 @@ /* * Divert or tee packet to the divert protocol if required. */ + divert_info = divert_find_info(m); if (divert_info != 0) { - struct mbuf *clone = NULL; + struct mbuf *clone; /* Clone packet if we're doing a 'tee' */ if ((divert_info & IP_FW_PORT_TEE_FLAG) != 0) - clone = m_dup(m, M_DONTWAIT); + clone = divert_clone(m); + else + clone = NULL; /* Restore packet header fields to original values */ ip->ip_len += hlen; @@ -885,7 +882,7 @@ ip->ip_off = htons(ip->ip_off); /* Deliver packet to divert input routine */ - divert_packet(m, 1, divert_info & 0xffff, args.divert_rule); + divert_packet(m, 1); ipstat.ips_delivered++; /* If 'tee', continue with original packet */ @@ -896,12 +893,11 @@ ip->ip_len += hlen; /* * Jump backwards to complete processing of the - * packet. But first clear divert_info to avoid - * entering this block again. - * We do not need to clear args.divert_rule - * or args.next_hop as they will not be used. + * packet. We do not need to clear args.next_hop + * as that will not be used again and the cloned packet + * doesn't contain a divert packet tag so we won't + * re-entry this block. */ - divert_info = 0; goto pass; } #endif @@ -995,8 +991,7 @@ */ static struct mbuf * -ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp, - u_int32_t *divinfo, u_int16_t *divert_rule) +ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp) { struct ip *ip = mtod(m, struct ip *); register struct mbuf *p, *q, *nq; @@ -1038,10 +1033,6 @@ fp->ipq_dst = ip->ip_dst; fp->ipq_frags = m; m->m_nextpkt = NULL; -#ifdef IPDIVERT - fp->ipq_div_info = 0; - fp->ipq_div_cookie = 0; -#endif goto inserted; } else { fp->ipq_nfrags++; @@ -1125,16 +1116,15 @@ inserted: #ifdef IPDIVERT - /* - * Transfer firewall instructions to the fragment structure. - * Only trust info in the fragment at offset 0. - */ - if (ip->ip_off == 0) { - fp->ipq_div_info = *divinfo; - fp->ipq_div_cookie = *divert_rule; + if (ip->ip_off != 0) { + /* + * Strip any divert information; only the info + * on the first fragment is used/kept. + */ + struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL); + if (mtag) + m_tag_delete(m, mtag); } - *divinfo = 0; - *divert_rule = 0; #endif /* @@ -1200,15 +1190,7 @@ mac_destroy_ipq(fp); #endif -#ifdef IPDIVERT /* - * Extract firewall instructions from the fragment structure. - */ - *divinfo = fp->ipq_div_info; - *divert_rule = fp->ipq_div_cookie; -#endif - - /* * Create header for new ip packet by * modifying header of first packet; * dequeue and discard fragment reassembly header. @@ -1228,10 +1210,6 @@ return (m); dropfrag: -#ifdef IPDIVERT - *divinfo = 0; - *divert_rule = 0; -#endif ipstat.ips_fragdropped++; if (fp != NULL) fp->ipq_nfrags--; ==== //depot/projects/netperf/sys/netinet/ip_output.c#19 (text+ko) ==== @@ -90,6 +90,7 @@ #endif /*FAST_IPSEC*/ #include +#include #include #define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\ @@ -160,7 +161,6 @@ args.eh = NULL; args.rule = NULL; args.next_hop = NULL; - args.divert_rule = 0; /* divert cookie */ /* Grab info from MT_TAG mbufs prepended to the chain. */ for (; m0 && m0->m_type == MT_TAG; m0 = m0->m_next) { @@ -170,10 +170,6 @@ m0->_m_tag_id); break; - case PACKET_TAG_DIVERT: - args.divert_rule = (intptr_t)m0->m_data & 0xffff; - break; - case PACKET_TAG_IPFORWARD: args.next_hop = (struct sockaddr_in *)m0->m_data; break; @@ -819,11 +815,13 @@ } #ifdef IPDIVERT if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) { - struct mbuf *clone = NULL; + struct mbuf *clone; /* Clone packet if we're doing a 'tee' */ if ((off & IP_FW_PORT_TEE_FLAG) != 0) - clone = m_dup(m, M_DONTWAIT); + clone = divert_clone(m); + else + clone = NULL; /* * XXX @@ -840,7 +838,7 @@ ip->ip_off = htons(ip->ip_off); /* Deliver packet to divert input routine */ - divert_packet(m, 0, off & 0xffff, args.divert_rule); + divert_packet(m, 0); /* If 'tee', continue with original packet */ if (clone != NULL) { ==== //depot/projects/netperf/sys/netinet/ip_var.h#14 (text+ko) ==== @@ -65,8 +65,6 @@ struct mbuf *ipq_frags; /* to ip headers of fragments */ struct in_addr ipq_src,ipq_dst; u_char ipq_nfrags; /* # frags in this packet */ - u_int32_t ipq_div_info; /* ipfw divert port & flags */ - u_int16_t ipq_div_cookie; /* ipfw divert cookie */ struct label *ipq_label; /* MAC label */ }; #endif /* _KERNEL */ @@ -198,14 +196,6 @@ extern void (*rsvp_input_p)(struct mbuf *m, int off); -#ifdef IPDIVERT -void div_init(void); -void div_input(struct mbuf *, int); -void div_ctlinput(int, struct sockaddr *, void *); -void divert_packet(struct mbuf *m, int incoming, int port, int rule); -extern struct pr_usrreqs div_usrreqs; -#endif - #ifdef PFIL_HOOKS extern struct pfil_head inet_pfil_hook; #endif