From ab953dfa18ca35c9330577b7dd054f98517f0645 Mon Sep 17 00:00:00 2001 From: mpi Date: Mon, 12 May 2014 09:15:00 +0000 Subject: [PATCH] Includes a router altert option (RAO) in IGMP packets. Without this option, required by the RFC2236, some L3 switches do not examine the packets. Based on FreeBSD's r14622 via Florian Riehm on tech@. ok bluhm@, jca@ --- sys/netinet/igmp.c | 33 ++++++++++++++++++++++++++++----- sys/netinet/ip.h | 3 ++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 5c53f557b03..0bc618ad0ab 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: igmp.c,v 1.39 2014/04/21 12:22:26 henning Exp $ */ +/* $OpenBSD: igmp.c,v 1.40 2014/05/12 09:15:00 mpi Exp $ */ /* $NetBSD: igmp.c,v 1.15 1996/02/13 23:41:25 christos Exp $ */ /* @@ -103,6 +103,7 @@ int *igmpctl_vars[IGMPCTL_MAXID] = IGMPCTL_VARS; int igmp_timers_are_running; static struct router_info *rti_head; +static struct mbuf *router_alert; struct igmpstat igmpstat; void igmp_checktimer(struct ifnet *); @@ -113,12 +114,34 @@ struct router_info * rti_find(struct ifnet *); void igmp_init(void) { + struct ipoption *ra; - /* - * To avoid byte-swapping the same value over and over again. - */ igmp_timers_are_running = 0; rti_head = 0; + + router_alert = m_get(M_DONTWAIT, MT_DATA); + if (router_alert == NULL) { + printf("%s: no mbuf\n", __func__); + return; + } + + /* + * Construct a Router Alert option (RAO) to use in report + * messages as required by RFC2236. This option has the + * following format: + * + * | 10010100 | 00000100 | 2 octet value | + * + * where a value of "0" indicates that routers shall examine + * the packet. + */ + ra = mtod(router_alert, struct ipoption *); + ra->ipopt_dst.s_addr = INADDR_ANY; + ra->ipopt_list[0] = IPOPT_RA; + ra->ipopt_list[1] = 0x04; + ra->ipopt_list[2] = 0x00; + ra->ipopt_list[3] = 0x00; + router_alert->m_len = sizeof(ra->ipopt_dst) + ra->ipopt_list[1]; } /* Return -1 for error. */ @@ -634,7 +657,7 @@ igmp_sendpkt(struct in_multi *inm, int type, in_addr_t addr) imo.imo_multicast_loop = 0; #endif /* MROUTING */ - ip_output(m, NULL, NULL, IP_MULTICASTOPTS, &imo, NULL, 0); + ip_output(m, router_alert, NULL, IP_MULTICASTOPTS, &imo, NULL, 0); ++igmpstat.igps_snd_reports; } diff --git a/sys/netinet/ip.h b/sys/netinet/ip.h index fc6c0bea3f4..16a06272fea 100644 --- a/sys/netinet/ip.h +++ b/sys/netinet/ip.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip.h,v 1.14 2013/10/24 15:21:21 deraadt Exp $ */ +/* $OpenBSD: ip.h,v 1.15 2014/05/12 09:15:00 mpi Exp $ */ /* $NetBSD: ip.h,v 1.9 1995/05/15 01:22:44 cgd Exp $ */ /* @@ -150,6 +150,7 @@ struct ip { #define IPOPT_LSRR 131 /* loose source route */ #define IPOPT_SATID 136 /* satnet id */ #define IPOPT_SSRR 137 /* strict source route */ +#define IPOPT_RA 148 /* router alert */ /* * Offsets to fields in options other than EOL and NOP. -- 2.20.1