summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_options.c
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2009-03-04 02:51:22 +0000
committerbms <bms@FreeBSD.org>2009-03-04 02:51:22 +0000
commit0bcee3a566c117ffa18c27edc1dcc09cc951c10b (patch)
treede8d354ce665368c01e20a91affc2741fb4d08b9 /sys/netinet/ip_options.c
parent4fdc56d3dc7f01475ef728333f2ed348155f9107 (diff)
downloadFreeBSD-src-0bcee3a566c117ffa18c27edc1dcc09cc951c10b.zip
FreeBSD-src-0bcee3a566c117ffa18c27edc1dcc09cc951c10b.tar.gz
Add function ip_checkrouteralert(), which will be used
by IGMPv3 to check for the IPv4 Router Alert [RFC2113] option in a pulled-up IP mbuf chain.
Diffstat (limited to 'sys/netinet/ip_options.c')
-rw-r--r--sys/netinet/ip_options.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/sys/netinet/ip_options.c b/sys/netinet/ip_options.c
index 27b1569..74d54f2 100644
--- a/sys/netinet/ip_options.c
+++ b/sys/netinet/ip_options.c
@@ -683,3 +683,64 @@ bad:
(void)m_free(m);
return (EINVAL);
}
+
+/*
+ * Check for the presence of the IP Router Alert option [RFC2113]
+ * in the header of an IPv4 datagram.
+ *
+ * This call is not intended for use from the forwarding path; it is here
+ * so that protocol domains may check for the presence of the option.
+ * Given how FreeBSD's IPv4 stack is currently structured, the Router Alert
+ * option does not have much relevance to the implementation, though this
+ * may change in future.
+ * Router alert options SHOULD be passed if running in IPSTEALTH mode and
+ * we are not the endpoint.
+ * Length checks on individual options should already have been peformed
+ * by ip_dooptions() therefore they are folded under INVARIANTS here.
+ *
+ * Return zero if not present or options are invalid, non-zero if present.
+ */
+int
+ip_checkrouteralert(struct mbuf *m)
+{
+ struct ip *ip = mtod(m, struct ip *);
+ u_char *cp;
+ int opt, optlen, cnt, found_ra;
+
+ found_ra = 0;
+ cp = (u_char *)(ip + 1);
+ cnt = (ip->ip_hl << 2) - sizeof (struct ip);
+ for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ opt = cp[IPOPT_OPTVAL];
+ if (opt == IPOPT_EOL)
+ break;
+ if (opt == IPOPT_NOP)
+ optlen = 1;
+ else {
+#ifdef INVARIANTS
+ if (cnt < IPOPT_OLEN + sizeof(*cp))
+ break;
+#endif
+ optlen = cp[IPOPT_OLEN];
+#ifdef INVARIANTS
+ if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt)
+ break;
+#endif
+ }
+ switch (opt) {
+ case IPOPT_RA:
+#ifdef INVARIANTS
+ if (optlen != IPOPT_OFFSET + sizeof(uint16_t) ||
+ (*((uint16_t *)&cp[IPOPT_OFFSET]) != 0))
+ break;
+ else
+#endif
+ found_ra = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return (found_ra);
+}
OpenPOWER on IntegriCloud