11ae349f5Scvs2svn /* 21ae349f5Scvs2svn * PPP Routing related Module 31ae349f5Scvs2svn * 41ae349f5Scvs2svn * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 51ae349f5Scvs2svn * 61ae349f5Scvs2svn * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 71ae349f5Scvs2svn * 81ae349f5Scvs2svn * Redistribution and use in source and binary forms are permitted 91ae349f5Scvs2svn * provided that the above copyright notice and this paragraph are 101ae349f5Scvs2svn * duplicated in all such forms and that any documentation, 111ae349f5Scvs2svn * advertising materials, and other materials related to such 121ae349f5Scvs2svn * distribution and use acknowledge that the software was developed 131ae349f5Scvs2svn * by the Internet Initiative Japan, Inc. The name of the 141ae349f5Scvs2svn * IIJ may not be used to endorse or promote products derived 151ae349f5Scvs2svn * from this software without specific prior written permission. 161ae349f5Scvs2svn * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 171ae349f5Scvs2svn * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 181ae349f5Scvs2svn * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 191ae349f5Scvs2svn * 20183df580SBrian Somers * $Id: route.c,v 1.42.2.22 1998/05/05 23:30:12 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn */ 231ae349f5Scvs2svn 242764b86aSBrian Somers #include <sys/types.h> 251ae349f5Scvs2svn #include <sys/socket.h> 261ae349f5Scvs2svn #include <net/if_types.h> 271ae349f5Scvs2svn #include <net/route.h> 281ae349f5Scvs2svn #include <net/if.h> 291ae349f5Scvs2svn #include <netinet/in.h> 301ae349f5Scvs2svn #include <arpa/inet.h> 311ae349f5Scvs2svn #include <net/if_dl.h> 32eaa4df37SBrian Somers #include <netinet/in_systm.h> 33eaa4df37SBrian Somers #include <netinet/ip.h> 341fa665f5SBrian Somers #include <sys/un.h> 351ae349f5Scvs2svn 361ae349f5Scvs2svn #include <errno.h> 371ae349f5Scvs2svn #include <stdio.h> 381ae349f5Scvs2svn #include <stdlib.h> 391ae349f5Scvs2svn #include <string.h> 401ae349f5Scvs2svn #include <sys/sysctl.h> 4185b542cfSBrian Somers #include <termios.h> 421ae349f5Scvs2svn 431ae349f5Scvs2svn #include "command.h" 441ae349f5Scvs2svn #include "mbuf.h" 451ae349f5Scvs2svn #include "log.h" 461ae349f5Scvs2svn #include "defs.h" 471ae349f5Scvs2svn #include "iplist.h" 4829e275ceSBrian Somers #include "timer.h" 4929e275ceSBrian Somers #include "throughput.h" 50879ed6faSBrian Somers #include "lqr.h" 518c07a7b2SBrian Somers #include "hdlc.h" 527308ec68SBrian Somers #include "fsm.h" 533b0f8d2eSBrian Somers #include "lcp.h" 543b0f8d2eSBrian Somers #include "ccp.h" 553b0f8d2eSBrian Somers #include "link.h" 56eaa4df37SBrian Somers #include "slcompress.h" 5729e275ceSBrian Somers #include "ipcp.h" 585ca5389aSBrian Somers #include "filter.h" 592f786681SBrian Somers #include "descriptor.h" 603b0f8d2eSBrian Somers #include "mp.h" 615828db6dSBrian Somers #include "bundle.h" 621ae349f5Scvs2svn #include "route.h" 6385b542cfSBrian Somers #include "prompt.h" 641ae349f5Scvs2svn 651ae349f5Scvs2svn static void 66b6217683SBrian Somers p_sockaddr(struct prompt *prompt, struct sockaddr *phost, 67b6217683SBrian Somers struct sockaddr *pmask, int width) 681ae349f5Scvs2svn { 691ae349f5Scvs2svn char buf[29]; 701ae349f5Scvs2svn struct sockaddr_in *ihost = (struct sockaddr_in *)phost; 711ae349f5Scvs2svn struct sockaddr_in *mask = (struct sockaddr_in *)pmask; 721ae349f5Scvs2svn struct sockaddr_dl *dl = (struct sockaddr_dl *)phost; 731ae349f5Scvs2svn 741ae349f5Scvs2svn switch (phost->sa_family) { 751ae349f5Scvs2svn case AF_INET: 761ae349f5Scvs2svn if (!phost) 771ae349f5Scvs2svn buf[0] = '\0'; 781ae349f5Scvs2svn else if (ihost->sin_addr.s_addr == INADDR_ANY) 791ae349f5Scvs2svn strcpy(buf, "default"); 801ae349f5Scvs2svn else if (!mask) 811ae349f5Scvs2svn strcpy(buf, inet_ntoa(ihost->sin_addr)); 821ae349f5Scvs2svn else { 831ae349f5Scvs2svn u_int msk = ntohl(mask->sin_addr.s_addr); 841ae349f5Scvs2svn u_int tst; 851ae349f5Scvs2svn int bits; 861ae349f5Scvs2svn int len; 871ae349f5Scvs2svn struct sockaddr_in net; 881ae349f5Scvs2svn 891ae349f5Scvs2svn for (tst = 1, bits=32; tst; tst <<= 1, bits--) 901ae349f5Scvs2svn if (msk & tst) 911ae349f5Scvs2svn break; 921ae349f5Scvs2svn 931ae349f5Scvs2svn for (tst <<=1; tst; tst <<= 1) 941ae349f5Scvs2svn if (!(msk & tst)) 951ae349f5Scvs2svn break; 961ae349f5Scvs2svn 971ae349f5Scvs2svn net.sin_addr.s_addr = ihost->sin_addr.s_addr & mask->sin_addr.s_addr; 981ae349f5Scvs2svn strcpy(buf, inet_ntoa(net.sin_addr)); 991ae349f5Scvs2svn for (len = strlen(buf); len > 3; buf[len-=2] = '\0') 1001ae349f5Scvs2svn if (strcmp(buf+len-2, ".0")) 1011ae349f5Scvs2svn break; 1021ae349f5Scvs2svn 1031ae349f5Scvs2svn if (tst) /* non-contiguous :-( */ 1041ae349f5Scvs2svn sprintf(buf+strlen(buf),"&0x%08x", msk); 1051ae349f5Scvs2svn else 1061ae349f5Scvs2svn sprintf(buf+strlen(buf), "/%d", bits); 1071ae349f5Scvs2svn } 1081ae349f5Scvs2svn break; 1091ae349f5Scvs2svn 1101ae349f5Scvs2svn case AF_LINK: 1111ae349f5Scvs2svn if (dl->sdl_nlen) 1121ae349f5Scvs2svn snprintf(buf, sizeof buf, "%.*s", dl->sdl_nlen, dl->sdl_data); 113e43ebac1SBrian Somers else if (dl->sdl_alen) { 114e43ebac1SBrian Somers if (dl->sdl_type == IFT_ETHER) { 1151ae349f5Scvs2svn if (dl->sdl_alen < sizeof buf / 3) { 1161ae349f5Scvs2svn int f; 1171ae349f5Scvs2svn u_char *MAC; 1181ae349f5Scvs2svn 1191ae349f5Scvs2svn MAC = (u_char *)dl->sdl_data + dl->sdl_nlen; 1201ae349f5Scvs2svn for (f = 0; f < dl->sdl_alen; f++) 1211ae349f5Scvs2svn sprintf(buf+f*3, "%02x:", MAC[f]); 1221ae349f5Scvs2svn buf[f*3-1] = '\0'; 1231ae349f5Scvs2svn } else 1241ae349f5Scvs2svn strcpy(buf, "??:??:??:??:??:??"); 125e43ebac1SBrian Somers } else 1261ae349f5Scvs2svn sprintf(buf, "<IFT type %d>", dl->sdl_type); 127e43ebac1SBrian Somers } else if (dl->sdl_slen) 1281ae349f5Scvs2svn sprintf(buf, "<slen %d?>", dl->sdl_slen); 1291ae349f5Scvs2svn else 1301ae349f5Scvs2svn sprintf(buf, "link#%d", dl->sdl_index); 1311ae349f5Scvs2svn break; 1321ae349f5Scvs2svn 1331ae349f5Scvs2svn default: 1341ae349f5Scvs2svn sprintf(buf, "<AF type %d>", phost->sa_family); 1351ae349f5Scvs2svn break; 1361ae349f5Scvs2svn } 1371ae349f5Scvs2svn 138b6217683SBrian Somers prompt_Printf(prompt, "%-*s ", width-1, buf); 1391ae349f5Scvs2svn } 1401ae349f5Scvs2svn 1411ae349f5Scvs2svn static struct bits { 1421ae349f5Scvs2svn u_long b_mask; 1431ae349f5Scvs2svn char b_val; 1441ae349f5Scvs2svn } bits[] = { 1451ae349f5Scvs2svn { RTF_UP, 'U' }, 1461ae349f5Scvs2svn { RTF_GATEWAY, 'G' }, 1471ae349f5Scvs2svn { RTF_HOST, 'H' }, 1481ae349f5Scvs2svn { RTF_REJECT, 'R' }, 1491ae349f5Scvs2svn { RTF_DYNAMIC, 'D' }, 1501ae349f5Scvs2svn { RTF_MODIFIED, 'M' }, 1511ae349f5Scvs2svn { RTF_DONE, 'd' }, 1521ae349f5Scvs2svn { RTF_CLONING, 'C' }, 1531ae349f5Scvs2svn { RTF_XRESOLVE, 'X' }, 1541ae349f5Scvs2svn { RTF_LLINFO, 'L' }, 1551ae349f5Scvs2svn { RTF_STATIC, 'S' }, 1561ae349f5Scvs2svn { RTF_PROTO1, '1' }, 1571ae349f5Scvs2svn { RTF_PROTO2, '2' }, 1581ae349f5Scvs2svn { RTF_BLACKHOLE, 'B' }, 1591ae349f5Scvs2svn #ifdef RTF_WASCLONED 1601ae349f5Scvs2svn { RTF_WASCLONED, 'W' }, 1611ae349f5Scvs2svn #endif 1621ae349f5Scvs2svn #ifdef RTF_PRCLONING 1631ae349f5Scvs2svn { RTF_PRCLONING, 'c' }, 1641ae349f5Scvs2svn #endif 1651ae349f5Scvs2svn #ifdef RTF_PROTO3 1661ae349f5Scvs2svn { RTF_PROTO3, '3' }, 1671ae349f5Scvs2svn #endif 1681ae349f5Scvs2svn #ifdef RTF_BROADCAST 1691ae349f5Scvs2svn { RTF_BROADCAST, 'b' }, 1701ae349f5Scvs2svn #endif 1711ae349f5Scvs2svn { 0, '\0' } 1721ae349f5Scvs2svn }; 1731ae349f5Scvs2svn 1741ae349f5Scvs2svn #ifndef RTF_WASCLONED 1751ae349f5Scvs2svn #define RTF_WASCLONED (0) 1761ae349f5Scvs2svn #endif 1771ae349f5Scvs2svn 1781ae349f5Scvs2svn static void 179b6217683SBrian Somers p_flags(struct prompt *prompt, u_long f, int max) 1801ae349f5Scvs2svn { 1811ae349f5Scvs2svn char name[33], *flags; 1821ae349f5Scvs2svn register struct bits *p = bits; 1831ae349f5Scvs2svn 1841ae349f5Scvs2svn if (max > sizeof name - 1) 1851ae349f5Scvs2svn max = sizeof name - 1; 1861ae349f5Scvs2svn 1871ae349f5Scvs2svn for (flags = name; p->b_mask && flags - name < max; p++) 1881ae349f5Scvs2svn if (p->b_mask & f) 1891ae349f5Scvs2svn *flags++ = p->b_val; 1901ae349f5Scvs2svn *flags = '\0'; 191b6217683SBrian Somers prompt_Printf(prompt, "%-*.*s", max, max, name); 1921ae349f5Scvs2svn } 1931ae349f5Scvs2svn 1941ae349f5Scvs2svn const char * 1951ae349f5Scvs2svn Index2Nam(int idx) 1961ae349f5Scvs2svn { 1971ae349f5Scvs2svn static char **ifs; 1981ae349f5Scvs2svn static int nifs, debug_done; 1991ae349f5Scvs2svn 2001ae349f5Scvs2svn if (!nifs) { 2011ae349f5Scvs2svn int mib[6], have, had; 2021ae349f5Scvs2svn size_t needed; 2031ae349f5Scvs2svn char *buf, *ptr, *end; 2041ae349f5Scvs2svn struct sockaddr_dl *dl; 2051ae349f5Scvs2svn struct if_msghdr *ifm; 2061ae349f5Scvs2svn 2071ae349f5Scvs2svn mib[0] = CTL_NET; 2081ae349f5Scvs2svn mib[1] = PF_ROUTE; 2091ae349f5Scvs2svn mib[2] = 0; 2101ae349f5Scvs2svn mib[3] = 0; 2111ae349f5Scvs2svn mib[4] = NET_RT_IFLIST; 2121ae349f5Scvs2svn mib[5] = 0; 2131ae349f5Scvs2svn 2141ae349f5Scvs2svn if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 215dd7e2610SBrian Somers log_Printf(LogERROR, "Index2Nam: sysctl: estimate: %s\n", strerror(errno)); 2161ae349f5Scvs2svn return "???"; 2171ae349f5Scvs2svn } 2181ae349f5Scvs2svn if ((buf = malloc(needed)) == NULL) 2191ae349f5Scvs2svn return "???"; 2201ae349f5Scvs2svn if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 2211ae349f5Scvs2svn free(buf); 2221ae349f5Scvs2svn return "???"; 2231ae349f5Scvs2svn } 2241ae349f5Scvs2svn end = buf + needed; 2251ae349f5Scvs2svn 2261ae349f5Scvs2svn have = 0; 2271ae349f5Scvs2svn for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) { 2281ae349f5Scvs2svn ifm = (struct if_msghdr *)ptr; 2291ae349f5Scvs2svn dl = (struct sockaddr_dl *)(ifm + 1); 2301ae349f5Scvs2svn if (ifm->ifm_index > 0) { 2311ae349f5Scvs2svn if (ifm->ifm_index > have) { 2321ae349f5Scvs2svn had = have; 2331ae349f5Scvs2svn have = ifm->ifm_index + 5; 2341ae349f5Scvs2svn if (had) 2351ae349f5Scvs2svn ifs = (char **)realloc(ifs, sizeof(char *) * have); 2361ae349f5Scvs2svn else 2371ae349f5Scvs2svn ifs = (char **)malloc(sizeof(char *) * have); 2381ae349f5Scvs2svn if (!ifs) { 239dd7e2610SBrian Somers log_Printf(LogDEBUG, "Index2Nam: %s\n", strerror(errno)); 2401ae349f5Scvs2svn nifs = 0; 2411ae349f5Scvs2svn return "???"; 2421ae349f5Scvs2svn } 2431ae349f5Scvs2svn memset(ifs + had, '\0', sizeof(char *) * (have - had)); 2441ae349f5Scvs2svn } 2451ae349f5Scvs2svn if (ifs[ifm->ifm_index-1] == NULL) { 2461ae349f5Scvs2svn ifs[ifm->ifm_index-1] = (char *)malloc(dl->sdl_nlen+1); 2471ae349f5Scvs2svn memcpy(ifs[ifm->ifm_index-1], dl->sdl_data, dl->sdl_nlen); 2481ae349f5Scvs2svn ifs[ifm->ifm_index-1][dl->sdl_nlen] = '\0'; 2491ae349f5Scvs2svn if (nifs < ifm->ifm_index) 2501ae349f5Scvs2svn nifs = ifm->ifm_index; 2511ae349f5Scvs2svn } 252dd7e2610SBrian Somers } else if (log_IsKept(LogDEBUG)) 253dd7e2610SBrian Somers log_Printf(LogDEBUG, "Skipping out-of-range interface %d!\n", 2541ae349f5Scvs2svn ifm->ifm_index); 2551ae349f5Scvs2svn } 2561ae349f5Scvs2svn free(buf); 2571ae349f5Scvs2svn } 2581ae349f5Scvs2svn 259dd7e2610SBrian Somers if (log_IsKept(LogDEBUG) && !debug_done) { 2601ae349f5Scvs2svn int f; 2611ae349f5Scvs2svn 262dd7e2610SBrian Somers log_Printf(LogDEBUG, "Found the following interfaces:\n"); 2631ae349f5Scvs2svn for (f = 0; f < nifs; f++) 2641ae349f5Scvs2svn if (ifs[f] != NULL) 265dd7e2610SBrian Somers log_Printf(LogDEBUG, " Index %d, name \"%s\"\n", f+1, ifs[f]); 2661ae349f5Scvs2svn debug_done = 1; 2671ae349f5Scvs2svn } 2681ae349f5Scvs2svn 2691ae349f5Scvs2svn if (idx < 1 || idx > nifs || ifs[idx-1] == NULL) 2701ae349f5Scvs2svn return "???"; 2711ae349f5Scvs2svn 2721ae349f5Scvs2svn return ifs[idx-1]; 2731ae349f5Scvs2svn } 2741ae349f5Scvs2svn 2751ae349f5Scvs2svn int 276dd7e2610SBrian Somers route_Show(struct cmdargs const *arg) 2771ae349f5Scvs2svn { 2781ae349f5Scvs2svn struct rt_msghdr *rtm; 2791ae349f5Scvs2svn struct sockaddr *sa_dst, *sa_gw, *sa_mask; 2801ae349f5Scvs2svn char *sp, *ep, *cp, *wp; 2811ae349f5Scvs2svn size_t needed; 2821ae349f5Scvs2svn int mib[6]; 2831ae349f5Scvs2svn 2841ae349f5Scvs2svn mib[0] = CTL_NET; 2851ae349f5Scvs2svn mib[1] = PF_ROUTE; 2861ae349f5Scvs2svn mib[2] = 0; 2871ae349f5Scvs2svn mib[3] = 0; 2881ae349f5Scvs2svn mib[4] = NET_RT_DUMP; 2891ae349f5Scvs2svn mib[5] = 0; 2901ae349f5Scvs2svn if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 291dd7e2610SBrian Somers log_Printf(LogERROR, "route_Show: sysctl: estimate: %s\n", strerror(errno)); 2921ae349f5Scvs2svn return (1); 2931ae349f5Scvs2svn } 2941ae349f5Scvs2svn if (needed < 0) 2951ae349f5Scvs2svn return (1); 2961ae349f5Scvs2svn sp = malloc(needed); 2971ae349f5Scvs2svn if (sp == NULL) 2981ae349f5Scvs2svn return (1); 2991ae349f5Scvs2svn if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 300dd7e2610SBrian Somers log_Printf(LogERROR, "route_Show: sysctl: getroute: %s\n", strerror(errno)); 3011ae349f5Scvs2svn free(sp); 3021ae349f5Scvs2svn return (1); 3031ae349f5Scvs2svn } 3041ae349f5Scvs2svn ep = sp + needed; 3051ae349f5Scvs2svn 306b6217683SBrian Somers prompt_Printf(arg->prompt, "%-20s%-20sFlags Netif\n", 307b6217683SBrian Somers "Destination", "Gateway"); 3081ae349f5Scvs2svn for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 3091ae349f5Scvs2svn rtm = (struct rt_msghdr *) cp; 3101ae349f5Scvs2svn wp = (char *)(rtm+1); 3111ae349f5Scvs2svn 3121ae349f5Scvs2svn if (rtm->rtm_addrs & RTA_DST) { 3131ae349f5Scvs2svn sa_dst = (struct sockaddr *)wp; 3141ae349f5Scvs2svn wp += sa_dst->sa_len; 3151ae349f5Scvs2svn } else 3161ae349f5Scvs2svn sa_dst = NULL; 3171ae349f5Scvs2svn 3181ae349f5Scvs2svn if (rtm->rtm_addrs & RTA_GATEWAY) { 3191ae349f5Scvs2svn sa_gw = (struct sockaddr *)wp; 3201ae349f5Scvs2svn wp += sa_gw->sa_len; 3211ae349f5Scvs2svn } else 3221ae349f5Scvs2svn sa_gw = NULL; 3231ae349f5Scvs2svn 3241ae349f5Scvs2svn if (rtm->rtm_addrs & RTA_NETMASK) { 3251ae349f5Scvs2svn sa_mask = (struct sockaddr *)wp; 3261ae349f5Scvs2svn wp += sa_mask->sa_len; 3271ae349f5Scvs2svn } else 3281ae349f5Scvs2svn sa_mask = NULL; 3291ae349f5Scvs2svn 330b6217683SBrian Somers p_sockaddr(arg->prompt, sa_dst, sa_mask, 20); 331b6217683SBrian Somers p_sockaddr(arg->prompt, sa_gw, NULL, 20); 3321ae349f5Scvs2svn 333b6217683SBrian Somers p_flags(arg->prompt, rtm->rtm_flags, 6); 334b6217683SBrian Somers prompt_Printf(arg->prompt, " %s\n", Index2Nam(rtm->rtm_index)); 3351ae349f5Scvs2svn } 3361ae349f5Scvs2svn free(sp); 3371ae349f5Scvs2svn return 0; 3381ae349f5Scvs2svn } 3391ae349f5Scvs2svn 3401ae349f5Scvs2svn /* 3411ae349f5Scvs2svn * Delete routes associated with our interface 3421ae349f5Scvs2svn */ 3431ae349f5Scvs2svn void 344dd7e2610SBrian Somers route_IfDelete(struct bundle *bundle, int all) 3451ae349f5Scvs2svn { 3461ae349f5Scvs2svn struct rt_msghdr *rtm; 3471ae349f5Scvs2svn struct sockaddr *sa; 3481ae349f5Scvs2svn struct in_addr sa_dst, sa_none; 3491ae349f5Scvs2svn int pass; 3501ae349f5Scvs2svn size_t needed; 3511ae349f5Scvs2svn char *sp, *cp, *ep; 3521ae349f5Scvs2svn int mib[6]; 3531ae349f5Scvs2svn 354dd7e2610SBrian Somers log_Printf(LogDEBUG, "route_IfDelete (%d)\n", bundle->ifIndex); 3551ae349f5Scvs2svn sa_none.s_addr = INADDR_ANY; 3561ae349f5Scvs2svn 3571ae349f5Scvs2svn mib[0] = CTL_NET; 3581ae349f5Scvs2svn mib[1] = PF_ROUTE; 3591ae349f5Scvs2svn mib[2] = 0; 3601ae349f5Scvs2svn mib[3] = 0; 3611ae349f5Scvs2svn mib[4] = NET_RT_DUMP; 3621ae349f5Scvs2svn mib[5] = 0; 3631ae349f5Scvs2svn if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 364dd7e2610SBrian Somers log_Printf(LogERROR, "route_IfDelete: sysctl: estimate: %s\n", 3651ae349f5Scvs2svn strerror(errno)); 3661ae349f5Scvs2svn return; 3671ae349f5Scvs2svn } 3681ae349f5Scvs2svn if (needed < 0) 3691ae349f5Scvs2svn return; 3701ae349f5Scvs2svn 3711ae349f5Scvs2svn sp = malloc(needed); 3721ae349f5Scvs2svn if (sp == NULL) 3731ae349f5Scvs2svn return; 3741ae349f5Scvs2svn 3751ae349f5Scvs2svn if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 376dd7e2610SBrian Somers log_Printf(LogERROR, "route_IfDelete: sysctl: getroute: %s\n", 3771ae349f5Scvs2svn strerror(errno)); 3781ae349f5Scvs2svn free(sp); 3791ae349f5Scvs2svn return; 3801ae349f5Scvs2svn } 3811ae349f5Scvs2svn ep = sp + needed; 3821ae349f5Scvs2svn 3831ae349f5Scvs2svn for (pass = 0; pass < 2; pass++) { 3841ae349f5Scvs2svn /* 3851ae349f5Scvs2svn * We do 2 passes. The first deletes all cloned routes. The second 3861ae349f5Scvs2svn * deletes all non-cloned routes. This is necessary to avoid 3871ae349f5Scvs2svn * potential errors from trying to delete route X after route Y where 388ba081e43SBrian Somers * route X was cloned from route Y (and is no longer there 'cos it 389ba081e43SBrian Somers * may have gone with route Y). 3901ae349f5Scvs2svn */ 3911ae349f5Scvs2svn if (RTF_WASCLONED == 0 && pass == 0) 3921ae349f5Scvs2svn /* So we can't tell ! */ 3931ae349f5Scvs2svn continue; 3941ae349f5Scvs2svn for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 3951ae349f5Scvs2svn rtm = (struct rt_msghdr *) cp; 3961ae349f5Scvs2svn sa = (struct sockaddr *) (rtm + 1); 397dd7e2610SBrian Somers log_Printf(LogDEBUG, "route_IfDelete: addrs: %x, Netif: %d (%s)," 3981ae349f5Scvs2svn " flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index, 3991ae349f5Scvs2svn Index2Nam(rtm->rtm_index), rtm->rtm_flags, 4001ae349f5Scvs2svn inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); 4011ae349f5Scvs2svn if (rtm->rtm_addrs & RTA_DST && rtm->rtm_addrs & RTA_GATEWAY && 4027a6f8720SBrian Somers rtm->rtm_index == bundle->ifIndex && 4031ae349f5Scvs2svn (all || (rtm->rtm_flags & RTF_GATEWAY))) { 4041ae349f5Scvs2svn sa_dst.s_addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 4051ae349f5Scvs2svn sa = (struct sockaddr *)((char *)sa + sa->sa_len); 4061ae349f5Scvs2svn if (sa->sa_family == AF_INET || sa->sa_family == AF_LINK) { 4071ae349f5Scvs2svn if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) || 4081ae349f5Scvs2svn (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) { 409dd7e2610SBrian Somers log_Printf(LogDEBUG, "route_IfDelete: Remove it (pass %d)\n", pass); 4107a6f8720SBrian Somers bundle_SetRoute(bundle, RTM_DELETE, sa_dst, sa_none, sa_none, 0); 4111ae349f5Scvs2svn } else 412dd7e2610SBrian Somers log_Printf(LogDEBUG, "route_IfDelete: Skip it (pass %d)\n", pass); 4131ae349f5Scvs2svn } else 414dd7e2610SBrian Somers log_Printf(LogDEBUG, 415dd7e2610SBrian Somers "route_IfDelete: Can't remove routes of %d family !\n", 4161ae349f5Scvs2svn sa->sa_family); 4171ae349f5Scvs2svn } 4181ae349f5Scvs2svn } 4191ae349f5Scvs2svn } 4201ae349f5Scvs2svn free(sp); 4211ae349f5Scvs2svn } 4221ae349f5Scvs2svn 4231ae349f5Scvs2svn int 4241ae349f5Scvs2svn GetIfIndex(char *name) 4251ae349f5Scvs2svn { 4261ae349f5Scvs2svn int idx; 4271ae349f5Scvs2svn const char *got; 4281ae349f5Scvs2svn 4291ae349f5Scvs2svn idx = 1; 4301ae349f5Scvs2svn while (strcmp(got = Index2Nam(idx), "???")) 4311ae349f5Scvs2svn if (!strcmp(got, name)) 4327a6f8720SBrian Somers return idx; 4331ae349f5Scvs2svn else 4341ae349f5Scvs2svn idx++; 4351ae349f5Scvs2svn return -1; 4361ae349f5Scvs2svn } 437610b185fSBrian Somers 438610b185fSBrian Somers void 439610b185fSBrian Somers route_Change(struct bundle *bundle, struct sticky_route *r, 440610b185fSBrian Somers struct in_addr me, struct in_addr peer) 441610b185fSBrian Somers { 442610b185fSBrian Somers struct in_addr none, del; 443610b185fSBrian Somers 444610b185fSBrian Somers none.s_addr = INADDR_ANY; 445610b185fSBrian Somers for (; r; r = r->next) { 446610b185fSBrian Somers if ((r->type & ROUTE_DSTMYADDR) && r->dst.s_addr != me.s_addr) { 447610b185fSBrian Somers del.s_addr = r->dst.s_addr & r->mask.s_addr; 448610b185fSBrian Somers bundle_SetRoute(bundle, RTM_DELETE, del, none, none, 1); 449610b185fSBrian Somers r->dst = me; 450610b185fSBrian Somers if (r->type & ROUTE_GWHISADDR) 451610b185fSBrian Somers r->gw = peer; 452610b185fSBrian Somers } else if ((r->type & ROUTE_DSTHISADDR) && r->dst.s_addr != peer.s_addr) { 453610b185fSBrian Somers del.s_addr = r->dst.s_addr & r->mask.s_addr; 454610b185fSBrian Somers bundle_SetRoute(bundle, RTM_DELETE, del, none, none, 1); 455610b185fSBrian Somers r->dst = peer; 456610b185fSBrian Somers if (r->type & ROUTE_GWHISADDR) 457610b185fSBrian Somers r->gw = peer; 458610b185fSBrian Somers } else if ((r->type & ROUTE_GWHISADDR) && r->gw.s_addr != peer.s_addr) 459610b185fSBrian Somers r->gw = peer; 460610b185fSBrian Somers else 461610b185fSBrian Somers continue; 462610b185fSBrian Somers bundle_SetRoute(bundle, RTM_ADD, r->dst, r->gw, r->mask, 1); 463610b185fSBrian Somers } 464610b185fSBrian Somers } 465610b185fSBrian Somers 466610b185fSBrian Somers void 467610b185fSBrian Somers route_Clean(struct bundle *bundle, struct sticky_route *r) 468610b185fSBrian Somers { 469610b185fSBrian Somers struct in_addr none, del; 470610b185fSBrian Somers 471610b185fSBrian Somers none.s_addr = INADDR_ANY; 472610b185fSBrian Somers for (; r; r = r->next) { 473610b185fSBrian Somers del.s_addr = r->dst.s_addr & r->mask.s_addr; 474610b185fSBrian Somers bundle_SetRoute(bundle, RTM_DELETE, del, none, none, 1); 475610b185fSBrian Somers } 476610b185fSBrian Somers } 477610b185fSBrian Somers 478610b185fSBrian Somers void 479610b185fSBrian Somers route_Add(struct sticky_route **rp, int type, struct in_addr dst, 480610b185fSBrian Somers struct in_addr mask, struct in_addr gw) 481610b185fSBrian Somers { 482610b185fSBrian Somers if (type != ROUTE_STATIC) { 483610b185fSBrian Somers struct sticky_route *r; 484610b185fSBrian Somers int dsttype = type & ROUTE_DSTANY; 485610b185fSBrian Somers 486610b185fSBrian Somers r = NULL; 487610b185fSBrian Somers while (*rp) { 488183df580SBrian Somers if ((dsttype && dsttype == ((*rp)->type & ROUTE_DSTANY)) || 489183df580SBrian Somers (!dsttype && (*rp)->dst.s_addr == dst.s_addr)) { 490610b185fSBrian Somers r = *rp; 491610b185fSBrian Somers *rp = r->next; 492610b185fSBrian Somers } else 493610b185fSBrian Somers rp = &(*rp)->next; 494610b185fSBrian Somers } 495610b185fSBrian Somers 496610b185fSBrian Somers if (!r) 497610b185fSBrian Somers r = (struct sticky_route *)malloc(sizeof(struct sticky_route)); 498610b185fSBrian Somers r->type = type; 499610b185fSBrian Somers r->next = NULL; 500610b185fSBrian Somers r->dst = dst; 501610b185fSBrian Somers r->mask = mask; 502610b185fSBrian Somers r->gw = gw; 503610b185fSBrian Somers *rp = r; 504610b185fSBrian Somers } 505610b185fSBrian Somers } 506610b185fSBrian Somers 507610b185fSBrian Somers void 508610b185fSBrian Somers route_Delete(struct sticky_route **rp, int type, struct in_addr dst) 509610b185fSBrian Somers { 510610b185fSBrian Somers struct sticky_route *r; 511610b185fSBrian Somers int dsttype = type & ROUTE_DSTANY; 512610b185fSBrian Somers 513610b185fSBrian Somers for (; *rp; rp = &(*rp)->next) { 514610b185fSBrian Somers if ((dsttype && dsttype == ((*rp)->type & ROUTE_DSTANY)) || 515610b185fSBrian Somers (!dsttype && dst.s_addr == ((*rp)->dst.s_addr & (*rp)->mask.s_addr))) { 516610b185fSBrian Somers r = *rp; 517610b185fSBrian Somers *rp = r->next; 518610b185fSBrian Somers free(r); 519610b185fSBrian Somers break; 520610b185fSBrian Somers } 521610b185fSBrian Somers } 522610b185fSBrian Somers } 523610b185fSBrian Somers 524610b185fSBrian Somers void 525610b185fSBrian Somers route_DeleteAll(struct sticky_route **rp) 526610b185fSBrian Somers { 527610b185fSBrian Somers struct sticky_route *r, *rn; 528610b185fSBrian Somers 529610b185fSBrian Somers for (r = *rp; r; r = rn) { 530610b185fSBrian Somers rn = r->next; 531610b185fSBrian Somers free(r); 532610b185fSBrian Somers } 533610b185fSBrian Somers *rp = NULL; 534610b185fSBrian Somers } 535610b185fSBrian Somers 536610b185fSBrian Somers void 537610b185fSBrian Somers route_ShowSticky(struct prompt *p, struct sticky_route *r) 538610b185fSBrian Somers { 539610b185fSBrian Somers int def; 540610b185fSBrian Somers 541610b185fSBrian Somers prompt_Printf(p, "Sticky routes:\n"); 542610b185fSBrian Somers for (; r; r = r->next) { 543610b185fSBrian Somers def = r->dst.s_addr == INADDR_ANY && r->mask.s_addr == INADDR_ANY; 544610b185fSBrian Somers 545610b185fSBrian Somers prompt_Printf(p, " add "); 546610b185fSBrian Somers if (r->type & ROUTE_DSTMYADDR) 547610b185fSBrian Somers prompt_Printf(p, "MYADDR"); 548610b185fSBrian Somers else if (r->type & ROUTE_DSTHISADDR) 549610b185fSBrian Somers prompt_Printf(p, "HISADDR"); 550610b185fSBrian Somers else if (!def) 551610b185fSBrian Somers prompt_Printf(p, "%s", inet_ntoa(r->dst)); 552610b185fSBrian Somers 553610b185fSBrian Somers if (def) 554610b185fSBrian Somers prompt_Printf(p, "default "); 555610b185fSBrian Somers else 556610b185fSBrian Somers prompt_Printf(p, " %s ", inet_ntoa(r->mask)); 557610b185fSBrian Somers 558610b185fSBrian Somers if (r->type & ROUTE_GWHISADDR) 559610b185fSBrian Somers prompt_Printf(p, "HISADDR\n"); 560610b185fSBrian Somers else 561610b185fSBrian Somers prompt_Printf(p, "%s\n", inet_ntoa(r->gw)); 562610b185fSBrian Somers } 563610b185fSBrian Somers } 564