xref: /freebsd/usr.sbin/ppp/route.c (revision 85b542cf4f3d3d3338529aad0f9f006cdaeef9a8)
11ae349f5Scvs2svn /*
21ae349f5Scvs2svn  *	      PPP Routing related Module
31ae349f5Scvs2svn  *
41ae349f5Scvs2svn  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
51ae349f5Scvs2svn  *
61ae349f5Scvs2svn  *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
71ae349f5Scvs2svn  *
81ae349f5Scvs2svn  * Redistribution and use in source and binary forms are permitted
91ae349f5Scvs2svn  * provided that the above copyright notice and this paragraph are
101ae349f5Scvs2svn  * duplicated in all such forms and that any documentation,
111ae349f5Scvs2svn  * advertising materials, and other materials related to such
121ae349f5Scvs2svn  * distribution and use acknowledge that the software was developed
131ae349f5Scvs2svn  * by the Internet Initiative Japan, Inc.  The name of the
141ae349f5Scvs2svn  * IIJ may not be used to endorse or promote products derived
151ae349f5Scvs2svn  * from this software without specific prior written permission.
161ae349f5Scvs2svn  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
171ae349f5Scvs2svn  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
181ae349f5Scvs2svn  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
191ae349f5Scvs2svn  *
2085b542cfSBrian Somers  * $Id: route.c,v 1.42.2.6 1998/02/07 20:50:06 brian Exp $
211ae349f5Scvs2svn  *
221ae349f5Scvs2svn  */
231ae349f5Scvs2svn 
241ae349f5Scvs2svn #include <sys/param.h>
251ae349f5Scvs2svn #include <sys/time.h>
261ae349f5Scvs2svn #include <sys/socket.h>
271ae349f5Scvs2svn #include <net/if_types.h>
281ae349f5Scvs2svn #include <net/route.h>
291ae349f5Scvs2svn #include <net/if.h>
301ae349f5Scvs2svn #include <netinet/in.h>
311ae349f5Scvs2svn #include <arpa/inet.h>
321ae349f5Scvs2svn #include <net/if_dl.h>
331ae349f5Scvs2svn 
341ae349f5Scvs2svn #include <errno.h>
351ae349f5Scvs2svn #include <machine/endian.h>
361ae349f5Scvs2svn #include <stdio.h>
371ae349f5Scvs2svn #include <stdlib.h>
381ae349f5Scvs2svn #include <string.h>
391ae349f5Scvs2svn #include <sys/ioctl.h>
401ae349f5Scvs2svn #include <sys/sysctl.h>
4185b542cfSBrian Somers #include <termios.h>
421ae349f5Scvs2svn #include <unistd.h>
431ae349f5Scvs2svn 
441ae349f5Scvs2svn #include "command.h"
451ae349f5Scvs2svn #include "mbuf.h"
461ae349f5Scvs2svn #include "log.h"
471ae349f5Scvs2svn #include "loadalias.h"
481ae349f5Scvs2svn #include "defs.h"
491ae349f5Scvs2svn #include "vars.h"
501ae349f5Scvs2svn #include "id.h"
517a6f8720SBrian Somers #include "bundle.h"
521ae349f5Scvs2svn #include "iplist.h"
5329e275ceSBrian Somers #include "timer.h"
5429e275ceSBrian Somers #include "throughput.h"
558c07a7b2SBrian Somers #include "hdlc.h"
568c07a7b2SBrian Somers #include "link.h"
577308ec68SBrian Somers #include "fsm.h"
5829e275ceSBrian Somers #include "ipcp.h"
591ae349f5Scvs2svn #include "route.h"
6085b542cfSBrian Somers #include "descriptor.h"
6185b542cfSBrian Somers #include "prompt.h"
621ae349f5Scvs2svn 
631ae349f5Scvs2svn static void
641ae349f5Scvs2svn p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width)
651ae349f5Scvs2svn {
661ae349f5Scvs2svn   char buf[29];
671ae349f5Scvs2svn   struct sockaddr_in *ihost = (struct sockaddr_in *)phost;
681ae349f5Scvs2svn   struct sockaddr_in *mask = (struct sockaddr_in *)pmask;
691ae349f5Scvs2svn   struct sockaddr_dl *dl = (struct sockaddr_dl *)phost;
701ae349f5Scvs2svn 
711ae349f5Scvs2svn   switch (phost->sa_family) {
721ae349f5Scvs2svn   case AF_INET:
731ae349f5Scvs2svn     if (!phost)
741ae349f5Scvs2svn       buf[0] = '\0';
751ae349f5Scvs2svn     else if (ihost->sin_addr.s_addr == INADDR_ANY)
761ae349f5Scvs2svn       strcpy(buf, "default");
771ae349f5Scvs2svn     else if (!mask)
781ae349f5Scvs2svn       strcpy(buf, inet_ntoa(ihost->sin_addr));
791ae349f5Scvs2svn     else {
801ae349f5Scvs2svn       u_int msk = ntohl(mask->sin_addr.s_addr);
811ae349f5Scvs2svn       u_int tst;
821ae349f5Scvs2svn       int bits;
831ae349f5Scvs2svn       int len;
841ae349f5Scvs2svn       struct sockaddr_in net;
851ae349f5Scvs2svn 
861ae349f5Scvs2svn       for (tst = 1, bits=32; tst; tst <<= 1, bits--)
871ae349f5Scvs2svn         if (msk & tst)
881ae349f5Scvs2svn           break;
891ae349f5Scvs2svn 
901ae349f5Scvs2svn       for (tst <<=1; tst; tst <<= 1)
911ae349f5Scvs2svn         if (!(msk & tst))
921ae349f5Scvs2svn           break;
931ae349f5Scvs2svn 
941ae349f5Scvs2svn       net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr;
951ae349f5Scvs2svn       strcpy(buf, inet_ntoa(net.sin_addr));
961ae349f5Scvs2svn       for (len = strlen(buf); len > 3; buf[len-=2] = '\0')
971ae349f5Scvs2svn         if (strcmp(buf+len-2, ".0"))
981ae349f5Scvs2svn           break;
991ae349f5Scvs2svn 
1001ae349f5Scvs2svn       if (tst)    /* non-contiguous :-( */
1011ae349f5Scvs2svn         sprintf(buf+strlen(buf),"&0x%08x", msk);
1021ae349f5Scvs2svn       else
1031ae349f5Scvs2svn         sprintf(buf+strlen(buf), "/%d", bits);
1041ae349f5Scvs2svn     }
1051ae349f5Scvs2svn     break;
1061ae349f5Scvs2svn 
1071ae349f5Scvs2svn   case AF_LINK:
1081ae349f5Scvs2svn     if (dl->sdl_nlen)
1091ae349f5Scvs2svn       snprintf(buf, sizeof buf, "%.*s", dl->sdl_nlen, dl->sdl_data);
1101ae349f5Scvs2svn     else if (dl->sdl_alen)
1111ae349f5Scvs2svn       if (dl->sdl_type == IFT_ETHER)
1121ae349f5Scvs2svn         if (dl->sdl_alen < sizeof buf / 3) {
1131ae349f5Scvs2svn           int f;
1141ae349f5Scvs2svn           u_char *MAC;
1151ae349f5Scvs2svn 
1161ae349f5Scvs2svn           MAC = (u_char *)dl->sdl_data + dl->sdl_nlen;
1171ae349f5Scvs2svn           for (f = 0; f < dl->sdl_alen; f++)
1181ae349f5Scvs2svn             sprintf(buf+f*3, "%02x:", MAC[f]);
1191ae349f5Scvs2svn           buf[f*3-1] = '\0';
1201ae349f5Scvs2svn         } else
1211ae349f5Scvs2svn 	  strcpy(buf, "??:??:??:??:??:??");
1221ae349f5Scvs2svn       else
1231ae349f5Scvs2svn         sprintf(buf, "<IFT type %d>", dl->sdl_type);
1241ae349f5Scvs2svn     else if (dl->sdl_slen)
1251ae349f5Scvs2svn       sprintf(buf, "<slen %d?>", dl->sdl_slen);
1261ae349f5Scvs2svn     else
1271ae349f5Scvs2svn       sprintf(buf, "link#%d", dl->sdl_index);
1281ae349f5Scvs2svn     break;
1291ae349f5Scvs2svn 
1301ae349f5Scvs2svn   default:
1311ae349f5Scvs2svn     sprintf(buf, "<AF type %d>", phost->sa_family);
1321ae349f5Scvs2svn     break;
1331ae349f5Scvs2svn   }
1341ae349f5Scvs2svn 
13585b542cfSBrian Somers   prompt_Printf(&prompt, "%-*s ", width-1, buf);
1361ae349f5Scvs2svn }
1371ae349f5Scvs2svn 
1381ae349f5Scvs2svn static struct bits {
1391ae349f5Scvs2svn   u_long b_mask;
1401ae349f5Scvs2svn   char b_val;
1411ae349f5Scvs2svn } bits[] = {
1421ae349f5Scvs2svn   { RTF_UP, 'U' },
1431ae349f5Scvs2svn   { RTF_GATEWAY, 'G' },
1441ae349f5Scvs2svn   { RTF_HOST, 'H' },
1451ae349f5Scvs2svn   { RTF_REJECT, 'R' },
1461ae349f5Scvs2svn   { RTF_DYNAMIC, 'D' },
1471ae349f5Scvs2svn   { RTF_MODIFIED, 'M' },
1481ae349f5Scvs2svn   { RTF_DONE, 'd' },
1491ae349f5Scvs2svn   { RTF_CLONING, 'C' },
1501ae349f5Scvs2svn   { RTF_XRESOLVE, 'X' },
1511ae349f5Scvs2svn   { RTF_LLINFO, 'L' },
1521ae349f5Scvs2svn   { RTF_STATIC, 'S' },
1531ae349f5Scvs2svn   { RTF_PROTO1, '1' },
1541ae349f5Scvs2svn   { RTF_PROTO2, '2' },
1551ae349f5Scvs2svn   { RTF_BLACKHOLE, 'B' },
1561ae349f5Scvs2svn #ifdef RTF_WASCLONED
1571ae349f5Scvs2svn   { RTF_WASCLONED, 'W' },
1581ae349f5Scvs2svn #endif
1591ae349f5Scvs2svn #ifdef RTF_PRCLONING
1601ae349f5Scvs2svn   { RTF_PRCLONING, 'c' },
1611ae349f5Scvs2svn #endif
1621ae349f5Scvs2svn #ifdef RTF_PROTO3
1631ae349f5Scvs2svn   { RTF_PROTO3, '3' },
1641ae349f5Scvs2svn #endif
1651ae349f5Scvs2svn #ifdef RTF_BROADCAST
1661ae349f5Scvs2svn   { RTF_BROADCAST, 'b' },
1671ae349f5Scvs2svn #endif
1681ae349f5Scvs2svn   { 0, '\0' }
1691ae349f5Scvs2svn };
1701ae349f5Scvs2svn 
1711ae349f5Scvs2svn #ifndef RTF_WASCLONED
1721ae349f5Scvs2svn #define RTF_WASCLONED (0)
1731ae349f5Scvs2svn #endif
1741ae349f5Scvs2svn 
1751ae349f5Scvs2svn static void
1761ae349f5Scvs2svn p_flags(u_long f, int max)
1771ae349f5Scvs2svn {
1781ae349f5Scvs2svn   char name[33], *flags;
1791ae349f5Scvs2svn   register struct bits *p = bits;
1801ae349f5Scvs2svn 
1811ae349f5Scvs2svn   if (max > sizeof name - 1)
1821ae349f5Scvs2svn     max = sizeof name - 1;
1831ae349f5Scvs2svn 
1841ae349f5Scvs2svn   for (flags = name; p->b_mask && flags - name < max; p++)
1851ae349f5Scvs2svn     if (p->b_mask & f)
1861ae349f5Scvs2svn       *flags++ = p->b_val;
1871ae349f5Scvs2svn   *flags = '\0';
18885b542cfSBrian Somers   prompt_Printf(&prompt, "%-*.*s", max, max, name);
1891ae349f5Scvs2svn }
1901ae349f5Scvs2svn 
1911ae349f5Scvs2svn const char *
1921ae349f5Scvs2svn Index2Nam(int idx)
1931ae349f5Scvs2svn {
1941ae349f5Scvs2svn   static char **ifs;
1951ae349f5Scvs2svn   static int nifs, debug_done;
1961ae349f5Scvs2svn 
1971ae349f5Scvs2svn   if (!nifs) {
1981ae349f5Scvs2svn     int mib[6], have, had;
1991ae349f5Scvs2svn     size_t needed;
2001ae349f5Scvs2svn     char *buf, *ptr, *end;
2011ae349f5Scvs2svn     struct sockaddr_dl *dl;
2021ae349f5Scvs2svn     struct if_msghdr *ifm;
2031ae349f5Scvs2svn 
2041ae349f5Scvs2svn     mib[0] = CTL_NET;
2051ae349f5Scvs2svn     mib[1] = PF_ROUTE;
2061ae349f5Scvs2svn     mib[2] = 0;
2071ae349f5Scvs2svn     mib[3] = 0;
2081ae349f5Scvs2svn     mib[4] = NET_RT_IFLIST;
2091ae349f5Scvs2svn     mib[5] = 0;
2101ae349f5Scvs2svn 
2111ae349f5Scvs2svn     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
2121ae349f5Scvs2svn       LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno));
2131ae349f5Scvs2svn       return "???";
2141ae349f5Scvs2svn     }
2151ae349f5Scvs2svn     if ((buf = malloc(needed)) == NULL)
2161ae349f5Scvs2svn       return "???";
2171ae349f5Scvs2svn     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
2181ae349f5Scvs2svn       free(buf);
2191ae349f5Scvs2svn       return "???";
2201ae349f5Scvs2svn     }
2211ae349f5Scvs2svn     end = buf + needed;
2221ae349f5Scvs2svn 
2231ae349f5Scvs2svn     have = 0;
2241ae349f5Scvs2svn     for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
2251ae349f5Scvs2svn       ifm = (struct if_msghdr *)ptr;
2261ae349f5Scvs2svn       dl = (struct sockaddr_dl *)(ifm + 1);
2271ae349f5Scvs2svn       if (ifm->ifm_index > 0) {
2281ae349f5Scvs2svn         if (ifm->ifm_index > have) {
2291ae349f5Scvs2svn           had = have;
2301ae349f5Scvs2svn           have = ifm->ifm_index + 5;
2311ae349f5Scvs2svn           if (had)
2321ae349f5Scvs2svn             ifs = (char **)realloc(ifs, sizeof(char *) * have);
2331ae349f5Scvs2svn           else
2341ae349f5Scvs2svn             ifs = (char **)malloc(sizeof(char *) * have);
2351ae349f5Scvs2svn           if (!ifs) {
2361ae349f5Scvs2svn             LogPrintf(LogDEBUG, "Index2Nam: %s\n", strerror(errno));
2371ae349f5Scvs2svn             nifs = 0;
2381ae349f5Scvs2svn             return "???";
2391ae349f5Scvs2svn           }
2401ae349f5Scvs2svn           memset(ifs + had, '\0', sizeof(char *) * (have - had));
2411ae349f5Scvs2svn         }
2421ae349f5Scvs2svn         if (ifs[ifm->ifm_index-1] == NULL) {
2431ae349f5Scvs2svn           ifs[ifm->ifm_index-1] = (char *)malloc(dl->sdl_nlen+1);
2441ae349f5Scvs2svn           memcpy(ifs[ifm->ifm_index-1], dl->sdl_data, dl->sdl_nlen);
2451ae349f5Scvs2svn           ifs[ifm->ifm_index-1][dl->sdl_nlen] = '\0';
2461ae349f5Scvs2svn           if (nifs < ifm->ifm_index)
2471ae349f5Scvs2svn             nifs = ifm->ifm_index;
2481ae349f5Scvs2svn         }
2491ae349f5Scvs2svn       } else if (LogIsKept(LogDEBUG))
2501ae349f5Scvs2svn         LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n",
2511ae349f5Scvs2svn                   ifm->ifm_index);
2521ae349f5Scvs2svn     }
2531ae349f5Scvs2svn     free(buf);
2541ae349f5Scvs2svn   }
2551ae349f5Scvs2svn 
2561ae349f5Scvs2svn   if (LogIsKept(LogDEBUG) && !debug_done) {
2571ae349f5Scvs2svn     int f;
2581ae349f5Scvs2svn 
2591ae349f5Scvs2svn     LogPrintf(LogDEBUG, "Found the following interfaces:\n");
2601ae349f5Scvs2svn     for (f = 0; f < nifs; f++)
2611ae349f5Scvs2svn       if (ifs[f] != NULL)
2621ae349f5Scvs2svn         LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]);
2631ae349f5Scvs2svn     debug_done = 1;
2641ae349f5Scvs2svn   }
2651ae349f5Scvs2svn 
2661ae349f5Scvs2svn   if (idx < 1 || idx > nifs || ifs[idx-1] == NULL)
2671ae349f5Scvs2svn     return "???";
2681ae349f5Scvs2svn 
2691ae349f5Scvs2svn   return ifs[idx-1];
2701ae349f5Scvs2svn }
2711ae349f5Scvs2svn 
2721ae349f5Scvs2svn int
2731ae349f5Scvs2svn ShowRoute(struct cmdargs const *arg)
2741ae349f5Scvs2svn {
2751ae349f5Scvs2svn   struct rt_msghdr *rtm;
2761ae349f5Scvs2svn   struct sockaddr *sa_dst, *sa_gw, *sa_mask;
2771ae349f5Scvs2svn   char *sp, *ep, *cp, *wp;
2781ae349f5Scvs2svn   size_t needed;
2791ae349f5Scvs2svn   int mib[6];
2801ae349f5Scvs2svn 
2811ae349f5Scvs2svn   mib[0] = CTL_NET;
2821ae349f5Scvs2svn   mib[1] = PF_ROUTE;
2831ae349f5Scvs2svn   mib[2] = 0;
2841ae349f5Scvs2svn   mib[3] = 0;
2851ae349f5Scvs2svn   mib[4] = NET_RT_DUMP;
2861ae349f5Scvs2svn   mib[5] = 0;
2871ae349f5Scvs2svn   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
2881ae349f5Scvs2svn     LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno));
2891ae349f5Scvs2svn     return (1);
2901ae349f5Scvs2svn   }
2911ae349f5Scvs2svn   if (needed < 0)
2921ae349f5Scvs2svn     return (1);
2931ae349f5Scvs2svn   sp = malloc(needed);
2941ae349f5Scvs2svn   if (sp == NULL)
2951ae349f5Scvs2svn     return (1);
2961ae349f5Scvs2svn   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
2971ae349f5Scvs2svn     LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno));
2981ae349f5Scvs2svn     free(sp);
2991ae349f5Scvs2svn     return (1);
3001ae349f5Scvs2svn   }
3011ae349f5Scvs2svn   ep = sp + needed;
3021ae349f5Scvs2svn 
30385b542cfSBrian Somers   prompt_Printf(&prompt, "%-20s%-20sFlags  Netif\n", "Destination", "Gateway");
3041ae349f5Scvs2svn   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
3051ae349f5Scvs2svn     rtm = (struct rt_msghdr *) cp;
3061ae349f5Scvs2svn     wp = (char *)(rtm+1);
3071ae349f5Scvs2svn 
3081ae349f5Scvs2svn     if (rtm->rtm_addrs & RTA_DST) {
3091ae349f5Scvs2svn       sa_dst = (struct sockaddr *)wp;
3101ae349f5Scvs2svn       wp += sa_dst->sa_len;
3111ae349f5Scvs2svn     } else
3121ae349f5Scvs2svn       sa_dst = NULL;
3131ae349f5Scvs2svn 
3141ae349f5Scvs2svn     if (rtm->rtm_addrs & RTA_GATEWAY) {
3151ae349f5Scvs2svn       sa_gw = (struct sockaddr *)wp;
3161ae349f5Scvs2svn       wp += sa_gw->sa_len;
3171ae349f5Scvs2svn     } else
3181ae349f5Scvs2svn       sa_gw = NULL;
3191ae349f5Scvs2svn 
3201ae349f5Scvs2svn     if (rtm->rtm_addrs & RTA_NETMASK) {
3211ae349f5Scvs2svn       sa_mask = (struct sockaddr *)wp;
3221ae349f5Scvs2svn       wp += sa_mask->sa_len;
3231ae349f5Scvs2svn     } else
3241ae349f5Scvs2svn       sa_mask = NULL;
3251ae349f5Scvs2svn 
3261ae349f5Scvs2svn     p_sockaddr(sa_dst, sa_mask, 20);
3271ae349f5Scvs2svn     p_sockaddr(sa_gw, NULL, 20);
3281ae349f5Scvs2svn 
3291ae349f5Scvs2svn     p_flags(rtm->rtm_flags, 6);
33085b542cfSBrian Somers     prompt_Printf(&prompt, " %s\n", Index2Nam(rtm->rtm_index));
3311ae349f5Scvs2svn   }
3321ae349f5Scvs2svn   free(sp);
3331ae349f5Scvs2svn   return 0;
3341ae349f5Scvs2svn }
3351ae349f5Scvs2svn 
3361ae349f5Scvs2svn /*
3371ae349f5Scvs2svn  *  Delete routes associated with our interface
3381ae349f5Scvs2svn  */
3391ae349f5Scvs2svn void
340820de6ebSBrian Somers DeleteIfRoutes(struct bundle *bundle, int all)
3411ae349f5Scvs2svn {
3421ae349f5Scvs2svn   struct rt_msghdr *rtm;
3431ae349f5Scvs2svn   struct sockaddr *sa;
3441ae349f5Scvs2svn   struct in_addr sa_dst, sa_none;
3451ae349f5Scvs2svn   int pass;
3461ae349f5Scvs2svn   size_t needed;
3471ae349f5Scvs2svn   char *sp, *cp, *ep;
3481ae349f5Scvs2svn   int mib[6];
3491ae349f5Scvs2svn 
3507a6f8720SBrian Somers   LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", bundle->ifIndex);
3511ae349f5Scvs2svn   sa_none.s_addr = INADDR_ANY;
3521ae349f5Scvs2svn 
3531ae349f5Scvs2svn   mib[0] = CTL_NET;
3541ae349f5Scvs2svn   mib[1] = PF_ROUTE;
3551ae349f5Scvs2svn   mib[2] = 0;
3561ae349f5Scvs2svn   mib[3] = 0;
3571ae349f5Scvs2svn   mib[4] = NET_RT_DUMP;
3581ae349f5Scvs2svn   mib[5] = 0;
3591ae349f5Scvs2svn   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
3601ae349f5Scvs2svn     LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n",
3611ae349f5Scvs2svn 	      strerror(errno));
3621ae349f5Scvs2svn     return;
3631ae349f5Scvs2svn   }
3641ae349f5Scvs2svn   if (needed < 0)
3651ae349f5Scvs2svn     return;
3661ae349f5Scvs2svn 
3671ae349f5Scvs2svn   sp = malloc(needed);
3681ae349f5Scvs2svn   if (sp == NULL)
3691ae349f5Scvs2svn     return;
3701ae349f5Scvs2svn 
3711ae349f5Scvs2svn   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
3721ae349f5Scvs2svn     LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n",
3731ae349f5Scvs2svn 	      strerror(errno));
3741ae349f5Scvs2svn     free(sp);
3751ae349f5Scvs2svn     return;
3761ae349f5Scvs2svn   }
3771ae349f5Scvs2svn   ep = sp + needed;
3781ae349f5Scvs2svn 
3791ae349f5Scvs2svn   for (pass = 0; pass < 2; pass++) {
3801ae349f5Scvs2svn     /*
3811ae349f5Scvs2svn      * We do 2 passes.  The first deletes all cloned routes.  The second
3821ae349f5Scvs2svn      * deletes all non-cloned routes.  This is necessary to avoid
3831ae349f5Scvs2svn      * potential errors from trying to delete route X after route Y where
3841ae349f5Scvs2svn      * route X was cloned from route Y (which is no longer there).
3851ae349f5Scvs2svn      */
3861ae349f5Scvs2svn     if (RTF_WASCLONED == 0 && pass == 0)
3871ae349f5Scvs2svn       /* So we can't tell ! */
3881ae349f5Scvs2svn       continue;
3891ae349f5Scvs2svn     for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
3901ae349f5Scvs2svn       rtm = (struct rt_msghdr *) cp;
3911ae349f5Scvs2svn       sa = (struct sockaddr *) (rtm + 1);
3921ae349f5Scvs2svn       LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s),"
3931ae349f5Scvs2svn                 " flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index,
3941ae349f5Scvs2svn                 Index2Nam(rtm->rtm_index), rtm->rtm_flags,
3951ae349f5Scvs2svn 	        inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
3961ae349f5Scvs2svn       if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY &&
3977a6f8720SBrian Somers 	  rtm->rtm_index == bundle->ifIndex &&
3981ae349f5Scvs2svn 	  (all || (rtm->rtm_flags & RTF_GATEWAY))) {
3991ae349f5Scvs2svn         sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
4001ae349f5Scvs2svn         sa = (struct sockaddr *)((char *)sa + sa->sa_len);
4011ae349f5Scvs2svn         if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) {
4021ae349f5Scvs2svn           if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) ||
4031ae349f5Scvs2svn               (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) {
4041ae349f5Scvs2svn             LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it (pass %d)\n", pass);
4057a6f8720SBrian Somers             bundle_SetRoute(bundle, RTM_DELETE, sa_dst, sa_none, sa_none, 0);
4061ae349f5Scvs2svn           } else
4071ae349f5Scvs2svn             LogPrintf(LogDEBUG, "DeleteIfRoutes: Skip it (pass %d)\n", pass);
4081ae349f5Scvs2svn         } else
4091ae349f5Scvs2svn           LogPrintf(LogDEBUG,
4101ae349f5Scvs2svn                     "DeleteIfRoutes: Can't remove routes of %d family !\n",
4111ae349f5Scvs2svn                     sa->sa_family);
4121ae349f5Scvs2svn       }
4131ae349f5Scvs2svn     }
4141ae349f5Scvs2svn   }
4151ae349f5Scvs2svn   free(sp);
4161ae349f5Scvs2svn }
4171ae349f5Scvs2svn 
4181ae349f5Scvs2svn int
4191ae349f5Scvs2svn GetIfIndex(char *name)
4201ae349f5Scvs2svn {
4211ae349f5Scvs2svn   int idx;
4221ae349f5Scvs2svn   const char *got;
4231ae349f5Scvs2svn 
4241ae349f5Scvs2svn   idx = 1;
4251ae349f5Scvs2svn   while (strcmp(got = Index2Nam(idx), "???"))
4261ae349f5Scvs2svn     if (!strcmp(got, name))
4277a6f8720SBrian Somers       return idx;
4281ae349f5Scvs2svn     else
4291ae349f5Scvs2svn       idx++;
4301ae349f5Scvs2svn   return -1;
4311ae349f5Scvs2svn }
432