use new kerninfo instead of SIOCGCONF, routing socket instead of
authorKeith Sklower <sklower@ucbvax.Berkeley.EDU>
Fri, 21 Feb 1992 03:59:57 +0000 (19:59 -0800)
committerKeith Sklower <sklower@ucbvax.Berkeley.EDU>
Fri, 21 Feb 1992 03:59:57 +0000 (19:59 -0800)
SIOC{ADD,DEL}RT; edit only, can't test for a while.

SCCS-vsn: sbin/XNSrouted/tables.c 5.10
SCCS-vsn: sbin/XNSrouted/startup.c 5.12
SCCS-vsn: sbin/XNSrouted/main.c 5.12
SCCS-vsn: sbin/XNSrouted/defs.h 5.10

usr/src/sbin/XNSrouted/defs.h
usr/src/sbin/XNSrouted/main.c
usr/src/sbin/XNSrouted/startup.c
usr/src/sbin/XNSrouted/tables.c

index 1994bed..c76732d 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)defs.h      5.9 (Berkeley) %G%
+ *     @(#)defs.h      5.10 (Berkeley) %G%
  */
 
 #include <sys/types.h>
  */
 
 #include <sys/types.h>
@@ -51,6 +51,8 @@ int   performnlist;           /* if 1 check if /vmunix has changed */
 int    externalinterfaces;     /* # of remote and local interfaces */
 int    timeval;                /* local idea of time */
 int    noteremoterequests;     /* squawk on requests from non-local nets */
 int    externalinterfaces;     /* # of remote and local interfaces */
 int    timeval;                /* local idea of time */
 int    noteremoterequests;     /* squawk on requests from non-local nets */
+int    r;                      /* Routing socket to install updates with */
+struct sockaddr_ns ns_netmask; /* Used in installing routes */
 
 char   packet[MAXPACKETSIZE+sizeof(struct idp)+1];
 struct rip *msg;
 
 char   packet[MAXPACKETSIZE+sizeof(struct idp)+1];
 struct rip *msg;
@@ -60,3 +62,7 @@ char  **argv0;
 int    sndmsg();
 int    supply();
 int    cleanup();
 int    sndmsg();
 int    supply();
 int    cleanup();
+int    rtioctl();
+#define        ADD     1
+#define        DELETE  2
+#define CHANGE 3
index c1d92e4..af89713 100644 (file)
@@ -15,7 +15,7 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     5.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     5.12 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -92,10 +92,20 @@ main(argc, argv)
 #endif
        openlog("XNSrouted", LOG_PID, LOG_DAEMON);
 
 #endif
        openlog("XNSrouted", LOG_PID, LOG_DAEMON);
 
-       ns_anynet.s_net[0] = -1; ns_anynet.s_net[1] = -1;
        addr.sns_family = AF_NS;
        addr.sns_len = sizeof(addr);
        addr.sns_port = htons(IDPPORT_RIF);
        addr.sns_family = AF_NS;
        addr.sns_len = sizeof(addr);
        addr.sns_port = htons(IDPPORT_RIF);
+       ns_anynet.s_net[0] = ns_anynet.s_net[1] = -1;
+       ns_netmask.sns_addr.x_net = ns_anynet;
+       ns_netmask.sns_len = 6;
+       r = socket(AF_ROUTE, SOCK_RAW, 0);
+       /* later, get smart about lookingforinterfaces */
+       if (r)
+               shutdown(r, 0); /* for now, don't want reponses */
+       else {
+               fprintf(stderr, "routed: no routing socket\n");
+               exit(1);
+       }
        s = getsocket(SOCK_DGRAM, 0, &addr);
        if (s < 0)
                exit(1);
        s = getsocket(SOCK_DGRAM, 0, &addr);
        if (s < 0)
                exit(1);
index bbd9178..cfa831f 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)startup.c  5.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)startup.c  5.12 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -17,7 +17,9 @@ static char sccsid[] = "@(#)startup.c 5.11 (Berkeley) %G%";
  */
 #include "defs.h"
 #include <sys/ioctl.h>
  */
 #include "defs.h"
 #include <sys/ioctl.h>
+#include <sys/kinfo.h>
 #include <net/if.h>
 #include <net/if.h>
+#include <net/if_dl.h>
 #include <nlist.h>
 #include <stdlib.h>
 
 #include <nlist.h>
 #include <stdlib.h>
 
