X-Git-Url: https://git.saurik.com/apple/network_cmds.git/blobdiff_plain/7f5b2e89a4f702a4180adf6481fd2153039ee5eb..7af5ce03cf81eb8cf0c6e1bfd903b52fcc7c224a:/route.tproj/route.c diff --git a/route.tproj/route.c b/route.tproj/route.c index b1960d7..23cba41 100644 --- a/route.tproj/route.c +++ b/route.tproj/route.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All rights reserved. + * Copyright (c) 2008-2011 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -125,6 +125,8 @@ int locking, lockrest, debugonly; struct rt_metrics rt_metrics; u_long rtm_inits; 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(); @@ -185,7 +187,7 @@ main(argc, argv) argv += optind; pid = getpid(); - uid = getuid(); + uid = geteuid(); if (tflag) s = open(_PATH_DEVNULL, O_WRONLY, 0); else @@ -326,13 +328,13 @@ routename(sa) if (gethostname(domain, MAXHOSTNAMELEN) == 0 && (cp = index(domain, '.'))) { domain[MAXHOSTNAMELEN] = '\0'; - (void) strcpy(domain, cp + 1); + (void) strlcpy(domain, cp + 1, sizeof(domain)); } 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: @@ -359,7 +361,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; @@ -381,6 +383,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 = @@ -405,7 +408,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 */ @@ -469,15 +472,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; @@ -499,6 +502,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 = @@ -524,7 +528,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) @@ -535,6 +539,22 @@ 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; @@ -567,7 +587,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; @@ -770,21 +790,7 @@ newroute(argc, argv) 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)); } } @@ -833,6 +839,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. @@ -925,6 +961,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); @@ -934,21 +971,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); @@ -956,7 +999,15 @@ 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 */ @@ -1170,7 +1221,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) { @@ -1246,7 +1297,7 @@ char routeflags[] = "\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016" "\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024b024" "\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\031IFSCOPE\032CONDEMNED" -"\033IFREF"; +"\033IFREF\034PROXY\035ROUTER"; char ifnetflags[] = "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP" "\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1" @@ -1299,9 +1350,9 @@ print_rtmsg(rtm, msglen) (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) + if (rtm->rtm_flags & RTF_IFREF) (void) printf("ifref, "); - (void) printf("flags:"); + (void) printf("flags:"); bprintf(stdout, rtm->rtm_flags, routeflags); pmsg_common(rtm); } @@ -1318,7 +1369,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);