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 * 20aa8e0519SBrian Somers * $Id: route.c,v 1.41 1998/01/19 02:59:33 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.h> 31628d2ac1SGarrett Wollman #include <arpa/inet.h> 325d5e5070SBrian Somers #include <net/if_dl.h> 33628d2ac1SGarrett Wollman 3475240ed1SBrian Somers #include <errno.h> 3575240ed1SBrian Somers #include <machine/endian.h> 3675240ed1SBrian Somers #include <stdio.h> 3775240ed1SBrian Somers #include <stdlib.h> 3875240ed1SBrian Somers #include <string.h> 3975240ed1SBrian Somers #include <sys/ioctl.h> 4075240ed1SBrian Somers #include <sys/sysctl.h> 4175240ed1SBrian Somers #include <unistd.h> 4275240ed1SBrian Somers 43b6e82f33SBrian Somers #include "command.h" 4475240ed1SBrian Somers #include "mbuf.h" 45215a4696SAtsushi Murai #include "log.h" 46927145beSBrian Somers #include "loadalias.h" 4786e02934SBrian Somers #include "defs.h" 48927145beSBrian Somers #include "vars.h" 495106c671SBrian Somers #include "id.h" 50bcc332bdSBrian Somers #include "os.h" 51bcc332bdSBrian Somers #include "ipcp.h" 52bcc332bdSBrian Somers #include "iplist.h" 5375240ed1SBrian Somers #include "route.h" 54af57ed9fSAtsushi Murai 55af57ed9fSAtsushi Murai static int IfIndex; 56af57ed9fSAtsushi Murai 57af57ed9fSAtsushi Murai struct rtmsg { 58af57ed9fSAtsushi Murai struct rt_msghdr m_rtm; 59af57ed9fSAtsushi Murai char m_space[64]; 60af57ed9fSAtsushi Murai }; 61af57ed9fSAtsushi Murai 62af57ed9fSAtsushi Murai static int seqno; 63af57ed9fSAtsushi Murai 64af57ed9fSAtsushi Murai void 65944f7098SBrian Somers OsSetRoute(int cmd, 66944f7098SBrian Somers struct in_addr dst, 67944f7098SBrian Somers struct in_addr gateway, 6865eea2e0SBrian Somers struct in_addr mask, 6965eea2e0SBrian Somers int bang) 70af57ed9fSAtsushi Murai { 71af57ed9fSAtsushi Murai struct rtmsg rtmes; 72af57ed9fSAtsushi Murai int s, nb, wb; 73b6e82f33SBrian Somers char *cp; 74b6e82f33SBrian Somers const char *cmdstr; 75af57ed9fSAtsushi Murai struct sockaddr_in rtdata; 76af57ed9fSAtsushi Murai 7765eea2e0SBrian Somers if (bang) 7865eea2e0SBrian Somers cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!"); 7965eea2e0SBrian Somers else 805106c671SBrian Somers cmdstr = (cmd == RTM_ADD ? "Add" : "Delete"); 815106c671SBrian Somers s = ID0socket(PF_ROUTE, SOCK_RAW, 0); 826614d8c5SBrian Somers if (s < 0) { 83afc7fa2cSBrian Somers LogPrintf(LogERROR, "OsSetRoute: socket(): %s\n", strerror(errno)); 846614d8c5SBrian Somers return; 856614d8c5SBrian Somers } 8670ee81ffSBrian Somers memset(&rtmes, '\0', sizeof rtmes); 87af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_version = RTM_VERSION; 88af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_type = cmd; 89f01e577bSBrian Somers rtmes.m_rtm.rtm_addrs = RTA_DST; 90af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_seq = ++seqno; 91af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_pid = getpid(); 922db86e5bSPeter Wemm rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 93af57ed9fSAtsushi Murai 9470ee81ffSBrian Somers memset(&rtdata, '\0', sizeof rtdata); 95af57ed9fSAtsushi Murai rtdata.sin_len = 16; 96af57ed9fSAtsushi Murai rtdata.sin_family = AF_INET; 97af57ed9fSAtsushi Murai rtdata.sin_port = 0; 98af57ed9fSAtsushi Murai rtdata.sin_addr = dst; 99af57ed9fSAtsushi Murai 100af57ed9fSAtsushi Murai cp = rtmes.m_space; 10175240ed1SBrian Somers memcpy(cp, &rtdata, 16); 102af57ed9fSAtsushi Murai cp += 16; 103f01e577bSBrian Somers if (cmd == RTM_ADD) 104f01e577bSBrian Somers if (gateway.s_addr == INADDR_ANY) { 105f01e577bSBrian Somers /* Add a route through the interface */ 106f01e577bSBrian Somers struct sockaddr_dl dl; 107f01e577bSBrian Somers const char *iname; 108f01e577bSBrian Somers int ilen; 109f01e577bSBrian Somers 110f01e577bSBrian Somers iname = Index2Nam(IfIndex); 111f01e577bSBrian Somers ilen = strlen(iname); 11270ee81ffSBrian Somers dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen; 113f01e577bSBrian Somers dl.sdl_family = AF_LINK; 114f01e577bSBrian Somers dl.sdl_index = IfIndex; 115f01e577bSBrian Somers dl.sdl_type = 0; 116f01e577bSBrian Somers dl.sdl_nlen = ilen; 117f01e577bSBrian Somers dl.sdl_alen = 0; 118f01e577bSBrian Somers dl.sdl_slen = 0; 11970ee81ffSBrian Somers strncpy(dl.sdl_data, iname, sizeof dl.sdl_data); 120f01e577bSBrian Somers 121f01e577bSBrian Somers memcpy(cp, &dl, dl.sdl_len); 122f01e577bSBrian Somers cp += dl.sdl_len; 123f01e577bSBrian Somers rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 124f01e577bSBrian Somers } else { 125af57ed9fSAtsushi Murai rtdata.sin_addr = gateway; 12675240ed1SBrian Somers memcpy(cp, &rtdata, 16); 127af57ed9fSAtsushi Murai cp += 16; 128d3a3ec3bSBrian Somers rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 129af57ed9fSAtsushi Murai } 130f01e577bSBrian Somers 131af57ed9fSAtsushi Murai if (dst.s_addr == INADDR_ANY) 132af57ed9fSAtsushi Murai mask.s_addr = INADDR_ANY; 133af57ed9fSAtsushi Murai 134f01e577bSBrian Somers if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) { 135f01e577bSBrian Somers rtdata.sin_addr = mask; 136f01e577bSBrian Somers memcpy(cp, &rtdata, 16); 137f01e577bSBrian Somers cp += 16; 138f01e577bSBrian Somers rtmes.m_rtm.rtm_addrs |= RTA_NETMASK; 139f01e577bSBrian Somers } 140af57ed9fSAtsushi Murai 141af57ed9fSAtsushi Murai nb = cp - (char *) &rtmes; 142af57ed9fSAtsushi Murai rtmes.m_rtm.rtm_msglen = nb; 143de7453bbSBrian Somers wb = ID0write(s, &rtmes, nb); 144af57ed9fSAtsushi Murai if (wb < 0) { 14532ca3341SBrian Somers LogPrintf(LogTCPIP, "OsSetRoute failure:\n"); 14632ca3341SBrian Somers LogPrintf(LogTCPIP, "OsSetRoute: Cmd = %s\n", cmd); 147e696ee3bSBrian Somers LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst)); 148e696ee3bSBrian Somers LogPrintf(LogTCPIP, "OsSetRoute: Gateway = %s\n", inet_ntoa(gateway)); 149e696ee3bSBrian Somers LogPrintf(LogTCPIP, "OsSetRoute: Mask = %s\n", inet_ntoa(mask)); 15065eea2e0SBrian Somers failed: 15165eea2e0SBrian Somers if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST || 15265eea2e0SBrian Somers (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) 15365eea2e0SBrian Somers if (!bang) 154bcc332bdSBrian Somers LogPrintf(LogWARN, "Add route failed: %s already exists\n", 155bcc332bdSBrian Somers inet_ntoa(dst)); 15665eea2e0SBrian Somers else { 15765eea2e0SBrian Somers rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE; 15865eea2e0SBrian Somers if ((wb = ID0write(s, &rtmes, nb)) < 0) 15965eea2e0SBrian Somers goto failed; 16065eea2e0SBrian Somers } 16165eea2e0SBrian Somers else if (cmd == RTM_DELETE && 16265eea2e0SBrian Somers (rtmes.m_rtm.rtm_errno == ESRCH || 16365eea2e0SBrian Somers (rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) { 16465eea2e0SBrian Somers if (!bang) 165bcc332bdSBrian Somers LogPrintf(LogWARN, "Del route failed: %s: Non-existent\n", 166bcc332bdSBrian Somers inet_ntoa(dst)); 16765eea2e0SBrian Somers } else if (rtmes.m_rtm.rtm_errno == 0) 16832ca3341SBrian Somers LogPrintf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr, 16932ca3341SBrian Somers inet_ntoa(dst), strerror(errno)); 17065eea2e0SBrian Somers else 17132ca3341SBrian Somers LogPrintf(LogWARN, "%s route failed: %s: %s\n", 17232ca3341SBrian Somers cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno)); 173e696ee3bSBrian Somers } 1745106c671SBrian Somers LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n", 1755106c671SBrian Somers wb, cmdstr, dst.s_addr, gateway.s_addr); 176af57ed9fSAtsushi Murai close(s); 177af57ed9fSAtsushi Murai } 178af57ed9fSAtsushi Murai 179af57ed9fSAtsushi Murai static void 1805d5e5070SBrian Somers p_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width) 181af57ed9fSAtsushi Murai { 182b6e82f33SBrian Somers char buf[29]; 1835d5e5070SBrian Somers struct sockaddr_in *ihost = (struct sockaddr_in *)phost; 1845d5e5070SBrian Somers struct sockaddr_in *mask = (struct sockaddr_in *)pmask; 1855d5e5070SBrian Somers struct sockaddr_dl *dl = (struct sockaddr_dl *)phost; 186af57ed9fSAtsushi Murai 1875d5e5070SBrian Somers switch (phost->sa_family) { 1885d5e5070SBrian Somers case AF_INET: 1895d5e5070SBrian Somers if (!phost) 1904bfaee90SBrian Somers buf[0] = '\0'; 1915d5e5070SBrian Somers else if (ihost->sin_addr.s_addr == INADDR_ANY) 1924bfaee90SBrian Somers strcpy(buf, "default"); 1935d5e5070SBrian Somers else if (!mask) 1944bfaee90SBrian Somers strcpy(buf, inet_ntoa(ihost->sin_addr)); 1955d5e5070SBrian Somers else { 1965d5e5070SBrian Somers u_int msk = ntohl(mask->sin_addr.s_addr); 1975d5e5070SBrian Somers u_int tst; 1985d5e5070SBrian Somers int bits; 1995d5e5070SBrian Somers int len; 2005d5e5070SBrian Somers struct sockaddr_in net; 2015d5e5070SBrian Somers 2025d5e5070SBrian Somers for (tst = 1, bits=32; tst; tst <<= 1, bits--) 2035d5e5070SBrian Somers if (msk & tst) 2045d5e5070SBrian Somers break; 2055d5e5070SBrian Somers 2065d5e5070SBrian Somers for (tst <<=1; tst; tst <<= 1) 2075d5e5070SBrian Somers if (!(msk & tst)) 2085d5e5070SBrian Somers break; 2095d5e5070SBrian Somers 2105d5e5070SBrian Somers net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr; 21183c0952dSBrian Somers strcpy(buf, inet_ntoa(net.sin_addr)); 2125d5e5070SBrian Somers for (len = strlen(buf); len > 3; buf[len-=2] = '\0') 2135d5e5070SBrian Somers if (strcmp(buf+len-2, ".0")) 2145d5e5070SBrian Somers break; 2155d5e5070SBrian Somers 2165d5e5070SBrian Somers if (tst) /* non-contiguous :-( */ 2175d5e5070SBrian Somers sprintf(buf+strlen(buf),"&0x%08x", msk); 2185d5e5070SBrian Somers else 2195d5e5070SBrian Somers sprintf(buf+strlen(buf), "/%d", bits); 220927145beSBrian Somers } 2215d5e5070SBrian Somers break; 2225d5e5070SBrian Somers 2235d5e5070SBrian Somers case AF_LINK: 2244bfaee90SBrian Somers if (dl->sdl_nlen) 2254bfaee90SBrian Somers snprintf(buf, sizeof buf, "%.*s", dl->sdl_nlen, dl->sdl_data); 2264bfaee90SBrian Somers else if (dl->sdl_alen) 2274bfaee90SBrian Somers if (dl->sdl_type == IFT_ETHER) 22870ee81ffSBrian Somers if (dl->sdl_alen < sizeof buf / 3) { 2295d5e5070SBrian Somers int f; 2305d5e5070SBrian Somers u_char *MAC; 2315d5e5070SBrian Somers 2325d5e5070SBrian Somers MAC = (u_char *)dl->sdl_data + dl->sdl_nlen; 2335d5e5070SBrian Somers for (f = 0; f < dl->sdl_alen; f++) 2345d5e5070SBrian Somers sprintf(buf+f*3, "%02x:", MAC[f]); 2355d5e5070SBrian Somers buf[f*3-1] = '\0'; 2365d5e5070SBrian Somers } else 23783c0952dSBrian Somers strcpy(buf, "??:??:??:??:??:??"); 2384bfaee90SBrian Somers else 2394bfaee90SBrian Somers sprintf(buf, "<IFT type %d>", dl->sdl_type); 2404bfaee90SBrian Somers else if (dl->sdl_slen) 2414bfaee90SBrian Somers sprintf(buf, "<slen %d?>", dl->sdl_slen); 2424bfaee90SBrian Somers else 2434bfaee90SBrian Somers sprintf(buf, "link#%d", dl->sdl_index); 2445d5e5070SBrian Somers break; 2455d5e5070SBrian Somers 2465d5e5070SBrian Somers default: 2474bfaee90SBrian Somers sprintf(buf, "<AF type %d>", phost->sa_family); 2485d5e5070SBrian Somers break; 2495d5e5070SBrian Somers } 2505d5e5070SBrian Somers 2514bfaee90SBrian Somers fprintf(VarTerm, "%-*s ", width-1, buf); 252af57ed9fSAtsushi Murai } 253af57ed9fSAtsushi Murai 254aa8e0519SBrian Somers static struct bits { 2555d5e5070SBrian Somers u_long b_mask; 256af57ed9fSAtsushi Murai char b_val; 257af57ed9fSAtsushi Murai } bits[] = { 2585d5e5070SBrian Somers { RTF_UP, 'U' }, 2595d5e5070SBrian Somers { RTF_GATEWAY, 'G' }, 2605d5e5070SBrian Somers { RTF_HOST, 'H' }, 2615d5e5070SBrian Somers { RTF_REJECT, 'R' }, 2625d5e5070SBrian Somers { RTF_DYNAMIC, 'D' }, 2635d5e5070SBrian Somers { RTF_MODIFIED, 'M' }, 2645d5e5070SBrian Somers { RTF_DONE, 'd' }, 2655d5e5070SBrian Somers { RTF_CLONING, 'C' }, 2665d5e5070SBrian Somers { RTF_XRESOLVE, 'X' }, 2675d5e5070SBrian Somers { RTF_LLINFO, 'L' }, 2685d5e5070SBrian Somers { RTF_STATIC, 'S' }, 2695d5e5070SBrian Somers { RTF_PROTO1, '1' }, 2705d5e5070SBrian Somers { RTF_PROTO2, '2' }, 2715d5e5070SBrian Somers { RTF_BLACKHOLE, 'B' }, 27232ca3341SBrian Somers #ifdef RTF_WASCLONED 2735d5e5070SBrian Somers { RTF_WASCLONED, 'W' }, 27432ca3341SBrian Somers #endif 27532ca3341SBrian Somers #ifdef RTF_PRCLONING 2765d5e5070SBrian Somers { RTF_PRCLONING, 'c' }, 27732ca3341SBrian Somers #endif 27832ca3341SBrian Somers #ifdef RTF_PROTO3 2795d5e5070SBrian Somers { RTF_PROTO3, '3' }, 28032ca3341SBrian Somers #endif 28132ca3341SBrian Somers #ifdef RTF_BROADCAST 2825d5e5070SBrian Somers { RTF_BROADCAST, 'b' }, 2835d5e5070SBrian Somers #endif 2845d5e5070SBrian Somers { 0, '\0' } 285af57ed9fSAtsushi Murai }; 286af57ed9fSAtsushi Murai 28732ca3341SBrian Somers #ifndef RTF_WASCLONED 28832ca3341SBrian Somers #define RTF_WASCLONED (0) 28932ca3341SBrian Somers #endif 29032ca3341SBrian Somers 291af57ed9fSAtsushi Murai static void 292d27d502cSBrian Somers p_flags(u_long f, int max) 293af57ed9fSAtsushi Murai { 294927145beSBrian Somers if (VarTerm) { 295af57ed9fSAtsushi Murai char name[33], *flags; 296af57ed9fSAtsushi Murai register struct bits *p = bits; 297af57ed9fSAtsushi Murai 29870ee81ffSBrian Somers if (max > sizeof name - 1) 29970ee81ffSBrian Somers max = sizeof name - 1; 300d27d502cSBrian Somers 301d27d502cSBrian Somers for (flags = name; p->b_mask && flags - name < max; p++) 302af57ed9fSAtsushi Murai if (p->b_mask & f) 303af57ed9fSAtsushi Murai *flags++ = p->b_val; 304af57ed9fSAtsushi Murai *flags = '\0'; 305d27d502cSBrian Somers fprintf(VarTerm, "%-*.*s", max, max, name); 306927145beSBrian Somers } 307af57ed9fSAtsushi Murai } 308af57ed9fSAtsushi Murai 309c6fe0cb2SBrian Somers const char * 3105d5e5070SBrian Somers Index2Nam(int idx) 3115d5e5070SBrian Somers { 312b1435e41SBrian Somers static char **ifs; 3139cb1d89eSBrian Somers static int nifs, debug_done; 3145d5e5070SBrian Somers 3155d5e5070SBrian Somers if (!nifs) { 316b1435e41SBrian Somers int mib[6], have, had; 317e7250038SBrian Somers size_t needed; 3185d5e5070SBrian Somers char *buf, *ptr, *end; 3195d5e5070SBrian Somers struct sockaddr_dl *dl; 3205d5e5070SBrian Somers struct if_msghdr *ifm; 3215d5e5070SBrian Somers 3225d5e5070SBrian Somers mib[0] = CTL_NET; 3235d5e5070SBrian Somers mib[1] = PF_ROUTE; 3245d5e5070SBrian Somers mib[2] = 0; 3255d5e5070SBrian Somers mib[3] = 0; 3265d5e5070SBrian Somers mib[4] = NET_RT_IFLIST; 3275d5e5070SBrian Somers mib[5] = 0; 3285d5e5070SBrian Somers 3295d5e5070SBrian Somers if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 3305d5e5070SBrian Somers LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno)); 3315d5e5070SBrian Somers return "???"; 3325d5e5070SBrian Somers } 3335d5e5070SBrian Somers if ((buf = malloc(needed)) == NULL) 3345d5e5070SBrian Somers return "???"; 3355d5e5070SBrian Somers if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 3365d5e5070SBrian Somers free(buf); 3375d5e5070SBrian Somers return "???"; 3385d5e5070SBrian Somers } 3395d5e5070SBrian Somers end = buf + needed; 3405d5e5070SBrian Somers 341b1435e41SBrian Somers have = 0; 3429cb1d89eSBrian Somers for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) { 3435d5e5070SBrian Somers ifm = (struct if_msghdr *)ptr; 3445d5e5070SBrian Somers dl = (struct sockaddr_dl *)(ifm + 1); 345b1435e41SBrian Somers if (ifm->ifm_index > 0) { 346b1435e41SBrian Somers if (ifm->ifm_index > have) { 347b1435e41SBrian Somers had = have; 348b1435e41SBrian Somers have = ifm->ifm_index + 5; 349b1435e41SBrian Somers if (had) 350b1435e41SBrian Somers ifs = (char **)realloc(ifs, sizeof(char *) * have); 351b1435e41SBrian Somers else 352b1435e41SBrian Somers ifs = (char **)malloc(sizeof(char *) * have); 353b1435e41SBrian Somers if (!ifs) { 354b1435e41SBrian Somers LogPrintf(LogDEBUG, "Index2Nam: %s\n", strerror(errno)); 355b1435e41SBrian Somers nifs = 0; 356b1435e41SBrian Somers return "???"; 357b1435e41SBrian Somers } 358b1435e41SBrian Somers memset(ifs + had, '\0', sizeof(char *) * (have - had)); 359b1435e41SBrian Somers } 360b1435e41SBrian Somers if (ifs[ifm->ifm_index-1] == NULL) { 361b1435e41SBrian Somers ifs[ifm->ifm_index-1] = (char *)malloc(dl->sdl_nlen+1); 362b1435e41SBrian Somers memcpy(ifs[ifm->ifm_index-1], dl->sdl_data, dl->sdl_nlen); 363b1435e41SBrian Somers ifs[ifm->ifm_index-1][dl->sdl_nlen] = '\0'; 364b1435e41SBrian Somers if (nifs < ifm->ifm_index) 3659cb1d89eSBrian Somers nifs = ifm->ifm_index; 366b1435e41SBrian Somers } 3679cb1d89eSBrian Somers } else if (LogIsKept(LogDEBUG)) 3689cb1d89eSBrian Somers LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n", 3699cb1d89eSBrian Somers ifm->ifm_index); 3705d5e5070SBrian Somers } 3715d5e5070SBrian Somers free(buf); 3725d5e5070SBrian Somers } 3735d5e5070SBrian Somers 3749cb1d89eSBrian Somers if (LogIsKept(LogDEBUG) && !debug_done) { 3759cb1d89eSBrian Somers int f; 3769cb1d89eSBrian Somers 3779cb1d89eSBrian Somers LogPrintf(LogDEBUG, "Found the following interfaces:\n"); 3789cb1d89eSBrian Somers for (f = 0; f < nifs; f++) 379b1435e41SBrian Somers if (ifs[f] != NULL) 3809cb1d89eSBrian Somers LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]); 3819cb1d89eSBrian Somers debug_done = 1; 3829cb1d89eSBrian Somers } 3839cb1d89eSBrian Somers 384b1435e41SBrian Somers if (idx < 1 || idx > nifs || ifs[idx-1] == NULL) 3855d5e5070SBrian Somers return "???"; 3869cb1d89eSBrian Somers 3879cb1d89eSBrian Somers return ifs[idx-1]; 3885d5e5070SBrian Somers } 3895d5e5070SBrian Somers 390af57ed9fSAtsushi Murai int 391b6e82f33SBrian Somers ShowRoute(struct cmdargs const *arg) 392af57ed9fSAtsushi Murai { 393af57ed9fSAtsushi Murai struct rt_msghdr *rtm; 3945d5e5070SBrian Somers struct sockaddr *sa_dst, *sa_gw, *sa_mask; 3955d5e5070SBrian Somers char *sp, *ep, *cp, *wp; 396e7250038SBrian Somers size_t needed; 397af57ed9fSAtsushi Murai int mib[6]; 398af57ed9fSAtsushi Murai 399927145beSBrian Somers if (!VarTerm) 400927145beSBrian Somers return 1; 401927145beSBrian Somers 402af57ed9fSAtsushi Murai mib[0] = CTL_NET; 403af57ed9fSAtsushi Murai mib[1] = PF_ROUTE; 40453c9f6c0SAtsushi Murai mib[2] = 0; 40553c9f6c0SAtsushi Murai mib[3] = 0; 406af57ed9fSAtsushi Murai mib[4] = NET_RT_DUMP; 40753c9f6c0SAtsushi Murai mib[5] = 0; 40853c9f6c0SAtsushi Murai if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 409afc7fa2cSBrian Somers LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno)); 41053c9f6c0SAtsushi Murai return (1); 41153c9f6c0SAtsushi Murai } 412af57ed9fSAtsushi Murai if (needed < 0) 413af57ed9fSAtsushi Murai return (1); 414af57ed9fSAtsushi Murai sp = malloc(needed); 415af57ed9fSAtsushi Murai if (sp == NULL) 416af57ed9fSAtsushi Murai return (1); 41753c9f6c0SAtsushi Murai if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 418afc7fa2cSBrian Somers LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno)); 419b0cdb3ceSJordan K. Hubbard free(sp); 420af57ed9fSAtsushi Murai return (1); 42153c9f6c0SAtsushi Murai } 422af57ed9fSAtsushi Murai ep = sp + needed; 423af57ed9fSAtsushi Murai 4245d5e5070SBrian Somers fprintf(VarTerm, "%-20s%-20sFlags Netif\n", "Destination", "Gateway"); 425af57ed9fSAtsushi Murai for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 426af57ed9fSAtsushi Murai rtm = (struct rt_msghdr *) cp; 4275d5e5070SBrian Somers wp = (char *)(rtm+1); 4285d5e5070SBrian Somers 4295d5e5070SBrian Somers if (rtm->rtm_addrs & RTA_DST) { 4305d5e5070SBrian Somers sa_dst = (struct sockaddr *)wp; 4315d5e5070SBrian Somers wp += sa_dst->sa_len; 4325d5e5070SBrian Somers } else 4335d5e5070SBrian Somers sa_dst = NULL; 4345d5e5070SBrian Somers 4355d5e5070SBrian Somers if (rtm->rtm_addrs & RTA_GATEWAY) { 4365d5e5070SBrian Somers sa_gw = (struct sockaddr *)wp; 4375d5e5070SBrian Somers wp += sa_gw->sa_len; 4385d5e5070SBrian Somers } else 4395d5e5070SBrian Somers sa_gw = NULL; 4405d5e5070SBrian Somers 4415d5e5070SBrian Somers if (rtm->rtm_addrs & RTA_NETMASK) { 4425d5e5070SBrian Somers sa_mask = (struct sockaddr *)wp; 4435d5e5070SBrian Somers wp += sa_mask->sa_len; 4445d5e5070SBrian Somers } else 4455d5e5070SBrian Somers sa_mask = NULL; 4465d5e5070SBrian Somers 4475d5e5070SBrian Somers p_sockaddr(sa_dst, sa_mask, 20); 4485d5e5070SBrian Somers p_sockaddr(sa_gw, NULL, 20); 4495d5e5070SBrian Somers 450d27d502cSBrian Somers p_flags(rtm->rtm_flags, 6); 4515d5e5070SBrian Somers fprintf(VarTerm, " %s\n", Index2Nam(rtm->rtm_index)); 452af57ed9fSAtsushi Murai } 453b0cdb3ceSJordan K. Hubbard free(sp); 454927145beSBrian Somers return 0; 455af57ed9fSAtsushi Murai } 456af57ed9fSAtsushi Murai 457af57ed9fSAtsushi Murai /* 458af57ed9fSAtsushi Murai * Delete routes associated with our interface 459af57ed9fSAtsushi Murai */ 460af57ed9fSAtsushi Murai void 461944f7098SBrian Somers DeleteIfRoutes(int all) 462af57ed9fSAtsushi Murai { 463af57ed9fSAtsushi Murai struct rt_msghdr *rtm; 464af57ed9fSAtsushi Murai struct sockaddr *sa; 465f01e577bSBrian Somers struct in_addr sa_dst, sa_none; 466e7250038SBrian Somers int pass; 467e7250038SBrian Somers size_t needed; 468af57ed9fSAtsushi Murai char *sp, *cp, *ep; 469af57ed9fSAtsushi Murai int mib[6]; 470af57ed9fSAtsushi Murai 471927145beSBrian Somers LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex); 472f01e577bSBrian Somers sa_none.s_addr = INADDR_ANY; 473927145beSBrian Somers 474af57ed9fSAtsushi Murai mib[0] = CTL_NET; 475af57ed9fSAtsushi Murai mib[1] = PF_ROUTE; 47653c9f6c0SAtsushi Murai mib[2] = 0; 47753c9f6c0SAtsushi Murai mib[3] = 0; 478af57ed9fSAtsushi Murai mib[4] = NET_RT_DUMP; 47953c9f6c0SAtsushi Murai mib[5] = 0; 48053c9f6c0SAtsushi Murai if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 481afc7fa2cSBrian Somers LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n", 482afc7fa2cSBrian Somers strerror(errno)); 48353c9f6c0SAtsushi Murai return; 48453c9f6c0SAtsushi Murai } 485af57ed9fSAtsushi Murai if (needed < 0) 486af57ed9fSAtsushi Murai return; 487af57ed9fSAtsushi Murai 488af57ed9fSAtsushi Murai sp = malloc(needed); 489af57ed9fSAtsushi Murai if (sp == NULL) 490af57ed9fSAtsushi Murai return; 491af57ed9fSAtsushi Murai 492af57ed9fSAtsushi Murai if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 493afc7fa2cSBrian Somers LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n", 494afc7fa2cSBrian Somers strerror(errno)); 495af57ed9fSAtsushi Murai free(sp); 496af57ed9fSAtsushi Murai return; 497af57ed9fSAtsushi Murai } 498af57ed9fSAtsushi Murai ep = sp + needed; 499af57ed9fSAtsushi Murai 50032ca3341SBrian Somers for (pass = 0; pass < 2; pass++) { 50132ca3341SBrian Somers /* 50232ca3341SBrian Somers * We do 2 passes. The first deletes all cloned routes. The second 50332ca3341SBrian Somers * deletes all non-cloned routes. This is necessary to avoid 50432ca3341SBrian Somers * potential errors from trying to delete route X after route Y where 50532ca3341SBrian Somers * route X was cloned from route Y (which is no longer there). 50632ca3341SBrian Somers */ 50732ca3341SBrian Somers if (RTF_WASCLONED == 0 && pass == 0) 50832ca3341SBrian Somers /* So we can't tell ! */ 50932ca3341SBrian Somers continue; 510af57ed9fSAtsushi Murai for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 511af57ed9fSAtsushi Murai rtm = (struct rt_msghdr *) cp; 512af57ed9fSAtsushi Murai sa = (struct sockaddr *) (rtm + 1); 51332ca3341SBrian Somers LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s)," 51432ca3341SBrian Somers " flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index, 5155d5e5070SBrian Somers Index2Nam(rtm->rtm_index), rtm->rtm_flags, 5169b5a20e1SBrian Somers inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); 5175d5e5070SBrian Somers if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY && 5185d5e5070SBrian Somers rtm->rtm_index == IfIndex && 519af57ed9fSAtsushi Murai (all || (rtm->rtm_flags & RTF_GATEWAY))) { 5205d5e5070SBrian Somers sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 5215d5e5070SBrian Somers sa = (struct sockaddr *)((char *)sa + sa->sa_len); 522f01e577bSBrian Somers if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) { 52332ca3341SBrian Somers if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) || 52432ca3341SBrian Somers (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) { 52532ca3341SBrian Somers LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it (pass %d)\n", pass); 52665eea2e0SBrian Somers OsSetRoute(RTM_DELETE, sa_dst, sa_none, sa_none, 0); 5275d5e5070SBrian Somers } else 52832ca3341SBrian Somers LogPrintf(LogDEBUG, "DeleteIfRoutes: Skip it (pass %d)\n", pass); 52932ca3341SBrian Somers } else 530f01e577bSBrian Somers LogPrintf(LogDEBUG, 531f01e577bSBrian Somers "DeleteIfRoutes: Can't remove routes of %d family !\n", 532f01e577bSBrian Somers sa->sa_family); 533af57ed9fSAtsushi Murai } 534af57ed9fSAtsushi Murai } 53532ca3341SBrian Somers } 536af57ed9fSAtsushi Murai free(sp); 537af57ed9fSAtsushi Murai } 538af57ed9fSAtsushi Murai 539af57ed9fSAtsushi Murai int 540944f7098SBrian Somers GetIfIndex(char *name) 541af57ed9fSAtsushi Murai { 5425d5e5070SBrian Somers int idx; 543b6e82f33SBrian Somers const char *got; 544944f7098SBrian Somers 5459cb1d89eSBrian Somers idx = 1; 5465d5e5070SBrian Somers while (strcmp(got = Index2Nam(idx), "???")) 5475d5e5070SBrian Somers if (!strcmp(got, name)) 5485d5e5070SBrian Somers return IfIndex = idx; 5495d5e5070SBrian Somers else 5505d5e5070SBrian Somers idx++; 5515d5e5070SBrian Somers return -1; 552af57ed9fSAtsushi Murai } 553bcc332bdSBrian Somers 554bcc332bdSBrian Somers struct in_addr 555bcc332bdSBrian Somers ChooseHisAddr(const struct in_addr gw) 556bcc332bdSBrian Somers { 557bcc332bdSBrian Somers struct in_addr try; 558bcc332bdSBrian Somers int f; 559bcc332bdSBrian Somers 560bcc332bdSBrian Somers for (f = 0; f < DefHisChoice.nItems; f++) { 561bcc332bdSBrian Somers try = iplist_next(&DefHisChoice); 562bcc332bdSBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 563bcc332bdSBrian Somers f, inet_ntoa(try)); 564bcc332bdSBrian Somers if (OsTrySetIpaddress(gw, try) == 0) { 565bcc332bdSBrian Somers LogPrintf(LogIPCP, "ChooseHisAddr: Selected IP address %s\n", 566bcc332bdSBrian Somers inet_ntoa(try)); 567bcc332bdSBrian Somers break; 568bcc332bdSBrian Somers } 569bcc332bdSBrian Somers } 570bcc332bdSBrian Somers 571bcc332bdSBrian Somers if (f == DefHisChoice.nItems) { 572bcc332bdSBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 573bcc332bdSBrian Somers try.s_addr = INADDR_ANY; 574bcc332bdSBrian Somers } 575bcc332bdSBrian Somers 576bcc332bdSBrian Somers return try; 577bcc332bdSBrian Somers } 578