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