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 * 20d27d502cSBrian Somers * $Id: route.c,v 1.33 1997/12/17 00:19:25 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" 51bcc332bdSBrian Somers #include "os.h" 52bcc332bdSBrian Somers #include "ipcp.h" 53bcc332bdSBrian Somers #include "iplist.h" 5475240ed1SBrian Somers #include "route.h" 55af57ed9fSAtsushi Murai 56af57ed9fSAtsushi Murai static int IfIndex; 57f01e577bSBrian Somers static const char *Index2Nam(int); 58af57ed9fSAtsushi Murai 59af57ed9fSAtsushi Murai struct rtmsg { 60af57ed9fSAtsushi Murai struct rt_msghdr m_rtm; 61af57ed9fSAtsushi Murai char m_space[64]; 62af57ed9fSAtsushi Murai }; 63af57ed9fSAtsushi Murai 64af57ed9fSAtsushi Murai static int seqno; 65af57ed9fSAtsushi Murai 66af57ed9fSAtsushi Murai void 67944f7098SBrian Somers OsSetRoute(int cmd, 68944f7098SBrian Somers struct in_addr dst, 69944f7098SBrian Somers struct in_addr gateway, 70944f7098SBrian Somers struct in_addr mask) 71af57ed9fSAtsushi Murai { 72af57ed9fSAtsushi Murai struct rtmsg rtmes; 73af57ed9fSAtsushi Murai int s, nb, wb; 74b6e82f33SBrian Somers char *cp; 75b6e82f33SBrian Somers const char *cmdstr; 76af57ed9fSAtsushi Murai struct sockaddr_in rtdata; 77af57ed9fSAtsushi Murai 785106c671SBrian Somers cmdstr = (cmd == RTM_ADD ? "Add" : "Delete"); 795106c671SBrian Somers s = ID0socket(PF_ROUTE, SOCK_RAW, 0); 806614d8c5SBrian Somers if (s < 0) { 81afc7fa2cSBrian Somers LogPrintf(LogERROR, "OsSetRoute: socket(): %s\n", strerror(errno)); 826614d8c5SBrian Somers return; 836614d8c5SBrian Somers } 8475240ed1SBrian Somers memset(&rtmes, '\0', sizeof(rtmes)); 85af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_version = RTM_VERSION; 86af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_type = cmd; 87f01e577bSBrian Somers rtmes.m_rtm.rtm_addrs = RTA_DST; 88af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_seq = ++seqno; 89af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_pid = getpid(); 902db86e5bSPeter Wemm rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 91af57ed9fSAtsushi Murai 9275240ed1SBrian Somers memset(&rtdata, '\0', sizeof(rtdata)); 93af57ed9fSAtsushi Murai rtdata.sin_len = 16; 94af57ed9fSAtsushi Murai rtdata.sin_family = AF_INET; 95af57ed9fSAtsushi Murai rtdata.sin_port = 0; 96af57ed9fSAtsushi Murai rtdata.sin_addr = dst; 97af57ed9fSAtsushi Murai 98af57ed9fSAtsushi Murai cp = rtmes.m_space; 9975240ed1SBrian Somers memcpy(cp, &rtdata, 16); 100af57ed9fSAtsushi Murai cp += 16; 101f01e577bSBrian Somers if (cmd == RTM_ADD) 102f01e577bSBrian Somers if (gateway.s_addr == INADDR_ANY) { 103f01e577bSBrian Somers /* Add a route through the interface */ 104f01e577bSBrian Somers struct sockaddr_dl dl; 105f01e577bSBrian Somers const char *iname; 106f01e577bSBrian Somers int ilen; 107f01e577bSBrian Somers 108f01e577bSBrian Somers iname = Index2Nam(IfIndex); 109f01e577bSBrian Somers ilen = strlen(iname); 110f01e577bSBrian Somers dl.sdl_len = sizeof(dl)-sizeof(dl.sdl_data)+ilen; 111f01e577bSBrian Somers dl.sdl_family = AF_LINK; 112f01e577bSBrian Somers dl.sdl_index = IfIndex; 113f01e577bSBrian Somers dl.sdl_type = 0; 114f01e577bSBrian Somers dl.sdl_nlen = ilen; 115f01e577bSBrian Somers dl.sdl_alen = 0; 116f01e577bSBrian Somers dl.sdl_slen = 0; 117f01e577bSBrian Somers strcpy(dl.sdl_data, iname); 118f01e577bSBrian Somers 119f01e577bSBrian Somers memcpy(cp, &dl, dl.sdl_len); 120f01e577bSBrian Somers cp += dl.sdl_len; 121f01e577bSBrian Somers rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 122f01e577bSBrian Somers } else { 123af57ed9fSAtsushi Murai rtdata.sin_addr = gateway; 12475240ed1SBrian Somers memcpy(cp, &rtdata, 16); 125af57ed9fSAtsushi Murai cp += 16; 126d3a3ec3bSBrian Somers rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 127af57ed9fSAtsushi Murai } 128f01e577bSBrian Somers 129af57ed9fSAtsushi Murai if (dst.s_addr == INADDR_ANY) 130af57ed9fSAtsushi Murai mask.s_addr = INADDR_ANY; 131af57ed9fSAtsushi Murai 132f01e577bSBrian Somers if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) { 133f01e577bSBrian Somers rtdata.sin_addr = mask; 134f01e577bSBrian Somers memcpy(cp, &rtdata, 16); 135f01e577bSBrian Somers cp += 16; 136f01e577bSBrian Somers rtmes.m_rtm.rtm_addrs |= RTA_NETMASK; 137f01e577bSBrian Somers } 138af57ed9fSAtsushi Murai 139af57ed9fSAtsushi Murai nb = cp - (char *) &rtmes; 140af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_msglen = nb; 141af57ed9fSAtsushi Murai wb = write(s, &rtmes, nb); 142af57ed9fSAtsushi Murai if (wb < 0) { 14332ca3341SBrian Somers LogPrintf(LogTCPIP, "OsSetRoute failure:\n"); 14432ca3341SBrian Somers LogPrintf(LogTCPIP, "OsSetRoute: Cmd = %s\n", cmd); 145e696ee3bSBrian Somers LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst)); 146e696ee3bSBrian Somers LogPrintf(LogTCPIP, "OsSetRoute: Gateway = %s\n", inet_ntoa(gateway)); 147e696ee3bSBrian Somers LogPrintf(LogTCPIP, "OsSetRoute: Mask = %s\n", inet_ntoa(mask)); 148e696ee3bSBrian Somers switch (rtmes.m_rtm.rtm_errno) { 149e696ee3bSBrian Somers case EEXIST: 150bcc332bdSBrian Somers LogPrintf(LogWARN, "Add route failed: %s already exists\n", 151bcc332bdSBrian Somers inet_ntoa(dst)); 152e696ee3bSBrian Somers break; 153e696ee3bSBrian Somers case ESRCH: 154bcc332bdSBrian Somers LogPrintf(LogWARN, "Del route failed: %s: Non-existent\n", 155bcc332bdSBrian Somers inet_ntoa(dst)); 156e696ee3bSBrian Somers break; 1575106c671SBrian Somers case 0: 15832ca3341SBrian Somers LogPrintf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr, 15932ca3341SBrian Somers inet_ntoa(dst), strerror(errno)); 1605106c671SBrian Somers break; 161e696ee3bSBrian Somers case ENOBUFS: 162e696ee3bSBrian Somers default: 16332ca3341SBrian Somers LogPrintf(LogWARN, "%s route failed: %s: %s\n", 16432ca3341SBrian Somers cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno)); 165e696ee3bSBrian Somers break; 166af57ed9fSAtsushi Murai } 167e696ee3bSBrian Somers } 1685106c671SBrian Somers LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n", 1695106c671SBrian Somers wb, cmdstr, dst.s_addr, gateway.s_addr); 170af57ed9fSAtsushi Murai close(s); 171af57ed9fSAtsushi Murai } 172af57ed9fSAtsushi Murai 173af57ed9fSAtsushi Murai static void 1745d5e5070SBrian Somers p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width) 175af57ed9fSAtsushi Murai { 176b6e82f33SBrian Somers char buf[29]; 1775d5e5070SBrian Somers struct sockaddr_in *ihost = (struct sockaddr_in *)phost; 1785d5e5070SBrian Somers struct sockaddr_in *mask = (struct sockaddr_in *)pmask; 1795d5e5070SBrian Somers struct sockaddr_dl *dl = (struct sockaddr_dl *)phost; 180af57ed9fSAtsushi Murai 1815d5e5070SBrian Somers switch (phost->sa_family) { 1825d5e5070SBrian Somers case AF_INET: 1835d5e5070SBrian Somers if (!phost) 1844bfaee90SBrian Somers buf[0] = '\0'; 1855d5e5070SBrian Somers else if (ihost->sin_addr.s_addr == INADDR_ANY) 1864bfaee90SBrian Somers strcpy(buf, "default"); 1875d5e5070SBrian Somers else if (!mask) 1884bfaee90SBrian Somers strcpy(buf, inet_ntoa(ihost->sin_addr)); 1895d5e5070SBrian Somers else { 1905d5e5070SBrian Somers u_int msk = ntohl(mask->sin_addr.s_addr); 1915d5e5070SBrian Somers u_int tst; 1925d5e5070SBrian Somers int bits; 1935d5e5070SBrian Somers int len; 1945d5e5070SBrian Somers struct sockaddr_in net; 1955d5e5070SBrian Somers 1965d5e5070SBrian Somers for (tst = 1, bits=32; tst; tst <<= 1, bits--) 1975d5e5070SBrian Somers if (msk & tst) 1985d5e5070SBrian Somers break; 1995d5e5070SBrian Somers 2005d5e5070SBrian Somers for (tst <<=1; tst; tst <<= 1) 2015d5e5070SBrian Somers if (!(msk & tst)) 2025d5e5070SBrian Somers break; 2035d5e5070SBrian Somers 2045d5e5070SBrian Somers net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr; 20583c0952dSBrian Somers strcpy(buf, inet_ntoa(net.sin_addr)); 2065d5e5070SBrian Somers for (len = strlen(buf); len > 3; buf[len-=2] = '\0') 2075d5e5070SBrian Somers if (strcmp(buf+len-2, ".0")) 2085d5e5070SBrian Somers break; 2095d5e5070SBrian Somers 2105d5e5070SBrian Somers if (tst) /* non-contiguous :-( */ 2115d5e5070SBrian Somers sprintf(buf+strlen(buf),"&0x%08x", msk); 2125d5e5070SBrian Somers else 2135d5e5070SBrian Somers sprintf(buf+strlen(buf), "/%d", bits); 214927145beSBrian Somers } 2155d5e5070SBrian Somers break; 2165d5e5070SBrian Somers 2175d5e5070SBrian Somers case AF_LINK: 2184bfaee90SBrian Somers if (dl->sdl_nlen) 2194bfaee90SBrian Somers snprintf(buf, sizeof buf, "%.*s", dl->sdl_nlen, dl->sdl_data); 2204bfaee90SBrian Somers else if (dl->sdl_alen) 2214bfaee90SBrian Somers if (dl->sdl_type == IFT_ETHER) 2224bfaee90SBrian Somers if (dl->sdl_alen < sizeof(buf)/3) { 2235d5e5070SBrian Somers int f; 2245d5e5070SBrian Somers u_char *MAC; 2255d5e5070SBrian Somers 2265d5e5070SBrian Somers MAC = (u_char *)dl->sdl_data + dl->sdl_nlen; 2275d5e5070SBrian Somers for (f = 0; f < dl->sdl_alen; f++) 2285d5e5070SBrian Somers sprintf(buf+f*3, "%02x:", MAC[f]); 2295d5e5070SBrian Somers buf[f*3-1] = '\0'; 2305d5e5070SBrian Somers } else 23183c0952dSBrian Somers strcpy(buf, "??:??:??:??:??:??"); 2324bfaee90SBrian Somers else 2334bfaee90SBrian Somers sprintf(buf, "<IFT type %d>", dl->sdl_type); 2344bfaee90SBrian Somers else if (dl->sdl_slen) 2354bfaee90SBrian Somers sprintf(buf, "<slen %d?>", dl->sdl_slen); 2364bfaee90SBrian Somers else 2374bfaee90SBrian Somers sprintf(buf, "link#%d", dl->sdl_index); 2385d5e5070SBrian Somers break; 2395d5e5070SBrian Somers 2405d5e5070SBrian Somers default: 2414bfaee90SBrian Somers sprintf(buf, "<AF type %d>", phost->sa_family); 2425d5e5070SBrian Somers break; 2435d5e5070SBrian Somers } 2445d5e5070SBrian Somers 2454bfaee90SBrian Somers fprintf(VarTerm, "%-*s ", width-1, buf); 246af57ed9fSAtsushi Murai } 247af57ed9fSAtsushi Murai 248af57ed9fSAtsushi Murai struct bits { 2495d5e5070SBrian Somers u_long b_mask; 250af57ed9fSAtsushi Murai char b_val; 251af57ed9fSAtsushi Murai } bits[] = { 2525d5e5070SBrian Somers { RTF_UP, 'U' }, 2535d5e5070SBrian Somers { RTF_GATEWAY, 'G' }, 2545d5e5070SBrian Somers { RTF_HOST, 'H' }, 2555d5e5070SBrian Somers { RTF_REJECT, 'R' }, 2565d5e5070SBrian Somers { RTF_DYNAMIC, 'D' }, 2575d5e5070SBrian Somers { RTF_MODIFIED, 'M' }, 2585d5e5070SBrian Somers { RTF_DONE, 'd' }, 2595d5e5070SBrian Somers { RTF_CLONING, 'C' }, 2605d5e5070SBrian Somers { RTF_XRESOLVE, 'X' }, 2615d5e5070SBrian Somers { RTF_LLINFO, 'L' }, 2625d5e5070SBrian Somers { RTF_STATIC, 'S' }, 2635d5e5070SBrian Somers { RTF_PROTO1, '1' }, 2645d5e5070SBrian Somers { RTF_PROTO2, '2' }, 2655d5e5070SBrian Somers { RTF_BLACKHOLE, 'B' }, 26632ca3341SBrian Somers #ifdef RTF_WASCLONED 2675d5e5070SBrian Somers { RTF_WASCLONED, 'W' }, 26832ca3341SBrian Somers #endif 26932ca3341SBrian Somers #ifdef RTF_PRCLONING 2705d5e5070SBrian Somers { RTF_PRCLONING, 'c' }, 27132ca3341SBrian Somers #endif 27232ca3341SBrian Somers #ifdef RTF_PROTO3 2735d5e5070SBrian Somers { RTF_PROTO3, '3' }, 27432ca3341SBrian Somers #endif 27532ca3341SBrian Somers #ifdef RTF_BROADCAST 2765d5e5070SBrian Somers { RTF_BROADCAST, 'b' }, 2775d5e5070SBrian Somers #endif 2785d5e5070SBrian Somers { 0, '\0' } 279af57ed9fSAtsushi Murai }; 280af57ed9fSAtsushi Murai 28132ca3341SBrian Somers #ifndef RTF_WASCLONED 28232ca3341SBrian Somers #define RTF_WASCLONED (0) 28332ca3341SBrian Somers #endif 28432ca3341SBrian Somers 285af57ed9fSAtsushi Murai static void 286d27d502cSBrian Somers p_flags(u_long f, int max) 287af57ed9fSAtsushi Murai { 288927145beSBrian Somers if (VarTerm) { 289af57ed9fSAtsushi Murai char name[33], *flags; 290af57ed9fSAtsushi Murai register struct bits *p = bits; 291af57ed9fSAtsushi Murai 292d27d502cSBrian Somers if (max > sizeof(name)-1) 293d27d502cSBrian Somers max = sizeof(name)-1; 294d27d502cSBrian Somers 295d27d502cSBrian Somers for (flags = name; p->b_mask && flags - name < max; p++) 296af57ed9fSAtsushi Murai if (p->b_mask & f) 297af57ed9fSAtsushi Murai *flags++ = p->b_val; 298af57ed9fSAtsushi Murai *flags = '\0'; 299d27d502cSBrian Somers fprintf(VarTerm, "%-*.*s", max, max, name); 300927145beSBrian Somers } 301af57ed9fSAtsushi Murai } 302af57ed9fSAtsushi Murai 303b6e82f33SBrian Somers static const char * 3045d5e5070SBrian Somers Index2Nam(int idx) 3055d5e5070SBrian Somers { 306bcc332bdSBrian Somers static char ifs[200][6]; /* We could have 256 tun devices ! */ 3079cb1d89eSBrian Somers static int nifs, debug_done; 3085d5e5070SBrian Somers 3095d5e5070SBrian Somers if (!nifs) { 3105d5e5070SBrian Somers int mib[6], needed, len; 3115d5e5070SBrian Somers char *buf, *ptr, *end; 3125d5e5070SBrian Somers struct sockaddr_dl *dl; 3135d5e5070SBrian Somers struct if_msghdr *ifm; 3145d5e5070SBrian Somers 3155d5e5070SBrian Somers mib[0] = CTL_NET; 3165d5e5070SBrian Somers mib[1] = PF_ROUTE; 3175d5e5070SBrian Somers mib[2] = 0; 3185d5e5070SBrian Somers mib[3] = 0; 3195d5e5070SBrian Somers mib[4] = NET_RT_IFLIST; 3205d5e5070SBrian Somers mib[5] = 0; 3215d5e5070SBrian Somers 3225d5e5070SBrian Somers if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 3235d5e5070SBrian Somers LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno)); 3245d5e5070SBrian Somers return "???"; 3255d5e5070SBrian Somers } 3265d5e5070SBrian Somers if ((buf = malloc(needed)) == NULL) 3275d5e5070SBrian Somers return "???"; 3285d5e5070SBrian Somers if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 3295d5e5070SBrian Somers free(buf); 3305d5e5070SBrian Somers return "???"; 3315d5e5070SBrian Somers } 3325d5e5070SBrian Somers end = buf + needed; 3335d5e5070SBrian Somers 3349cb1d89eSBrian Somers for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) { 3355d5e5070SBrian Somers ifm = (struct if_msghdr *)ptr; 3365d5e5070SBrian Somers dl = (struct sockaddr_dl *)(ifm + 1); 3379cb1d89eSBrian Somers if (ifm->ifm_index > 0 && ifm->ifm_index <= sizeof(ifs)/sizeof(ifs[0]) 3389cb1d89eSBrian Somers && ifs[ifm->ifm_index-1][0] == '\0') { 3395d5e5070SBrian Somers if ((len = dl->sdl_nlen) > sizeof(ifs[0])-1) 3405d5e5070SBrian Somers len = sizeof(ifs[0])-1; 3419cb1d89eSBrian Somers strncpy(ifs[ifm->ifm_index-1], dl->sdl_data, len); 3429cb1d89eSBrian Somers ifs[ifm->ifm_index-1][len] = '\0'; 3439cb1d89eSBrian Somers if (len && nifs < ifm->ifm_index) 3449cb1d89eSBrian Somers nifs = ifm->ifm_index; 3459cb1d89eSBrian Somers } else if (LogIsKept(LogDEBUG)) 3469cb1d89eSBrian Somers LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n", 3479cb1d89eSBrian Somers ifm->ifm_index); 3485d5e5070SBrian Somers } 3495d5e5070SBrian Somers free(buf); 3505d5e5070SBrian Somers } 3515d5e5070SBrian Somers 3529cb1d89eSBrian Somers if (LogIsKept(LogDEBUG) && !debug_done) { 3539cb1d89eSBrian Somers int f; 3549cb1d89eSBrian Somers 3559cb1d89eSBrian Somers LogPrintf(LogDEBUG, "Found the following interfaces:\n"); 3569cb1d89eSBrian Somers for (f = 0; f < nifs; f++) 3579cb1d89eSBrian Somers if (*ifs[f] != '\0') 3589cb1d89eSBrian Somers LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]); 3599cb1d89eSBrian Somers debug_done = 1; 3609cb1d89eSBrian Somers } 3619cb1d89eSBrian Somers 3629cb1d89eSBrian Somers if (idx < 1 || idx > nifs || ifs[idx-1][0] == '\0') 3635d5e5070SBrian Somers return "???"; 3649cb1d89eSBrian Somers 3659cb1d89eSBrian Somers return ifs[idx-1]; 3665d5e5070SBrian Somers } 3675d5e5070SBrian Somers 368af57ed9fSAtsushi Murai int 369b6e82f33SBrian Somers ShowRoute(struct cmdargs const *arg) 370af57ed9fSAtsushi Murai { 371af57ed9fSAtsushi Murai struct rt_msghdr *rtm; 3725d5e5070SBrian Somers struct sockaddr *sa_dst, *sa_gw, *sa_mask; 3735d5e5070SBrian Somers char *sp, *ep, *cp, *wp; 3745d5e5070SBrian Somers int needed; 375af57ed9fSAtsushi Murai int mib[6]; 376af57ed9fSAtsushi Murai 377927145beSBrian Somers if (!VarTerm) 378927145beSBrian Somers return 1; 379927145beSBrian Somers 380af57ed9fSAtsushi Murai mib[0] = CTL_NET; 381af57ed9fSAtsushi Murai mib[1] = PF_ROUTE; 38253c9f6c0SAtsushi Murai mib[2] = 0; 38353c9f6c0SAtsushi Murai mib[3] = 0; 384af57ed9fSAtsushi Murai mib[4] = NET_RT_DUMP; 38553c9f6c0SAtsushi Murai mib[5] = 0; 38653c9f6c0SAtsushi Murai if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 387afc7fa2cSBrian Somers LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno)); 38853c9f6c0SAtsushi Murai return (1); 38953c9f6c0SAtsushi Murai } 390af57ed9fSAtsushi Murai if (needed < 0) 391af57ed9fSAtsushi Murai return (1); 392af57ed9fSAtsushi Murai sp = malloc(needed); 393af57ed9fSAtsushi Murai if (sp == NULL) 394af57ed9fSAtsushi Murai return (1); 39553c9f6c0SAtsushi Murai if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 396afc7fa2cSBrian Somers LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno)); 397b0cdb3ceSJordan K. Hubbard free(sp); 398af57ed9fSAtsushi Murai return (1); 39953c9f6c0SAtsushi Murai } 400af57ed9fSAtsushi Murai ep = sp + needed; 401af57ed9fSAtsushi Murai 4025d5e5070SBrian Somers fprintf(VarTerm, "%-20s%-20sFlags Netif\n", "Destination", "Gateway"); 403af57ed9fSAtsushi Murai for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 404af57ed9fSAtsushi Murai rtm = (struct rt_msghdr *) cp; 4055d5e5070SBrian Somers wp = (char *)(rtm+1); 4065d5e5070SBrian Somers 4075d5e5070SBrian Somers if (rtm->rtm_addrs & RTA_DST) { 4085d5e5070SBrian Somers sa_dst = (struct sockaddr *)wp; 4095d5e5070SBrian Somers wp += sa_dst->sa_len; 4105d5e5070SBrian Somers } else 4115d5e5070SBrian Somers sa_dst = NULL; 4125d5e5070SBrian Somers 4135d5e5070SBrian Somers if (rtm->rtm_addrs & RTA_GATEWAY) { 4145d5e5070SBrian Somers sa_gw = (struct sockaddr *)wp; 4155d5e5070SBrian Somers wp += sa_gw->sa_len; 4165d5e5070SBrian Somers } else 4175d5e5070SBrian Somers sa_gw = NULL; 4185d5e5070SBrian Somers 4195d5e5070SBrian Somers if (rtm->rtm_addrs & RTA_NETMASK) { 4205d5e5070SBrian Somers sa_mask = (struct sockaddr *)wp; 4215d5e5070SBrian Somers wp += sa_mask->sa_len; 4225d5e5070SBrian Somers } else 4235d5e5070SBrian Somers sa_mask = NULL; 4245d5e5070SBrian Somers 4255d5e5070SBrian Somers p_sockaddr(sa_dst, sa_mask, 20); 4265d5e5070SBrian Somers p_sockaddr(sa_gw, NULL, 20); 4275d5e5070SBrian Somers 428d27d502cSBrian Somers p_flags(rtm->rtm_flags, 6); 4295d5e5070SBrian Somers fprintf(VarTerm, " %s\n", Index2Nam(rtm->rtm_index)); 430af57ed9fSAtsushi Murai } 431b0cdb3ceSJordan K. Hubbard free(sp); 432927145beSBrian Somers return 0; 433af57ed9fSAtsushi Murai } 434af57ed9fSAtsushi Murai 435af57ed9fSAtsushi Murai /* 436af57ed9fSAtsushi Murai * Delete routes associated with our interface 437af57ed9fSAtsushi Murai */ 438af57ed9fSAtsushi Murai void 439944f7098SBrian Somers DeleteIfRoutes(int all) 440af57ed9fSAtsushi Murai { 441af57ed9fSAtsushi Murai struct rt_msghdr *rtm; 442af57ed9fSAtsushi Murai struct sockaddr *sa; 443f01e577bSBrian Somers struct in_addr sa_dst, sa_none; 44432ca3341SBrian Somers int needed, pass; 445af57ed9fSAtsushi Murai char *sp, *cp, *ep; 446af57ed9fSAtsushi Murai int mib[6]; 447af57ed9fSAtsushi Murai 448927145beSBrian Somers LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex); 449f01e577bSBrian Somers sa_none.s_addr = INADDR_ANY; 450927145beSBrian Somers 451af57ed9fSAtsushi Murai mib[0] = CTL_NET; 452af57ed9fSAtsushi Murai mib[1] = PF_ROUTE; 45353c9f6c0SAtsushi Murai mib[2] = 0; 45453c9f6c0SAtsushi Murai mib[3] = 0; 455af57ed9fSAtsushi Murai mib[4] = NET_RT_DUMP; 45653c9f6c0SAtsushi Murai mib[5] = 0; 45753c9f6c0SAtsushi Murai if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 458afc7fa2cSBrian Somers LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n", 459afc7fa2cSBrian Somers strerror(errno)); 46053c9f6c0SAtsushi Murai return; 46153c9f6c0SAtsushi Murai } 462af57ed9fSAtsushi Murai if (needed < 0) 463af57ed9fSAtsushi Murai return; 464af57ed9fSAtsushi Murai 465af57ed9fSAtsushi Murai sp = malloc(needed); 466af57ed9fSAtsushi Murai if (sp == NULL) 467af57ed9fSAtsushi Murai return; 468af57ed9fSAtsushi Murai 469af57ed9fSAtsushi Murai if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 470afc7fa2cSBrian Somers LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n", 471afc7fa2cSBrian Somers strerror(errno)); 472af57ed9fSAtsushi Murai free(sp); 473af57ed9fSAtsushi Murai return; 474af57ed9fSAtsushi Murai } 475af57ed9fSAtsushi Murai ep = sp + needed; 476af57ed9fSAtsushi Murai 47732ca3341SBrian Somers for (pass = 0; pass < 2; pass++) { 47832ca3341SBrian Somers /* 47932ca3341SBrian Somers * We do 2 passes. The first deletes all cloned routes. The second 48032ca3341SBrian Somers * deletes all non-cloned routes. This is necessary to avoid 48132ca3341SBrian Somers * potential errors from trying to delete route X after route Y where 48232ca3341SBrian Somers * route X was cloned from route Y (which is no longer there). 48332ca3341SBrian Somers */ 48432ca3341SBrian Somers if (RTF_WASCLONED == 0 && pass == 0) 48532ca3341SBrian Somers /* So we can't tell ! */ 48632ca3341SBrian Somers continue; 487af57ed9fSAtsushi Murai for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 488af57ed9fSAtsushi Murai rtm = (struct rt_msghdr *) cp; 489af57ed9fSAtsushi Murai sa = (struct sockaddr *) (rtm + 1); 49032ca3341SBrian Somers LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s)," 49132ca3341SBrian Somers " flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index, 4925d5e5070SBrian Somers Index2Nam(rtm->rtm_index), rtm->rtm_flags, 4939b5a20e1SBrian Somers inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); 4945d5e5070SBrian Somers if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY && 4955d5e5070SBrian Somers rtm->rtm_index == IfIndex && 496af57ed9fSAtsushi Murai (all || (rtm->rtm_flags & RTF_GATEWAY))) { 4975d5e5070SBrian Somers sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 4985d5e5070SBrian Somers sa = (struct sockaddr *)((char *)sa + sa->sa_len); 499f01e577bSBrian Somers if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) { 50032ca3341SBrian Somers if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) || 50132ca3341SBrian Somers (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) { 50232ca3341SBrian Somers LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it (pass %d)\n", pass); 503f01e577bSBrian Somers OsSetRoute(RTM_DELETE, sa_dst, sa_none, sa_none); 5045d5e5070SBrian Somers } else 50532ca3341SBrian Somers LogPrintf(LogDEBUG, "DeleteIfRoutes: Skip it (pass %d)\n", pass); 50632ca3341SBrian Somers } else 507f01e577bSBrian Somers LogPrintf(LogDEBUG, 508f01e577bSBrian Somers "DeleteIfRoutes: Can't remove routes of %d family !\n", 509f01e577bSBrian Somers sa->sa_family); 510af57ed9fSAtsushi Murai } 511af57ed9fSAtsushi Murai } 51232ca3341SBrian Somers } 513af57ed9fSAtsushi Murai free(sp); 514af57ed9fSAtsushi Murai } 515af57ed9fSAtsushi Murai 516af57ed9fSAtsushi Murai int 517944f7098SBrian Somers GetIfIndex(char *name) 518af57ed9fSAtsushi Murai { 5195d5e5070SBrian Somers int idx; 520b6e82f33SBrian Somers const char *got; 521944f7098SBrian Somers 5229cb1d89eSBrian Somers idx = 1; 5235d5e5070SBrian Somers while (strcmp(got = Index2Nam(idx), "???")) 5245d5e5070SBrian Somers if (!strcmp(got, name)) 5255d5e5070SBrian Somers return IfIndex = idx; 5265d5e5070SBrian Somers else 5275d5e5070SBrian Somers idx++; 5285d5e5070SBrian Somers return -1; 529af57ed9fSAtsushi Murai } 530bcc332bdSBrian Somers 531bcc332bdSBrian Somers struct in_addr 532bcc332bdSBrian Somers ChooseHisAddr(const struct in_addr gw) 533bcc332bdSBrian Somers { 534bcc332bdSBrian Somers struct in_addr try; 535bcc332bdSBrian Somers int f; 536bcc332bdSBrian Somers 537bcc332bdSBrian Somers for (f = 0; f < DefHisChoice.nItems; f++) { 538bcc332bdSBrian Somers try = iplist_next(&DefHisChoice); 539bcc332bdSBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 540bcc332bdSBrian Somers f, inet_ntoa(try)); 541bcc332bdSBrian Somers if (OsTrySetIpaddress(gw, try) == 0) { 542bcc332bdSBrian Somers LogPrintf(LogIPCP, "ChooseHisAddr: Selected IP address %s\n", 543bcc332bdSBrian Somers inet_ntoa(try)); 544bcc332bdSBrian Somers break; 545bcc332bdSBrian Somers } 546bcc332bdSBrian Somers } 547bcc332bdSBrian Somers 548bcc332bdSBrian Somers if (f == DefHisChoice.nItems) { 549bcc332bdSBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 550bcc332bdSBrian Somers try.s_addr = INADDR_ANY; 551bcc332bdSBrian Somers } 552bcc332bdSBrian Somers 553bcc332bdSBrian Somers return try; 554bcc332bdSBrian Somers } 555