@@ -29,6 +31,48 @@ int  externalinterfaces = 0;         /* # of remote and local interfaces */
 char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 
 char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 
+void
+quit(s)
+       char *s;
+{
+       extern int errno;
+       int sverrno = errno;
+
+       (void) fprintf(stderr, "route: ");
+       if (s)
+               (void) fprintf(stderr, "%s: ", s);
+       (void) fprintf(stderr, "%s\n", strerror(sverrno));
+       exit(1);
+       /* NOTREACHED */
+}
+
+struct rt_addrinfo info;
+/* Sleazy use of local variables throughout file, warning!!!! */
+#define netmask        info.rti_info[RTAX_NETMASK]
+#define ifaaddr        info.rti_info[RTAX_IFA]
+#define brdaddr        info.rti_info[RTAX_BRD]
+
+#define ROUNDUP(a) \
+       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+void
+rt_xaddrs(cp, cplim, rtinfo)
+       register caddr_t cp, cplim;
+       register struct rt_addrinfo *rtinfo;
+{
+       register struct sockaddr *sa;
+       register int i;
+
+       bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
+       for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
+               if ((rtinfo->rti_addrs & (1 << i)) == 0)
+                       continue;
+               rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
+               ADVANCE(cp, sa);
+       }
+}
+
 /*
  * Find the network interfaces which have configured themselves.
  * If the interface is present but not yet up (for example an
 /*
  * Find the network interfaces which have configured themselves.
  * If the interface is present but not yet up (for example an
@@ -38,63 +82,67 @@ char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 ifinit()
 {
        struct interface ifs, *ifp;
 ifinit()
 {
        struct interface ifs, *ifp;
-       int s;
-        struct ifconf ifc;
-       char buf[BUFSIZ], *cp, *cplim;
-        struct ifreq ifreq, *ifr;
+       int needed, rlen, no_nsaddr = 0, flags = 0;
+       char *buf, *cplim, *cp;
+       register struct if_msghdr *ifm;
+       register struct ifa_msghdr *ifam;
+       struct sockaddr_dl *sdl;
        u_long i;
 
        u_long i;
 
-       if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) {
-               syslog(LOG_ERR, "socket: %m");
-               exit(1);
-       }
-        ifc.ifc_len = sizeof (buf);
-        ifc.ifc_buf = buf;
-        if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
-                syslog(LOG_ERR, "ioctl (get interface configuration)");
-               close(s);
-                exit(1);
-        }
-        ifr = ifc.ifc_req;
+       if ((needed = getkerninfo(KINFO_RT_IFLIST, 0, 0, 0)) < 0)
+               quit("route-getkerninfo-estimate");
+       if ((buf = malloc(needed)) == NULL)
+               quit("malloc");
+       if ((rlen = getkerninfo(KINFO_RT_IFLIST, buf, &needed, 0)) < 0)
+               quit("actual retrieval of interface table");
        lookforinterfaces = 0;
        lookforinterfaces = 0;
-#ifdef RTM_ADD
-#define max(a, b) (a > b ? a : b)
-#define size(p)        max((p).sa_len, sizeof(p))
-#else
-#define size(p) (sizeof (p))
-#endif
-       cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
-       for (cp = buf; cp < cplim;
-                       cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
-               ifr = (struct ifreq *)cp;
-               bzero((char *)&ifs, sizeof(ifs));
-               ifs.int_addr = ifr->ifr_addr;
-               ifreq = *ifr;
-                if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
-                        syslog(LOG_ERR, "ioctl (get interface flags)");
-                        continue;
-                }
-               ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
-               if ((ifs.int_flags & IFF_UP) == 0 ||
-                   ifr->ifr_addr.sa_family == AF_UNSPEC) {
-                       lookforinterfaces = 1;
+       cplim = buf + rlen;
+       for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
+               ifm = (struct if_msghdr *)cp;
+               if (ifm->ifm_type == RTM_IFINFO) {
+                       bzero(&ifs, sizeof(ifs));
+                       ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE;
+                       if ((flags & IFF_UP) == 0 || no_nsaddr)
+                               lookforinterfaces = 1;
+                       sdl = (struct sockaddr_dl *) (ifm + 1);
+                       sdl->sdl_data[sdl->sdl_nlen] = 0;
+                       no_nsaddr = 1;
+                       continue;
+               }
+               if (ifm->ifm_type != RTM_NEWADDR)
+                       quit("ifinit: out of sync");
+               if ((flags & IFF_UP) == 0)
+                       continue;
+               ifam = (struct ifa_msghdr *)ifm;
+               info.rti_addrs = ifam->ifam_addrs;
+               rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
+               if (ifaaddr == 0) {
+                       syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
                        continue;
                }
                        continue;
                }
+               ifs.int_addr = *ifaaddr;
                if (ifs.int_addr.sa_family != AF_NS)
                        continue;
                if (ifs.int_addr.sa_family != AF_NS)
                        continue;
-                if (ifs.int_flags & IFF_POINTOPOINT) {
-                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
-                                syslog(LOG_ERR, "ioctl (get dstaddr): %m");
-                                continue;
+               no_nsaddr = 0;
+               if (ifs.int_flags & IFF_POINTOPOINT) {
+                       if (brdaddr == 0) {
+                               syslog(LOG_ERR, "%s: (get dstaddr)",
+                                       sdl->sdl_data);
+                               continue;
                        }
                        }
-                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
+                       if (brdaddr->sa_family == AF_UNSPEC) {
+                               lookforinterfaces = 1;
+                               continue;
+                       }
+                       ifs.int_dstaddr = *brdaddr;
                }
                }
-                if (ifs.int_flags & IFF_BROADCAST) {
-                        if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
-                                syslog(LOG_ERR, "ioctl (get broadaddr: %m");
-                                continue;
-                        }
-                       ifs.int_broadaddr = ifreq.ifr_broadaddr;
+               if (ifs.int_flags & IFF_BROADCAST) {
+                       if (brdaddr == 0) {
+                               syslog(LOG_ERR, "%s: (get broadaddr)",
+                                       sdl->sdl_data);
+                               continue;
+                       }
+                       ifs.int_dstaddr = *brdaddr;
                }
                /* 
                 * already known to us? 
                }
                /* 
                 * already known to us? 
@@ -107,11 +155,13 @@ ifinit()
                        if_ifwithaddr(&ifs.int_addr)))
                        continue;
                /* no one cares about software loopback interfaces */
                        if_ifwithaddr(&ifs.int_addr)))
                        continue;
                /* no one cares about software loopback interfaces */
