route.c revision 34536
14Srgrimes/* 21690Sdg * PPP Routing related Module 31690Sdg * 41690Sdg * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 54Srgrimes * 64Srgrimes * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 74Srgrimes * 84Srgrimes * Redistribution and use in source and binary forms are permitted 94Srgrimes * provided that the above copyright notice and this paragraph are 104Srgrimes * duplicated in all such forms and that any documentation, 114Srgrimes * advertising materials, and other materials related to such 124Srgrimes * distribution and use acknowledge that the software was developed 134Srgrimes * by the Internet Initiative Japan, Inc. The name of the 144Srgrimes * IIJ may not be used to endorse or promote products derived 154Srgrimes * from this software without specific prior written permission. 164Srgrimes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 174Srgrimes * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 184Srgrimes * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 194Srgrimes * 204Srgrimes * $Id: route.c,v 1.42 1998/01/21 02:15:26 brian Exp $ 214Srgrimes * 224Srgrimes */ 234Srgrimes 244Srgrimes#include <sys/param.h> 254Srgrimes#include <sys/time.h> 264Srgrimes#include <sys/socket.h> 274Srgrimes#include <net/if_types.h> 284Srgrimes#include <net/route.h> 294Srgrimes#include <net/if.h> 304Srgrimes#include <netinet/in.h> 314Srgrimes#include <arpa/inet.h> 324Srgrimes#include <net/if_dl.h> 334Srgrimes 344Srgrimes#include <errno.h> 354Srgrimes#include <machine/endian.h> 364Srgrimes#include <stdio.h> 37608Srgrimes#include <stdlib.h> 385603Sbde#include <string.h> 394Srgrimes#include <sys/ioctl.h> 404Srgrimes#include <sys/sysctl.h> 414Srgrimes#include <unistd.h> 421704Sdg 434Srgrimes#include "command.h" 444Srgrimes#include "mbuf.h" 451549Srgrimes#include "log.h" 461549Srgrimes#include "loadalias.h" 471549Srgrimes#include "defs.h" 481549Srgrimes#include "vars.h" 491549Srgrimes#include "id.h" 501549Srgrimes#include "os.h" 511549Srgrimes#include "ipcp.h" 522257Ssos#include "iplist.h" 534Srgrimes#include "route.h" 541549Srgrimes 554Srgrimesstatic int IfIndex; 564Srgrimes 571549Srgrimesstruct rtmsg { 581549Srgrimes struct rt_msghdr m_rtm; 591549Srgrimes char m_space[64]; 601549Srgrimes}; 614Srgrimes 621549Srgrimesstatic int seqno; 631549Srgrimes 641549Srgrimesvoid 651549SrgrimesOsSetRoute(int cmd, 663436Sphk struct in_addr dst, 671549Srgrimes struct in_addr gateway, 681549Srgrimes struct in_addr mask, 691549Srgrimes int bang) 701549Srgrimes{ 711690Sdg struct rtmsg rtmes; 721690Sdg int s, nb, wb; 734Srgrimes char *cp; 74757Sdg const char *cmdstr; 75757Sdg struct sockaddr_in rtdata; 765603Sbde 77757Sdg if (bang) 785603Sbde cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!"); 79757Sdg else 80757Sdg cmdstr = (cmd == RTM_ADD ? "Add" : "Delete"); 815603Sbde s = ID0socket(PF_ROUTE, SOCK_RAW, 0); 82757Sdg if (s < 0) { 83757Sdg LogPrintf(LogERROR, "OsSetRoute: socket(): %s\n", strerror(errno)); 845603Sbde return; 851690Sdg } 86757Sdg memset(&rtmes, '\0', sizeof rtmes); 87757Sdg rtmes.m_rtm.rtm_version = RTM_VERSION; 88757Sdg rtmes.m_rtm.rtm_type = cmd; 895603Sbde rtmes.m_rtm.rtm_addrs = RTA_DST; 90757Sdg rtmes.m_rtm.rtm_seq = ++seqno; 915603Sbde rtmes.m_rtm.rtm_pid = getpid(); 925603Sbde rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 935603Sbde 94757Sdg memset(&rtdata, '\0', sizeof rtdata); 95757Sdg rtdata.sin_len = 16; 96757Sdg rtdata.sin_family = AF_INET; 97757Sdg rtdata.sin_port = 0; 98757Sdg rtdata.sin_addr = dst; 99757Sdg 100757Sdg cp = rtmes.m_space; 101757Sdg memcpy(cp, &rtdata, 16); 102757Sdg cp += 16; 103757Sdg if (cmd == RTM_ADD) { 104757Sdg if (gateway.s_addr == INADDR_ANY) { 1054Srgrimes /* Add a route through the interface */ 1061690Sdg struct sockaddr_dl dl; 1071690Sdg const char *iname; 1081690Sdg int ilen; 1091690Sdg 1101690Sdg iname = Index2Nam(IfIndex); 1111690Sdg ilen = strlen(iname); 1121690Sdg dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen; 113757Sdg dl.sdl_family = AF_LINK; 1143436Sphk dl.sdl_index = IfIndex; 1151690Sdg dl.sdl_type = 0; 1161690Sdg dl.sdl_nlen = ilen; 1171690Sdg dl.sdl_alen = 0; 1181690Sdg dl.sdl_slen = 0; 1191690Sdg strncpy(dl.sdl_data, iname, sizeof dl.sdl_data); 1201690Sdg 1211690Sdg memcpy(cp, &dl, dl.sdl_len); 1221690Sdg cp += dl.sdl_len; 1231690Sdg rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 1241690Sdg } else { 1251690Sdg rtdata.sin_addr = gateway; 1261690Sdg memcpy(cp, &rtdata, 16); 1271690Sdg cp += 16; 1281690Sdg rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 1291690Sdg } 1301690Sdg } 1313436Sphk 1321690Sdg if (dst.s_addr == INADDR_ANY) 1331690Sdg mask.s_addr = INADDR_ANY; 1341690Sdg 1351690Sdg if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) { 1361690Sdg rtdata.sin_addr = mask; 1371690Sdg memcpy(cp, &rtdata, 16); 1381690Sdg cp += 16; 1391690Sdg rtmes.m_rtm.rtm_addrs |= RTA_NETMASK; 1401690Sdg } 1411690Sdg 1421690Sdg nb = cp - (char *) &rtmes; 1431690Sdg rtmes.m_rtm.rtm_msglen = nb; 1441690Sdg wb = ID0write(s, &rtmes, nb); 1451690Sdg if (wb < 0) { 1461690Sdg LogPrintf(LogTCPIP, "OsSetRoute failure:\n"); 1471690Sdg LogPrintf(LogTCPIP, "OsSetRoute: Cmd = %s\n", cmd); 1481690Sdg LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst)); 1491690Sdg LogPrintf(LogTCPIP, "OsSetRoute: Gateway = %s\n", inet_ntoa(gateway)); 1504Srgrimes LogPrintf(LogTCPIP, "OsSetRoute: Mask = %s\n", inet_ntoa(mask)); 1514Srgrimesfailed: 1521690Sdg if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST || 1531690Sdg (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) { 1544Srgrimes if (!bang) 1551690Sdg LogPrintf(LogWARN, "Add route failed: %s already exists\n", 1564Srgrimes inet_ntoa(dst)); 1574Srgrimes else { 1584Srgrimes rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE; 159798Swollman if ((wb = ID0write(s, &rtmes, nb)) < 0) 1604Srgrimes goto failed; 1614Srgrimes } 1624Srgrimes } else if (cmd == RTM_DELETE && 1631690Sdg (rtmes.m_rtm.rtm_errno == ESRCH || 1641549Srgrimes (rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) { 1653436Sphk if (!bang) 1663744Swollman LogPrintf(LogWARN, "Del route failed: %s: Non-existent\n", 1673744Swollman inet_ntoa(dst)); 1683744Swollman } else if (rtmes.m_rtm.rtm_errno == 0) 1694Srgrimes LogPrintf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr, 1704Srgrimes inet_ntoa(dst), strerror(errno)); 1711690Sdg else 1724Srgrimes LogPrintf(LogWARN, "%s route failed: %s: %s\n", 1731690Sdg cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno)); 1741690Sdg } 175200Sdg LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n", 1761690Sdg wb, cmdstr, dst.s_addr, gateway.s_addr); 1771549Srgrimes close(s); 1784Srgrimes} 1791690Sdg 1801690Sdgstatic void 1811690Sdgp_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width) 1821690Sdg{ 1831690Sdg char buf[29]; 184974Sdg struct sockaddr_in *ihost = (struct sockaddr_in *)phost; 1851690Sdg struct sockaddr_in *mask = (struct sockaddr_in *)pmask; 1861690Sdg struct sockaddr_dl *dl = (struct sockaddr_dl *)phost; 1871690Sdg 1881690Sdg switch (phost->sa_family) { 1891690Sdg case AF_INET: 190974Sdg if (!phost) 1911690Sdg buf[0] = '\0'; 1921690Sdg else if (ihost->sin_addr.s_addr == INADDR_ANY) 1931690Sdg strcpy(buf, "default"); 1941690Sdg else if (!mask) 1954Srgrimes strcpy(buf, inet_ntoa(ihost->sin_addr)); 1961690Sdg else { 1971690Sdg u_int msk = ntohl(mask->sin_addr.s_addr); 1981690Sdg u_int tst; 1991690Sdg int bits; 2001690Sdg int len; 2011690Sdg struct sockaddr_in net; 2021690Sdg 2031690Sdg for (tst = 1, bits=32; tst; tst <<= 1, bits--) 2044Srgrimes if (msk & tst) 2051690Sdg break; 2061690Sdg 2071690Sdg for (tst <<=1; tst; tst <<= 1) 2085603Sbde if (!(msk & tst)) 2095603Sbde break; 2105603Sbde 2111690Sdg net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr; 2121690Sdg strcpy(buf, inet_ntoa(net.sin_addr)); 2131690Sdg for (len = strlen(buf); len > 3; buf[len-=2] = '\0') 2144Srgrimes if (strcmp(buf+len-2, ".0")) 2151690Sdg break; 2161690Sdg 2174014Sbde if (tst) /* non-contiguous :-( */ 2184014Sbde sprintf(buf+strlen(buf),"&0x%08x", msk); 2191690Sdg else 2201690Sdg sprintf(buf+strlen(buf), "/%d", bits); 2214Srgrimes } 2221690Sdg break; 2231690Sdg 2244Srgrimes case AF_LINK: 2251690Sdg if (dl->sdl_nlen) 2261690Sdg snprintf(buf, sizeof buf, "%.*s", dl->sdl_nlen, dl->sdl_data); 2271690Sdg else if (dl->sdl_alen) { 2281690Sdg if (dl->sdl_type == IFT_ETHER) { 2294Srgrimes if (dl->sdl_alen < sizeof buf / 3) { 2301690Sdg int f; 2311690Sdg u_char *MAC; 2322320Sdg 2331690Sdg MAC = (u_char *)dl->sdl_data + dl->sdl_nlen; 2341690Sdg for (f = 0; f < dl->sdl_alen; f++) 2351690Sdg sprintf(buf+f*3, "%02x:", MAC[f]); 2361690Sdg buf[f*3-1] = '\0'; 2371690Sdg } else 2381690Sdg strcpy(buf, "??:??:??:??:??:??"); 2391690Sdg } else 2402001Swollman sprintf(buf, "<IFT type %d>", dl->sdl_type); 2411690Sdg } else if (dl->sdl_slen) 2424Srgrimes sprintf(buf, "<slen %d?>", dl->sdl_slen); 2431690Sdg else 2441690Sdg sprintf(buf, "link#%d", dl->sdl_index); 2451690Sdg break; 2461690Sdg 2474Srgrimes default: 2481690Sdg sprintf(buf, "<AF type %d>", phost->sa_family); 2491690Sdg break; 2501690Sdg } 2511690Sdg 2524Srgrimes fprintf(VarTerm, "%-*s ", width-1, buf); 2531690Sdg} 2541690Sdg 2551690Sdgstatic struct bits { 2561690Sdg u_long b_mask; 2571690Sdg char b_val; 2581690Sdg} bits[] = { 2591127Sdg { RTF_UP, 'U' }, 2601690Sdg { RTF_GATEWAY, 'G' }, 2611690Sdg { RTF_HOST, 'H' }, 2625220Sbde { RTF_REJECT, 'R' }, 2635220Sbde { RTF_DYNAMIC, 'D' }, 2645220Sbde { RTF_MODIFIED, 'M' }, 2655220Sbde { RTF_DONE, 'd' }, 2665220Sbde { RTF_CLONING, 'C' }, 2675220Sbde { RTF_XRESOLVE, 'X' }, 2685220Sbde { RTF_LLINFO, 'L' }, 2691690Sdg { RTF_STATIC, 'S' }, 2705220Sbde { RTF_PROTO1, '1' }, 2715220Sbde { RTF_PROTO2, '2' }, 2721690Sdg { RTF_BLACKHOLE, 'B' }, 2731690Sdg#ifdef RTF_WASCLONED 274974Sdg { RTF_WASCLONED, 'W' }, 2751690Sdg#endif 2761690Sdg#ifdef RTF_PRCLONING 2771690Sdg { RTF_PRCLONING, 'c' }, 2781690Sdg#endif 279974Sdg#ifdef RTF_PROTO3 2801690Sdg { RTF_PROTO3, '3' }, 2811690Sdg#endif 282974Sdg#ifdef RTF_BROADCAST 2831690Sdg { RTF_BROADCAST, 'b' }, 2841690Sdg#endif 2851690Sdg { 0, '\0' } 2861690Sdg}; 2874Srgrimes 2881690Sdg#ifndef RTF_WASCLONED 2891690Sdg#define RTF_WASCLONED (0) 2905603Sbde#endif 2915603Sbde 2925603Sbdestatic void 2935603Sbdep_flags(u_long f, int max) 2945603Sbde{ 2955603Sbde if (VarTerm) { 2965603Sbde char name[33], *flags; 2975603Sbde register struct bits *p = bits; 2985603Sbde 2995603Sbde if (max > sizeof name - 1) 3005603Sbde max = sizeof name - 1; 3015603Sbde 3025603Sbde for (flags = name; p->b_mask && flags - name < max; p++) 3035603Sbde if (p->b_mask & f) 3045603Sbde *flags++ = p->b_val; 3055603Sbde *flags = '\0'; 3065603Sbde fprintf(VarTerm, "%-*.*s", max, max, name); 3075603Sbde } 3085603Sbde} 3095603Sbde 3105603Sbdeconst char * 3115603SbdeIndex2Nam(int idx) 3125603Sbde{ 3135603Sbde static char **ifs; 3145603Sbde static int nifs, debug_done; 3155603Sbde 3165603Sbde if (!nifs) { 3175603Sbde int mib[6], have, had; 3181690Sdg size_t needed; 3191690Sdg char *buf, *ptr, *end; 3201690Sdg struct sockaddr_dl *dl; 321849Sdg struct if_msghdr *ifm; 3221690Sdg 3234Srgrimes mib[0] = CTL_NET; 3245603Sbde mib[1] = PF_ROUTE; 3255603Sbde mib[2] = 0; 3265603Sbde mib[3] = 0; 3275603Sbde mib[4] = NET_RT_IFLIST; 3285603Sbde mib[5] = 0; 3295603Sbde 3305603Sbde if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 3315603Sbde LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno)); 3325603Sbde return "???"; 3335603Sbde } 3345603Sbde if ((buf = malloc(needed)) == NULL) 3355603Sbde return "???"; 3365603Sbde if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 3375603Sbde free(buf); 3385603Sbde return "???"; 3395603Sbde } 3402320Sdg end = buf + needed; 3411690Sdg 3421690Sdg have = 0; 3431690Sdg for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) { 3444Srgrimes ifm = (struct if_msghdr *)ptr; 3451690Sdg dl = (struct sockaddr_dl *)(ifm + 1); 3461690Sdg if (ifm->ifm_index > 0) { 3471690Sdg if (ifm->ifm_index > have) { 3484Srgrimes had = have; 3491690Sdg have = ifm->ifm_index + 5; 3501690Sdg if (had) 3514Srgrimes ifs = (char **)realloc(ifs, sizeof(char *) * have); 3524Srgrimes else 3531072Sdg ifs = (char **)malloc(sizeof(char *) * have); 3541690Sdg if (!ifs) { 3552320Sdg LogPrintf(LogDEBUG, "Index2Nam: %s\n", strerror(errno)); 3561690Sdg nifs = 0; 3571690Sdg return "???"; 3581342Sdg } 3591342Sdg memset(ifs + had, '\0', sizeof(char *) * (have - had)); 3601342Sdg } 3611690Sdg if (ifs[ifm->ifm_index-1] == NULL) { 3621690Sdg ifs[ifm->ifm_index-1] = (char *)malloc(dl->sdl_nlen+1); 3631690Sdg memcpy(ifs[ifm->ifm_index-1], dl->sdl_data, dl->sdl_nlen); 3641690Sdg ifs[ifm->ifm_index-1][dl->sdl_nlen] = '\0'; 3651072Sdg if (nifs < ifm->ifm_index) 3661072Sdg nifs = ifm->ifm_index; 3671690Sdg } 3684014Sbde } else if (LogIsKept(LogDEBUG)) 3694Srgrimes LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n", 3704Srgrimes ifm->ifm_index); 3714Srgrimes } 3721342Sdg free(buf); 3731342Sdg } 3741690Sdg 3751690Sdg if (LogIsKept(LogDEBUG) && !debug_done) { 3761342Sdg int f; 3771690Sdg 3781690Sdg LogPrintf(LogDEBUG, "Found the following interfaces:\n"); 3791342Sdg for (f = 0; f < nifs; f++) 3801342Sdg if (ifs[f] != NULL) 3811342Sdg LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]); 3821342Sdg debug_done = 1; 3831342Sdg } 3844Srgrimes 3851690Sdg if (idx < 1 || idx > nifs || ifs[idx-1] == NULL) 3861690Sdg return "???"; 3871690Sdg 3881690Sdg return ifs[idx-1]; 3891690Sdg} 3901690Sdg 3911690Sdgint 3921690SdgShowRoute(struct cmdargs const *arg) 3931690Sdg{ 3942660Sdg struct rt_msghdr *rtm; 3951690Sdg struct sockaddr *sa_dst, *sa_gw, *sa_mask; 3963436Sphk char *sp, *ep, *cp, *wp; 3971690Sdg size_t needed; 3981690Sdg int mib[6]; 3991690Sdg 4001690Sdg if (!VarTerm) 4011690Sdg return 1; 4021690Sdg 4031690Sdg mib[0] = CTL_NET; 4041690Sdg mib[1] = PF_ROUTE; 4052660Sdg mib[2] = 0; 4062660Sdg mib[3] = 0; 4072660Sdg mib[4] = NET_RT_DUMP; 4082660Sdg mib[5] = 0; 4092660Sdg if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 4102660Sdg LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno)); 4111690Sdg return (1); 4121690Sdg } 4131690Sdg if (needed < 0) 4142660Sdg return (1); 4152660Sdg sp = malloc(needed); 4162660Sdg if (sp == NULL) 4172660Sdg return (1); 4182660Sdg if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 4192660Sdg LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno)); 4202660Sdg free(sp); 4212660Sdg return (1); 4222660Sdg } 4232660Sdg ep = sp + needed; 4242660Sdg 4251690Sdg fprintf(VarTerm, "%-20s%-20sFlags Netif\n", "Destination", "Gateway"); 4261690Sdg for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 4271690Sdg rtm = (struct rt_msghdr *) cp; 4281690Sdg wp = (char *)(rtm+1); 4291690Sdg 4301690Sdg if (rtm->rtm_addrs & RTA_DST) { 4311690Sdg sa_dst = (struct sockaddr *)wp; 4321690Sdg wp += sa_dst->sa_len; 4331690Sdg } else 4341690Sdg sa_dst = NULL; 4351690Sdg 4361690Sdg if (rtm->rtm_addrs & RTA_GATEWAY) { 4374Srgrimes sa_gw = (struct sockaddr *)wp; 4381690Sdg wp += sa_gw->sa_len; 4391690Sdg } else 4404Srgrimes sa_gw = NULL; 4411690Sdg 4421690Sdg if (rtm->rtm_addrs & RTA_NETMASK) { 4431690Sdg sa_mask = (struct sockaddr *)wp; 4441690Sdg wp += sa_mask->sa_len; 4451690Sdg } else 4461690Sdg sa_mask = NULL; 4471690Sdg 4481690Sdg p_sockaddr(sa_dst, sa_mask, 20); 4491690Sdg p_sockaddr(sa_gw, NULL, 20); 4501690Sdg 4511690Sdg p_flags(rtm->rtm_flags, 6); 4521690Sdg fprintf(VarTerm, " %s\n", Index2Nam(rtm->rtm_index)); 4531690Sdg } 4541690Sdg free(sp); 4551690Sdg return 0; 4561690Sdg} 4571690Sdg 4581690Sdg/* 4591690Sdg * Delete routes associated with our interface 4601690Sdg */ 4611690Sdgvoid 4621690SdgDeleteIfRoutes(int all) 4631690Sdg{ 4641690Sdg struct rt_msghdr *rtm; 4651690Sdg struct sockaddr *sa; 4661690Sdg struct in_addr sa_dst, sa_none; 4671690Sdg int pass; 4681690Sdg size_t needed; 4691690Sdg char *sp, *cp, *ep; 4701690Sdg int mib[6]; 4711690Sdg 4721690Sdg LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex); 4731690Sdg sa_none.s_addr = INADDR_ANY; 4741690Sdg 4751690Sdg mib[0] = CTL_NET; 4761690Sdg mib[1] = PF_ROUTE; 4771690Sdg mib[2] = 0; 4781690Sdg mib[3] = 0; 4791690Sdg mib[4] = NET_RT_DUMP; 4801690Sdg mib[5] = 0; 4811690Sdg if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 4821690Sdg LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n", 4831690Sdg strerror(errno)); 4841690Sdg return; 4851690Sdg } 4861690Sdg if (needed < 0) 4871690Sdg return; 4881690Sdg 4894Srgrimes sp = malloc(needed); 4904Srgrimes if (sp == NULL) 4911690Sdg return; 4921690Sdg 4931690Sdg if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 4941690Sdg LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n", 4952660Sdg strerror(errno)); 4961690Sdg free(sp); 4971690Sdg return; 4984Srgrimes } 4991690Sdg ep = sp + needed; 5004014Sbde 5014Srgrimes for (pass = 0; pass < 2; pass++) { 5021690Sdg /* 5031690Sdg * We do 2 passes. The first deletes all cloned routes. The second 5041690Sdg * deletes all non-cloned routes. This is necessary to avoid 5051690Sdg * potential errors from trying to delete route X after route Y where 5061690Sdg * route X was cloned from route Y (which is no longer there). 5074Srgrimes */ 5084Srgrimes if (RTF_WASCLONED == 0 && pass == 0) 5091690Sdg /* So we can't tell ! */ 5101690Sdg continue; 5111690Sdg for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 5121690Sdg rtm = (struct rt_msghdr *) cp; 5131690Sdg sa = (struct sockaddr *) (rtm + 1); 5143258Sdg LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s)," 5151690Sdg " flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index, 5161690Sdg Index2Nam(rtm->rtm_index), rtm->rtm_flags, 5171690Sdg inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); 5181690Sdg if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY && 5194014Sbde rtm->rtm_index == IfIndex && 5201690Sdg (all || (rtm->rtm_flags & RTF_GATEWAY))) { 5211690Sdg sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 5221690Sdg sa = (struct sockaddr *)((char *)sa + sa->sa_len); 5231690Sdg if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) { 5241690Sdg if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) || 5251690Sdg (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) { 5261690Sdg LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it (pass %d)\n", pass); 5271690Sdg OsSetRoute(RTM_DELETE, sa_dst, sa_none, sa_none, 0); 5281690Sdg } else 5291690Sdg LogPrintf(LogDEBUG, "DeleteIfRoutes: Skip it (pass %d)\n", pass); 5301690Sdg } else 5311690Sdg LogPrintf(LogDEBUG, 5323258Sdg "DeleteIfRoutes: Can't remove routes of %d family !\n", 5333258Sdg sa->sa_family); 5343258Sdg } 5353258Sdg } 5363258Sdg } 5371690Sdg free(sp); 5382578Sbde} 5391690Sdg 5402578Sbdeint 5411690SdgGetIfIndex(char *name) 5422578Sbde{ 5431690Sdg int idx; 5442578Sbde const char *got; 5451690Sdg 5462578Sbde idx = 1; 5471690Sdg while (strcmp(got = Index2Nam(idx), "???")) 5482578Sbde if (!strcmp(got, name)) 5491690Sdg return IfIndex = idx; 5501690Sdg else 5513436Sphk idx++; 5523436Sphk return -1; 5531690Sdg} 5541690Sdg 5551690Sdgstruct in_addr 5561690SdgChooseHisAddr(const struct in_addr gw) 5571690Sdg{ 5581690Sdg struct in_addr try; 5591690Sdg int f; 5601690Sdg 5611690Sdg for (f = 0; f < DefHisChoice.nItems; f++) { 5621690Sdg try = iplist_next(&DefHisChoice); 5631690Sdg LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 5641690Sdg f, inet_ntoa(try)); 5651690Sdg if (OsTrySetIpaddress(gw, try) == 0) { 5661690Sdg LogPrintf(LogIPCP, "ChooseHisAddr: Selected IP address %s\n", 5671690Sdg inet_ntoa(try)); 5681690Sdg break; 5691690Sdg } 5701690Sdg } 5711690Sdg 5722320Sdg if (f == DefHisChoice.nItems) { 5731690Sdg LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 5741690Sdg try.s_addr = INADDR_ANY; 5751690Sdg } 5761690Sdg 5771690Sdg return try; 5781690Sdg} 5791690Sdg