xref: /freebsd/usr.sbin/ppp/route.c (revision b6217683dc0269a53b799399522dbdfb5a4919cc)
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  *
20b6217683SBrian Somers  * $Id: route.c,v 1.42.2.14 1998/04/03 19:21:51 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>
33eaa4df37SBrian Somers #include <netinet/in_systm.h>
34eaa4df37SBrian Somers #include <netinet/ip.h>
351ae349f5Scvs2svn 
361ae349f5Scvs2svn #include <errno.h>
371ae349f5Scvs2svn #include <machine/endian.h>
381ae349f5Scvs2svn #include <stdio.h>
391ae349f5Scvs2svn #include <stdlib.h>
401ae349f5Scvs2svn #include <string.h>
411ae349f5Scvs2svn #include <sys/ioctl.h>
421ae349f5Scvs2svn #include <sys/sysctl.h>
4385b542cfSBrian Somers #include <termios.h>
441ae349f5Scvs2svn #include <unistd.h>
451ae349f5Scvs2svn 
461ae349f5Scvs2svn #include "command.h"
471ae349f5Scvs2svn #include "mbuf.h"
481ae349f5Scvs2svn #include "log.h"
491ae349f5Scvs2svn #include "loadalias.h"
501ae349f5Scvs2svn #include "defs.h"
511ae349f5Scvs2svn #include "vars.h"
521ae349f5Scvs2svn #include "id.h"
531ae349f5Scvs2svn #include "iplist.h"
5429e275ceSBrian Somers #include "timer.h"
5529e275ceSBrian Somers #include "throughput.h"
56879ed6faSBrian Somers #include "lqr.h"
578c07a7b2SBrian Somers #include "hdlc.h"
583b0f8d2eSBrian Somers #include "async.h"
597308ec68SBrian Somers #include "fsm.h"
603b0f8d2eSBrian Somers #include "lcp.h"
613b0f8d2eSBrian Somers #include "ccp.h"
623b0f8d2eSBrian Somers #include "link.h"
63eaa4df37SBrian Somers #include "slcompress.h"
6429e275ceSBrian Somers #include "ipcp.h"
655ca5389aSBrian Somers #include "filter.h"
662f786681SBrian Somers #include "descriptor.h"
673b0f8d2eSBrian Somers #include "mp.h"
685828db6dSBrian Somers #include "bundle.h"
691ae349f5Scvs2svn #include "route.h"
7085b542cfSBrian Somers #include "prompt.h"
711ae349f5Scvs2svn 
721ae349f5Scvs2svn static void
73b6217683SBrian Somers p_sockaddr(struct prompt *prompt, struct sockaddr *phost,
74b6217683SBrian Somers            struct sockaddr *pmask, int width)
751ae349f5Scvs2svn {
761ae349f5Scvs2svn   char buf[29];
771ae349f5Scvs2svn   struct sockaddr_in *ihost = (struct sockaddr_in *)phost;
781ae349f5Scvs2svn   struct sockaddr_in *mask = (struct sockaddr_in *)pmask;
791ae349f5Scvs2svn   struct sockaddr_dl *dl = (struct sockaddr_dl *)phost;
801ae349f5Scvs2svn 
811ae349f5Scvs2svn   switch (phost->sa_family) {
821ae349f5Scvs2svn   case AF_INET:
831ae349f5Scvs2svn     if (!phost)
841ae349f5Scvs2svn       buf[0] = '\0';
851ae349f5Scvs2svn     else if (ihost->sin_addr.s_addr == INADDR_ANY)
861ae349f5Scvs2svn       strcpy(buf, "default");
871ae349f5Scvs2svn     else if (!mask)
881ae349f5Scvs2svn       strcpy(buf, inet_ntoa(ihost->sin_addr));
891ae349f5Scvs2svn     else {
901ae349f5Scvs2svn       u_int msk = ntohl(mask->sin_addr.s_addr);
911ae349f5Scvs2svn       u_int tst;
921ae349f5Scvs2svn       int bits;
931ae349f5Scvs2svn       int len;
941ae349f5Scvs2svn       struct sockaddr_in net;
951ae349f5Scvs2svn 
961ae349f5Scvs2svn       for (tst = 1, bits=32; tst; tst <<= 1, bits--)
971ae349f5Scvs2svn         if (msk & tst)
981ae349f5Scvs2svn           break;
991ae349f5Scvs2svn 
1001ae349f5Scvs2svn       for (tst <<=1; tst; tst <<= 1)
1011ae349f5Scvs2svn         if (!(msk & tst))
1021ae349f5Scvs2svn           break;
1031ae349f5Scvs2svn 
1041ae349f5Scvs2svn       net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr;
1051ae349f5Scvs2svn       strcpy(buf, inet_ntoa(net.sin_addr));
1061ae349f5Scvs2svn       for (len = strlen(buf); len > 3; buf[len-=2] = '\0')
1071ae349f5Scvs2svn         if (strcmp(buf+len-2, ".0"))
1081ae349f5Scvs2svn           break;
1091ae349f5Scvs2svn 
1101ae349f5Scvs2svn       if (tst)    /* non-contiguous :-( */
1111ae349f5Scvs2svn         sprintf(buf+strlen(buf),"&0x%08x", msk);
1121ae349f5Scvs2svn       else
1131ae349f5Scvs2svn         sprintf(buf+strlen(buf), "/%d", bits);
1141ae349f5Scvs2svn     }
1151ae349f5Scvs2svn     break;
1161ae349f5Scvs2svn 
1171ae349f5Scvs2svn   case AF_LINK:
1181ae349f5Scvs2svn     if (dl->sdl_nlen)
1191ae349f5Scvs2svn       snprintf(buf, sizeof buf, "%.*s", dl->sdl_nlen, dl->sdl_data);
1201ae349f5Scvs2svn     else if (dl->sdl_alen)
1211ae349f5Scvs2svn       if (dl->sdl_type == IFT_ETHER)
1221ae349f5Scvs2svn         if (dl->sdl_alen < sizeof buf / 3) {
1231ae349f5Scvs2svn           int f;
1241ae349f5Scvs2svn           u_char *MAC;
1251ae349f5Scvs2svn 
1261ae349f5Scvs2svn           MAC = (u_char *)dl->sdl_data + dl->sdl_nlen;
1271ae349f5Scvs2svn           for (f = 0; f < dl->sdl_alen; f++)
1281ae349f5Scvs2svn             sprintf(buf+f*3, "%02x:", MAC[f]);
1291ae349f5Scvs2svn           buf[f*3-1] = '\0';
1301ae349f5Scvs2svn         } else
1311ae349f5Scvs2svn 	  strcpy(buf, "??:??:??:??:??:??");
1321ae349f5Scvs2svn       else
1331ae349f5Scvs2svn         sprintf(buf, "<IFT type %d>", dl->sdl_type);
1341ae349f5Scvs2svn     else if (dl->sdl_slen)
1351ae349f5Scvs2svn       sprintf(buf, "<slen %d?>", dl->sdl_slen);
1361ae349f5Scvs2svn     else
1371ae349f5Scvs2svn       sprintf(buf, "link#%d", dl->sdl_index);
1381ae349f5Scvs2svn     break;
1391ae349f5Scvs2svn 
1401ae349f5Scvs2svn   default:
1411ae349f5Scvs2svn     sprintf(buf, "<AF type %d>", phost->sa_family);
1421ae349f5Scvs2svn     break;
1431ae349f5Scvs2svn   }
1441ae349f5Scvs2svn 
145b6217683SBrian Somers   prompt_Printf(prompt, "%-*s ", width-1, buf);
1461ae349f5Scvs2svn }
1471ae349f5Scvs2svn 
1481ae349f5Scvs2svn static struct bits {
1491ae349f5Scvs2svn   u_long b_mask;
1501ae349f5Scvs2svn   char b_val;
1511ae349f5Scvs2svn } bits[] = {
1521ae349f5Scvs2svn   { RTF_UP, 'U' },
1531ae349f5Scvs2svn   { RTF_GATEWAY, 'G' },
1541ae349f5Scvs2svn   { RTF_HOST, 'H' },
1551ae349f5Scvs2svn   { RTF_REJECT, 'R' },
1561ae349f5Scvs2svn   { RTF_DYNAMIC, 'D' },
1571ae349f5Scvs2svn   { RTF_MODIFIED, 'M' },
1581ae349f5Scvs2svn   { RTF_DONE, 'd' },
1591ae349f5Scvs2svn   { RTF_CLONING, 'C' },
1601ae349f5Scvs2svn   { RTF_XRESOLVE, 'X' },
1611ae349f5Scvs2svn   { RTF_LLINFO, 'L' },
1621ae349f5Scvs2svn   { RTF_STATIC, 'S' },
1631ae349f5Scvs2svn   { RTF_PROTO1, '1' },
1641ae349f5Scvs2svn   { RTF_PROTO2, '2' },
1651ae349f5Scvs2svn   { RTF_BLACKHOLE, 'B' },
1661ae349f5Scvs2svn #ifdef RTF_WASCLONED
1671ae349f5Scvs2svn   { RTF_WASCLONED, 'W' },
1681ae349f5Scvs2svn #endif
1691ae349f5Scvs2svn #ifdef RTF_PRCLONING
1701ae349f5Scvs2svn   { RTF_PRCLONING, 'c' },
1711ae349f5Scvs2svn #endif
1721ae349f5Scvs2svn #ifdef RTF_PROTO3
1731ae349f5Scvs2svn   { RTF_PROTO3, '3' },
1741ae349f5Scvs2svn #endif
1751ae349f5Scvs2svn #ifdef RTF_BROADCAST
1761ae349f5Scvs2svn   { RTF_BROADCAST, 'b' },
1771ae349f5Scvs2svn #endif
1781ae349f5Scvs2svn   { 0, '\0' }
1791ae349f5Scvs2svn };
1801ae349f5Scvs2svn 
1811ae349f5Scvs2svn #ifndef RTF_WASCLONED
1821ae349f5Scvs2svn #define RTF_WASCLONED (0)
1831ae349f5Scvs2svn #endif
1841ae349f5Scvs2svn 
1851ae349f5Scvs2svn static void
186b6217683SBrian Somers p_flags(struct prompt *prompt, u_long f, int max)
1871ae349f5Scvs2svn {
1881ae349f5Scvs2svn   char name[33], *flags;
1891ae349f5Scvs2svn   register struct bits *p = bits;
1901ae349f5Scvs2svn 
1911ae349f5Scvs2svn   if (max > sizeof name - 1)
1921ae349f5Scvs2svn     max = sizeof name - 1;
1931ae349f5Scvs2svn 
1941ae349f5Scvs2svn   for (flags = name; p->b_mask && flags - name < max; p++)
1951ae349f5Scvs2svn     if (p->b_mask & f)
1961ae349f5Scvs2svn       *flags++ = p->b_val;
1971ae349f5Scvs2svn   *flags = '\0';
198b6217683SBrian Somers   prompt_Printf(prompt, "%-*.*s", max, max, name);
1991ae349f5Scvs2svn }
2001ae349f5Scvs2svn 
2011ae349f5Scvs2svn const char *
2021ae349f5Scvs2svn Index2Nam(int idx)
2031ae349f5Scvs2svn {
2041ae349f5Scvs2svn   static char **ifs;
2051ae349f5Scvs2svn   static int nifs, debug_done;
2061ae349f5Scvs2svn 
2071ae349f5Scvs2svn   if (!nifs) {
2081ae349f5Scvs2svn     int mib[6], have, had;
2091ae349f5Scvs2svn     size_t needed;
2101ae349f5Scvs2svn     char *buf, *ptr, *end;
2111ae349f5Scvs2svn     struct sockaddr_dl *dl;
2121ae349f5Scvs2svn     struct if_msghdr *ifm;
2131ae349f5Scvs2svn 
2141ae349f5Scvs2svn     mib[0] = CTL_NET;
2151ae349f5Scvs2svn     mib[1] = PF_ROUTE;
2161ae349f5Scvs2svn     mib[2] = 0;
2171ae349f5Scvs2svn     mib[3] = 0;
2181ae349f5Scvs2svn     mib[4] = NET_RT_IFLIST;
2191ae349f5Scvs2svn     mib[5] = 0;
2201ae349f5Scvs2svn 
2211ae349f5Scvs2svn     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
2221ae349f5Scvs2svn       LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno));
2231ae349f5Scvs2svn       return "???";
2241ae349f5Scvs2svn     }
2251ae349f5Scvs2svn     if ((buf = malloc(needed)) == NULL)
2261ae349f5Scvs2svn       return "???";
2271ae349f5Scvs2svn     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
2281ae349f5Scvs2svn       free(buf);
2291ae349f5Scvs2svn       return "???";
2301ae349f5Scvs2svn     }
2311ae349f5Scvs2svn     end = buf + needed;
2321ae349f5Scvs2svn 
2331ae349f5Scvs2svn     have = 0;
2341ae349f5Scvs2svn     for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
2351ae349f5Scvs2svn       ifm = (struct if_msghdr *)ptr;
2361ae349f5Scvs2svn       dl = (struct sockaddr_dl *)(ifm + 1);
2371ae349f5Scvs2svn       if (ifm->ifm_index > 0) {
2381ae349f5Scvs2svn         if (ifm->ifm_index > have) {
2391ae349f5Scvs2svn           had = have;
2401ae349f5Scvs2svn           have = ifm->ifm_index + 5;
2411ae349f5Scvs2svn           if (had)
2421ae349f5Scvs2svn             ifs = (char **)realloc(ifs, sizeof(char *) * have);
2431ae349f5Scvs2svn           else
2441ae349f5Scvs2svn             ifs = (char **)malloc(sizeof(char *) * have);
2451ae349f5Scvs2svn           if (!ifs) {
2461ae349f5Scvs2svn             LogPrintf(LogDEBUG, "Index2Nam: %s\n", strerror(errno));
2471ae349f5Scvs2svn             nifs = 0;
2481ae349f5Scvs2svn             return "???";
2491ae349f5Scvs2svn           }
2501ae349f5Scvs2svn           memset(ifs + had, '\0', sizeof(char *) * (have - had));
2511ae349f5Scvs2svn         }
2521ae349f5Scvs2svn         if (ifs[ifm->ifm_index-1] == NULL) {
2531ae349f5Scvs2svn           ifs[ifm->ifm_index-1] = (char *)malloc(dl->sdl_nlen+1);
2541ae349f5Scvs2svn           memcpy(ifs[ifm->ifm_index-1], dl->sdl_data, dl->sdl_nlen);
2551ae349f5Scvs2svn           ifs[ifm->ifm_index-1][dl->sdl_nlen] = '\0';
2561ae349f5Scvs2svn           if (nifs < ifm->ifm_index)
2571ae349f5Scvs2svn             nifs = ifm->ifm_index;
2581ae349f5Scvs2svn         }
2591ae349f5Scvs2svn       } else if (LogIsKept(LogDEBUG))
2601ae349f5Scvs2svn         LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n",
2611ae349f5Scvs2svn                   ifm->ifm_index);
2621ae349f5Scvs2svn     }
2631ae349f5Scvs2svn     free(buf);
2641ae349f5Scvs2svn   }
2651ae349f5Scvs2svn 
2661ae349f5Scvs2svn   if (LogIsKept(LogDEBUG) && !debug_done) {
2671ae349f5Scvs2svn     int f;
2681ae349f5Scvs2svn 
2691ae349f5Scvs2svn     LogPrintf(LogDEBUG, "Found the following interfaces:\n");
2701ae349f5Scvs2svn     for (f = 0; f < nifs; f++)
2711ae349f5Scvs2svn       if (ifs[f] != NULL)
2721ae349f5Scvs2svn         LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]);
2731ae349f5Scvs2svn     debug_done = 1;
2741ae349f5Scvs2svn   }
2751ae349f5Scvs2svn 
2761ae349f5Scvs2svn   if (idx < 1 || idx > nifs || ifs[idx-1] == NULL)
2771ae349f5Scvs2svn     return "???";
2781ae349f5Scvs2svn 
2791ae349f5Scvs2svn   return ifs[idx-1];
2801ae349f5Scvs2svn }
2811ae349f5Scvs2svn 
2821ae349f5Scvs2svn int
2831ae349f5Scvs2svn ShowRoute(struct cmdargs const *arg)
2841ae349f5Scvs2svn {
2851ae349f5Scvs2svn   struct rt_msghdr *rtm;
2861ae349f5Scvs2svn   struct sockaddr *sa_dst, *sa_gw, *sa_mask;
2871ae349f5Scvs2svn   char *sp, *ep, *cp, *wp;
2881ae349f5Scvs2svn   size_t needed;
2891ae349f5Scvs2svn   int mib[6];
2901ae349f5Scvs2svn 
2911ae349f5Scvs2svn   mib[0] = CTL_NET;
2921ae349f5Scvs2svn   mib[1] = PF_ROUTE;
2931ae349f5Scvs2svn   mib[2] = 0;
2941ae349f5Scvs2svn   mib[3] = 0;
2951ae349f5Scvs2svn   mib[4] = NET_RT_DUMP;
2961ae349f5Scvs2svn   mib[5] = 0;
2971ae349f5Scvs2svn   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
2981ae349f5Scvs2svn     LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno));
2991ae349f5Scvs2svn     return (1);
3001ae349f5Scvs2svn   }
3011ae349f5Scvs2svn   if (needed < 0)
3021ae349f5Scvs2svn     return (1);
3031ae349f5Scvs2svn   sp = malloc(needed);
3041ae349f5Scvs2svn   if (sp == NULL)
3051ae349f5Scvs2svn     return (1);
3061ae349f5Scvs2svn   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
3071ae349f5Scvs2svn     LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno));
3081ae349f5Scvs2svn     free(sp);
3091ae349f5Scvs2svn     return (1);
3101ae349f5Scvs2svn   }
3111ae349f5Scvs2svn   ep = sp + needed;
3121ae349f5Scvs2svn 
313b6217683SBrian Somers   prompt_Printf(arg->prompt, "%-20s%-20sFlags  Netif\n",
314b6217683SBrian Somers                 "Destination", "Gateway");
3151ae349f5Scvs2svn   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
3161ae349f5Scvs2svn     rtm = (struct rt_msghdr *) cp;
3171ae349f5Scvs2svn     wp = (char *)(rtm+1);
3181ae349f5Scvs2svn 
3191ae349f5Scvs2svn     if (rtm->rtm_addrs & RTA_DST) {
3201ae349f5Scvs2svn       sa_dst = (struct sockaddr *)wp;
3211ae349f5Scvs2svn       wp += sa_dst->sa_len;
3221ae349f5Scvs2svn     } else
3231ae349f5Scvs2svn       sa_dst = NULL;
3241ae349f5Scvs2svn 
3251ae349f5Scvs2svn     if (rtm->rtm_addrs & RTA_GATEWAY) {
3261ae349f5Scvs2svn       sa_gw = (struct sockaddr *)wp;
3271ae349f5Scvs2svn       wp += sa_gw->sa_len;
3281ae349f5Scvs2svn     } else
3291ae349f5Scvs2svn       sa_gw = NULL;
3301ae349f5Scvs2svn 
3311ae349f5Scvs2svn     if (rtm->rtm_addrs & RTA_NETMASK) {
3321ae349f5Scvs2svn       sa_mask = (struct sockaddr *)wp;
3331ae349f5Scvs2svn       wp += sa_mask->sa_len;
3341ae349f5Scvs2svn     } else
3351ae349f5Scvs2svn       sa_mask = NULL;
3361ae349f5Scvs2svn 
337b6217683SBrian Somers     p_sockaddr(arg->prompt, sa_dst, sa_mask, 20);
338b6217683SBrian Somers     p_sockaddr(arg->prompt, sa_gw, NULL, 20);
3391ae349f5Scvs2svn 
340b6217683SBrian Somers     p_flags(arg->prompt, rtm->rtm_flags, 6);
341b6217683SBrian Somers     prompt_Printf(arg->prompt, " %s\n", Index2Nam(rtm->rtm_index));
3421ae349f5Scvs2svn   }
3431ae349f5Scvs2svn   free(sp);
3441ae349f5Scvs2svn   return 0;
3451ae349f5Scvs2svn }
3461ae349f5Scvs2svn 
3471ae349f5Scvs2svn /*
3481ae349f5Scvs2svn  *  Delete routes associated with our interface
3491ae349f5Scvs2svn  */
3501ae349f5Scvs2svn void
351820de6ebSBrian Somers DeleteIfRoutes(struct bundle *bundle, int all)
3521ae349f5Scvs2svn {
3531ae349f5Scvs2svn   struct rt_msghdr *rtm;
3541ae349f5Scvs2svn   struct sockaddr *sa;
3551ae349f5Scvs2svn   struct in_addr sa_dst, sa_none;
3561ae349f5Scvs2svn   int pass;
3571ae349f5Scvs2svn   size_t needed;
3581ae349f5Scvs2svn   char *sp, *cp, *ep;
3591ae349f5Scvs2svn   int mib[6];
3601ae349f5Scvs2svn 
3617a6f8720SBrian Somers   LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", bundle->ifIndex);
3621ae349f5Scvs2svn   sa_none.s_addr = INADDR_ANY;
3631ae349f5Scvs2svn 
3641ae349f5Scvs2svn   mib[0] = CTL_NET;
3651ae349f5Scvs2svn   mib[1] = PF_ROUTE;
3661ae349f5Scvs2svn   mib[2] = 0;
3671ae349f5Scvs2svn   mib[3] = 0;
3681ae349f5Scvs2svn   mib[4] = NET_RT_DUMP;
3691ae349f5Scvs2svn   mib[5] = 0;
3701ae349f5Scvs2svn   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
3711ae349f5Scvs2svn     LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n",
3721ae349f5Scvs2svn 	      strerror(errno));
3731ae349f5Scvs2svn     return;
3741ae349f5Scvs2svn   }
3751ae349f5Scvs2svn   if (needed < 0)
3761ae349f5Scvs2svn     return;
3771ae349f5Scvs2svn 
3781ae349f5Scvs2svn   sp = malloc(needed);
3791ae349f5Scvs2svn   if (sp == NULL)
3801ae349f5Scvs2svn     return;
3811ae349f5Scvs2svn 
3821ae349f5Scvs2svn   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
3831ae349f5Scvs2svn     LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n",
3841ae349f5Scvs2svn 	      strerror(errno));
3851ae349f5Scvs2svn     free(sp);
3861ae349f5Scvs2svn     return;
3871ae349f5Scvs2svn   }
3881ae349f5Scvs2svn   ep = sp + needed;
3891ae349f5Scvs2svn 
3901ae349f5Scvs2svn   for (pass = 0; pass < 2; pass++) {
3911ae349f5Scvs2svn     /*
3921ae349f5Scvs2svn      * We do 2 passes.  The first deletes all cloned routes.  The second
3931ae349f5Scvs2svn      * deletes all non-cloned routes.  This is necessary to avoid
3941ae349f5Scvs2svn      * potential errors from trying to delete route X after route Y where
3951ae349f5Scvs2svn      * route X was cloned from route Y (which is no longer there).
3961ae349f5Scvs2svn      */
3971ae349f5Scvs2svn     if (RTF_WASCLONED == 0 && pass == 0)
3981ae349f5Scvs2svn       /* So we can't tell ! */
3991ae349f5Scvs2svn       continue;
4001ae349f5Scvs2svn     for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
4011ae349f5Scvs2svn       rtm = (struct rt_msghdr *) cp;
4021ae349f5Scvs2svn       sa = (struct sockaddr *) (rtm + 1);
4031ae349f5Scvs2svn       LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s),"
4041ae349f5Scvs2svn                 " flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index,
4051ae349f5Scvs2svn                 Index2Nam(rtm->rtm_index), rtm->rtm_flags,
4061ae349f5Scvs2svn 	        inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
4071ae349f5Scvs2svn       if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY &&
4087a6f8720SBrian Somers 	  rtm->rtm_index == bundle->ifIndex &&
4091ae349f5Scvs2svn 	  (all || (rtm->rtm_flags & RTF_GATEWAY))) {
4101ae349f5Scvs2svn         sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
4111ae349f5Scvs2svn         sa = (struct sockaddr *)((char *)sa + sa->sa_len);
4121ae349f5Scvs2svn         if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) {
4131ae349f5Scvs2svn           if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) ||
4141ae349f5Scvs2svn               (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) {
4151ae349f5Scvs2svn             LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it (pass %d)\n", pass);
4167a6f8720SBrian Somers             bundle_SetRoute(bundle, RTM_DELETE, sa_dst, sa_none, sa_none, 0);
4171ae349f5Scvs2svn           } else
4181ae349f5Scvs2svn             LogPrintf(LogDEBUG, "DeleteIfRoutes: Skip it (pass %d)\n", pass);
4191ae349f5Scvs2svn         } else
4201ae349f5Scvs2svn           LogPrintf(LogDEBUG,
4211ae349f5Scvs2svn                     "DeleteIfRoutes: Can't remove routes of %d family !\n",
4221ae349f5Scvs2svn                     sa->sa_family);
4231ae349f5Scvs2svn       }
4241ae349f5Scvs2svn     }
4251ae349f5Scvs2svn   }
4261ae349f5Scvs2svn   free(sp);
4271ae349f5Scvs2svn }
4281ae349f5Scvs2svn 
4291ae349f5Scvs2svn int
4301ae349f5Scvs2svn GetIfIndex(char *name)
4311ae349f5Scvs2svn {
4321ae349f5Scvs2svn   int idx;
4331ae349f5Scvs2svn   const char *got;
4341ae349f5Scvs2svn 
4351ae349f5Scvs2svn   idx = 1;
4361ae349f5Scvs2svn   while (strcmp(got = Index2Nam(idx), "???"))
4371ae349f5Scvs2svn     if (!strcmp(got, name))
4387a6f8720SBrian Somers       return idx;
4391ae349f5Scvs2svn     else
4401ae349f5Scvs2svn       idx++;
4411ae349f5Scvs2svn   return -1;
4421ae349f5Scvs2svn }
443