summaryrefslogtreecommitdiffstats
path: root/usr.sbin/routed/rdisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/routed/rdisc.c')
-rw-r--r--usr.sbin/routed/rdisc.c84
1 files changed, 60 insertions, 24 deletions
diff --git a/usr.sbin/routed/rdisc.c b/usr.sbin/routed/rdisc.c
index f4cb219..489da11 100644
--- a/usr.sbin/routed/rdisc.c
+++ b/usr.sbin/routed/rdisc.c
@@ -31,10 +31,12 @@
* SUCH DAMAGE.
*/
-#if !defined(lint) && !defined(sgi)
-static const char rcsid[] =
- "$Id: rdisc.c,v 1.2 1996/06/15 17:10:27 wollman Exp $";
-#endif /* not lint */
+#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
+#elif defined(__NetBSD__)
+static char rcsid[] = "$NetBSD$";
+#endif
+#ident "$Revision: 1.1.3.3 $"
#include "defs.h"
#include <netinet/in_systm.h>
@@ -43,12 +45,12 @@ static const char rcsid[] =
/* router advertisement ICMP packet */
struct icmp_ad {
- u_char icmp_type; /* type of message */
- u_char icmp_code; /* type sub code */
- u_short icmp_cksum; /* ones complement cksum of struct */
- u_char icmp_ad_num; /* # of following router addresses */
- u_char icmp_ad_asize; /* 2--words in each advertisement */
- u_short icmp_ad_life; /* seconds of validity */
+ u_int8_t icmp_type; /* type of message */
+ u_int8_t icmp_code; /* type sub code */
+ u_int16_t icmp_cksum; /* ones complement cksum of struct */
+ u_int8_t icmp_ad_num; /* # of following router addresses */
+ u_int8_t icmp_ad_asize; /* 2--words in each advertisement */
+ u_int16_t icmp_ad_life; /* seconds of validity */
struct icmp_ad_info {
n_long icmp_ad_addr;
n_long icmp_ad_pref;
@@ -57,10 +59,10 @@ struct icmp_ad {
/* router solicitation ICMP packet */
struct icmp_so {
- u_char icmp_type; /* type of message */
- u_char icmp_code; /* type sub code */
- u_short icmp_cksum; /* ones complement cksum of struct */
- n_long icmp_so_rsvd;
+ u_int8_t icmp_type; /* type of message */
+ u_int8_t icmp_code; /* type sub code */
+ u_int16_t icmp_cksum; /* ones complement cksum of struct */
+ n_long icmp_so_rsvd;
};
union ad_u {
@@ -126,7 +128,7 @@ trace_rdisc(char *act,
lim = &wp[(len - sizeof(p->ad)) / sizeof(*wp)];
for (i = 0; i < p->ad.icmp_ad_num && wp <= lim; i++) {
(void)fprintf(ftrace, "\t%s preference=%#x",
- naddr_ntoa(wp[0]), ntohl(wp[1]));
+ naddr_ntoa(wp[0]), (int)ntohl(wp[1]));
wp += p->ad.icmp_ad_asize;
}
(void)fputc('\n',ftrace);
@@ -140,6 +142,20 @@ trace_rdisc(char *act,
}
}
+/* prepare Router Discovery socket.
+ */
+static void
+get_rdisc_sock(void)
+{
+ if (rdisc_sock < 0) {
+ rdisc_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ if (rdisc_sock < 0)
+ BADERR(1,"rdisc_sock = socket()");
+ fix_sock(rdisc_sock,"rdisc_sock");
+ fix_select();
+ }
+}
+
/* Pick multicast group for router-discovery socket
*/
@@ -148,8 +164,17 @@ set_rdisc_mg(struct interface *ifp,
int on) { /* 0=turn it off */
struct ip_mreq m;
- if (rdisc_sock == -1
- || !(ifp->int_if_flags & IFF_MULTICAST)
+ if (rdisc_sock < 0) {
+ /* Create the raw socket so that we can hear at least
+ * broadcast router discovery packets.
+ */
+ if ((ifp->int_state & IS_NO_RDISC) == IS_NO_RDISC
+ || !on)
+ return;
+ get_rdisc_sock();
+ }
+
+ if (!(ifp->int_if_flags & IFF_MULTICAST)
|| (ifp->int_state & IS_ALIAS)) {
ifp->int_state &= ~(IS_ALL_HOSTS | IS_ALL_ROUTERS);
return;
@@ -166,7 +191,8 @@ set_rdisc_mg(struct interface *ifp,
if (supplier
|| (ifp->int_state & IS_NO_ADV_IN)
|| !on) {
- /* stop listening to advertisements */
+ /* stop listening to advertisements
+ */
if (ifp->int_state & IS_ALL_HOSTS) {
m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
if (setsockopt(rdisc_sock, IPPROTO_IP,
@@ -177,7 +203,8 @@ set_rdisc_mg(struct interface *ifp,
}
} else if (!(ifp->int_state & IS_ALL_HOSTS)) {
- /* start listening to advertisements */
+ /* start listening to advertisements
+ */
m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&m, sizeof(m)) < 0) {
@@ -190,7 +217,8 @@ set_rdisc_mg(struct interface *ifp,
if (!supplier
|| (ifp->int_state & IS_NO_ADV_OUT)
|| !on) {
- /* stop listening to solicitations */
+ /* stop listening to solicitations
+ */
if (ifp->int_state & IS_ALL_ROUTERS) {
m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP);
if (setsockopt(rdisc_sock, IPPROTO_IP,
@@ -201,7 +229,8 @@ set_rdisc_mg(struct interface *ifp,
}
} else if (!(ifp->int_state & IS_ALL_ROUTERS)) {
- /* start hearing solicitations */
+ /* start hearing solicitations
+ */
m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP);
if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&m, sizeof(m)) < 0) {
@@ -540,12 +569,12 @@ parse_ad(naddr from,
/* ignore pointers to ourself and routes via unreachable networks
*/
if (ifwithaddr(gate, 1, 0) != 0) {
- trace_pkt("\tdiscard our own Router Discovery Ad\n");
+ trace_pkt("\tdiscard Router Discovery Ad pointing at us\n");
return;
}
if (!on_net(gate, ifp->int_net, ifp->int_mask)) {
trace_pkt("\tdiscard Router Discovery Ad"
- " from unreachable net\n");
+ " toward unreachable net\n");
return;
}
@@ -553,7 +582,7 @@ parse_ad(naddr from,
* and later bias it by the metric of the interface.
*/
pref = ntohl(pref) ^ MIN_PreferenceLevel;
-
+
if (pref == 0 || life == 0) {
pref = 0;
life = 0;
@@ -656,6 +685,10 @@ send_rdisc(union ad_u *p,
bzero(&sin, sizeof(sin));
sin.sin_addr.s_addr = dst;
+ sin.sin_family = AF_INET;
+#ifdef _HAVE_SIN_LEN
+ sin.sin_len = sizeof(sin);
+#endif
flags = MSG_DONTROUTE;
switch (type) {
@@ -710,6 +743,9 @@ send_rdisc(union ad_u *p,
break;
}
+ if (rdisc_sock < 0)
+ get_rdisc_sock();
+
trace_rdisc(msg, ifp->int_addr, sin.sin_addr.s_addr, ifp,
p, p_size);
OpenPOWER on IntegriCloud