]> git.saurik.com Git - apple/network_cmds.git/blobdiff - route.tproj/route.c
network_cmds-457.tar.gz
[apple/network_cmds.git] / route.tproj / route.c
index 4e8b4ee6a699dd0f8e93ea807a1c4a6b865fb680..c2508bdef7e2140610dc5eea9437b2a32af1a103 100644 (file)
@@ -1,25 +1,29 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  * Copyright (c) 1983, 1989, 1991, 1993
  * SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
+
 #ifndef lint
-static const char copyright[] =
+__unused static const char copyright[] =
 "@(#) Copyright (c) 1983, 1989, 1991, 1993\n\
        The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)route.c    8.3 (Berkeley) 3/19/94";
-#endif
-static const char rcsid[] =
-       "$Id: route.c,v 1.2 2002/03/05 20:35:16 lindak Exp $";
-#endif /* not lint */
-
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/socket.h>
@@ -79,12 +77,6 @@ static const char rcsid[] =
 #include <net/route.h>
 #include <net/if_dl.h>
 #include <netinet/in.h>
-#ifndef __APPLE__
-#include <netatalk/at.h>
-#endif
-#ifdef NS
-#include <netns/ns.h>
-#endif
 #include <arpa/inet.h>
 #include <netdb.h>
 
@@ -107,18 +99,11 @@ struct keytab {
        {0, 0}
 };
 
-struct ortentry route;
 union  sockunion {
        struct  sockaddr sa;
        struct  sockaddr_in sin;
 #ifdef INET6
        struct  sockaddr_in6 sin6;
-#endif
-#ifndef __APPLE__
-       struct  sockaddr_at sat;
-#endif
-#ifdef NS
-       struct  sockaddr_ns sns;
 #endif
        struct  sockaddr_dl sdl;
        struct  sockaddr_storage ss; /* added to avoid memory overrun */
@@ -132,10 +117,9 @@ int        iflag, verbose, aflen = sizeof (struct sockaddr_in);
 int    locking, lockrest, debugonly;
 struct rt_metrics rt_metrics;
 u_long  rtm_inits;
-#ifndef __APPLE__
-int    atalk_aton __P((const char *, struct at_addr *));
-char   *atalk_ntoa __P((struct at_addr));
-#endif
+unsigned int ifscope;
+
+static const char *route_strerror(int);
 const char     *routename(), *netname();
 void   flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
 void   print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
@@ -143,7 +127,7 @@ int getaddr(), rtmsg(), x25_makemask();
 int    prefixlen();
 extern char *iso_ntoa();
 
-void usage __P((const char *));
+void usage __P((const char *)) __dead2;
 
 void
 usage(cp)
@@ -158,7 +142,7 @@ usage(cp)
 }
 
 #define ROUNDUP(a) \
-       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
 
 int
@@ -196,7 +180,7 @@ main(argc, argv)
        argv += optind;
 
        pid = getpid();
-       uid = getuid();
+       uid = geteuid();
        if (tflag)
                s = open(_PATH_DEVNULL, O_WRONLY, 0);
        else
@@ -259,16 +243,6 @@ flushroutes(argc, argv)
                        case K_INET6:
                                af = AF_INET6;
                                break;
-#endif
-#ifndef __APPLE__
-                       case K_ATALK:
-                               af = AF_APPLETALK;
-                               break;
-#endif
-#ifdef NS
-                       case K_XNS:
-                               af = AF_NS;
-                               break;
 #endif
                        case K_LINK:
                                af = AF_LINK;
@@ -341,22 +315,19 @@ routename(sa)
        struct hostent *hp;
        static char domain[MAXHOSTNAMELEN + 1];
        static int first = 1;
-#ifdef NS
-       char *ns_print();
-#endif
 
        if (first) {
                first = 0;
                if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
                    (cp = index(domain, '.'))) {
                        domain[MAXHOSTNAMELEN] = '\0';
-                       (void) strcpy(domain, cp + 1);
+                       (void) memmove(domain, cp + 1, strlen(cp + 1) + 1);
                } else
                        domain[0] = 0;
        }
 
        if (sa->sa_len == 0)
