xref: /freebsd/usr.sbin/ppp/route.c (revision 9cb1d89ee2c17b7e8b6b1bfc016f68fc03f9d3ff)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *	      PPP Routing related Module
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan, Inc.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
209cb1d89eSBrian Somers  * $Id: route.c,v 1.27 1997/11/22 03:37:44 brian Exp $
2153c9f6c0SAtsushi Murai  *
22af57ed9fSAtsushi Murai  */
2375240ed1SBrian Somers 
24af57ed9fSAtsushi Murai #include <sys/param.h>
25628d2ac1SGarrett Wollman #include <sys/time.h>
2675240ed1SBrian Somers #include <sys/socket.h>
275d5e5070SBrian Somers #include <net/if_types.h>
28628d2ac1SGarrett Wollman #include <net/route.h>
29628d2ac1SGarrett Wollman #include <net/if.h>
30628d2ac1SGarrett Wollman #include <netinet/in_systm.h>
31628d2ac1SGarrett Wollman #include <netinet/in.h>
32628d2ac1SGarrett Wollman #include <arpa/inet.h>
335d5e5070SBrian Somers #include <net/if_dl.h>
34628d2ac1SGarrett Wollman 
3575240ed1SBrian Somers #include <errno.h>
3675240ed1SBrian Somers #include <machine/endian.h>
3775240ed1SBrian Somers #include <stdio.h>
3875240ed1SBrian Somers #include <stdlib.h>
3975240ed1SBrian Somers #include <string.h>
4075240ed1SBrian Somers #include <sys/ioctl.h>
4175240ed1SBrian Somers #include <sys/sysctl.h>
4275240ed1SBrian Somers #include <unistd.h>
4375240ed1SBrian Somers 
44b6e82f33SBrian Somers #include "command.h"
4575240ed1SBrian Somers #include "mbuf.h"
46215a4696SAtsushi Murai #include "log.h"
47927145beSBrian Somers #include "loadalias.h"
4886e02934SBrian Somers #include "defs.h"
49927145beSBrian Somers #include "vars.h"
505106c671SBrian Somers #include "id.h"
5175240ed1SBrian Somers #include "route.h"
52af57ed9fSAtsushi Murai 
53af57ed9fSAtsushi Murai static int IfIndex;
54af57ed9fSAtsushi Murai 
55af57ed9fSAtsushi Murai struct rtmsg {
56af57ed9fSAtsushi Murai   struct rt_msghdr m_rtm;
57af57ed9fSAtsushi Murai   char m_space[64];
58af57ed9fSAtsushi Murai };
59af57ed9fSAtsushi Murai 
60af57ed9fSAtsushi Murai static int seqno;
61af57ed9fSAtsushi Murai 
62af57ed9fSAtsushi Murai void
63944f7098SBrian Somers OsSetRoute(int cmd,
64944f7098SBrian Somers 	   struct in_addr dst,
65944f7098SBrian Somers 	   struct in_addr gateway,
66944f7098SBrian Somers 	   struct in_addr mask)
67af57ed9fSAtsushi Murai {
68af57ed9fSAtsushi Murai   struct rtmsg rtmes;
69af57ed9fSAtsushi Murai   int s, nb, wb;
70b6e82f33SBrian Somers   char *cp;
71b6e82f33SBrian Somers   const char *cmdstr;
72af57ed9fSAtsushi Murai   u_long *lp;
73af57ed9fSAtsushi Murai   struct sockaddr_in rtdata;
74af57ed9fSAtsushi Murai 
755106c671SBrian Somers   cmdstr = (cmd == RTM_ADD ? "Add" : "Delete");
765106c671SBrian Somers   s = ID0socket(PF_ROUTE, SOCK_RAW, 0);
776614d8c5SBrian Somers   if (s < 0) {
78afc7fa2cSBrian Somers     LogPrintf(LogERROR, "OsSetRoute: socket(): %s\n", strerror(errno));
796614d8c5SBrian Somers     return;
806614d8c5SBrian Somers   }
8175240ed1SBrian Somers   memset(&rtmes, '\0', sizeof(rtmes));
82af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_version = RTM_VERSION;
83af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_type = cmd;
84d3a3ec3bSBrian Somers   rtmes.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
85af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_seq = ++seqno;
86af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_pid = getpid();
872db86e5bSPeter Wemm   rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
88af57ed9fSAtsushi Murai 
8975240ed1SBrian Somers   memset(&rtdata, '\0', sizeof(rtdata));
90af57ed9fSAtsushi Murai   rtdata.sin_len = 16;
91af57ed9fSAtsushi Murai   rtdata.sin_family = AF_INET;
92af57ed9fSAtsushi Murai   rtdata.sin_port = 0;
93af57ed9fSAtsushi Murai   rtdata.sin_addr = dst;
94af57ed9fSAtsushi Murai 
95af57ed9fSAtsushi Murai   cp = rtmes.m_space;
9675240ed1SBrian Somers   memcpy(cp, &rtdata, 16);
97af57ed9fSAtsushi Murai   cp += 16;
98af57ed9fSAtsushi Murai   if (gateway.s_addr) {
99af57ed9fSAtsushi Murai     rtdata.sin_addr = gateway;
10075240ed1SBrian Somers     memcpy(cp, &rtdata, 16);
101af57ed9fSAtsushi Murai     cp += 16;
102d3a3ec3bSBrian Somers     rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
103af57ed9fSAtsushi Murai   }
104af57ed9fSAtsushi Murai   if (dst.s_addr == INADDR_ANY)
105af57ed9fSAtsushi Murai     mask.s_addr = INADDR_ANY;
106af57ed9fSAtsushi Murai 
107af57ed9fSAtsushi Murai   lp = (u_long *) cp;
108af57ed9fSAtsushi Murai 
109af57ed9fSAtsushi Murai   if (mask.s_addr) {
110af57ed9fSAtsushi Murai     *lp++ = 8;
111af57ed9fSAtsushi Murai     cp += sizeof(int);
112af57ed9fSAtsushi Murai     *lp = mask.s_addr;
113af57ed9fSAtsushi Murai   } else
114af57ed9fSAtsushi Murai     *lp = 0;
115af57ed9fSAtsushi Murai   cp += sizeof(u_long);
116af57ed9fSAtsushi Murai 
117af57ed9fSAtsushi Murai   nb = cp - (char *) &rtmes;
118af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_msglen = nb;
119af57ed9fSAtsushi Murai   wb = write(s, &rtmes, nb);
120af57ed9fSAtsushi Murai   if (wb < 0) {
121e696ee3bSBrian Somers     LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst));
122e696ee3bSBrian Somers     LogPrintf(LogTCPIP, "OsSetRoute:  Gateway = %s\n", inet_ntoa(gateway));
123e696ee3bSBrian Somers     LogPrintf(LogTCPIP, "OsSetRoute:  Mask = %s\n", inet_ntoa(mask));
124e696ee3bSBrian Somers     switch (rtmes.m_rtm.rtm_errno) {
125e696ee3bSBrian Somers     case EEXIST:
126e696ee3bSBrian Somers       LogPrintf(LogTCPIP, "Add route failed: Already exists\n");
127e696ee3bSBrian Somers       break;
128e696ee3bSBrian Somers     case ESRCH:
129e696ee3bSBrian Somers       LogPrintf(LogTCPIP, "Del route failed: Non-existent\n");
130e696ee3bSBrian Somers       break;
1315106c671SBrian Somers     case 0:
1325106c671SBrian Somers       LogPrintf(LogTCPIP, "%s route failed: %s\n", cmdstr, strerror(errno));
1335106c671SBrian Somers       break;
134e696ee3bSBrian Somers     case ENOBUFS:
135e696ee3bSBrian Somers     default:
1365106c671SBrian Somers       LogPrintf(LogTCPIP, "%s route failed: %s\n",
1375106c671SBrian Somers 		cmdstr, strerror(rtmes.m_rtm.rtm_errno));
138e696ee3bSBrian Somers       break;
139af57ed9fSAtsushi Murai     }
140e696ee3bSBrian Somers   }
1415106c671SBrian Somers   LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n",
1425106c671SBrian Somers             wb, cmdstr, dst.s_addr, gateway.s_addr);
143af57ed9fSAtsushi Murai   close(s);
144af57ed9fSAtsushi Murai }
145af57ed9fSAtsushi Murai 
146af57ed9fSAtsushi Murai static void
1475d5e5070SBrian Somers p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width)
148af57ed9fSAtsushi Murai {
149b6e82f33SBrian Somers   char buf[29];
150b6e82f33SBrian Somers   const char *cp;
1515d5e5070SBrian Somers   struct sockaddr_in *ihost = (struct sockaddr_in *)phost;
1525d5e5070SBrian Somers   struct sockaddr_in *mask = (struct sockaddr_in *)pmask;
1535d5e5070SBrian Somers   struct sockaddr_dl *dl = (struct sockaddr_dl *)phost;
154af57ed9fSAtsushi Murai 
1555d5e5070SBrian Somers   switch (phost->sa_family) {
1565d5e5070SBrian Somers   case AF_INET:
1575d5e5070SBrian Somers     if (!phost)
1585d5e5070SBrian Somers       cp = "";
1595d5e5070SBrian Somers     else if (ihost->sin_addr.s_addr == INADDR_ANY)
1605d5e5070SBrian Somers       cp = "default";
1615d5e5070SBrian Somers     else if (!mask)
1625d5e5070SBrian Somers       cp = inet_ntoa(ihost->sin_addr);
1635d5e5070SBrian Somers     else {
1645d5e5070SBrian Somers       u_int msk = ntohl(mask->sin_addr.s_addr);
1655d5e5070SBrian Somers       u_int tst;
1665d5e5070SBrian Somers       int bits;
1675d5e5070SBrian Somers       int len;
1685d5e5070SBrian Somers       struct sockaddr_in net;
1695d5e5070SBrian Somers 
1705d5e5070SBrian Somers       for (tst = 1, bits=32; tst; tst <<= 1, bits--)
1715d5e5070SBrian Somers         if (msk & tst)
1725d5e5070SBrian Somers           break;
1735d5e5070SBrian Somers 
1745d5e5070SBrian Somers       for (tst <<=1; tst; tst <<= 1)
1755d5e5070SBrian Somers         if (!(msk & tst))
1765d5e5070SBrian Somers           break;
1775d5e5070SBrian Somers 
1785d5e5070SBrian Somers       net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr;
1795d5e5070SBrian Somers       sprintf(buf, "%s", inet_ntoa(net.sin_addr));
1805d5e5070SBrian Somers       for (len = strlen(buf); len > 3; buf[len-=2] = '\0')
1815d5e5070SBrian Somers         if (strcmp(buf+len-2, ".0"))
1825d5e5070SBrian Somers           break;
1835d5e5070SBrian Somers 
1845d5e5070SBrian Somers       if (tst)    /* non-contiguous :-( */
1855d5e5070SBrian Somers         sprintf(buf+strlen(buf),"&0x%08x", msk);
1865d5e5070SBrian Somers       else
1875d5e5070SBrian Somers         sprintf(buf+strlen(buf), "/%d", bits);
1885d5e5070SBrian Somers       cp = buf;
189927145beSBrian Somers     }
1905d5e5070SBrian Somers     break;
1915d5e5070SBrian Somers 
1925d5e5070SBrian Somers   case AF_LINK:
1935d5e5070SBrian Somers     if (!dl)
1945d5e5070SBrian Somers       cp = "";
1955d5e5070SBrian Somers     else if (dl->sdl_nlen == 0 && dl->sdl_alen == 0 && dl->sdl_slen == 0) {
1965d5e5070SBrian Somers       sprintf(buf, "link#%d", dl->sdl_index);
1975d5e5070SBrian Somers       cp = buf;
1985d5e5070SBrian Somers     } else if (dl->sdl_type == IFT_ETHER && dl->sdl_alen &&
1995d5e5070SBrian Somers                dl->sdl_alen < sizeof(buf)/3) {
2005d5e5070SBrian Somers       int f;
2015d5e5070SBrian Somers       u_char *MAC;
2025d5e5070SBrian Somers 
2035d5e5070SBrian Somers       MAC = (u_char *)dl->sdl_data + dl->sdl_nlen;
2045d5e5070SBrian Somers       for (f = 0; f < dl->sdl_alen; f++)
2055d5e5070SBrian Somers         sprintf(buf+f*3, "%02x:", MAC[f]);
2065d5e5070SBrian Somers       buf[f*3-1] = '\0';
2075d5e5070SBrian Somers       cp = buf;
2085d5e5070SBrian Somers     } else
2095d5e5070SBrian Somers       cp = "???";
2105d5e5070SBrian Somers     break;
2115d5e5070SBrian Somers 
2125d5e5070SBrian Somers   default:
2135d5e5070SBrian Somers     cp = "???";
2145d5e5070SBrian Somers     break;
2155d5e5070SBrian Somers   }
2165d5e5070SBrian Somers 
2175d5e5070SBrian Somers   fprintf(VarTerm, "%-*s ", width-1, cp);
218af57ed9fSAtsushi Murai }
219af57ed9fSAtsushi Murai 
220af57ed9fSAtsushi Murai struct bits {
2215d5e5070SBrian Somers   u_long b_mask;
222af57ed9fSAtsushi Murai   char b_val;
223af57ed9fSAtsushi Murai } bits[] = {
224944f7098SBrian Somers 
2255d5e5070SBrian Somers   { RTF_UP, 'U' },
2265d5e5070SBrian Somers   { RTF_GATEWAY, 'G' },
2275d5e5070SBrian Somers   { RTF_HOST, 'H' },
2285d5e5070SBrian Somers   { RTF_REJECT, 'R' },
2295d5e5070SBrian Somers   { RTF_DYNAMIC, 'D' },
2305d5e5070SBrian Somers   { RTF_MODIFIED, 'M' },
2315d5e5070SBrian Somers   { RTF_DONE, 'd' },
2325d5e5070SBrian Somers   { RTF_CLONING, 'C' },
2335d5e5070SBrian Somers   { RTF_XRESOLVE, 'X' },
2345d5e5070SBrian Somers   { RTF_LLINFO, 'L' },
2355d5e5070SBrian Somers   { RTF_STATIC, 'S' },
2365d5e5070SBrian Somers   { RTF_PROTO1, '1' },
2375d5e5070SBrian Somers   { RTF_PROTO2, '2' },
2385d5e5070SBrian Somers   { RTF_BLACKHOLE, 'B' },
2395d5e5070SBrian Somers #ifdef __FreeBSD__
2405d5e5070SBrian Somers   { RTF_WASCLONED, 'W' },
2415d5e5070SBrian Somers   { RTF_PRCLONING, 'c' },
2425d5e5070SBrian Somers   { RTF_PROTO3, '3' },
2435d5e5070SBrian Somers   { RTF_BROADCAST, 'b' },
2445d5e5070SBrian Somers #endif
2455d5e5070SBrian Somers   { 0, '\0' }
246af57ed9fSAtsushi Murai };
247af57ed9fSAtsushi Murai 
248af57ed9fSAtsushi Murai static void
249b6e82f33SBrian Somers p_flags(u_long f, const char *format)
250af57ed9fSAtsushi Murai {
251927145beSBrian Somers   if (VarTerm) {
252af57ed9fSAtsushi Murai     char name[33], *flags;
253af57ed9fSAtsushi Murai     register struct bits *p = bits;
254af57ed9fSAtsushi Murai 
255af57ed9fSAtsushi Murai     for (flags = name; p->b_mask; p++)
256af57ed9fSAtsushi Murai       if (p->b_mask & f)
257af57ed9fSAtsushi Murai 	*flags++ = p->b_val;
258af57ed9fSAtsushi Murai     *flags = '\0';
259927145beSBrian Somers     fprintf(VarTerm, format, name);
260927145beSBrian Somers   }
261af57ed9fSAtsushi Murai }
262af57ed9fSAtsushi Murai 
263b6e82f33SBrian Somers static const char *
2645d5e5070SBrian Somers Index2Nam(int idx)
2655d5e5070SBrian Somers {
2665d5e5070SBrian Somers   static char ifs[50][6];
2679cb1d89eSBrian Somers   static int nifs, debug_done;
2685d5e5070SBrian Somers 
2695d5e5070SBrian Somers   if (!nifs) {
2705d5e5070SBrian Somers     int mib[6], needed, len;
2715d5e5070SBrian Somers     char *buf, *ptr, *end;
2725d5e5070SBrian Somers     struct sockaddr_dl *dl;
2735d5e5070SBrian Somers     struct if_msghdr *ifm;
2745d5e5070SBrian Somers 
2755d5e5070SBrian Somers     mib[0] = CTL_NET;
2765d5e5070SBrian Somers     mib[1] = PF_ROUTE;
2775d5e5070SBrian Somers     mib[2] = 0;
2785d5e5070SBrian Somers     mib[3] = 0;
2795d5e5070SBrian Somers     mib[4] = NET_RT_IFLIST;
2805d5e5070SBrian Somers     mib[5] = 0;
2815d5e5070SBrian Somers 
2825d5e5070SBrian Somers     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
2835d5e5070SBrian Somers       LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno));
2845d5e5070SBrian Somers       return "???";
2855d5e5070SBrian Somers     }
2865d5e5070SBrian Somers     if ((buf = malloc(needed)) == NULL)
2875d5e5070SBrian Somers       return "???";
2885d5e5070SBrian Somers     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
2895d5e5070SBrian Somers       free(buf);
2905d5e5070SBrian Somers       return "???";
2915d5e5070SBrian Somers     }
2925d5e5070SBrian Somers     end = buf + needed;
2935d5e5070SBrian Somers 
2949cb1d89eSBrian Somers     for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
2955d5e5070SBrian Somers       ifm = (struct if_msghdr *)ptr;
2965d5e5070SBrian Somers       dl = (struct sockaddr_dl *)(ifm + 1);
2979cb1d89eSBrian Somers       if (ifm->ifm_index > 0 && ifm->ifm_index <= sizeof(ifs)/sizeof(ifs[0])
2989cb1d89eSBrian Somers           && ifs[ifm->ifm_index-1][0] == '\0') {
2995d5e5070SBrian Somers         if ((len = dl->sdl_nlen) > sizeof(ifs[0])-1)
3005d5e5070SBrian Somers           len = sizeof(ifs[0])-1;
3019cb1d89eSBrian Somers         strncpy(ifs[ifm->ifm_index-1], dl->sdl_data, len);
3029cb1d89eSBrian Somers         ifs[ifm->ifm_index-1][len] = '\0';
3039cb1d89eSBrian Somers         if (len && nifs < ifm->ifm_index)
3049cb1d89eSBrian Somers           nifs = ifm->ifm_index;
3059cb1d89eSBrian Somers       } else if (LogIsKept(LogDEBUG))
3069cb1d89eSBrian Somers         LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n",
3079cb1d89eSBrian Somers                   ifm->ifm_index);
3085d5e5070SBrian Somers     }
3095d5e5070SBrian Somers     free(buf);
3105d5e5070SBrian Somers   }
3115d5e5070SBrian Somers 
3129cb1d89eSBrian Somers   if (LogIsKept(LogDEBUG) && !debug_done) {
3139cb1d89eSBrian Somers     int f;
3149cb1d89eSBrian Somers 
3159cb1d89eSBrian Somers     LogPrintf(LogDEBUG, "Found the following interfaces:\n");
3169cb1d89eSBrian Somers     for (f = 0; f < nifs; f++)
3179cb1d89eSBrian Somers       if (*ifs[f] != '\0')
3189cb1d89eSBrian Somers         LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]);
3199cb1d89eSBrian Somers     debug_done = 1;
3209cb1d89eSBrian Somers   }
3219cb1d89eSBrian Somers 
3229cb1d89eSBrian Somers   if (idx < 1 || idx > nifs || ifs[idx-1][0] == '\0')
3235d5e5070SBrian Somers     return "???";
3249cb1d89eSBrian Somers 
3259cb1d89eSBrian Somers   return ifs[idx-1];
3265d5e5070SBrian Somers }
3275d5e5070SBrian Somers 
328af57ed9fSAtsushi Murai int
329b6e82f33SBrian Somers ShowRoute(struct cmdargs const *arg)
330af57ed9fSAtsushi Murai {
331af57ed9fSAtsushi Murai   struct rt_msghdr *rtm;
3325d5e5070SBrian Somers   struct sockaddr *sa_dst, *sa_gw, *sa_mask;
3335d5e5070SBrian Somers   char *sp, *ep, *cp, *wp;
3345d5e5070SBrian Somers   int needed;
335af57ed9fSAtsushi Murai   int mib[6];
336af57ed9fSAtsushi Murai 
337927145beSBrian Somers   if (!VarTerm)
338927145beSBrian Somers     return 1;
339927145beSBrian Somers 
340af57ed9fSAtsushi Murai   mib[0] = CTL_NET;
341af57ed9fSAtsushi Murai   mib[1] = PF_ROUTE;
34253c9f6c0SAtsushi Murai   mib[2] = 0;
34353c9f6c0SAtsushi Murai   mib[3] = 0;
344af57ed9fSAtsushi Murai   mib[4] = NET_RT_DUMP;
34553c9f6c0SAtsushi Murai   mib[5] = 0;
34653c9f6c0SAtsushi Murai   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
347afc7fa2cSBrian Somers     LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno));
34853c9f6c0SAtsushi Murai     return (1);
34953c9f6c0SAtsushi Murai   }
350af57ed9fSAtsushi Murai   if (needed < 0)
351af57ed9fSAtsushi Murai     return (1);
352af57ed9fSAtsushi Murai   sp = malloc(needed);
353af57ed9fSAtsushi Murai   if (sp == NULL)
354af57ed9fSAtsushi Murai     return (1);
35553c9f6c0SAtsushi Murai   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
356afc7fa2cSBrian Somers     LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno));
357b0cdb3ceSJordan K. Hubbard     free(sp);
358af57ed9fSAtsushi Murai     return (1);
35953c9f6c0SAtsushi Murai   }
360af57ed9fSAtsushi Murai   ep = sp + needed;
361af57ed9fSAtsushi Murai 
3625d5e5070SBrian Somers   fprintf(VarTerm, "%-20s%-20sFlags  Netif\n", "Destination", "Gateway");
363af57ed9fSAtsushi Murai   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
364af57ed9fSAtsushi Murai     rtm = (struct rt_msghdr *) cp;
3655d5e5070SBrian Somers     wp = (char *)(rtm+1);
3665d5e5070SBrian Somers 
3675d5e5070SBrian Somers     if (rtm->rtm_addrs & RTA_DST) {
3685d5e5070SBrian Somers       sa_dst = (struct sockaddr *)wp;
3695d5e5070SBrian Somers       wp += sa_dst->sa_len;
3705d5e5070SBrian Somers     } else
3715d5e5070SBrian Somers       sa_dst = NULL;
3725d5e5070SBrian Somers 
3735d5e5070SBrian Somers     if (rtm->rtm_addrs & RTA_GATEWAY) {
3745d5e5070SBrian Somers       sa_gw = (struct sockaddr *)wp;
3755d5e5070SBrian Somers       wp += sa_gw->sa_len;
3765d5e5070SBrian Somers     } else
3775d5e5070SBrian Somers       sa_gw = NULL;
3785d5e5070SBrian Somers 
3795d5e5070SBrian Somers     if (rtm->rtm_addrs & RTA_NETMASK) {
3805d5e5070SBrian Somers       sa_mask = (struct sockaddr *)wp;
3815d5e5070SBrian Somers       wp += sa_mask->sa_len;
3825d5e5070SBrian Somers     } else
3835d5e5070SBrian Somers       sa_mask = NULL;
3845d5e5070SBrian Somers 
3855d5e5070SBrian Somers     p_sockaddr(sa_dst, sa_mask, 20);
3865d5e5070SBrian Somers     p_sockaddr(sa_gw, NULL, 20);
3875d5e5070SBrian Somers 
3885d5e5070SBrian Somers     p_flags(rtm->rtm_flags, "%-6.6s ");
3895d5e5070SBrian Somers     fprintf(VarTerm, "%s\n", Index2Nam(rtm->rtm_index));
390af57ed9fSAtsushi Murai   }
391b0cdb3ceSJordan K. Hubbard   free(sp);
392927145beSBrian Somers   return 0;
393af57ed9fSAtsushi Murai }
394af57ed9fSAtsushi Murai 
395af57ed9fSAtsushi Murai /*
396af57ed9fSAtsushi Murai  *  Delete routes associated with our interface
397af57ed9fSAtsushi Murai  */
398af57ed9fSAtsushi Murai void
399944f7098SBrian Somers DeleteIfRoutes(int all)
400af57ed9fSAtsushi Murai {
401af57ed9fSAtsushi Murai   struct rt_msghdr *rtm;
402af57ed9fSAtsushi Murai   struct sockaddr *sa;
4035d5e5070SBrian Somers   struct in_addr sa_dst, sa_gw, sa_mask;
404af57ed9fSAtsushi Murai   int needed;
405af57ed9fSAtsushi Murai   char *sp, *cp, *ep;
406af57ed9fSAtsushi Murai   u_char *wp;
407af57ed9fSAtsushi Murai   int mib[6];
408af57ed9fSAtsushi Murai 
409927145beSBrian Somers   LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex);
410927145beSBrian Somers 
411af57ed9fSAtsushi Murai   mib[0] = CTL_NET;
412af57ed9fSAtsushi Murai   mib[1] = PF_ROUTE;
41353c9f6c0SAtsushi Murai   mib[2] = 0;
41453c9f6c0SAtsushi Murai   mib[3] = 0;
415af57ed9fSAtsushi Murai   mib[4] = NET_RT_DUMP;
41653c9f6c0SAtsushi Murai   mib[5] = 0;
41753c9f6c0SAtsushi Murai   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
418afc7fa2cSBrian Somers     LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n",
419afc7fa2cSBrian Somers 	      strerror(errno));
42053c9f6c0SAtsushi Murai     return;
42153c9f6c0SAtsushi Murai   }
422af57ed9fSAtsushi Murai   if (needed < 0)
423af57ed9fSAtsushi Murai     return;
424af57ed9fSAtsushi Murai 
425af57ed9fSAtsushi Murai   sp = malloc(needed);
426af57ed9fSAtsushi Murai   if (sp == NULL)
427af57ed9fSAtsushi Murai     return;
428af57ed9fSAtsushi Murai 
429af57ed9fSAtsushi Murai   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
430afc7fa2cSBrian Somers     LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n",
431afc7fa2cSBrian Somers 	      strerror(errno));
432af57ed9fSAtsushi Murai     free(sp);
433af57ed9fSAtsushi Murai     return;
434af57ed9fSAtsushi Murai   }
435af57ed9fSAtsushi Murai   ep = sp + needed;
436af57ed9fSAtsushi Murai 
437af57ed9fSAtsushi Murai   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
438af57ed9fSAtsushi Murai     rtm = (struct rt_msghdr *) cp;
439af57ed9fSAtsushi Murai     sa = (struct sockaddr *) (rtm + 1);
4405d5e5070SBrian Somers     LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s), flags: %x,"
4415d5e5070SBrian Somers 	      " dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index,
4425d5e5070SBrian Somers               Index2Nam(rtm->rtm_index), rtm->rtm_flags,
4439b5a20e1SBrian Somers 	      inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
4445d5e5070SBrian Somers     if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY &&
4455d5e5070SBrian Somers 	rtm->rtm_index == IfIndex &&
446af57ed9fSAtsushi Murai 	(all || (rtm->rtm_flags & RTF_GATEWAY))) {
4475d5e5070SBrian Somers       sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
448af57ed9fSAtsushi Murai       wp = (u_char *) cp + rtm->rtm_msglen;
4495d5e5070SBrian Somers       sa = (struct sockaddr *)((char *)sa + sa->sa_len);
4505d5e5070SBrian Somers       if (sa->sa_family == AF_INET) {
4515d5e5070SBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it\n");
4525d5e5070SBrian Somers         sa_gw.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
4535d5e5070SBrian Somers         sa = (struct sockaddr *)((char *)sa + sa->sa_len);
4545d5e5070SBrian Somers         if (rtm->rtm_addrs & RTA_NETMASK)
4555d5e5070SBrian Somers           sa_mask.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
4565d5e5070SBrian Somers         else
4575d5e5070SBrian Somers           sa_mask.s_addr = 0xffffffff;
4585d5e5070SBrian Somers         if (sa_dst.s_addr == INADDR_ANY)
4595d5e5070SBrian Somers 	  sa_mask.s_addr = INADDR_ANY;
4605d5e5070SBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Dst: %s\n", inet_ntoa(sa_dst));
4615d5e5070SBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Gw: %s\n", inet_ntoa(sa_gw));
462927145beSBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Index: %d\n", rtm->rtm_index);
4635d5e5070SBrian Somers         OsSetRoute(RTM_DELETE, sa_dst, sa_gw, sa_mask);
4645d5e5070SBrian Somers       } else
4655d5e5070SBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Can't remove an AF_LINK !\n");
466af57ed9fSAtsushi Murai     }
467af57ed9fSAtsushi Murai   }
468af57ed9fSAtsushi Murai   free(sp);
469af57ed9fSAtsushi Murai }
470af57ed9fSAtsushi Murai 
471af57ed9fSAtsushi Murai int
472944f7098SBrian Somers GetIfIndex(char *name)
473af57ed9fSAtsushi Murai {
4745d5e5070SBrian Somers   int idx;
475b6e82f33SBrian Somers   const char *got;
476944f7098SBrian Somers 
4779cb1d89eSBrian Somers   idx = 1;
4785d5e5070SBrian Somers   while (strcmp(got = Index2Nam(idx), "???"))
4795d5e5070SBrian Somers     if (!strcmp(got, name))
4805d5e5070SBrian Somers       return IfIndex = idx;
4815d5e5070SBrian Somers     else
4825d5e5070SBrian Somers       idx++;
4835d5e5070SBrian Somers   return -1;
484af57ed9fSAtsushi Murai }
485