-               if (strncmp(ifr->ifr_name,"lo", 2)==0)
+               if (ifs.int_flags & IFF_LOOPBACK)
                        continue;
                        continue;
-               ifp = (struct interface *)malloc(sizeof (struct interface));
+               ifp = (struct interface *)
+                       malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
                if (ifp == 0) {
                if (ifp == 0) {
-                       syslog(LOG_ERR,"XNSrouted: out of memory\n");
+                       syslog(LOG_ERR, "XNSrouted: out of memory\n");
+                       lookforinterfaces = 1;
                        break;
                }
                *ifp = ifs;
                        break;
                }
                *ifp = ifs;
@@ -132,13 +182,9 @@ ifinit()
                 */
                if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
                        supplier = 1;
                 */
                if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
                        supplier = 1;
-               ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
-               if (ifp->int_name == 0) {
-                       syslog(LOG_ERR,"XNSrouted: out of memory\n");
-                       exit(1);
-               }
-               strcpy(ifp->int_name, ifr->ifr_name);
-               ifp->int_metric = 0;
+               ifp->int_name = (char *)(ifp + 1);
+               strcpy(ifp->int_name, sdl->sdl_data);
+               ifp->int_metric = ifam->ifam_metric;
                ifp->int_next = ifnet;
                ifnet = ifp;
                traceinit(ifp);
                ifp->int_next = ifnet;
                ifnet = ifp;
                traceinit(ifp);
@@ -146,7 +192,7 @@ ifinit()
        }
        if (externalinterfaces > 1 && supplier < 0)
                supplier = 1;
        }
        if (externalinterfaces > 1 && supplier < 0)
                supplier = 1;
-       close(s);
+       free(buf);
 }
 
 addrouteforif(ifp)
 }
 
 addrouteforif(ifp)
