Made router discovery at least build and run. There are a few things

left to do (e.g. it doesn't yet run on systems with aliased addresses)
but this should work for simple configurations.

I don't plan to enable the rdisc directory in the sbin/ makefile until
I get feedback on this and add the missing features, so please, if you
have routers that perform router discovery, or if your FreeBSD box is
itself a router, give this a try.
This commit is contained in:
Bill Fenner 1996-01-19 01:28:30 +00:00
parent 4840541232
commit f78623a989
3 changed files with 81 additions and 56 deletions

8
sbin/rdisc/Makefile Normal file
View File

@ -0,0 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 6/5/93
PROG= rdisc
MAN8= rdisc.8
BINOWN= root
BINMODE=555
.include <bsd.prog.mk>

View File

@ -43,14 +43,6 @@
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
/*
* The next include contains all defs and structures for multicast
* that are not in SunOS 4.1.x. On a SunOS 4.1.x system none of this code
* is ever used because it does not support multicast
* Fraser Gardiner - Sun Microsystems Australia
*/
#include "rdisc.h"
#include <netdb.h>
#include <arpa/inet.h>
@ -96,21 +88,6 @@ static int join();
#define MAXIFS 32
/* For router advertisement */
struct icmp_ra {
u_char icmp_type; /* type of message, see below */
u_char icmp_code; /* type sub code */
u_short icmp_cksum; /* ones complement cksum of struct */
u_char icmp_num_addrs;
u_char icmp_wpa; /* Words per address */
short icmp_lifetime;
};
struct icmp_ra_addr {
u_long addr;
u_long preference;
};
/* Router constants */
#define MAX_INITIAL_ADVERT_INTERVAL 16
#define MAX_INITIAL_ADVERTISEMENTS 3
@ -517,7 +494,7 @@ advertise(sin)
struct sockaddr_in *sin;
{
static u_char outpack[MAXPACKET];
register struct icmp_ra *rap = (struct icmp_ra *) ALLIGN(outpack);
register struct icmp *rap = (struct icmp *) ALLIGN(outpack);
struct icmp_ra_addr *ap;
int packetlen, i, cc;
@ -541,8 +518,8 @@ advertise(sin)
* each address.)
*/
ap = (struct icmp_ra_addr *)ALLIGN(outpack + ICMP_MINLEN);
ap->addr = interfaces[i].localaddr.s_addr;
ap->preference = interfaces[i].preference;
ap->ira_addr = interfaces[i].localaddr.s_addr;
ap->ira_preference = interfaces[i].preference;
packetlen += rap->icmp_wpa * 4;
rap->icmp_num_addrs++;
@ -681,7 +658,7 @@ struct sockaddr_in *from;
}
switch (icp->icmp_type) {
case ICMP_ROUTER_ADVERTISEMENT: {
struct icmp_ra *rap = (struct icmp_ra *)ALLIGN(icp);
struct icmp *rap = (struct icmp *)ALLIGN(icp);
struct icmp_ra_addr *ap;
if (responder)
@ -736,6 +713,7 @@ struct sockaddr_in *from;
rap->icmp_num_addrs * rap->icmp_wpa * 4);
return;
}
rap->icmp_lifetime = ntohs(rap->icmp_lifetime);
if (rap->icmp_lifetime < 4) {
if (verbose)
logtrace("ICMP %s from %s: Lifetime = %d\n",
@ -758,15 +736,15 @@ struct sockaddr_in *from;
ap = (struct icmp_ra_addr *)
ALLIGN(buf + hlen + ICMP_MINLEN +
i * rap->icmp_wpa * 4);
ina.s_addr = ntohl(ap->addr);
ina.s_addr = ap->ira_addr;
if (verbose)
logtrace("\taddress %s, preference 0x%x\n",
pr_name(ina),
ntohl(ap->preference));
ntohl(ap->ira_preference));
if (!responder) {
if (is_directly_connected(ina))
record_router(ina,
(long)ntohl(ap->preference),
(long)ntohl(ap->ira_preference),
rap->icmp_lifetime);
}
}
@ -988,7 +966,7 @@ isbroadcast(sin)
ismulticast(sin)
struct sockaddr_in *sin;
{
return (IN_CLASSD(sin->sin_addr.s_addr));
return (IN_CLASSD(ntohl(sin->sin_addr.s_addr)));
}
/* From libc/rpc/pmap_rmt.c */
@ -1114,7 +1092,7 @@ initifs()
{
int sock;
struct ifconf ifc;
struct ifreq ifreq, *ifr;
struct ifreq ifreq, *ifrp, *ifend;
struct sockaddr_in *sin;
int n, i;
char *buf;
@ -1140,6 +1118,7 @@ initifs()
(void) close(sock);
return;
}
bzero(buf, bufsize);
if (interfaces)
interfaces = (struct interface *)ALLIGN(realloc((char *)interfaces,
numifs * sizeof(struct interface)));
@ -1162,14 +1141,18 @@ initifs()
(void) free(buf);
return;
}
ifr = ifc.ifc_req;
for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) {
ifreq = *ifr;
ifrp = (struct ifreq *)buf;
ifend = (struct ifreq *)(buf + ifc.ifc_len);
for (i = 0; ifrp < ifend; ifrp = (struct ifreq *)((char *)ifrp + n)) {
ifreq = *ifrp;
if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
logperror("initifs: ioctl (get interface flags)");
continue;
}
if (ifr->ifr_addr.sa_family != AF_INET)
n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
if (n < sizeof(*ifrp))
n = sizeof(*ifrp);
if (ifrp->ifr_addr.sa_family != AF_INET)
continue;
if ((ifreq.ifr_flags & IFF_UP) == 0)
continue;
@ -1177,7 +1160,7 @@ initifs()
continue;
if ((ifreq.ifr_flags & (IFF_MULTICAST | IFF_BROADCAST)) == 0)
continue;
sin = (struct sockaddr_in *)ALLIGN(&ifr->ifr_addr);
sin = (struct sockaddr_in *)ALLIGN(&ifrp->ifr_addr);
interfaces[i].localaddr = sin->sin_addr;
interfaces[i].flags = ifreq.ifr_flags;
interfaces[i].netmask.s_addr = (unsigned long)0xffffffff;
@ -1461,7 +1444,11 @@ add_route(addr)
{
if (debug)
logdebug("Add default route to %s\n", pr_name(addr));
#if 1
rtioctl(addr, RTM_ADD);
#else
rtioctl(addr, SIOCADDRT);
#endif
}
void
@ -1470,7 +1457,11 @@ del_route(addr)
{
if (debug)
logdebug("Delete default route to %s\n", pr_name(addr));
#if 1
rtioctl(addr, RTM_DELETE);
#else
rtioctl(addr, SIOCDELRT);
#endif
}
void
@ -1479,7 +1470,48 @@ rtioctl(addr, op)
int op;
{
int sock;
#if 1
struct {
struct rt_msghdr m_rtm;
struct sockaddr_in m_dst;
struct sockaddr_in m_gateway;
struct sockaddr_in m_netmask;
} m_rtmsg;
static int seq = 0;
bzero(&m_rtmsg, sizeof(m_rtmsg));
#define rtm m_rtmsg.m_rtm
rtm.rtm_type = op;
rtm.rtm_flags = RTF_GATEWAY | RTF_UP; /* XXX more? */
rtm.rtm_version = RTM_VERSION;
rtm.rtm_seq = ++seq;
rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
bzero(&rtm.rtm_rmx, sizeof(rtm.rtm_rmx)); /* XXX ??? */
rtm.rtm_inits = 0;
rtm.rtm_msglen = sizeof(m_rtmsg);
m_rtmsg.m_dst.sin_len = m_rtmsg.m_gateway.sin_len =
sizeof(struct sockaddr_in);
m_rtmsg.m_netmask.sin_len = 0;
m_rtmsg.m_dst.sin_family = m_rtmsg.m_gateway.sin_family =
m_rtmsg.m_netmask.sin_family = AF_INET;
m_rtmsg.m_dst.sin_addr.s_addr = 0; /* default */
m_rtmsg.m_netmask.sin_addr.s_addr = 0; /* default */
m_rtmsg.m_gateway.sin_addr = addr; /* gateway */
sock = socket(PF_ROUTE, SOCK_RAW, 0);
if (sock < 0) {
logperror("rtioctl: socket");
return;
}
if (write(sock, &m_rtmsg, sizeof(m_rtmsg)) != sizeof(m_rtmsg)) {
logperror("rtioctl: write");
return;
}
close(sock);
#else
struct rtentry rt;
struct sockaddr_in *sin;
bzero((char *)&rt, sizeof(struct rtentry));
rt.rt_dst.sa_family = AF_INET;
@ -1498,6 +1530,7 @@ rtioctl(addr, op)
logperror("ioctl (add/delete route)");
}
(void) close(sock);
#endif
}
@ -1549,7 +1582,10 @@ logdebug(fmt, a,b,c,d,e,f,g,h)
(void) fprintf(stdout, fmt, a,b,c,d,e,f,g,h);
}
#if 0
extern char *sys_errlist[];
#endif
extern int errno;
void

View File

@ -1,19 +0,0 @@
/* From net/if.h */
#define IFF_MULTICAST 0x800 /* supports multicast */
/* From netinet/in.h */
#define INADDR_ALLHOSTS_GROUP (u_long)0xe0000001 /* 224.0.0.1 */
#define IP_MULTICAST_IF 0x10 /* set/get IP multicast interface */
#define IP_ADD_MEMBERSHIP 0x13 /* add an IP group membership */
#define IP_MULTICAST_TTL 0x11 /* set/get IP multicast timetolive */
/*
* Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
*/
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};