summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2012-05-25 02:58:21 +0000
committerbz <bz@FreeBSD.org>2012-05-25 02:58:21 +0000
commitf528e8d71f3a9fe1953f7fb822571d3050531acb (patch)
tree0bd1111f10078073af5b1bb69fec7060b0465f47
parent36fe475aa40328c1d04ccc35a5549fcacdb7dfad (diff)
downloadFreeBSD-src-f528e8d71f3a9fe1953f7fb822571d3050531acb.zip
FreeBSD-src-f528e8d71f3a9fe1953f7fb822571d3050531acb.tar.gz
MFp4 bz_ipv6_fast:
Factor out Hop-By-Hop option processing. It's still not heavily used, it reduces the footprint of ip6_input() and makes ip6_input() more readable. Sponsored by: The FreeBSD Foundation Sponsored by: iXsystems Reviewed by: gnn (as part of the whole) MFC After: 3 days
-rw-r--r--sys/netinet6/ip6_input.c143
1 files changed, 80 insertions, 63 deletions
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 2d2860b..0451888 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -331,6 +331,83 @@ ip6_init2(void *dummy)
/* This must be after route_init(), which is now SI_ORDER_THIRD */
SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
+static int
+ip6_input_hbh(struct mbuf *m, uint32_t *plen, uint32_t *rtalert, int *off,
+ int *nxt, int *ours)
+{
+ struct ip6_hdr *ip6;
+ struct ip6_hbh *hbh;
+
+ if (ip6_hopopts_input(plen, rtalert, &m, off)) {
+#if 0 /*touches NULL pointer*/
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
+#endif
+ goto out; /* m have already been freed */
+ }
+
+ /* adjust pointer */
+ ip6 = mtod(m, struct ip6_hdr *);
+
+ /*
+ * if the payload length field is 0 and the next header field
+ * indicates Hop-by-Hop Options header, then a Jumbo Payload
+ * option MUST be included.
+ */
+ if (ip6->ip6_plen == 0 && *plen == 0) {
+ /*
+ * Note that if a valid jumbo payload option is
+ * contained, ip6_hopopts_input() must set a valid
+ * (non-zero) payload length to the variable plen.
+ */
+ V_ip6stat.ip6s_badoptions++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
+ icmp6_error(m, ICMP6_PARAM_PROB,
+ ICMP6_PARAMPROB_HEADER,
+ (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
+ goto out;
+ }
+#ifndef PULLDOWN_TEST
+ /* ip6_hopopts_input() ensures that mbuf is contiguous */
+ hbh = (struct ip6_hbh *)(ip6 + 1);
+#else
+ IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
+ sizeof(struct ip6_hbh));
+ if (hbh == NULL) {
+ V_ip6stat.ip6s_tooshort++;
+ goto out;
+ }
+#endif
+ *nxt = hbh->ip6h_nxt;
+
+ /*
+ * If we are acting as a router and the packet contains a
+ * router alert option, see if we know the option value.
+ * Currently, we only support the option value for MLD, in which
+ * case we should pass the packet to the multicast routing
+ * daemon.
+ */
+ if (*rtalert != ~0) {
+ switch (*rtalert) {
+ case IP6OPT_RTALERT_MLD:
+ if (V_ip6_forwarding)
+ *ours = 1;
+ break;
+ default:
+ /*
+ * RFC2711 requires unrecognized values must be
+ * silently ignored.
+ */
+ break;
+ }
+ }
+
+ return (0);
+
+out:
+ return (1);
+}
+
void
ip6_input(struct mbuf *m)
{
@@ -825,71 +902,11 @@ passin:
*/
plen = (u_int32_t)ntohs(ip6->ip6_plen);
if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
- struct ip6_hbh *hbh;
+ int error;
- if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
-#if 0 /*touches NULL pointer*/
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
-#endif
- goto out; /* m have already been freed */
- }
-
- /* adjust pointer */
- ip6 = mtod(m, struct ip6_hdr *);
-
- /*
- * if the payload length field is 0 and the next header field
- * indicates Hop-by-Hop Options header, then a Jumbo Payload
- * option MUST be included.
- */
- if (ip6->ip6_plen == 0 && plen == 0) {
- /*
- * Note that if a valid jumbo payload option is
- * contained, ip6_hopopts_input() must set a valid
- * (non-zero) payload length to the variable plen.
- */
- V_ip6stat.ip6s_badoptions++;
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
- icmp6_error(m, ICMP6_PARAM_PROB,
- ICMP6_PARAMPROB_HEADER,
- (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
+ error = ip6_input_hbh(m, &plen, &rtalert, &off, &nxt, &ours);
+ if (error != 0)
goto out;
- }
-#ifndef PULLDOWN_TEST
- /* ip6_hopopts_input() ensures that mbuf is contiguous */
- hbh = (struct ip6_hbh *)(ip6 + 1);
-#else
- IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
- sizeof(struct ip6_hbh));
- if (hbh == NULL) {
- V_ip6stat.ip6s_tooshort++;
- goto out;
- }
-#endif
- nxt = hbh->ip6h_nxt;
-
- /*
- * If we are acting as a router and the packet contains a
- * router alert option, see if we know the option value.
- * Currently, we only support the option value for MLD, in which
- * case we should pass the packet to the multicast routing
- * daemon.
- */
- if (rtalert != ~0) {
- switch (rtalert) {
- case IP6OPT_RTALERT_MLD:
- if (V_ip6_forwarding)
- ours = 1;
- break;
- default:
- /*
- * RFC2711 requires unrecognized values must be
- * silently ignored.
- */
- break;
- }
- }
} else
nxt = ip6->ip6_nxt;
OpenPOWER on IntegriCloud