route.c revision 32663
16059Samurai/* 26059Samurai * PPP Routing related Module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 196059Samurai * 2032663Sbrian * $Id: route.c,v 1.41 1998/01/19 02:59:33 brian Exp $ 218857Srgrimes * 226059Samurai */ 2330715Sbrian 246059Samurai#include <sys/param.h> 2530715Sbrian#include <sys/time.h> 266059Samurai#include <sys/socket.h> 2731176Sbrian#include <net/if_types.h> 2830715Sbrian#include <net/route.h> 2930715Sbrian#include <net/if.h> 3030715Sbrian#include <netinet/in.h> 3130715Sbrian#include <arpa/inet.h> 3231176Sbrian#include <net/if_dl.h> 3320287Swollman 3420287Swollman#include <errno.h> 3530715Sbrian#include <machine/endian.h> 3630715Sbrian#include <stdio.h> 376059Samurai#include <stdlib.h> 386059Samurai#include <string.h> 3930715Sbrian#include <sys/ioctl.h> 4030715Sbrian#include <sys/sysctl.h> 416059Samurai#include <unistd.h> 4220287Swollman 4331343Sbrian#include "command.h" 4430715Sbrian#include "mbuf.h" 459439Samurai#include "log.h" 4626516Sbrian#include "loadalias.h" 4731070Sbrian#include "defs.h" 4826516Sbrian#include "vars.h" 4931061Sbrian#include "id.h" 5031690Sbrian#include "os.h" 5131690Sbrian#include "ipcp.h" 5231690Sbrian#include "iplist.h" 5330715Sbrian#include "route.h" 546059Samurai 556059Samuraistatic int IfIndex; 566059Samurai 576059Samuraistruct rtmsg { 586059Samurai struct rt_msghdr m_rtm; 596059Samurai char m_space[64]; 606059Samurai}; 616059Samurai 626059Samuraistatic int seqno; 636059Samurai 646059Samuraivoid 6528679SbrianOsSetRoute(int cmd, 6628679Sbrian struct in_addr dst, 6728679Sbrian struct in_addr gateway, 6832109Sbrian struct in_addr mask, 6932109Sbrian int bang) 706059Samurai{ 716059Samurai struct rtmsg rtmes; 726059Samurai int s, nb, wb; 7331343Sbrian char *cp; 7431343Sbrian const char *cmdstr; 756059Samurai struct sockaddr_in rtdata; 766059Samurai 7732109Sbrian if (bang) 7832109Sbrian cmdstr = (cmd == RTM_ADD ? "Add!" : "Delete!"); 7932109Sbrian else 8032109Sbrian cmdstr = (cmd == RTM_ADD ? "Add" : "Delete"); 8131061Sbrian s = ID0socket(PF_ROUTE, SOCK_RAW, 0); 8227725Sbrian if (s < 0) { 8328974Sbrian LogPrintf(LogERROR, "OsSetRoute: socket(): %s\n", strerror(errno)); 8427725Sbrian return; 8527725Sbrian } 8631962Sbrian memset(&rtmes, '\0', sizeof rtmes); 876059Samurai rtmes.m_rtm.rtm_version = RTM_VERSION; 886059Samurai rtmes.m_rtm.rtm_type = cmd; 8931598Sbrian rtmes.m_rtm.rtm_addrs = RTA_DST; 906059Samurai rtmes.m_rtm.rtm_seq = ++seqno; 916059Samurai rtmes.m_rtm.rtm_pid = getpid(); 9217571Speter rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 936059Samurai 9431962Sbrian memset(&rtdata, '\0', sizeof rtdata); 956059Samurai rtdata.sin_len = 16; 966059Samurai rtdata.sin_family = AF_INET; 976059Samurai rtdata.sin_port = 0; 986059Samurai rtdata.sin_addr = dst; 996059Samurai 1006059Samurai cp = rtmes.m_space; 10130715Sbrian memcpy(cp, &rtdata, 16); 1026059Samurai cp += 16; 10331598Sbrian if (cmd == RTM_ADD) 10431598Sbrian if (gateway.s_addr == INADDR_ANY) { 10531598Sbrian /* Add a route through the interface */ 10631598Sbrian struct sockaddr_dl dl; 10731598Sbrian const char *iname; 10831598Sbrian int ilen; 10931598Sbrian 11031598Sbrian iname = Index2Nam(IfIndex); 11131598Sbrian ilen = strlen(iname); 11231962Sbrian dl.sdl_len = sizeof dl - sizeof dl.sdl_data + ilen; 11331598Sbrian dl.sdl_family = AF_LINK; 11431598Sbrian dl.sdl_index = IfIndex; 11531598Sbrian dl.sdl_type = 0; 11631598Sbrian dl.sdl_nlen = ilen; 11731598Sbrian dl.sdl_alen = 0; 11831598Sbrian dl.sdl_slen = 0; 11931962Sbrian strncpy(dl.sdl_data, iname, sizeof dl.sdl_data); 12031598Sbrian 12131598Sbrian memcpy(cp, &dl, dl.sdl_len); 12231598Sbrian cp += dl.sdl_len; 12331598Sbrian rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 12431598Sbrian } else { 12531598Sbrian rtdata.sin_addr = gateway; 12631598Sbrian memcpy(cp, &rtdata, 16); 12731598Sbrian cp += 16; 12831598Sbrian rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 12931598Sbrian } 13031598Sbrian 13131598Sbrian if (dst.s_addr == INADDR_ANY) 13231598Sbrian mask.s_addr = INADDR_ANY; 13331598Sbrian 13431598Sbrian if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) { 13531598Sbrian rtdata.sin_addr = mask; 13630715Sbrian memcpy(cp, &rtdata, 16); 1376059Samurai cp += 16; 13831598Sbrian rtmes.m_rtm.rtm_addrs |= RTA_NETMASK; 1396059Samurai } 1406059Samurai 14128679Sbrian nb = cp - (char *) &rtmes; 1426059Samurai rtmes.m_rtm.rtm_msglen = nb; 14332025Sbrian wb = ID0write(s, &rtmes, nb); 1446059Samurai if (wb < 0) { 14531739Sbrian LogPrintf(LogTCPIP, "OsSetRoute failure:\n"); 14631739Sbrian LogPrintf(LogTCPIP, "OsSetRoute: Cmd = %s\n", cmd); 14731739Sbrian LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst)); 14826591Sbrian LogPrintf(LogTCPIP, "OsSetRoute: Gateway = %s\n", inet_ntoa(gateway)); 14926591Sbrian LogPrintf(LogTCPIP, "OsSetRoute: Mask = %s\n", inet_ntoa(mask)); 15032109Sbrianfailed: 15132109Sbrian if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST || 15232109Sbrian (rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) 15332109Sbrian if (!bang) 15432109Sbrian LogPrintf(LogWARN, "Add route failed: %s already exists\n", 15532109Sbrian inet_ntoa(dst)); 15632109Sbrian else { 15732109Sbrian rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE; 15832109Sbrian if ((wb = ID0write(s, &rtmes, nb)) < 0) 15932109Sbrian goto failed; 16032109Sbrian } 16132109Sbrian else if (cmd == RTM_DELETE && 16232109Sbrian (rtmes.m_rtm.rtm_errno == ESRCH || 16332109Sbrian (rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) { 16432109Sbrian if (!bang) 16532109Sbrian LogPrintf(LogWARN, "Del route failed: %s: Non-existent\n", 16632109Sbrian inet_ntoa(dst)); 16732109Sbrian } else if (rtmes.m_rtm.rtm_errno == 0) 16831739Sbrian LogPrintf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr, 16931739Sbrian inet_ntoa(dst), strerror(errno)); 17032109Sbrian else 17131739Sbrian LogPrintf(LogWARN, "%s route failed: %s: %s\n", 17231739Sbrian cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno)); 1736059Samurai } 17431061Sbrian LogPrintf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n", 17531061Sbrian wb, cmdstr, dst.s_addr, gateway.s_addr); 1766059Samurai close(s); 1776059Samurai} 1786059Samurai 1796059Samuraistatic void 18031176Sbrianp_sockaddr(struct sockaddr *phost, struct sockaddr *pmask, int width) 1816059Samurai{ 18231343Sbrian char buf[29]; 18331176Sbrian struct sockaddr_in *ihost = (struct sockaddr_in *)phost; 18431176Sbrian struct sockaddr_in *mask = (struct sockaddr_in *)pmask; 18531176Sbrian struct sockaddr_dl *dl = (struct sockaddr_dl *)phost; 1866059Samurai 18731176Sbrian switch (phost->sa_family) { 18831176Sbrian case AF_INET: 18931176Sbrian if (!phost) 19031541Sbrian buf[0] = '\0'; 19131176Sbrian else if (ihost->sin_addr.s_addr == INADDR_ANY) 19231541Sbrian strcpy(buf, "default"); 19331176Sbrian else if (!mask) 19431541Sbrian strcpy(buf, inet_ntoa(ihost->sin_addr)); 19531176Sbrian else { 19631176Sbrian u_int msk = ntohl(mask->sin_addr.s_addr); 19731176Sbrian u_int tst; 19831176Sbrian int bits; 19931176Sbrian int len; 20031176Sbrian struct sockaddr_in net; 20131176Sbrian 20231176Sbrian for (tst = 1, bits=32; tst; tst <<= 1, bits--) 20331176Sbrian if (msk & tst) 20431176Sbrian break; 20531176Sbrian 20631176Sbrian for (tst <<=1; tst; tst <<= 1) 20731176Sbrian if (!(msk & tst)) 20831176Sbrian break; 20931176Sbrian 21031176Sbrian net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr; 21131791Sbrian strcpy(buf, inet_ntoa(net.sin_addr)); 21231176Sbrian for (len = strlen(buf); len > 3; buf[len-=2] = '\0') 21331176Sbrian if (strcmp(buf+len-2, ".0")) 21431176Sbrian break; 21531176Sbrian 21631176Sbrian if (tst) /* non-contiguous :-( */ 21731176Sbrian sprintf(buf+strlen(buf),"&0x%08x", msk); 21831176Sbrian else 21931176Sbrian sprintf(buf+strlen(buf), "/%d", bits); 22031176Sbrian } 22131176Sbrian break; 22231176Sbrian 22331176Sbrian case AF_LINK: 22431541Sbrian if (dl->sdl_nlen) 22531541Sbrian snprintf(buf, sizeof buf, "%.*s", dl->sdl_nlen, dl->sdl_data); 22631541Sbrian else if (dl->sdl_alen) 22731541Sbrian if (dl->sdl_type == IFT_ETHER) 22831962Sbrian if (dl->sdl_alen < sizeof buf / 3) { 22931541Sbrian int f; 23031541Sbrian u_char *MAC; 23131541Sbrian 23231541Sbrian MAC = (u_char *)dl->sdl_data + dl->sdl_nlen; 23331541Sbrian for (f = 0; f < dl->sdl_alen; f++) 23431541Sbrian sprintf(buf+f*3, "%02x:", MAC[f]); 23531541Sbrian buf[f*3-1] = '\0'; 23631541Sbrian } else 23731791Sbrian strcpy(buf, "??:??:??:??:??:??"); 23831541Sbrian else 23931541Sbrian sprintf(buf, "<IFT type %d>", dl->sdl_type); 24031541Sbrian else if (dl->sdl_slen) 24131541Sbrian sprintf(buf, "<slen %d?>", dl->sdl_slen); 24231541Sbrian else 24331176Sbrian sprintf(buf, "link#%d", dl->sdl_index); 24431176Sbrian break; 24531176Sbrian 24631176Sbrian default: 24731541Sbrian sprintf(buf, "<AF type %d>", phost->sa_family); 24831176Sbrian break; 24926516Sbrian } 25031176Sbrian 25131541Sbrian fprintf(VarTerm, "%-*s ", width-1, buf); 2526059Samurai} 2536059Samurai 25432663Sbrianstatic struct bits { 25531176Sbrian u_long b_mask; 25628679Sbrian char b_val; 25731176Sbrian} bits[] = { 25831176Sbrian { RTF_UP, 'U' }, 25931176Sbrian { RTF_GATEWAY, 'G' }, 26031176Sbrian { RTF_HOST, 'H' }, 26131176Sbrian { RTF_REJECT, 'R' }, 26231176Sbrian { RTF_DYNAMIC, 'D' }, 26331176Sbrian { RTF_MODIFIED, 'M' }, 26431176Sbrian { RTF_DONE, 'd' }, 26531176Sbrian { RTF_CLONING, 'C' }, 26631176Sbrian { RTF_XRESOLVE, 'X' }, 26731176Sbrian { RTF_LLINFO, 'L' }, 26831176Sbrian { RTF_STATIC, 'S' }, 26931176Sbrian { RTF_PROTO1, '1' }, 27031176Sbrian { RTF_PROTO2, '2' }, 27131176Sbrian { RTF_BLACKHOLE, 'B' }, 27231739Sbrian#ifdef RTF_WASCLONED 27331176Sbrian { RTF_WASCLONED, 'W' }, 27431739Sbrian#endif 27531739Sbrian#ifdef RTF_PRCLONING 27631176Sbrian { RTF_PRCLONING, 'c' }, 27731739Sbrian#endif 27831739Sbrian#ifdef RTF_PROTO3 27931176Sbrian { RTF_PROTO3, '3' }, 28031739Sbrian#endif 28131739Sbrian#ifdef RTF_BROADCAST 28231176Sbrian { RTF_BROADCAST, 'b' }, 28331176Sbrian#endif 28431176Sbrian { 0, '\0' } 2856059Samurai}; 2866059Samurai 28731739Sbrian#ifndef RTF_WASCLONED 28831739Sbrian#define RTF_WASCLONED (0) 28931739Sbrian#endif 29031739Sbrian 2916059Samuraistatic void 29231827Sbrianp_flags(u_long f, int max) 2936059Samurai{ 29426516Sbrian if (VarTerm) { 29526516Sbrian char name[33], *flags; 29626516Sbrian register struct bits *p = bits; 2976059Samurai 29831962Sbrian if (max > sizeof name - 1) 29931962Sbrian max = sizeof name - 1; 30031827Sbrian 30131827Sbrian for (flags = name; p->b_mask && flags - name < max; p++) 30226516Sbrian if (p->b_mask & f) 30328679Sbrian *flags++ = p->b_val; 30426516Sbrian *flags = '\0'; 30531827Sbrian fprintf(VarTerm, "%-*.*s", max, max, name); 30626516Sbrian } 3076059Samurai} 3086059Samurai 30932616Sbrianconst char * 31031176SbrianIndex2Nam(int idx) 31131176Sbrian{ 31232425Sbrian static char **ifs; 31331354Sbrian static int nifs, debug_done; 31431176Sbrian 31531176Sbrian if (!nifs) { 31632425Sbrian int mib[6], have, had; 31732021Sbrian size_t needed; 31831176Sbrian char *buf, *ptr, *end; 31931176Sbrian struct sockaddr_dl *dl; 32031176Sbrian struct if_msghdr *ifm; 32131176Sbrian 32231176Sbrian mib[0] = CTL_NET; 32331176Sbrian mib[1] = PF_ROUTE; 32431176Sbrian mib[2] = 0; 32531176Sbrian mib[3] = 0; 32631176Sbrian mib[4] = NET_RT_IFLIST; 32731176Sbrian mib[5] = 0; 32831176Sbrian 32931176Sbrian if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 33031176Sbrian LogPrintf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno)); 33131176Sbrian return "???"; 33231176Sbrian } 33331176Sbrian if ((buf = malloc(needed)) == NULL) 33431176Sbrian return "???"; 33531176Sbrian if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 33631176Sbrian free(buf); 33731176Sbrian return "???"; 33831176Sbrian } 33931176Sbrian end = buf + needed; 34031176Sbrian 34132425Sbrian have = 0; 34231354Sbrian for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) { 34331176Sbrian ifm = (struct if_msghdr *)ptr; 34431176Sbrian dl = (struct sockaddr_dl *)(ifm + 1); 34532425Sbrian if (ifm->ifm_index > 0) { 34632425Sbrian if (ifm->ifm_index > have) { 34732425Sbrian had = have; 34832425Sbrian have = ifm->ifm_index + 5; 34932425Sbrian if (had) 35032425Sbrian ifs = (char **)realloc(ifs, sizeof(char *) * have); 35132425Sbrian else 35232425Sbrian ifs = (char **)malloc(sizeof(char *) * have); 35332425Sbrian if (!ifs) { 35432425Sbrian LogPrintf(LogDEBUG, "Index2Nam: %s\n", strerror(errno)); 35532425Sbrian nifs = 0; 35632425Sbrian return "???"; 35732425Sbrian } 35832425Sbrian memset(ifs + had, '\0', sizeof(char *) * (have - had)); 35932425Sbrian } 36032425Sbrian if (ifs[ifm->ifm_index-1] == NULL) { 36132425Sbrian ifs[ifm->ifm_index-1] = (char *)malloc(dl->sdl_nlen+1); 36232425Sbrian memcpy(ifs[ifm->ifm_index-1], dl->sdl_data, dl->sdl_nlen); 36332425Sbrian ifs[ifm->ifm_index-1][dl->sdl_nlen] = '\0'; 36432425Sbrian if (nifs < ifm->ifm_index) 36532425Sbrian nifs = ifm->ifm_index; 36632425Sbrian } 36731354Sbrian } else if (LogIsKept(LogDEBUG)) 36831354Sbrian LogPrintf(LogDEBUG, "Skipping out-of-range interface %d!\n", 36931354Sbrian ifm->ifm_index); 37031176Sbrian } 37131176Sbrian free(buf); 37231176Sbrian } 37331176Sbrian 37431354Sbrian if (LogIsKept(LogDEBUG) && !debug_done) { 37531354Sbrian int f; 37631354Sbrian 37731354Sbrian LogPrintf(LogDEBUG, "Found the following interfaces:\n"); 37831354Sbrian for (f = 0; f < nifs; f++) 37932425Sbrian if (ifs[f] != NULL) 38031354Sbrian LogPrintf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]); 38131354Sbrian debug_done = 1; 38231354Sbrian } 38331354Sbrian 38432425Sbrian if (idx < 1 || idx > nifs || ifs[idx-1] == NULL) 38531176Sbrian return "???"; 38631354Sbrian 38731354Sbrian return ifs[idx-1]; 38831176Sbrian} 38931176Sbrian 3906059Samuraiint 39131343SbrianShowRoute(struct cmdargs const *arg) 3926059Samurai{ 3936059Samurai struct rt_msghdr *rtm; 39431176Sbrian struct sockaddr *sa_dst, *sa_gw, *sa_mask; 39531176Sbrian char *sp, *ep, *cp, *wp; 39632021Sbrian size_t needed; 3976735Samurai int mib[6]; 3986059Samurai 39926516Sbrian if (!VarTerm) 40026516Sbrian return 1; 40126516Sbrian 4026059Samurai mib[0] = CTL_NET; 4036059Samurai mib[1] = PF_ROUTE; 4046735Samurai mib[2] = 0; 4056735Samurai mib[3] = 0; 4066059Samurai mib[4] = NET_RT_DUMP; 4076735Samurai mib[5] = 0; 4086735Samurai if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 40928974Sbrian LogPrintf(LogERROR, "ShowRoute: sysctl: estimate: %s\n", strerror(errno)); 41028679Sbrian return (1); 4116735Samurai } 4126059Samurai if (needed < 0) 41328679Sbrian return (1); 4146059Samurai sp = malloc(needed); 4156059Samurai if (sp == NULL) 41628679Sbrian return (1); 4176735Samurai if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 41828974Sbrian LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno)); 41918885Sjkh free(sp); 42028679Sbrian return (1); 4216735Samurai } 4226059Samurai ep = sp + needed; 4236059Samurai 42431176Sbrian fprintf(VarTerm, "%-20s%-20sFlags Netif\n", "Destination", "Gateway"); 4256059Samurai for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 42628679Sbrian rtm = (struct rt_msghdr *) cp; 42731176Sbrian wp = (char *)(rtm+1); 42831176Sbrian 42931176Sbrian if (rtm->rtm_addrs & RTA_DST) { 43031176Sbrian sa_dst = (struct sockaddr *)wp; 43131176Sbrian wp += sa_dst->sa_len; 43231176Sbrian } else 43331176Sbrian sa_dst = NULL; 43431176Sbrian 43531176Sbrian if (rtm->rtm_addrs & RTA_GATEWAY) { 43631176Sbrian sa_gw = (struct sockaddr *)wp; 43731176Sbrian wp += sa_gw->sa_len; 43831176Sbrian } else 43931176Sbrian sa_gw = NULL; 44031176Sbrian 44131176Sbrian if (rtm->rtm_addrs & RTA_NETMASK) { 44231176Sbrian sa_mask = (struct sockaddr *)wp; 44331176Sbrian wp += sa_mask->sa_len; 44431176Sbrian } else 44531176Sbrian sa_mask = NULL; 44631176Sbrian 44731176Sbrian p_sockaddr(sa_dst, sa_mask, 20); 44831176Sbrian p_sockaddr(sa_gw, NULL, 20); 44931176Sbrian 45031827Sbrian p_flags(rtm->rtm_flags, 6); 45131827Sbrian fprintf(VarTerm, " %s\n", Index2Nam(rtm->rtm_index)); 4526059Samurai } 45318885Sjkh free(sp); 45426516Sbrian return 0; 4556059Samurai} 4566059Samurai 4576059Samurai/* 4586059Samurai * Delete routes associated with our interface 4596059Samurai */ 4606059Samuraivoid 46128679SbrianDeleteIfRoutes(int all) 4626059Samurai{ 4636059Samurai struct rt_msghdr *rtm; 4646059Samurai struct sockaddr *sa; 46531598Sbrian struct in_addr sa_dst, sa_none; 46632021Sbrian int pass; 46732021Sbrian size_t needed; 4686059Samurai char *sp, *cp, *ep; 4696735Samurai int mib[6]; 4706059Samurai 47126516Sbrian LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex); 47231598Sbrian sa_none.s_addr = INADDR_ANY; 47326516Sbrian 4746059Samurai mib[0] = CTL_NET; 4756059Samurai mib[1] = PF_ROUTE; 4766735Samurai mib[2] = 0; 4776735Samurai mib[3] = 0; 4786059Samurai mib[4] = NET_RT_DUMP; 4796735Samurai mib[5] = 0; 4806735Samurai if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 48128974Sbrian LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: estimate: %s\n", 48228974Sbrian strerror(errno)); 4836735Samurai return; 4846735Samurai } 4856059Samurai if (needed < 0) 4866059Samurai return; 4876059Samurai 4886059Samurai sp = malloc(needed); 4896059Samurai if (sp == NULL) 4906059Samurai return; 4916059Samurai 4926735Samurai if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 49328974Sbrian LogPrintf(LogERROR, "DeleteIfRoutes: sysctl: getroute: %s\n", 49428974Sbrian strerror(errno)); 4956059Samurai free(sp); 4966059Samurai return; 4976059Samurai } 4986059Samurai ep = sp + needed; 4996059Samurai 50031739Sbrian for (pass = 0; pass < 2; pass++) { 50131739Sbrian /* 50231739Sbrian * We do 2 passes. The first deletes all cloned routes. The second 50331739Sbrian * deletes all non-cloned routes. This is necessary to avoid 50431739Sbrian * potential errors from trying to delete route X after route Y where 50531739Sbrian * route X was cloned from route Y (which is no longer there). 50631739Sbrian */ 50731739Sbrian if (RTF_WASCLONED == 0 && pass == 0) 50831739Sbrian /* So we can't tell ! */ 50931739Sbrian continue; 51031739Sbrian for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 51131739Sbrian rtm = (struct rt_msghdr *) cp; 51231739Sbrian sa = (struct sockaddr *) (rtm + 1); 51331739Sbrian LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, Netif: %d (%s)," 51431739Sbrian " flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index, 51531739Sbrian Index2Nam(rtm->rtm_index), rtm->rtm_flags, 51631739Sbrian inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); 51731739Sbrian if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY && 51831739Sbrian rtm->rtm_index == IfIndex && 51931739Sbrian (all || (rtm->rtm_flags & RTF_GATEWAY))) { 52031739Sbrian sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 52131739Sbrian sa = (struct sockaddr *)((char *)sa + sa->sa_len); 52231739Sbrian if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) { 52331739Sbrian if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) || 52431739Sbrian (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) { 52531739Sbrian LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it (pass %d)\n", pass); 52632109Sbrian OsSetRoute(RTM_DELETE, sa_dst, sa_none, sa_none, 0); 52731739Sbrian } else 52831739Sbrian LogPrintf(LogDEBUG, "DeleteIfRoutes: Skip it (pass %d)\n", pass); 52931739Sbrian } else 53031739Sbrian LogPrintf(LogDEBUG, 53131739Sbrian "DeleteIfRoutes: Can't remove routes of %d family !\n", 53231739Sbrian sa->sa_family); 53331739Sbrian } 5346059Samurai } 5356059Samurai } 5366059Samurai free(sp); 5376059Samurai} 5386059Samurai 5396059Samuraiint 54028679SbrianGetIfIndex(char *name) 5416059Samurai{ 54231176Sbrian int idx; 54331343Sbrian const char *got; 54428679Sbrian 54531354Sbrian idx = 1; 54631176Sbrian while (strcmp(got = Index2Nam(idx), "???")) 54731176Sbrian if (!strcmp(got, name)) 54831176Sbrian return IfIndex = idx; 54931176Sbrian else 55031176Sbrian idx++; 55131176Sbrian return -1; 5526059Samurai} 55331690Sbrian 55431690Sbrianstruct in_addr 55531690SbrianChooseHisAddr(const struct in_addr gw) 55631690Sbrian{ 55731690Sbrian struct in_addr try; 55831690Sbrian int f; 55931690Sbrian 56031690Sbrian for (f = 0; f < DefHisChoice.nItems; f++) { 56131690Sbrian try = iplist_next(&DefHisChoice); 56231690Sbrian LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 56331690Sbrian f, inet_ntoa(try)); 56431690Sbrian if (OsTrySetIpaddress(gw, try) == 0) { 56531690Sbrian LogPrintf(LogIPCP, "ChooseHisAddr: Selected IP address %s\n", 56631690Sbrian inet_ntoa(try)); 56731690Sbrian break; 56831690Sbrian } 56931690Sbrian } 57031690Sbrian 57131690Sbrian if (f == DefHisChoice.nItems) { 57231690Sbrian LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 57331690Sbrian try.s_addr = INADDR_ANY; 57431690Sbrian } 57531690Sbrian 57631690Sbrian return try; 57731690Sbrian} 578