-               strcpy(line, "default");
+               strlcpy(line, "default", sizeof(line));
        else switch (sa->sa_family) {
 
        case AF_INET:
@@ -383,7 +354,7 @@ routename(sa)
                        /* XXX - why not inet_ntoa()? */
 #define C(x)   (unsigned)((x) & 0xff)
                        in.s_addr = ntohl(in.s_addr);
-                       (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+                       (void) snprintf(line, sizeof(line), "%u.%u.%u.%u", C(in.s_addr >> 24),
                           C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
                }
                break;
@@ -405,6 +376,7 @@ routename(sa)
 #ifdef __KAME__
                if (sa->sa_len == sizeof(struct sockaddr_in6) &&
                    (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+                    IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
                     IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
                    sin6.sin6_scope_id == 0) {
                        sin6.sin6_scope_id =
@@ -422,17 +394,6 @@ routename(sa)
                return(line);
        }
 #endif
-#ifndef __APPLE__
-       case AF_APPLETALK:
-               (void) snprintf(line, sizeof(line), "atalk %s",
-                       atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
-               break;
-#endif
-
-#ifdef NS
-       case AF_NS:
-               return (ns_print((struct sockaddr_ns *)sa));
-#endif
 
        case AF_LINK:
                return (link_ntoa((struct sockaddr_dl *)sa));
@@ -440,7 +401,7 @@ routename(sa)
        default:
            {   u_short *s = (u_short *)sa;
                u_short *slim = s + ((sa->sa_len + 1) >> 1);
-               char *cp = line + sprintf(line, "(%d)", sa->sa_family);
+               char *cp = line + snprintf(line, sizeof(line), "(%d)", sa->sa_family);
                char *cpe = line + sizeof(line);
 
                while (++s < slim && cp < cpe) /* start with sa->sa_data */
@@ -462,12 +423,9 @@ netname(sa)
        char *cp = 0;
        static char line[MAXHOSTNAMELEN + 1];
        struct netent *np = 0;
-       u_long net, mask;
-       register u_long i;
+       in_addr_t net, mask;
+       register in_addr_t i;
        int subnetshift;
-#ifdef NS
-       char *ns_print();
-#endif
 
        switch (sa->sa_family) {
 
@@ -496,7 +454,7 @@ netname(sa)
                         * width subnet fields.
                         */
                        while (in.s_addr &~ mask)
-                               mask = (long)mask >> subnetshift;
+                               mask = mask >> subnetshift;
                        net = in.s_addr & mask;
                        while ((mask & 1) == 0)
                                mask >>= 1, net >>= 1;
@@ -507,15 +465,15 @@ netname(sa)
                if (cp)
                        strncpy(line, cp, sizeof(line));
                else if ((in.s_addr & 0xffffff) == 0)
-                       (void) sprintf(line, "%u", C(in.s_addr >> 24));
+                       (void) snprintf(line, sizeof(line), "%u", C(in.s_addr >> 24));
                else if ((in.s_addr & 0xffff) == 0)
-                       (void) sprintf(line, "%u.%u", C(in.s_addr >> 24),
+                       (void) snprintf(line, sizeof(line), "%u.%u", C(in.s_addr >> 24),
                            C(in.s_addr >> 16));
                else if ((in.s_addr & 0xff) == 0)
-                       (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
+                       (void) snprintf(line, sizeof(line), "%u.%u.%u", C(in.s_addr >> 24),
                            C(in.s_addr >> 16), C(in.s_addr >> 8));
                else
-                       (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+                       (void) snprintf(line, sizeof(line), "%u.%u.%u.%u", C(in.s_addr >> 24),
                            C(in.s_addr >> 16), C(in.s_addr >> 8),
                            C(in.s_addr));
                break;
@@ -537,6 +495,7 @@ netname(sa)
 #ifdef __KAME__
                if (sa->sa_len == sizeof(struct sockaddr_in6) &&
                    (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+                    IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
                     IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
                    sin6.sin6_scope_id == 0) {
                        sin6.sin6_scope_id =
@@ -555,19 +514,6 @@ netname(sa)
        }
 #endif
 
-#ifndef __APPLE__
-       case AF_APPLETALK:
-               (void) snprintf(line, sizeof(line), "atalk %s",
-                       atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
-               break;
-#endif
-
-#ifdef NS
-       case AF_NS:
-               return (ns_print((struct sockaddr_ns *)sa));
-               break;
-#endif
-
        case AF_LINK:
                return (link_ntoa((struct sockaddr_dl *)sa));
 
@@ -575,7 +521,7 @@ netname(sa)
        default:
            {   u_short *s = (u_short *)sa->sa_data;
                u_short *slim = s + ((sa->sa_len + 1)>>1);
-               char *cp = line + sprintf(line, "af %d:", sa->sa_family);
+               char *cp = line + snprintf(line, sizeof(line), "af %d:", sa->sa_family);
                char *cpe = line + sizeof(line);
 
                while (s < slim && cp < cpe)
@@ -586,16 +532,32 @@ netname(sa)
        return (line);
 }
 
+static const char *
+route_strerror(int error)
+{
+
+       switch (error) {
+       case ESRCH:
+               return "not in table";
+       case EBUSY:
+               return "entry in use";
+       case ENOBUFS:
+               return "routing table overflow";
+       default:
+               return (strerror(error));
+       }
+}
+
 void
 set_metric(value, key)
        char *value;
        int key;
 {
        int flag = 0;
-       u_long noval, *valp = &noval;
+       u_int noval, *valp = &noval;
 
        switch (key) {
-#define caseof(x, y, z)        case x: valp = &rt_metrics.z; flag = y; break
+#define caseof(x, y, z)        case x: valp = (u_int *)&rt_metrics.z; flag = y; break
        caseof(K_MTU, RTV_MTU, rmx_mtu);
        caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount);
        caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire);
@@ -618,7 +580,7 @@ newroute(argc, argv)
        int argc;
        register char **argv;
 {
-       char *cmd, *dest = "", *gateway = "", *err;
+       char *cmd, *dest = "", *gateway = "";
        int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC;
        int key;
        struct hostent *hp = 0;
@@ -645,23 +607,11 @@ newroute(argc, argv)
                                af = AF_INET6;
                                aflen = sizeof(struct sockaddr_in6);
                                break;
-#endif
-#ifndef __APPLE__
-                       case K_ATALK:
-                               af = AF_APPLETALK;
-                               aflen = sizeof(struct sockaddr_at);
-                               break;
 #endif
                        case K_SA:
                                af = PF_ROUTE;
                                aflen = sizeof(union sockunion);
                                break;
-#ifdef NS
-                       case K_XNS:
-                               af = AF_NS;
-                               aflen = sizeof(struct sockaddr_ns);
-                               break;
-#endif
                        case K_IFACE:
                        case K_INTERFACE:
                                iflag++;
@@ -759,6 +709,14 @@ newroute(argc, argv)
                                        usage((char *)NULL);
                                set_metric(*++argv, key);
                                break;
+                       case K_IFSCOPE:
+                               if (!--argc)
+                                       usage((char *)NULL);
+                               if ((ifscope = if_nametoindex(*++argv)) != 0)
+                                       flags |= RTF_IFSCOPE;
+                               else
+                                       errx(1, "bad interface name");
+                               break;
                        default:
                                usage(1+*argv);
                        }
@@ -790,6 +748,16 @@ newroute(argc, argv)
                flags |= RTF_HOST;
        if (iflag == 0)
                flags |= RTF_GATEWAY;
+       if (so_mask.sin.sin_family == AF_INET) {
+               // make sure the mask is contiguous
+               long i;
+               for (i = 0; i < 32; i++)
+                       if (((so_mask.sin.sin_addr.s_addr) & ntohl((1 << i))) != 0)
+                               break;
+               for (; i < 32; i++)
+                       if (((so_mask.sin.sin_addr.s_addr) & ntohl((1 << i))) == 0)
+                               errx(EX_NOHOST, "invalid mask: %s", inet_ntoa(so_mask.sin.sin_addr));
+       }
        for (attempts = 1; ; attempts++) {
                errno = 0;
                if ((ret = rtmsg(*cmd, flags)) == 0)
@@ -810,36 +778,21 @@ newroute(argc, argv)
        if (*gateway) {
                (void) printf(": gateway %s", gateway);
                if (attempts > 1 && ret == 0 && af == AF_INET)
-                   (void) printf(" (%s)",
-                       inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
+                   (void) printf(" (%s)", inet_ntoa(so_gate.sin.sin_addr));
        }
        if (ret == 0)
                (void) printf("\n");
        else {
-               switch (oerrno) {
-               case ESRCH:
-                       err = "not in table";
-                       break;
-               case EBUSY:
-                       err = "entry in use";
-                       break;
-               case ENOBUFS:
-                       err = "routing table overflow";
-                       break;
-               default:
-                       err = strerror(oerrno);
-                       break;
-               }
-               (void) printf(": %s\n", err);
+               (void)printf(": %s\n", route_strerror(oerrno));
        }
 }
 
 void
 inet_makenetandmask(net, sin, bits)
-       u_long net, bits;
+       in_addr_t net, bits;
        register struct sockaddr_in *sin;
 {
-       u_long addr, mask = 0;
+       in_addr_t addr, mask = 0;
        register char *cp;
 
        rtm_addrs |= RTA_NETMASK;
@@ -879,6 +832,36 @@ inet_makenetandmask(net, sin, bits)
        sin->sin_len = 1 + cp - (char *)sin;
 }
 
+#ifdef INET6
+/*
+ * XXX the function may need more improvement...
+ */
+static int
+inet6_makenetandmask(struct sockaddr_in6 *sin6, const char *plen)
+{
+       struct in6_addr in6;
+
+       if (plen == NULL) {
+               if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
+                   sin6->sin6_scope_id == 0) {
+                       plen = "0";
+               } else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) {
+                       /* aggregatable global unicast - RFC2374 */
+                       memset(&in6, 0, sizeof(in6));
+                       if (!memcmp(&sin6->sin6_addr.s6_addr[8],
+                                   &in6.s6_addr[8], 8))
+                               plen = "64";
+               }
+       }
+
+       if (plen == NULL || strcmp(plen, "128") == 0)
+               return (1);
+       rtm_addrs |= RTA_NETMASK;
+       prefixlen(plen);
+       return (0);
+}
+#endif
+
 /*
  * Interpret an argument as a network address of some kind,
  * returning 1 if a host address, 0 if a network address.
@@ -889,10 +872,10 @@ getaddr(which, s, hpp)
        char *s;
        struct hostent **hpp;
 {
-       register sup su;
+       register sup su = NULL;
        struct hostent *hp;
        struct netent *np;
-       u_long val;
+       in_addr_t val;
        char *q;
        int afamily;  /* local copy of af so we can change it */
 
@@ -971,6 +954,7 @@ getaddr(which, s, hpp)
                case RTA_NETMASK:
                case RTA_GENMASK:
                        /* bzero(su, sizeof(*su)); *//* for readability */
+                       su->sa.sa_len = 0;
                        break;
                }
                return (0);
@@ -980,21 +964,27 @@ getaddr(which, s, hpp)
        case AF_INET6:
        {
                struct addrinfo hints, *res;
+               int ecode;
 
+               q = NULL;
+               if (which == RTA_DST && (q = strchr(s, '/')) != NULL)
+                       *q = '\0';
                memset(&hints, 0, sizeof(hints));
                hints.ai_family = afamily;      /*AF_INET6*/
                hints.ai_flags = AI_NUMERICHOST;
                hints.ai_socktype = SOCK_DGRAM;         /*dummy*/
-               if (getaddrinfo(s, "0", &hints, &res) != 0 ||
-                   res->ai_family != AF_INET6 ||
+               ecode = getaddrinfo(s, NULL, &hints, &res);
+               if (ecode != 0 || res->ai_family != AF_INET6 ||
                    res->ai_addrlen != sizeof(su->sin6)) {
-                       (void) fprintf(stderr, "%s: bad value\n", s);
+                       (void) fprintf(stderr, "%s: %s\n", s,
+                           gai_strerror(ecode));
                        exit(1);
                }
                memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
 #ifdef __KAME__
                if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) ||
-                    IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr)) &&
+                    IN6_IS_ADDR_MC_NODELOCAL(&su->sin6.sin6_addr) ||
+                    IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr)) &&
                    su->sin6.sin6_scope_id) {
                        *(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] =
                                htons(su->sin6.sin6_scope_id);
@@ -1002,34 +992,18 @@ getaddr(which, s, hpp)
                }
 #endif
                freeaddrinfo(res);
-               return (0);
+               if (hints.ai_flags == AI_NUMERICHOST) {
+                       if (q != NULL)
+                               *q++ = '/';
+                       if (which == RTA_DST)
+                               return (inet6_makenetandmask(&su->sin6, q));
+                       return (0);
+               } else {
+                       return (1);
+               }
        }
 #endif /* INET6 */
 
-#ifdef NS
-       case AF_NS:
-               if (which == RTA_DST) {
-                       extern short ns_bh[3];
-                       struct sockaddr_ns *sms = &(so_mask.sns);
-                       bzero((char *)sms, sizeof(*sms));
-                       sms->sns_family = 0;
-                       sms->sns_len = 6;
-                       sms->sns_addr.x_net = *(union ns_net *)ns_bh;
-                       rtm_addrs |= RTA_NETMASK;
-               }
-               su->sns.sns_addr = ns_addr(s);
-               return (!ns_nullhost(su->sns.sns_addr));
-#endif
-
-
-#ifndef __APPLE__
-       case AF_APPLETALK:
-               if (!atalk_aton(s, &su->sat.sat_addr))
-                       errx(EX_NOHOST, "bad address: %s", s);
-               rtm_addrs |= RTA_NETMASK;
-               return(forcehost || su->sat.sat_addr.s_node != 0);
-#endif
-
        case AF_LINK:
                link_addr(s, &su->sdl);
                return (1);
@@ -1134,57 +1108,6 @@ prefixlen(s)
                return len;
 }
 
-#ifdef NS
-short ns_nullh[] = {0,0,0};
-short ns_bh[] = {-1,-1,-1};
-
-char *
-ns_print(sns)
-       struct sockaddr_ns *sns;
-{
-       struct ns_addr work;
-       union { union ns_net net_e; u_long long_e; } net;
-       u_short port;
-       static char mybuf[50+MAXHOSTNAMELEN], cport[10], chost[25];
-       char *host = "";
-       register char *p;
-       register u_char *q;
-
-       work = sns->sns_addr;
-       port = ntohs(work.x_port);
-       work.x_port = 0;
-       net.net_e  = work.x_net;
-       if (ns_nullhost(work) && net.long_e == 0) {
-               if (!port)
-                       return ("*.*");
-               (void) sprintf(mybuf, "*.%XH", port);
-               return (mybuf);
-       }
-
-       if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0)
-               host = "any";
-       else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0)
-               host = "*";
-       else {
-               q = work.x_host.c_host;
-               (void) sprintf(chost, "%02X%02X%02X%02X%02X%02XH",
-                       q[0], q[1], q[2], q[3], q[4], q[5]);
-               for (p = chost; *p == '0' && p < chost + 12; p++)
-                       /* void */;
-               host = p;
-       }
-       if (port)
-               (void) sprintf(cport, ".%XH", htons(port));
-       else
-               *cport = 0;
-
-       (void) snprintf(mybuf, sizeof(mybuf), "%lxH.%s%s",
-                       (unsigned long)ntohl(net.long_e),
-                       host, cport);
-       return (mybuf);
-}
-#endif
-
 void
 interfaces()
 {
@@ -1275,6 +1198,7 @@ rtmsg(cmd, flags)
        rtm.rtm_addrs = rtm_addrs;
        rtm.rtm_rmx = rt_metrics;
        rtm.rtm_inits = rtm_inits;
+       rtm.rtm_index = ifscope;
 
        if (rtm_addrs & RTA_NETMASK)
                mask_addr();
@@ -1290,7 +1214,7 @@ rtmsg(cmd, flags)
        if (debugonly)
                return (0);
        if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
-               warn("writing to routing socket");
+               warnx("writing to routing socket: %s", route_strerror(errno));
                return (-1);
        }
        if (cmd == RTM_GET) {
@@ -1320,9 +1244,6 @@ mask_addr()
        if ((rtm_addrs & RTA_DST) == 0)
                return;
        switch (so_dst.sa.sa_family) {
-#ifdef NS
-       case AF_NS:
-#endif
        case AF_INET:
 #ifdef INET6
        case AF_INET6:
@@ -1365,10 +1286,11 @@ char metricnames[] =
 "\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount"
 "\1mtu";
 char routeflags[] =
-"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT"
+"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010DELCLONE"
 "\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016"
-"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024CHAINDELETE"
-"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST";
+"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024b024"
+"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\031IFSCOPE\032CONDEMNED"
+"\033IFREF\034PROXY\035ROUTER";
 char ifnetflags[] =
 "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"
 "\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"
@@ -1417,8 +1339,13 @@ print_rtmsg(rtm, msglen)
                break;
 #endif
        default:
-               (void) printf("pid: %ld, seq %d, errno %d, flags:",
+               (void) printf("pid: %ld, seq %d, errno %d, ",
                        (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
+               if (rtm->rtm_flags & RTF_IFSCOPE)
+                       (void) printf("ifscope %d, ", rtm->rtm_index);
+                       if (rtm->rtm_flags & RTF_IFREF)
+                       (void) printf("ifref, ");
+                       (void) printf("flags:");
                bprintf(stdout, rtm->rtm_flags, routeflags);
                pmsg_common(rtm);
        }
@@ -1435,7 +1362,7 @@ print_getmsg(rtm, msglen)
        register char *cp;
        register int i;
 
-       (void) printf("   route to: %s\n", routename(&so_dst));
+       (void) printf("   route to: %s\n", routename(&so_dst.sa));
        if (rtm->rtm_version != RTM_VERSION) {
                warnx("routing message version %d not understood",
                     rtm->rtm_version);
@@ -1497,16 +1424,16 @@ print_getmsg(rtm, msglen)
 
        (void) printf("\n%s\n", "\
  recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire");
-       printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
-       printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
-       printf("%8ld%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
-       printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
-       printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR));
-       printf("%8ld%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT));
-       printf("%8ld%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
+       printf("%8u%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
+       printf("%8u%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
+       printf("%8u%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
+       printf("%8u%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
+       printf("%8u%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR));
+       printf("%8u%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT));
+       printf("%8u%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
        if (rtm->rtm_rmx.rmx_expire)
                rtm->rtm_rmx.rmx_expire -= time(0);
-       printf("%8ld%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
+       printf("%8d%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
 #undef lock
 #undef msec
 #define        RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
@@ -1610,18 +1537,6 @@ sodump(su, which)
                (void) printf("%s: inet %s; ",
                    which, inet_ntoa(su->sin.sin_addr));
                break;
-#ifndef __APPLE__
-       case AF_APPLETALK:
-               (void) printf("%s: atalk %s; ",
-                   which, atalk_ntoa(su->sat.sat_addr));
-               break;
-#endif
-#ifdef NS
-       case AF_NS:
-               (void) printf("%s: xns %s; ",
-                   which, ns_ntoa(su->sns.sns_addr));
-               break;
-#endif
        }
        (void) fflush(stdout);
 }
@@ -1678,27 +1593,3 @@ sockaddr(addr, sa)
        } while (cp < cplim);
        sa->sa_len = cp - (char *)sa;
 }
-
-#ifndef __APPLE__
-int
-atalk_aton(const char *text, struct at_addr *addr)
-{
-       u_int net, node;
-
-       if (sscanf(text, "%u.%u", &net, &node) != 2
-           || net > 0xffff || node > 0xff)
-               return(0);
-       addr->s_net = htons(net);
-       addr->s_node = node;
-       return(1);
-}
-
-char *
-atalk_ntoa(struct at_addr at)
-{
-       static char buf[20];
-
-       (void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node);
-       return(buf);
-}
-#endif