index 8a68e69..2311ee9 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)tables.c   5.9 (Berkeley) %G%";
+static char sccsid[] = "@(#)tables.c   5.10 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -145,7 +145,7 @@ rtadd(dst, gate, metric, state)
         * from this host, discard the entry.  This should only
         * occur because of an incorrect entry in /etc/gateways.
         */
         * from this host, discard the entry.  This should only
         * occur because of an incorrect entry in /etc/gateways.
         */
-       if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
+       if (install && rtioctl(ADD, &rt->rt_rt) < 0) {
                if (errno != EEXIST)
                        perror("SIOCADDRT");
                if (errno == ENETUNREACH) {
                if (errno != EEXIST)
                        perror("SIOCADDRT");
                if (errno == ENETUNREACH) {
@@ -191,17 +191,21 @@ rtchange(rt, gate, metric)
        }
        if (doioctl && install) {
 #ifndef RTM_ADD
        }
        if (doioctl && install) {
 #ifndef RTM_ADD
-               if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
-                 syslog(LOG_ERR, "SIOCADDRT dst %s, gw %s: %m",
+               if (rtioctl(ADD, &rt->rt_rt) < 0)
+                 syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m",
                   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
                   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
                   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
                   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
-               if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
-                       perror("SIOCDELRT");
+               if (delete && rtioctl(DELETE, &oldroute) < 0)
+                       perror("rtioctl DELETE");
 #else
 #else
-               if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
-                       perror("SIOCDELRT");
-               if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
-                 syslog(LOG_ERR, "SIOCADDRT dst %s, gw %s: %m",
+               if (delete == 0) {
+                       if (rtioctl(ADD, &rt->rt_rt) >= 0)
+                               return;
+               } else {
+                       if (rtioctl(CHANGE, &rt->rt_rt) >= 0)
+                               return;
+               }
+               syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m",
                   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
                   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
 #endif
                   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
                   xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
 #endif
@@ -222,8 +226,8 @@ rtdelete(rt)
                        rt->rt_ifp->int_name);
        }
        TRACE_ACTION(DELETE, rt);
                        rt->rt_ifp->int_name);
        }
        TRACE_ACTION(DELETE, rt);
-       if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
-               perror("SIOCDELRT");
+       if (install && rtioctl(DELETE, &rt->rt_rt) < 0)
+               perror("rtioctl DELETE");
        remque(rt);
        free((char *)rt);
 }
        remque(rt);
        free((char *)rt);
 }
@@ -237,3 +241,53 @@ rtinit()
        for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
                rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
 }
        for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
                rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
 }
+int seqno;
+
+rtioctl(action, ort)
+       int action;
+       struct ortentry *ort;
+{
+#ifndef RTM_ADD
+       switch (action) {
+
+       case ADD:
+               return (ioctl(s, SIOCADDRT, (char *)ort));
+
+       case DELETE:
+               return (ioctl(s, SIOCDELRT, (char *)ort));
+
+       default:
+               return (-1);
+       }
+#else /* RTM_ADD */
+       struct {
+               struct rt_msghdr w_rtm;
+               struct sockaddr w_dst;
+               struct sockaddr w_gate;
+               struct sockaddr_ns w_netmask;
+       } w;
+#define rtm w.w_rtm
+
+       bzero((char *)&w, sizeof(w));
+       rtm.rtm_msglen = sizeof(w);
+       rtm.rtm_version = RTM_VERSION;
+       rtm.rtm_type = (action == ADD ? RTM_ADD :
+                               (action == DELETE ? RTM_DELETE : RTM_CHANGE));
+#undef rt_flags
+       rtm.rtm_flags = ort->rt_flags;
+       rtm.rtm_seq = ++seqno;
+       rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
+       bcopy((char *)&ort->rt_dst, (char *)&w.w_dst, sizeof(w.w_dst));
+       bcopy((char *)&ort->rt_gateway, (char *)&w.w_gate, sizeof(w.w_gate));
+       w.w_gate.sa_family = w.w_dst.sa_family = AF_NS;
+       w.w_gate.sa_len = w.w_dst.sa_len = sizeof(w.w_dst);
+       if (rtm.rtm_flags & RTF_HOST) {
+               rtm.rtm_msglen -= sizeof(w.w_netmask);
+       } else {
+               w.w_netmask = ns_netmask;
+               rtm.rtm_msglen -= 8;
+       }
+       errno = 0;
+       return write(r, (char *)&w, rtm.rtm_msglen);
+#endif  /* RTM_ADD */
+}