summaryrefslogtreecommitdiffstats
path: root/sbin/routed/rdisc.c
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>1999-05-02 13:14:16 +0000
committermarkm <markm@FreeBSD.org>1999-05-02 13:14:16 +0000
commitc74fc4e83b599157005f6adfcfebde46851bd0d4 (patch)
treee8f3c95ddb4dcfbbc332816196635e042e72873b /sbin/routed/rdisc.c
parenta60c9cfa3a8359247f7ca33b3ebc8574c5c7194a (diff)
downloadFreeBSD-src-c74fc4e83b599157005f6adfcfebde46851bd0d4.zip
FreeBSD-src-c74fc4e83b599157005f6adfcfebde46851bd0d4.tar.gz
Merge-o-matic and add a bunch of $Id's
Diffstat (limited to 'sbin/routed/rdisc.c')
-rw-r--r--sbin/routed/rdisc.c166
1 files changed, 96 insertions, 70 deletions
diff --git a/sbin/routed/rdisc.c b/sbin/routed/rdisc.c
index 89efd2c..4d54b33 100644
--- a/sbin/routed/rdisc.c
+++ b/sbin/routed/rdisc.c
@@ -11,7 +11,7 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
+ * must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
@@ -29,21 +29,22 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * $Id$
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
-#endif
-static const char rcsid[] =
- "$Id$";
-#endif /* not lint */
-
#include "defs.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
+#if !defined(sgi) && !defined(__NetBSD__)
+static char sccsid[] __attribute__((unused)) = "@(#)rdisc.c 8.1 (Berkeley) x/y/95";
+#elif defined(__NetBSD__)
+__RCSID"$NetBSD$");
+#endif
+#ident "$Revision: 2.17 $"
+
/* router advertisement ICMP packet */
struct icmp_ad {
u_int8_t icmp_type; /* type of message */
@@ -80,7 +81,7 @@ struct timeval rdisc_timer;
int rdisc_ok; /* using solicited route */
-#define MAX_ADS 5
+#define MAX_ADS 16 /* at least one per interface */
struct dr { /* accumulated advertisements */
struct interface *dr_ifp;
naddr dr_gate; /* gateway */
@@ -90,8 +91,13 @@ struct dr { /* accumulated advertisements */
n_long dr_pref; /* preference adjusted by metric */
} *cur_drp, drs[MAX_ADS];
-/* adjust preference by interface metric without driving it to infinity */
-#define PREF(p, ifp) ((p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \
+/* convert between signed, balanced around zero,
+ * and unsigned zero-based preferences */
+#define SIGN_PREF(p) ((p) ^ MIN_PreferenceLevel)
+#define UNSIGN_PREF(p) SIGN_PREF(p)
+/* adjust unsigned preference by interface metric,
+ * without driving it to infinity */
+#define PREF(p, ifp) ((int)(p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \
: (p) - ((ifp)->int_metric))
static void rdisc_sort(void);
@@ -100,7 +106,7 @@ static void rdisc_sort(void);
/* dump an ICMP Router Discovery Advertisement Message
*/
static void
-trace_rdisc(char *act,
+trace_rdisc(const char *act,
naddr from,
naddr to,
struct interface *ifp,
@@ -138,7 +144,7 @@ trace_rdisc(char *act,
trace_act("%s Router Solic. from %s to %s via %s value=%#x",
act, naddr_ntoa(from), naddr_ntoa(to),
ifp ? ifp->int_name : "?",
- ntohl(p->so.icmp_so_rsvd));
+ (int)ntohl(p->so.icmp_so_rsvd));
}
}
@@ -184,7 +190,7 @@ set_rdisc_mg(struct interface *ifp,
if (ifp->int_if_flags & IFF_POINTOPOINT)
return;
#endif
- bzero(&m, sizeof(m));
+ memset(&m, 0, sizeof(m));
m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
? ifp->int_dstaddr
: ifp->int_addr);
@@ -297,7 +303,7 @@ rdisc_age(naddr bad_gate)
/* If only advertising, then do only that. */
if (supplier) {
- /* if switching from client to server, get rid of old
+ /* If switching from client to server, get rid of old
* default routes.
*/
if (cur_drp != 0)
@@ -337,14 +343,17 @@ rdisc_age(naddr bad_gate)
}
}
- /* delete old redirected routes to keep the kernel table small
- */
- sec = (cur_drp == 0) ? MaxMaxAdvertiseInterval : cur_drp->dr_life;
- del_redirects(bad_gate, now.tv_sec-sec);
-
rdisc_sol();
-
rdisc_sort();
+
+ /* Delete old redirected routes to keep the kernel table small,
+ * and to prevent black holes. Check that the kernel table
+ * matches the daemon table (i.e. has the default route).
+ * But only if RIP is not running and we are not dealing with
+ * a bad gateway, since otherwise age() will be called.
+ */
+ if (rip_sock < 0 && bad_gate == 0)
+ age(0);
}
@@ -360,10 +369,12 @@ if_bad_rdisc(struct interface *ifp)
if (drp->dr_ifp != ifp)
continue;
drp->dr_recv_pref = 0;
+ drp->dr_ts = 0;
drp->dr_life = 0;
}
- rdisc_sort();
+ /* make a note to re-solicit, turn RIP on or off, etc. */
+ rdisc_timer.tv_sec = 0;
}
@@ -389,10 +400,11 @@ static void
del_rdisc(struct dr *drp)
{
struct interface *ifp;
+ naddr gate;
int i;
- del_redirects(drp->dr_gate, 0);
+ del_redirects(gate = drp->dr_gate, 0);
drp->dr_ts = 0;
drp->dr_life = 0;
@@ -411,13 +423,21 @@ del_rdisc(struct dr *drp)
* then solicit a new one.
* This is contrary to RFC 1256, but defends against black holes.
*/
- if (i == 0
- && ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) {
- trace_act("discovered route is bad--re-solicit routers via %s",
- ifp->int_name);
+ if (i != 0) {
+ trace_act("discovered router %s via %s"
+ " is bad--have %d remaining",
+ naddr_ntoa(gate), ifp->int_name, i);
+ } else if (ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) {
+ trace_act("last discovered router %s via %s"
+ " is bad--re-solicit",
+ naddr_ntoa(gate), ifp->int_name);
ifp->int_rdisc_cnt = 0;
ifp->int_rdisc_timer.tv_sec = 0;
rdisc_sol();
+ } else {
+ trace_act("last discovered router %s via %s"
+ " is bad--wait to solicit",
+ naddr_ntoa(gate), ifp->int_name);
}
}
@@ -430,9 +450,10 @@ rdisc_sort(void)
{
struct dr *drp, *new_drp;
struct rt_entry *rt;
+ struct rt_spare new;
struct interface *ifp;
- u_int new_st;
- n_long new_pref;
+ u_int new_st = 0;
+ n_long new_pref = 0;
/* Find the best discovered route.
@@ -490,23 +511,20 @@ rdisc_sort(void)
if (rt != 0
&& (rt->rt_state & RS_RDISC)) {
+ new = rt->rt_spares[0];
+ new.rts_metric = HOPCNT_INFINITY;
+ new.rts_time = now.tv_sec - GARBAGE_TIME;
rtchange(rt, rt->rt_state & ~RS_RDISC,
- rt->rt_gate, rt->rt_router,
- HOPCNT_INFINITY, 0, rt->rt_ifp,
- now.tv_sec - GARBAGE_TIME, 0);
+ &new, 0);
rtswitch(rt, 0);
}
- /* turn on RIP if permitted */
- rip_on(0);
-
} else {
if (cur_drp == 0) {
trace_act("turn on Router Discovery client"
" using %s via %s",
naddr_ntoa(new_drp->dr_gate),
new_drp->dr_ifp->int_name);
-
rdisc_ok = 1;
} else {
@@ -518,27 +536,28 @@ rdisc_sort(void)
new_drp->dr_ifp->int_name);
}
+ memset(&new, 0, sizeof(new));
+ new.rts_ifp = new_drp->dr_ifp;
+ new.rts_gate = new_drp->dr_gate;
+ new.rts_router = new_drp->dr_gate;
+ new.rts_metric = HOPCNT_INFINITY-1;
+ new.rts_time = now.tv_sec;
if (rt != 0) {
- rtchange(rt, rt->rt_state | RS_RDISC,
- new_drp->dr_gate, new_drp->dr_gate,
- 0,0, new_drp->dr_ifp,
- now.tv_sec, 0);
+ rtchange(rt, rt->rt_state | RS_RDISC, &new, 0);
} else {
- rtadd(RIP_DEFAULT, 0,
- new_drp->dr_gate, new_drp->dr_gate,
- HOPCNT_INFINITY-1, 0,
- RS_RDISC, new_drp->dr_ifp);
+ rtadd(RIP_DEFAULT, 0, RS_RDISC, &new);
}
-
- /* Now turn off RIP and delete RIP routes,
- * which might otherwise include the default
- * we just modified.
- */
- rip_off();
}
cur_drp = new_drp;
}
+
+ /* turn RIP on or off */
+ if (!rdisc_ok || rip_interfaces > 1) {
+ rip_on(0);
+ } else {
+ rip_off();
+ }
}
@@ -547,7 +566,7 @@ rdisc_sort(void)
static void
parse_ad(naddr from,
naddr gate,
- n_long pref,
+ n_long pref, /* signed and in network order */
u_short life,
struct interface *ifp)
{
@@ -578,9 +597,9 @@ parse_ad(naddr from,
/* Convert preference to an unsigned value
* and later bias it by the metric of the interface.
*/
- pref = ntohl(pref) ^ MIN_PreferenceLevel;
+ pref = UNSIGN_PREF(ntohl(pref));
- if (pref == 0 || life == 0) {
+ if (pref == 0 || life < MinMaxAdvertiseInterval) {
pref = 0;
life = 0;
}
@@ -671,16 +690,16 @@ static void
send_rdisc(union ad_u *p,
int p_size,
struct interface *ifp,
- naddr dst, /* 0 or UNICAST destination */
+ naddr dst, /* 0 or unicast destination */
int type) /* 0=unicast, 1=bcast, 2=mcast */
{
struct sockaddr_in sin;
int flags;
- char *msg;
+ const char *msg;
naddr tgt_mcast;
- bzero(&sin, sizeof(sin));
+ memset(&sin, 0, sizeof(sin));
sin.sin_addr.s_addr = dst;
sin.sin_family = AF_INET;
#ifdef _HAVE_SIN_LEN
@@ -689,7 +708,7 @@ send_rdisc(union ad_u *p,
flags = MSG_DONTROUTE;
switch (type) {
- case 0: /* UNICAST */
+ case 0: /* unicast */
default:
msg = "Send";
break;
@@ -765,23 +784,27 @@ send_rdisc(union ad_u *p,
*/
static void
send_adv(struct interface *ifp,
- naddr dst, /* 0 or UNICAST destination */
+ naddr dst, /* 0 or unicast destination */
int type) /* 0=unicast, 1=bcast, 2=mcast */
{
union ad_u u;
n_long pref;
- bzero(&u,sizeof(u.ad));
+ memset(&u, 0, sizeof(u.ad));
u.ad.icmp_type = ICMP_ROUTERADVERT;
u.ad.icmp_ad_num = 1;
u.ad.icmp_ad_asize = sizeof(u.ad.icmp_ad_info[0])/4;
u.ad.icmp_ad_life = stopint ? 0 : htons(ifp->int_rdisc_int*3);
- pref = ifp->int_rdisc_pref ^ MIN_PreferenceLevel;
- pref = PREF(pref, ifp) ^ MIN_PreferenceLevel;
- u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(pref);
+
+ /* Convert the configured preference to an unsigned value,
+ * bias it by the interface metric, and then send it as a
+ * signed, network byte order value.
+ */
+ pref = UNSIGN_PREF(ifp->int_rdisc_pref);
+ u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(SIGN_PREF(PREF(pref, ifp)));
u.ad.icmp_ad_info[0].icmp_ad_addr = ifp->int_addr;
@@ -851,7 +874,7 @@ rdisc_sol(void)
continue;
if (!timercmp(&ifp->int_rdisc_timer, &now, >)) {
- bzero(&u,sizeof(u.so));
+ memset(&u, 0, sizeof(u.so));
u.so.icmp_type = ICMP_ROUTERSOLICIT;
u.so.icmp_cksum = in_cksum((u_short*)&u.so,
sizeof(u.so));
@@ -875,14 +898,14 @@ rdisc_sol(void)
/* check the IP header of a possible Router Discovery ICMP packet */
static struct interface * /* 0 if bad */
-ck_icmp(char *act,
+ck_icmp(const char *act,
naddr from,
struct interface *ifp,
naddr to,
union ad_u *p,
u_int len)
{
- char *type;
+ const char *type;
if (p->icmp.icmp_type == ICMP_ROUTERADVERT) {
@@ -988,7 +1011,7 @@ read_d(void)
switch (p->icmp.icmp_type) {
case ICMP_ROUTERADVERT:
if (p->ad.icmp_ad_asize*4
- < sizeof(p->ad.icmp_ad_info[0])) {
+ < (int)sizeof(p->ad.icmp_ad_info[0])) {
msglim(&bad_asize, from.sin_addr.s_addr,
"intolerable rdisc address size=%d",
p->ad.icmp_ad_asize);
@@ -998,9 +1021,10 @@ read_d(void)
trace_pkt(" empty?");
continue;
}
- if (cc != (sizeof(p->ad) - sizeof(p->ad.icmp_ad_info)
- + (p->ad.icmp_ad_num
- * sizeof(p->ad.icmp_ad_info[0])))) {
+ if (cc != (int)(sizeof(p->ad)
+ - sizeof(p->ad.icmp_ad_info)
+ + (p->ad.icmp_ad_num
+ * sizeof(p->ad.icmp_ad_info[0])))) {
msglim(&bad_len, from.sin_addr.s_addr,
"rdisc length %d does not match ad_num"
" %d", cc, p->ad.icmp_ad_num);
@@ -1027,6 +1051,8 @@ read_d(void)
continue;
if (ifp->int_state & IS_NO_ADV_OUT)
continue;
+ if (stopint)
+ continue;
/* XXX
* We should handle messages from address 0.
OpenPOWER on IntegriCloud