diff options
author | brian <brian@FreeBSD.org> | 1997-11-15 02:15:56 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1997-11-15 02:15:56 +0000 |
commit | 903fd99091056bd1be0151ed32bed0193f82a6af (patch) | |
tree | a1a35ccbc99f03bd08307edcdc8ffca9615ce02a /usr.sbin/ppp | |
parent | 08d3982b7d149131da63561e055f6221aab042f0 (diff) | |
download | FreeBSD-src-903fd99091056bd1be0151ed32bed0193f82a6af.zip FreeBSD-src-903fd99091056bd1be0151ed32bed0193f82a6af.tar.gz |
Interpret AF_LINK sockaddrs correctly in show/delete route.
Print out inteface names rather than numbers, and use the
same "find out the names" code in SetIfAddr(). This means
that the nasty ioctl(,SIOCGIFCONF,)/realloc loop is now
buried :-)
Diffstat (limited to 'usr.sbin/ppp')
-rw-r--r-- | usr.sbin/ppp/route.c | 405 |
1 files changed, 230 insertions, 175 deletions
diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c index 8520e95..19e7a12 100644 --- a/usr.sbin/ppp/route.c +++ b/usr.sbin/ppp/route.c @@ -17,18 +17,20 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: route.c,v 1.24 1997/11/09 14:18:50 brian Exp $ + * $Id: route.c,v 1.25 1997/11/11 22:58:13 brian Exp $ * */ #include <sys/param.h> #include <sys/time.h> #include <sys/socket.h> +#include <net/if_types.h> #include <net/route.h> #include <net/if.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <net/if_dl.h> #include <errno.h> #include <machine/endian.h> @@ -141,57 +143,108 @@ OsSetRoute(int cmd, } static void -p_sockaddr(struct sockaddr * sa, int width) +p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width) { - if (VarTerm) { - register char *cp; - register struct sockaddr_in *sock_in = (struct sockaddr_in *) sa; - - cp = (sock_in->sin_addr.s_addr == 0) ? "default" : - inet_ntoa(sock_in->sin_addr); - fprintf(VarTerm, "%-*.*s ", width, width, cp); + char buf[29], *cp; + struct sockaddr_in *ihost = (struct sockaddr_in *)phost; + struct sockaddr_in *mask = (struct sockaddr_in *)pmask; + struct sockaddr_dl *dl = (struct sockaddr_dl *)phost; + + switch (phost->sa_family) { + case AF_INET: + if (!phost) + cp = ""; + else if (ihost->sin_addr.s_addr == INADDR_ANY) + cp = "default"; + else if (!mask) + cp = inet_ntoa(ihost->sin_addr); + else { + u_int msk = ntohl(mask->sin_addr.s_addr); + u_int tst; + int bits; + int len; + struct sockaddr_in net; + + for (tst = 1, bits=32; tst; tst <<= 1, bits--) + if (msk & tst) + break; + + for (tst <<=1; tst; tst <<= 1) + if (!(msk & tst)) + break; + + net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr; + sprintf(buf, "%s", inet_ntoa(net.sin_addr)); + for (len = strlen(buf); len > 3; buf[len-=2] = '\0') + if (strcmp(buf+len-2, ".0")) + break; + + if (tst) /* non-contiguous :-( */ + sprintf(buf+strlen(buf),"&0x%08x", msk); + else + sprintf(buf+strlen(buf), "/%d", bits); + cp = buf; + } + break; + + case AF_LINK: + if (!dl) + cp = ""; + else if (dl->sdl_nlen == 0 && dl->sdl_alen == 0 && dl->sdl_slen == 0) { + sprintf(buf, "link#%d", dl->sdl_index); + cp = buf; + } else if (dl->sdl_type == IFT_ETHER && dl->sdl_alen && + dl->sdl_alen < sizeof(buf)/3) { + int f; + u_char *MAC; + + MAC = (u_char *)dl->sdl_data + dl->sdl_nlen; + for (f = 0; f < dl->sdl_alen; f++) + sprintf(buf+f*3, "%02x:", MAC[f]); + buf[f*3-1] = '\0'; + cp = buf; + } else + cp = "???"; + break; + + default: + cp = "???"; + break; } + + fprintf(VarTerm, "%-*s ", width-1, cp); } struct bits { - short b_mask; + u_long b_mask; char b_val; -} bits[] = { - - { - RTF_UP, 'U' - }, - { - RTF_GATEWAY, 'G' - }, - { - RTF_HOST, 'H' - }, - { - RTF_DYNAMIC, 'D' - }, - { - RTF_MODIFIED, 'M' - }, - { - RTF_CLONING, 'C' - }, - { - RTF_XRESOLVE, 'X' - }, - { - RTF_LLINFO, 'L' - }, - { - RTF_REJECT, 'R' - }, - { - 0 - } +} bits[] = { + + { RTF_UP, 'U' }, + { RTF_GATEWAY, 'G' }, + { RTF_HOST, 'H' }, + { RTF_REJECT, 'R' }, + { RTF_DYNAMIC, 'D' }, + { RTF_MODIFIED, 'M' }, + { RTF_DONE, 'd' }, + { RTF_CLONING, 'C' }, + { RTF_XRESOLVE, 'X' }, + { RTF_LLINFO, 'L' }, + { RTF_STATIC, 'S' }, + { RTF_PROTO1, '1' }, + { RTF_PROTO2, '2' }, + { RTF_BLACKHOLE, 'B' }, +#ifdef __FreeBSD__ + { RTF_WASCLONED, 'W' }, + { RTF_PRCLONING, 'c' }, + { RTF_PROTO3, '3' }, + { RTF_BROADCAST, 'b' }, +#endif + { 0, '\0' } }; static void -p_flags(int f, char *format) +p_flags(u_long f, char *format) { if (VarTerm) { char name[33], *flags; @@ -205,16 +258,79 @@ p_flags(int f, char *format) } } +static char * +Index2Nam(int idx) +{ + static char ifs[50][6]; + static int nifs; + + if (!nifs) { + int mib[6], needed, len; + char *buf, *ptr, *end; + struct if_msghdr *n; + struct sockaddr_dl *dl; + struct if_msghdr *ifm; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { + LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno)); + return "???"; + } + if ((buf = malloc(needed)) == NULL) + return "???"; + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + free(buf); + return "???"; + } + end = buf + needed; + + ptr = buf; + while (ptr < end) { + ifm = (struct if_msghdr *)ptr; + + if (ifm->ifm_type != RTM_IFINFO) { + free(buf); + return "???"; + } + dl = (struct sockaddr_dl *)(ifm + 1); + ptr += ifm->ifm_msglen; + while (ptr < end) { + n = (struct if_msghdr *)ptr; + if (n->ifm_type != RTM_NEWADDR) + break; + ptr += n->ifm_msglen; + } + if ((len = dl->sdl_nlen) > sizeof(ifs[0])-1) + len = sizeof(ifs[0])-1; + strncpy(ifs[nifs], dl->sdl_data, len); + ifs[nifs++][len] = '\0'; + if (nifs == sizeof(ifs)/sizeof(ifs[0])) + break; + } + free(buf); + } + +#ifdef __FreeBSD__ + idx--; /* We start at 1, not 0 */ +#endif + if (idx < 0 || idx >= nifs) + return "???"; + return ifs[idx]; +} + int ShowRoute() { struct rt_msghdr *rtm; - struct sockaddr *sa; - char *sp, *ep, *cp; - u_char *wp; - int *lp; - int needed, nb; - u_long mask; + struct sockaddr *sa_dst, *sa_gw, *sa_mask; + char *sp, *ep, *cp, *wp; + int needed; int mib[6]; if (!VarTerm) @@ -242,35 +358,34 @@ ShowRoute() } ep = sp + needed; + fprintf(VarTerm, "%-20s%-20sFlags Netif\n", "Destination", "Gateway"); for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { rtm = (struct rt_msghdr *) cp; - sa = (struct sockaddr *) (rtm + 1); - mask = 0xffffffff; - if (rtm->rtm_addrs == RTA_DST) - p_sockaddr(sa, 36); - else { - wp = (u_char *) cp + rtm->rtm_msglen; - p_sockaddr(sa, 16); - if (sa->sa_len == 0) - sa->sa_len = sizeof(long); - sa = (struct sockaddr *) (sa->sa_len + (char *) sa); - p_sockaddr(sa, 18); - lp = (int *) (sa->sa_len + (char *) sa); - if ((char *) lp < (char *) wp && *lp) { - LogPrintf(LogDEBUG, " flag = %x, rest = %d\n", rtm->rtm_flags, *lp); - wp = (u_char *) (lp + 1); - mask = 0; - for (nb = *(char *) lp; nb > 4; nb--) { - mask <<= 8; - mask |= *wp++; - } - for (nb = 8 - *(char *) lp; nb > 0; nb--) - mask <<= 8; - } - } - fprintf(VarTerm, "0x%08lx ", mask); - p_flags(rtm->rtm_flags & (RTF_UP | RTF_GATEWAY | RTF_HOST), "%-6.6s "); - fprintf(VarTerm, "(%d)\n", rtm->rtm_index); + wp = (char *)(rtm+1); + + if (rtm->rtm_addrs & RTA_DST) { + sa_dst = (struct sockaddr *)wp; + wp += sa_dst->sa_len; + } else + sa_dst = NULL; + + if (rtm->rtm_addrs & RTA_GATEWAY) { + sa_gw = (struct sockaddr *)wp; + wp += sa_gw->sa_len; + } else + sa_gw = NULL; + + if (rtm->rtm_addrs & RTA_NETMASK) { + sa_mask = (struct sockaddr *)wp; + wp += sa_mask->sa_len; + } else + sa_mask = NULL; + + p_sockaddr(sa_dst, sa_mask, 20); + p_sockaddr(sa_gw, NULL, 20); + + p_flags(rtm->rtm_flags, "%-6.6s "); + fprintf(VarTerm, "%s\n", Index2Nam(rtm->rtm_index)); } free(sp); return 0; @@ -284,11 +399,9 @@ DeleteIfRoutes(int all) { struct rt_msghdr *rtm; struct sockaddr *sa; - struct in_addr dstnet, gateway, maddr; + struct in_addr sa_dst, sa_gw, sa_mask; int needed; char *sp, *cp, *ep; - u_long mask; - int *lp, nb; u_char *wp; int mib[6]; @@ -323,111 +436,53 @@ DeleteIfRoutes(int all) for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { rtm = (struct rt_msghdr *) cp; sa = (struct sockaddr *) (rtm + 1); - LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, index: %d, flags: %x," - " dstnet: %s\n", - rtm->rtm_addrs, rtm->rtm_index, rtm->rtm_flags, + LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s), flags: %x," + " dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index, + Index2Nam(rtm->rtm_index), rtm->rtm_flags, inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); - if (rtm->rtm_addrs != RTA_DST && - (rtm->rtm_index == IfIndex) && + if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY && + rtm->rtm_index == IfIndex && (all || (rtm->rtm_flags & RTF_GATEWAY))) { - LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it\n"); - dstnet = ((struct sockaddr_in *) sa)->sin_addr; + sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; wp = (u_char *) cp + rtm->rtm_msglen; - if (sa->sa_len == 0) - sa->sa_len = sizeof(long); - sa = (struct sockaddr *) (sa->sa_len + (char *) sa); - gateway = ((struct sockaddr_in *) sa)->sin_addr; - lp = (int *) (sa->sa_len + (char *) sa); - mask = 0; - if ((char *) lp < (char *) wp && *lp) { - LogPrintf(LogDEBUG, "DeleteIfRoutes: flag = %x, rest = %d\n", - rtm->rtm_flags, *lp); - wp = (u_char *) (lp + 1); - for (nb = *lp; nb > 4; nb--) { - mask <<= 8; - mask |= *wp++; - } - for (nb = 8 - *lp; nb > 0; nb--) - mask <<= 8; - } - LogPrintf(LogDEBUG, "DeleteIfRoutes: Dst: %s\n", inet_ntoa(dstnet)); - LogPrintf(LogDEBUG, "DeleteIfRoutes: Gw: %s\n", inet_ntoa(gateway)); - LogPrintf(LogDEBUG, "DeleteIfRoutes: Index: %d\n", rtm->rtm_index); - if (dstnet.s_addr == INADDR_ANY) - mask = INADDR_ANY; - maddr.s_addr = htonl(mask); - OsSetRoute(RTM_DELETE, dstnet, gateway, maddr); + sa = (struct sockaddr *)((char *)sa + sa->sa_len); + if (sa->sa_family == AF_INET) { + LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it\n"); + sa_gw.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; + sa = (struct sockaddr *)((char *)sa + sa->sa_len); + if (rtm->rtm_addrs & RTA_NETMASK) + sa_mask.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; + else + sa_mask.s_addr = 0xffffffff; + if (sa_dst.s_addr == INADDR_ANY) + sa_mask.s_addr = INADDR_ANY; + LogPrintf(LogDEBUG, "DeleteIfRoutes: Dst: %s\n", inet_ntoa(sa_dst)); + LogPrintf(LogDEBUG, "DeleteIfRoutes: Gw: %s\n", inet_ntoa(sa_gw)); + LogPrintf(LogDEBUG, "DeleteIfRoutes: Index: %d\n", rtm->rtm_index); + OsSetRoute(RTM_DELETE, sa_dst, sa_gw, sa_mask); + } else + LogPrintf(LogDEBUG, "DeleteIfRoutes: Can't remove an AF_LINK !\n"); } } free(sp); } - /* - * 960603 - Modified to use dynamic buffer allocator as in ifconfig - */ - int GetIfIndex(char *name) { - char *buffer; - struct ifreq *ifrp; - int s, len, elen, newIfIndex; - struct ifconf ifconfs; - - /* struct ifreq reqbuf[256]; -- obsoleted :) */ - int oldbufsize, bufsize = sizeof(struct ifreq); - - s = socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) { - LogPrintf(LogERROR, "GetIfIndex: socket(): %s\n", strerror(errno)); - return (-1); - } - buffer = malloc(bufsize); /* allocate first buffer */ - ifconfs.ifc_len = bufsize; /* Initial setting */ - - /* - * Iterate through here until we don't get many more data - */ - - do { - oldbufsize = ifconfs.ifc_len; - bufsize += 1 + sizeof(struct ifreq); - buffer = realloc((void *) buffer, bufsize); /* Make it bigger */ - LogPrintf(LogDEBUG, "GetIfIndex: Growing buffer to %d\n", bufsize); - ifconfs.ifc_len = bufsize; - ifconfs.ifc_buf = buffer; - if (ioctl(s, SIOCGIFCONF, &ifconfs) < 0) { - LogPrintf(LogERROR, "GetIfIndex: ioctl(SIOCGIFCONF): %s\n", - strerror(errno)); - close(s); - free(buffer); - return (-1); - } - } while (ifconfs.ifc_len > oldbufsize); - - ifrp = ifconfs.ifc_req; - - newIfIndex = 1; - for (len = ifconfs.ifc_len; len > 0; len -= sizeof(struct ifreq)) { - elen = ifrp->ifr_addr.sa_len - sizeof(struct sockaddr); - if (ifrp->ifr_addr.sa_family == AF_LINK) { - LogPrintf(LogDEBUG, "GetIfIndex: %d: %-*.*s, %d, %d\n", - newIfIndex, IFNAMSIZ, IFNAMSIZ, ifrp->ifr_name, - ifrp->ifr_addr.sa_family, elen); - if (strcmp(ifrp->ifr_name, name) == 0) { - IfIndex = newIfIndex; - close(s); - free(buffer); - return (newIfIndex); - } - newIfIndex++; - } - len -= elen; - ifrp = (struct ifreq *) ((char *) ifrp + elen); - ifrp++; - } - - close(s); - free(buffer); - return (-1); + int idx; + char *got; + +#ifdef __FreeBSD__ + idx = 1; /* We start at 1, not 0 */ +#else + idx = 0; +#endif + + while (strcmp(got = Index2Nam(idx), "???")) + if (!strcmp(got, name)) + return IfIndex = idx; + else + idx++; + return -1; } |