xref: /freebsd/usr.sbin/ppp/route.c (revision 5d5e5070055fa6a3659448ce836051adc0befdc4)
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  *
205d5e5070SBrian Somers  * $Id: route.c,v 1.25 1997/11/11 22:58:13 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 
4475240ed1SBrian Somers #include "mbuf.h"
45215a4696SAtsushi Murai #include "log.h"
46927145beSBrian Somers #include "loadalias.h"
4775240ed1SBrian Somers #include "command.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;
705106c671SBrian Somers   char *cp, *cmdstr;
71af57ed9fSAtsushi Murai   u_long *lp;
72af57ed9fSAtsushi Murai   struct sockaddr_in rtdata;
73af57ed9fSAtsushi Murai 
745106c671SBrian Somers   cmdstr = (cmd == RTM_ADD ? "Add" : "Delete");
755106c671SBrian Somers   s = ID0socket(PF_ROUTE, SOCK_RAW, 0);
766614d8c5SBrian Somers   if (s < 0) {
77afc7fa2cSBrian Somers     LogPrintf(LogERROR, "OsSetRoute: socket(): %s\n", strerror(errno));
786614d8c5SBrian Somers     return;
796614d8c5SBrian Somers   }
8075240ed1SBrian Somers   memset(&rtmes, '\0', sizeof(rtmes));
81af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_version = RTM_VERSION;
82af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_type = cmd;
83d3a3ec3bSBrian Somers   rtmes.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
84af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_seq = ++seqno;
85af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_pid = getpid();
862db86e5bSPeter Wemm   rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
87af57ed9fSAtsushi Murai 
8875240ed1SBrian Somers   memset(&rtdata, '\0', sizeof(rtdata));
89af57ed9fSAtsushi Murai   rtdata.sin_len = 16;
90af57ed9fSAtsushi Murai   rtdata.sin_family = AF_INET;
91af57ed9fSAtsushi Murai   rtdata.sin_port = 0;
92af57ed9fSAtsushi Murai   rtdata.sin_addr = dst;
93af57ed9fSAtsushi Murai 
94af57ed9fSAtsushi Murai   cp = rtmes.m_space;
9575240ed1SBrian Somers   memcpy(cp, &rtdata, 16);
96af57ed9fSAtsushi Murai   cp += 16;
97af57ed9fSAtsushi Murai   if (gateway.s_addr) {
98af57ed9fSAtsushi Murai     rtdata.sin_addr = gateway;
9975240ed1SBrian Somers     memcpy(cp, &rtdata, 16);
100af57ed9fSAtsushi Murai     cp += 16;
101d3a3ec3bSBrian Somers     rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
102af57ed9fSAtsushi Murai   }
103af57ed9fSAtsushi Murai   if (dst.s_addr == INADDR_ANY)
104af57ed9fSAtsushi Murai     mask.s_addr = INADDR_ANY;
105af57ed9fSAtsushi Murai 
106af57ed9fSAtsushi Murai   lp = (u_long *) cp;
107af57ed9fSAtsushi Murai 
108af57ed9fSAtsushi Murai   if (mask.s_addr) {
109af57ed9fSAtsushi Murai     *lp++ = 8;
110af57ed9fSAtsushi Murai     cp += sizeof(int);
111af57ed9fSAtsushi Murai     *lp = mask.s_addr;
112af57ed9fSAtsushi Murai   } else
113af57ed9fSAtsushi Murai     *lp = 0;
114af57ed9fSAtsushi Murai   cp += sizeof(u_long);
115af57ed9fSAtsushi Murai 
116af57ed9fSAtsushi Murai   nb = cp - (char *) &rtmes;
117af57ed9fSAtsushi Murai   rtmes.m_rtm.rtm_msglen = nb;
118af57ed9fSAtsushi Murai   wb = write(s, &rtmes, nb);
119af57ed9fSAtsushi Murai   if (wb < 0) {
120e696ee3bSBrian Somers     LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst));
121e696ee3bSBrian Somers     LogPrintf(LogTCPIP, "OsSetRoute:  Gateway = %s\n", inet_ntoa(gateway));
122e696ee3bSBrian Somers     LogPrintf(LogTCPIP, "OsSetRoute:  Mask = %s\n", inet_ntoa(mask));
123e696ee3bSBrian Somers     switch (rtmes.m_rtm.rtm_errno) {
124e696ee3bSBrian Somers     case EEXIST:
125e696ee3bSBrian Somers       LogPrintf(LogTCPIP, "Add route failed: Already exists\n");
126e696ee3bSBrian Somers       break;
127e696ee3bSBrian Somers     case ESRCH:
128e696ee3bSBrian Somers       LogPrintf(LogTCPIP, "Del route failed: Non-existent\n");
129e696ee3bSBrian Somers       break;
1305106c671SBrian Somers     case 0:
1315106c671SBrian Somers       LogPrintf(LogTCPIP, "%s route failed: %s\n", cmdstr, strerror(errno));
1325106c671SBrian Somers       break;
133e696ee3bSBrian Somers     case ENOBUFS:
134e696ee3bSBrian Somers     default:
1355106c671SBrian Somers       LogPrintf(LogTCPIP, "%s route failed: %s\n",
1365106c671SBrian Somers 		cmdstr, strerror(rtmes.m_rtm.rtm_errno));
137e696ee3bSBrian Somers       break;
138af57ed9fSAtsushi Murai     }
139e696ee3bSBrian Somers   }
1405106c671SBrian Somers   LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n",
1415106c671SBrian Somers             wb, cmdstr, dst.s_addr, gateway.s_addr);
142af57ed9fSAtsushi Murai   close(s);
143af57ed9fSAtsushi Murai }
144af57ed9fSAtsushi Murai 
145af57ed9fSAtsushi Murai static void
1465d5e5070SBrian Somers p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width)
147af57ed9fSAtsushi Murai {
1485d5e5070SBrian Somers   char buf[29], *cp;
1495d5e5070SBrian Somers   struct sockaddr_in *ihost = (struct sockaddr_in *)phost;
1505d5e5070SBrian Somers   struct sockaddr_in *mask = (struct sockaddr_in *)pmask;
1515d5e5070SBrian Somers   struct sockaddr_dl *dl = (struct sockaddr_dl *)phost;
152af57ed9fSAtsushi Murai 
1535d5e5070SBrian Somers   switch (phost->sa_family) {
1545d5e5070SBrian Somers   case AF_INET:
1555d5e5070SBrian Somers     if (!phost)
1565d5e5070SBrian Somers       cp = "";
1575d5e5070SBrian Somers     else if (ihost->sin_addr.s_addr == INADDR_ANY)
1585d5e5070SBrian Somers       cp = "default";
1595d5e5070SBrian Somers     else if (!mask)
1605d5e5070SBrian Somers       cp = inet_ntoa(ihost->sin_addr);
1615d5e5070SBrian Somers     else {
1625d5e5070SBrian Somers       u_int msk = ntohl(mask->sin_addr.s_addr);
1635d5e5070SBrian Somers       u_int tst;
1645d5e5070SBrian Somers       int bits;
1655d5e5070SBrian Somers       int len;
1665d5e5070SBrian Somers       struct sockaddr_in net;
1675d5e5070SBrian Somers 
1685d5e5070SBrian Somers       for (tst = 1, bits=32; tst; tst <<= 1, bits--)
1695d5e5070SBrian Somers         if (msk & tst)
1705d5e5070SBrian Somers           break;
1715d5e5070SBrian Somers 
1725d5e5070SBrian Somers       for (tst <<=1; tst; tst <<= 1)
1735d5e5070SBrian Somers         if (!(msk & tst))
1745d5e5070SBrian Somers           break;
1755d5e5070SBrian Somers 
1765d5e5070SBrian Somers       net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr;
1775d5e5070SBrian Somers       sprintf(buf, "%s", inet_ntoa(net.sin_addr));
1785d5e5070SBrian Somers       for (len = strlen(buf); len > 3; buf[len-=2] = '\0')
1795d5e5070SBrian Somers         if (strcmp(buf+len-2, ".0"))
1805d5e5070SBrian Somers           break;
1815d5e5070SBrian Somers 
1825d5e5070SBrian Somers       if (tst)    /* non-contiguous :-( */
1835d5e5070SBrian Somers         sprintf(buf+strlen(buf),"&0x%08x", msk);
1845d5e5070SBrian Somers       else
1855d5e5070SBrian Somers         sprintf(buf+strlen(buf), "/%d", bits);
1865d5e5070SBrian Somers       cp = buf;
187927145beSBrian Somers     }
1885d5e5070SBrian Somers     break;
1895d5e5070SBrian Somers 
1905d5e5070SBrian Somers   case AF_LINK:
1915d5e5070SBrian Somers     if (!dl)
1925d5e5070SBrian Somers       cp = "";
1935d5e5070SBrian Somers     else if (dl->sdl_nlen == 0 && dl->sdl_alen == 0 && dl->sdl_slen == 0) {
1945d5e5070SBrian Somers       sprintf(buf, "link#%d", dl->sdl_index);
1955d5e5070SBrian Somers       cp = buf;
1965d5e5070SBrian Somers     } else if (dl->sdl_type == IFT_ETHER && dl->sdl_alen &&
1975d5e5070SBrian Somers                dl->sdl_alen < sizeof(buf)/3) {
1985d5e5070SBrian Somers       int f;
1995d5e5070SBrian Somers       u_char *MAC;
2005d5e5070SBrian Somers 
2015d5e5070SBrian Somers       MAC = (u_char *)dl->sdl_data + dl->sdl_nlen;
2025d5e5070SBrian Somers       for (f = 0; f < dl->sdl_alen; f++)
2035d5e5070SBrian Somers         sprintf(buf+f*3, "%02x:", MAC[f]);
2045d5e5070SBrian Somers       buf[f*3-1] = '\0';
2055d5e5070SBrian Somers       cp = buf;
2065d5e5070SBrian Somers     } else
2075d5e5070SBrian Somers       cp = "???";
2085d5e5070SBrian Somers     break;
2095d5e5070SBrian Somers 
2105d5e5070SBrian Somers   default:
2115d5e5070SBrian Somers     cp = "???";
2125d5e5070SBrian Somers     break;
2135d5e5070SBrian Somers   }
2145d5e5070SBrian Somers 
2155d5e5070SBrian Somers   fprintf(VarTerm, "%-*s ", width-1, cp);
216af57ed9fSAtsushi Murai }
217af57ed9fSAtsushi Murai 
218af57ed9fSAtsushi Murai struct bits {
2195d5e5070SBrian Somers   u_long b_mask;
220af57ed9fSAtsushi Murai   char b_val;
221af57ed9fSAtsushi Murai } bits[] = {
222944f7098SBrian Somers 
2235d5e5070SBrian Somers   { RTF_UP, 'U' },
2245d5e5070SBrian Somers   { RTF_GATEWAY, 'G' },
2255d5e5070SBrian Somers   { RTF_HOST, 'H' },
2265d5e5070SBrian Somers   { RTF_REJECT, 'R' },
2275d5e5070SBrian Somers   { RTF_DYNAMIC, 'D' },
2285d5e5070SBrian Somers   { RTF_MODIFIED, 'M' },
2295d5e5070SBrian Somers   { RTF_DONE, 'd' },
2305d5e5070SBrian Somers   { RTF_CLONING, 'C' },
2315d5e5070SBrian Somers   { RTF_XRESOLVE, 'X' },
2325d5e5070SBrian Somers   { RTF_LLINFO, 'L' },
2335d5e5070SBrian Somers   { RTF_STATIC, 'S' },
2345d5e5070SBrian Somers   { RTF_PROTO1, '1' },
2355d5e5070SBrian Somers   { RTF_PROTO2, '2' },
2365d5e5070SBrian Somers   { RTF_BLACKHOLE, 'B' },
2375d5e5070SBrian Somers #ifdef __FreeBSD__
2385d5e5070SBrian Somers   { RTF_WASCLONED, 'W' },
2395d5e5070SBrian Somers   { RTF_PRCLONING, 'c' },
2405d5e5070SBrian Somers   { RTF_PROTO3, '3' },
2415d5e5070SBrian Somers   { RTF_BROADCAST, 'b' },
2425d5e5070SBrian Somers #endif
2435d5e5070SBrian Somers   { 0, '\0' }
244af57ed9fSAtsushi Murai };
245af57ed9fSAtsushi Murai 
246af57ed9fSAtsushi Murai static void
2475d5e5070SBrian Somers p_flags(u_long f, char *format)
248af57ed9fSAtsushi Murai {
249927145beSBrian Somers   if (VarTerm) {
250af57ed9fSAtsushi Murai     char name[33], *flags;
251af57ed9fSAtsushi Murai     register struct bits *p = bits;
252af57ed9fSAtsushi Murai 
253af57ed9fSAtsushi Murai     for (flags = name; p->b_mask; p++)
254af57ed9fSAtsushi Murai       if (p->b_mask & f)
255af57ed9fSAtsushi Murai 	*flags++ = p->b_val;
256af57ed9fSAtsushi Murai     *flags = '\0';
257927145beSBrian Somers     fprintf(VarTerm, format, name);
258927145beSBrian Somers   }
259af57ed9fSAtsushi Murai }
260af57ed9fSAtsushi Murai 
2615d5e5070SBrian Somers static char *
2625d5e5070SBrian Somers Index2Nam(int idx)
2635d5e5070SBrian Somers {
2645d5e5070SBrian Somers   static char ifs[50][6];
2655d5e5070SBrian Somers   static int nifs;
2665d5e5070SBrian Somers 
2675d5e5070SBrian Somers   if (!nifs) {
2685d5e5070SBrian Somers     int mib[6], needed, len;
2695d5e5070SBrian Somers     char *buf, *ptr, *end;
2705d5e5070SBrian Somers     struct if_msghdr *n;
2715d5e5070SBrian Somers     struct sockaddr_dl *dl;
2725d5e5070SBrian Somers     struct if_msghdr *ifm;
2735d5e5070SBrian Somers 
2745d5e5070SBrian Somers     mib[0] = CTL_NET;
2755d5e5070SBrian Somers     mib[1] = PF_ROUTE;
2765d5e5070SBrian Somers     mib[2] = 0;
2775d5e5070SBrian Somers     mib[3] = 0;
2785d5e5070SBrian Somers     mib[4] = NET_RT_IFLIST;
2795d5e5070SBrian Somers     mib[5] = 0;
2805d5e5070SBrian Somers 
2815d5e5070SBrian Somers     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
2825d5e5070SBrian Somers       LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno));
2835d5e5070SBrian Somers       return "???";
2845d5e5070SBrian Somers     }
2855d5e5070SBrian Somers     if ((buf = malloc(needed)) == NULL)
2865d5e5070SBrian Somers       return "???";
2875d5e5070SBrian Somers     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
2885d5e5070SBrian Somers       free(buf);
2895d5e5070SBrian Somers       return "???";
2905d5e5070SBrian Somers     }
2915d5e5070SBrian Somers     end = buf + needed;
2925d5e5070SBrian Somers 
2935d5e5070SBrian Somers     ptr = buf;
2945d5e5070SBrian Somers     while (ptr < end) {
2955d5e5070SBrian Somers       ifm = (struct if_msghdr *)ptr;
2965d5e5070SBrian Somers 
2975d5e5070SBrian Somers       if (ifm->ifm_type != RTM_IFINFO) {
2985d5e5070SBrian Somers         free(buf);
2995d5e5070SBrian Somers         return "???";
3005d5e5070SBrian Somers       }
3015d5e5070SBrian Somers       dl = (struct sockaddr_dl *)(ifm + 1);
3025d5e5070SBrian Somers       ptr += ifm->ifm_msglen;
3035d5e5070SBrian Somers       while (ptr < end) {
3045d5e5070SBrian Somers         n = (struct if_msghdr *)ptr;
3055d5e5070SBrian Somers         if (n->ifm_type != RTM_NEWADDR)
3065d5e5070SBrian Somers           break;
3075d5e5070SBrian Somers         ptr += n->ifm_msglen;
3085d5e5070SBrian Somers       }
3095d5e5070SBrian Somers       if ((len = dl->sdl_nlen) > sizeof(ifs[0])-1)
3105d5e5070SBrian Somers         len = sizeof(ifs[0])-1;
3115d5e5070SBrian Somers       strncpy(ifs[nifs], dl->sdl_data, len);
3125d5e5070SBrian Somers       ifs[nifs++][len] = '\0';
3135d5e5070SBrian Somers       if (nifs == sizeof(ifs)/sizeof(ifs[0]))
3145d5e5070SBrian Somers         break;
3155d5e5070SBrian Somers     }
3165d5e5070SBrian Somers     free(buf);
3175d5e5070SBrian Somers   }
3185d5e5070SBrian Somers 
3195d5e5070SBrian Somers #ifdef __FreeBSD__
3205d5e5070SBrian Somers   idx--;	/* We start at 1, not 0 */
3215d5e5070SBrian Somers #endif
3225d5e5070SBrian Somers   if (idx < 0 || idx >= nifs)
3235d5e5070SBrian Somers     return "???";
3245d5e5070SBrian Somers   return ifs[idx];
3255d5e5070SBrian Somers }
3265d5e5070SBrian Somers 
327af57ed9fSAtsushi Murai int
328af57ed9fSAtsushi Murai ShowRoute()
329af57ed9fSAtsushi Murai {
330af57ed9fSAtsushi Murai   struct rt_msghdr *rtm;
3315d5e5070SBrian Somers   struct sockaddr *sa_dst, *sa_gw, *sa_mask;
3325d5e5070SBrian Somers   char *sp, *ep, *cp, *wp;
3335d5e5070SBrian Somers   int needed;
334af57ed9fSAtsushi Murai   int mib[6];
335af57ed9fSAtsushi Murai 
336927145beSBrian Somers   if (!VarTerm)
337927145beSBrian Somers     return 1;
338927145beSBrian Somers 
339af57ed9fSAtsushi Murai   mib[0] = CTL_NET;
340af57ed9fSAtsushi Murai   mib[1] = PF_ROUTE;
34153c9f6c0SAtsushi Murai   mib[2] = 0;
34253c9f6c0SAtsushi Murai   mib[3] = 0;
343af57ed9fSAtsushi Murai   mib[4] = NET_RT_DUMP;
34453c9f6c0SAtsushi Murai   mib[5] = 0;
34553c9f6c0SAtsushi Murai   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
346afc7fa2cSBrian Somers     LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno));
34753c9f6c0SAtsushi Murai     return (1);
34853c9f6c0SAtsushi Murai   }
349af57ed9fSAtsushi Murai   if (needed < 0)
350af57ed9fSAtsushi Murai     return (1);
351af57ed9fSAtsushi Murai   sp = malloc(needed);
352af57ed9fSAtsushi Murai   if (sp == NULL)
353af57ed9fSAtsushi Murai     return (1);
35453c9f6c0SAtsushi Murai   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
355afc7fa2cSBrian Somers     LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno));
356b0cdb3ceSJordan K. Hubbard     free(sp);
357af57ed9fSAtsushi Murai     return (1);
35853c9f6c0SAtsushi Murai   }
359af57ed9fSAtsushi Murai   ep = sp + needed;
360af57ed9fSAtsushi Murai 
3615d5e5070SBrian Somers   fprintf(VarTerm, "%-20s%-20sFlags  Netif\n", "Destination", "Gateway");
362af57ed9fSAtsushi Murai   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
363af57ed9fSAtsushi Murai     rtm = (struct rt_msghdr *) cp;
3645d5e5070SBrian Somers     wp = (char *)(rtm+1);
3655d5e5070SBrian Somers 
3665d5e5070SBrian Somers     if (rtm->rtm_addrs & RTA_DST) {
3675d5e5070SBrian Somers       sa_dst = (struct sockaddr *)wp;
3685d5e5070SBrian Somers       wp += sa_dst->sa_len;
3695d5e5070SBrian Somers     } else
3705d5e5070SBrian Somers       sa_dst = NULL;
3715d5e5070SBrian Somers 
3725d5e5070SBrian Somers     if (rtm->rtm_addrs & RTA_GATEWAY) {
3735d5e5070SBrian Somers       sa_gw = (struct sockaddr *)wp;
3745d5e5070SBrian Somers       wp += sa_gw->sa_len;
3755d5e5070SBrian Somers     } else
3765d5e5070SBrian Somers       sa_gw = NULL;
3775d5e5070SBrian Somers 
3785d5e5070SBrian Somers     if (rtm->rtm_addrs & RTA_NETMASK) {
3795d5e5070SBrian Somers       sa_mask = (struct sockaddr *)wp;
3805d5e5070SBrian Somers       wp += sa_mask->sa_len;
3815d5e5070SBrian Somers     } else
3825d5e5070SBrian Somers       sa_mask = NULL;
3835d5e5070SBrian Somers 
3845d5e5070SBrian Somers     p_sockaddr(sa_dst, sa_mask, 20);
3855d5e5070SBrian Somers     p_sockaddr(sa_gw, NULL, 20);
3865d5e5070SBrian Somers 
3875d5e5070SBrian Somers     p_flags(rtm->rtm_flags, "%-6.6s ");
3885d5e5070SBrian Somers     fprintf(VarTerm, "%s\n", Index2Nam(rtm->rtm_index));
389af57ed9fSAtsushi Murai   }
390b0cdb3ceSJordan K. Hubbard   free(sp);
391927145beSBrian Somers   return 0;
392af57ed9fSAtsushi Murai }
393af57ed9fSAtsushi Murai 
394af57ed9fSAtsushi Murai /*
395af57ed9fSAtsushi Murai  *  Delete routes associated with our interface
396af57ed9fSAtsushi Murai  */
397af57ed9fSAtsushi Murai void
398944f7098SBrian Somers DeleteIfRoutes(int all)
399af57ed9fSAtsushi Murai {
400af57ed9fSAtsushi Murai   struct rt_msghdr *rtm;
401af57ed9fSAtsushi Murai   struct sockaddr *sa;
4025d5e5070SBrian Somers   struct in_addr sa_dst, sa_gw, sa_mask;
403af57ed9fSAtsushi Murai   int needed;
404af57ed9fSAtsushi Murai   char *sp, *cp, *ep;
405af57ed9fSAtsushi Murai   u_char *wp;
406af57ed9fSAtsushi Murai   int mib[6];
407af57ed9fSAtsushi Murai 
408927145beSBrian Somers   LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex);
409927145beSBrian Somers 
410af57ed9fSAtsushi Murai   mib[0] = CTL_NET;
411af57ed9fSAtsushi Murai   mib[1] = PF_ROUTE;
41253c9f6c0SAtsushi Murai   mib[2] = 0;
41353c9f6c0SAtsushi Murai   mib[3] = 0;
414af57ed9fSAtsushi Murai   mib[4] = NET_RT_DUMP;
41553c9f6c0SAtsushi Murai   mib[5] = 0;
41653c9f6c0SAtsushi Murai   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
417afc7fa2cSBrian Somers     LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n",
418afc7fa2cSBrian Somers 	      strerror(errno));
41953c9f6c0SAtsushi Murai     return;
42053c9f6c0SAtsushi Murai   }
421af57ed9fSAtsushi Murai   if (needed < 0)
422af57ed9fSAtsushi Murai     return;
423af57ed9fSAtsushi Murai 
424af57ed9fSAtsushi Murai   sp = malloc(needed);
425af57ed9fSAtsushi Murai   if (sp == NULL)
426af57ed9fSAtsushi Murai     return;
427af57ed9fSAtsushi Murai 
428af57ed9fSAtsushi Murai   if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
429afc7fa2cSBrian Somers     LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n",
430afc7fa2cSBrian Somers 	      strerror(errno));
431af57ed9fSAtsushi Murai     free(sp);
432af57ed9fSAtsushi Murai     return;
433af57ed9fSAtsushi Murai   }
434af57ed9fSAtsushi Murai   ep = sp + needed;
435af57ed9fSAtsushi Murai 
436af57ed9fSAtsushi Murai   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
437af57ed9fSAtsushi Murai     rtm = (struct rt_msghdr *) cp;
438af57ed9fSAtsushi Murai     sa = (struct sockaddr *) (rtm + 1);
4395d5e5070SBrian Somers     LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s), flags: %x,"
4405d5e5070SBrian Somers 	      " dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index,
4415d5e5070SBrian Somers               Index2Nam(rtm->rtm_index), rtm->rtm_flags,
4429b5a20e1SBrian Somers 	      inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
4435d5e5070SBrian Somers     if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY &&
4445d5e5070SBrian Somers 	rtm->rtm_index == IfIndex &&
445af57ed9fSAtsushi Murai 	(all || (rtm->rtm_flags & RTF_GATEWAY))) {
4465d5e5070SBrian Somers       sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
447af57ed9fSAtsushi Murai       wp = (u_char *) cp + rtm->rtm_msglen;
4485d5e5070SBrian Somers       sa = (struct sockaddr *)((char *)sa + sa->sa_len);
4495d5e5070SBrian Somers       if (sa->sa_family == AF_INET) {
4505d5e5070SBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it\n");
4515d5e5070SBrian Somers         sa_gw.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
4525d5e5070SBrian Somers         sa = (struct sockaddr *)((char *)sa + sa->sa_len);
4535d5e5070SBrian Somers         if (rtm->rtm_addrs & RTA_NETMASK)
4545d5e5070SBrian Somers           sa_mask.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
4555d5e5070SBrian Somers         else
4565d5e5070SBrian Somers           sa_mask.s_addr = 0xffffffff;
4575d5e5070SBrian Somers         if (sa_dst.s_addr == INADDR_ANY)
4585d5e5070SBrian Somers 	  sa_mask.s_addr = INADDR_ANY;
4595d5e5070SBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Dst: %s\n", inet_ntoa(sa_dst));
4605d5e5070SBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Gw: %s\n", inet_ntoa(sa_gw));
461927145beSBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Index: %d\n", rtm->rtm_index);
4625d5e5070SBrian Somers         OsSetRoute(RTM_DELETE, sa_dst, sa_gw, sa_mask);
4635d5e5070SBrian Somers       } else
4645d5e5070SBrian Somers         LogPrintf(LogDEBUG, "DeleteIfRoutes: Can't remove an AF_LINK !\n");
465af57ed9fSAtsushi Murai     }
466af57ed9fSAtsushi Murai   }
467af57ed9fSAtsushi Murai   free(sp);
468af57ed9fSAtsushi Murai }
469af57ed9fSAtsushi Murai 
470af57ed9fSAtsushi Murai int
471944f7098SBrian Somers GetIfIndex(char *name)
472af57ed9fSAtsushi Murai {
4735d5e5070SBrian Somers   int idx;
4745d5e5070SBrian Somers   char *got;
475944f7098SBrian Somers 
4765d5e5070SBrian Somers #ifdef __FreeBSD__
4775d5e5070SBrian Somers   idx = 1;	/* We start at 1, not 0 */
4785d5e5070SBrian Somers #else
4795d5e5070SBrian Somers   idx = 0;
4805d5e5070SBrian Somers #endif
481af57ed9fSAtsushi Murai 
4825d5e5070SBrian Somers   while (strcmp(got = Index2Nam(idx), "???"))
4835d5e5070SBrian Somers     if (!strcmp(got, name))
4845d5e5070SBrian Somers       return IfIndex = idx;
4855d5e5070SBrian Somers     else
4865d5e5070SBrian Somers       idx++;
4875d5e5070SBrian Somers   return -1;
488af57ed9fSAtsushi Murai }
489