route.c revision 13389
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 * 2013389Sphk * $Id: route.c,v 1.4 1995/07/08 06:08:52 amurai Exp $ 218857Srgrimes * 226059Samurai */ 236059Samurai#include <sys/types.h> 246059Samurai#include <machine/endian.h> 256059Samurai#include <sys/param.h> 266059Samurai#include <sys/socket.h> 276059Samurai#include <net/route.h> 286059Samurai#include <sys/ioctl.h> 296059Samurai#include <net/if.h> 306059Samurai#include <errno.h> 316059Samurai#include <netinet/in_systm.h> 326059Samurai#include <netinet/in.h> 336059Samurai#include <arpa/inet.h> 346735Samurai#if (BSD >= 199306) 356059Samurai#include <sys/sysctl.h> 366059Samurai#else 376059Samurai#include <sys/kinfo.h> 386059Samurai#endif 396059Samurai#include <stdlib.h> 406059Samurai#include <stdio.h> 416059Samurai#include <string.h> 426059Samurai#include <unistd.h> 439439Samurai#include "log.h" 446059Samurai 456059Samuraistatic int IfIndex; 466059Samurai 476059Samuraistruct rtmsg { 486059Samurai struct rt_msghdr m_rtm; 496059Samurai char m_space[64]; 506059Samurai}; 516059Samurai 526059Samuraistatic int seqno; 536059Samurai 546059Samuraivoid 556059SamuraiOsSetRoute(cmd, dst, gateway, mask) 566059Samuraiint cmd; 576059Samuraistruct in_addr dst; 586059Samuraistruct in_addr gateway; 596059Samuraistruct in_addr mask; 606059Samurai{ 616059Samurai struct rtmsg rtmes; 626059Samurai int s, nb, wb; 636059Samurai char *cp; 646059Samurai u_long *lp; 656059Samurai struct sockaddr_in rtdata; 666059Samurai 676059Samurai s = socket(PF_ROUTE, SOCK_RAW, 0); 686059Samurai if (s < 0) 696059Samurai logprintf("socket\n"); 706059Samurai 716059Samurai bzero(&rtmes, sizeof(rtmes)); 726059Samurai rtmes.m_rtm.rtm_version = RTM_VERSION; 736059Samurai rtmes.m_rtm.rtm_type = cmd; 746059Samurai rtmes.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK; 756059Samurai if (cmd == RTM_ADD) rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 766059Samurai rtmes.m_rtm.rtm_seq = ++seqno; 776059Samurai rtmes.m_rtm.rtm_pid = getpid(); 786059Samurai rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY; 796059Samurai 806059Samurai bzero(&rtdata, sizeof(rtdata)); 816059Samurai rtdata.sin_len = 16; 826059Samurai rtdata.sin_family = AF_INET; 836059Samurai rtdata.sin_port = 0; 846059Samurai rtdata.sin_addr = dst; 856059Samurai 866059Samurai cp = rtmes.m_space; 876059Samurai bcopy(&rtdata, cp, 16); 886059Samurai cp += 16; 896059Samurai if (gateway.s_addr) { 906059Samurai rtdata.sin_addr = gateway; 916059Samurai bcopy(&rtdata, cp, 16); 926059Samurai cp += 16; 936059Samurai } 946059Samurai 956059Samurai if (dst.s_addr == INADDR_ANY) 966059Samurai mask.s_addr = INADDR_ANY; 976059Samurai 986059Samurai lp = (u_long *)cp; 996059Samurai 1006059Samurai if (mask.s_addr) { 1016059Samurai *lp++ = 8; 1026059Samurai cp += sizeof(int); 1036059Samurai *lp = mask.s_addr; 1046059Samurai } else 1056059Samurai *lp = 0; 1066059Samurai cp += sizeof(u_long); 1076059Samurai 1086059Samurai nb = cp - (char *)&rtmes; 1096059Samurai rtmes.m_rtm.rtm_msglen = nb; 1106059Samurai wb = write(s, &rtmes, nb); 1116059Samurai if (wb < 0) { 1129439Samurai LogPrintf(LOG_TCPIP, "Already set route addr dst=%x, gateway=%x\n" 1139439Samurai ,dst.s_addr, gateway.s_addr); 1146059Samurai } 1156059Samurai#ifdef DEBUG 1166059Samurai logprintf("wrote %d: dst = %x, gateway = %x\n", nb, dst.s_addr, gateway.s_addr); 1176059Samurai#endif 1186059Samurai close(s); 1196059Samurai} 1206059Samurai 1216059Samuraistatic void 1226059Samuraip_sockaddr(sa, width) 1236059Samuraistruct sockaddr *sa; 1246059Samuraiint width; 1256059Samurai{ 1266059Samurai register char *cp; 1276059Samurai register struct sockaddr_in *sin = (struct sockaddr_in *)sa; 1286059Samurai 1296059Samurai cp = (sin->sin_addr.s_addr == 0) ? "default" : 1306059Samurai inet_ntoa(sin->sin_addr); 1316059Samurai printf("%-*.*s ", width, width, cp); 1326059Samurai} 1336059Samurai 1346059Samuraistruct bits { 1356059Samurai short b_mask; 1366059Samurai char b_val; 1376059Samurai} bits[] = { 1386059Samurai { RTF_UP, 'U' }, 1396059Samurai { RTF_GATEWAY, 'G' }, 1406059Samurai { RTF_HOST, 'H' }, 1416059Samurai { RTF_DYNAMIC, 'D' }, 1426059Samurai { RTF_MODIFIED, 'M' }, 1436059Samurai { RTF_CLONING, 'C' }, 1446059Samurai { RTF_XRESOLVE, 'X' }, 1456059Samurai { RTF_LLINFO, 'L' }, 1466059Samurai { RTF_REJECT, 'R' }, 1476059Samurai { 0 } 1486059Samurai}; 1496059Samurai 1506059Samuraistatic void 1516059Samuraip_flags(f, format) 1526059Samurairegister int f; 1536059Samuraichar *format; 1546059Samurai{ 1556059Samurai char name[33], *flags; 1566059Samurai register struct bits *p = bits; 1576059Samurai 1586059Samurai for (flags = name; p->b_mask; p++) 1596059Samurai if (p->b_mask & f) 1606059Samurai *flags++ = p->b_val; 1616059Samurai *flags = '\0'; 1626059Samurai printf(format, name); 1636059Samurai} 1646059Samurai 1656059Samuraiint 1666059SamuraiShowRoute() 1676059Samurai{ 1686059Samurai struct rt_msghdr *rtm; 1696059Samurai struct sockaddr *sa; 1706059Samurai char *sp, *ep, *cp; 1716059Samurai u_char *wp; 1726059Samurai int *lp; 1736059Samurai int needed, nb; 1746059Samurai u_long mask; 1756735Samurai#if (BSD >= 199306) 1766735Samurai int mib[6]; 1776059Samurai#endif 1786059Samurai 1796735Samurai#if (BSD >= 199306) 1806059Samurai mib[0] = CTL_NET; 1816059Samurai mib[1] = PF_ROUTE; 1826735Samurai mib[2] = 0; 1836735Samurai mib[3] = 0; 1846059Samurai mib[4] = NET_RT_DUMP; 1856735Samurai mib[5] = 0; 1866735Samurai if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 1876735Samurai perror("sysctl-estimate"); 1886735Samurai return(1); 1896735Samurai } 1906059Samurai#else 1916059Samurai needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0); 1926059Samurai#endif 1936059Samurai if (needed < 0) 1946059Samurai return(1); 1956059Samurai sp = malloc(needed); 1966059Samurai if (sp == NULL) 1976059Samurai return(1); 1986735Samurai#if (BSD >= 199306) 1996735Samurai if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 2006735Samurai perror("sysctl-getroute"); 2016059Samurai return(1); 2026735Samurai } 2036059Samurai#else 2046059Samurai if (getkerninfo(KINFO_RT_DUMP, sp, &needed, 0) < 0) 2056059Samurai return(1); 2066059Samurai#endif 2076059Samurai ep = sp + needed; 2086059Samurai 2096059Samurai for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 2106059Samurai rtm = (struct rt_msghdr *)cp; 2116059Samurai sa = (struct sockaddr *)(rtm + 1); 2126059Samurai mask = 0xffffffff; 2136059Samurai if (rtm->rtm_addrs == RTA_DST) 2146059Samurai p_sockaddr(sa, 36); 2156059Samurai else { 2166059Samurai wp = (u_char *)cp + rtm->rtm_msglen; 2176059Samurai p_sockaddr(sa, 16); 2186059Samurai if (sa->sa_len == 0) 2196059Samurai sa->sa_len = sizeof(long); 2206059Samurai sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 2216059Samurai p_sockaddr(sa, 18); 2226059Samurai lp = (int *)(sa->sa_len + (char *)sa); 2236059Samurai if ((char *)lp < (char *)wp && *lp) { 2246059Samurai#ifdef DEBUG 2256059Samurai logprintf(" flag = %x, rest = %d", rtm->rtm_flags, *lp); 2266059Samurai#endif 2276059Samurai wp = (u_char *)(lp + 1); 2286059Samurai mask = 0; 2296059Samurai for (nb = *lp; nb > 4; nb--) { 2306059Samurai mask <<= 8; 2316059Samurai mask |= *wp++; 2326059Samurai } 2336059Samurai for (nb = 8 - *lp; nb > 0; nb--) 2346059Samurai mask <<= 8; 2356059Samurai } 2366059Samurai } 23713389Sphk printf("%08lx ", mask); 2386059Samurai p_flags(rtm->rtm_flags & (RTF_UP|RTF_GATEWAY|RTF_HOST), "%-6.6s "); 2396059Samurai printf("(%d)\n", rtm->rtm_index); 2406059Samurai } 2416059Samurai 2426059Samurai return(1); 2436059Samurai} 2446059Samurai 2456059Samurai/* 2466059Samurai * Delete routes associated with our interface 2476059Samurai */ 2486059Samuraivoid 2496059SamuraiDeleteIfRoutes(all) 2506059Samuraiint all; 2516059Samurai{ 2526059Samurai struct rt_msghdr *rtm; 2536059Samurai struct sockaddr *sa; 2546059Samurai struct in_addr dstnet, gateway; 2556059Samurai int needed; 2566059Samurai char *sp, *cp, *ep; 2576059Samurai u_long mask; 2586059Samurai int *lp, nb; 2596059Samurai u_char *wp; 2606735Samurai#if (BSD >= 199306) 2616735Samurai int mib[6]; 2626059Samurai#endif 2636059Samurai 2646059Samurai#ifdef DEBUG 2656059Samurai logprintf("DeleteIfRoutes (%d)\n", IfIndex); 2666059Samurai#endif 2676735Samurai#if (BSD >= 199306) 2686059Samurai mib[0] = CTL_NET; 2696059Samurai mib[1] = PF_ROUTE; 2706735Samurai mib[2] = 0; 2716735Samurai mib[3] = 0; 2726059Samurai mib[4] = NET_RT_DUMP; 2736735Samurai mib[5] = 0; 2746735Samurai if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 2756735Samurai perror("sysctl-estimate"); 2766735Samurai return; 2776735Samurai } 2786059Samurai#else 2796059Samurai needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0); 2806059Samurai#endif 2816735Samurai 2826059Samurai if (needed < 0) 2836059Samurai return; 2846059Samurai 2856059Samurai sp = malloc(needed); 2866059Samurai if (sp == NULL) 2876059Samurai return; 2886059Samurai 2896735Samurai#if (BSD >= 199306) 2906735Samurai if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 2916059Samurai free(sp); 2926735Samurai perror("sysctl-getroute"); 2936059Samurai return; 2946059Samurai } 2956059Samurai#else 2966059Samurai if (getkerninfo(KINFO_RT_DUMP, sp, &needed, 0) < 0) { 2976059Samurai free(sp); 2986059Samurai return; 2996059Samurai } 3006059Samurai#endif 3016059Samurai ep = sp + needed; 3026059Samurai 3036059Samurai for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 3046059Samurai rtm = (struct rt_msghdr *)cp; 3056059Samurai sa = (struct sockaddr *)(rtm + 1); 3066059Samurai#ifdef DEBUG 3076059Samurai logprintf("addrs: %x, index: %d, flags: %x, dstnet: %x\n", 3086059Samurai rtm->rtm_addrs, rtm->rtm_index, rtm->rtm_flags, 3096059Samurai ((struct sockaddr_in *)sa)->sin_addr); 3106059Samurai#endif 3116059Samurai if (rtm->rtm_addrs != RTA_DST && 3126059Samurai (rtm->rtm_index == IfIndex) && 3136059Samurai (all || (rtm->rtm_flags & RTF_GATEWAY))) { 3146059Samurai dstnet = ((struct sockaddr_in *)sa)->sin_addr; 3156059Samurai wp = (u_char *)cp + rtm->rtm_msglen; 3166059Samurai if (sa->sa_len == 0) 3176059Samurai sa->sa_len = sizeof(long); 3186059Samurai sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 3196059Samurai gateway = ((struct sockaddr_in *)sa)->sin_addr; 3206059Samurai lp = (int *)(sa->sa_len + (char *)sa); 3216059Samurai mask = 0; 3226059Samurai if ((char *)lp < (char *)wp && *lp) { 3236059Samurai#ifdef DEBUG 3246059Samurai printf(" flag = %x, rest = %d", rtm->rtm_flags, *lp); 3256059Samurai#endif 3266059Samurai wp = (u_char *)(lp + 1); 3276059Samurai for (nb = *lp; nb > 4; nb--) { 3286059Samurai mask <<= 8; 3296059Samurai mask |= *wp++; 3306059Samurai } 3316059Samurai for (nb = 8 - *lp; nb > 0; nb--) 3326059Samurai mask <<= 8; 3336059Samurai } 3346059Samurai#ifdef DEBUG 3356059Samurai logprintf("## %s ", inet_ntoa(dstnet)); 3366059Samurai logprintf(" %s %d\n", inet_ntoa(gateway), rtm->rtm_index); 3376059Samurai#endif 3386059Samurai if (dstnet.s_addr == INADDR_ANY) { 3396059Samurai gateway.s_addr = INADDR_ANY; 3406059Samurai mask = INADDR_ANY; 3416059Samurai } 3426059Samurai OsSetRoute(RTM_DELETE, dstnet, gateway, htonl(mask)); 3436059Samurai } 3446059Samurai#ifdef DEBUG 3456059Samurai else if (rtm->rtm_index == IfIndex) { 3466059Samurai logprintf("??? addrs: %x, flags = %x\n", rtm->rtm_addrs, rtm->rtm_flags); 3476059Samurai } 3486059Samurai#endif 3496059Samurai } 3506059Samurai free(sp); 3516059Samurai} 3526059Samurai 3536059Samuraiint 3546059SamuraiGetIfIndex(name) 3556059Samuraichar *name; 3566059Samurai{ 3576059Samurai struct ifreq *ifrp; 3586059Samurai int s, len, elen, index; 3596059Samurai struct ifconf ifconfs; 3606059Samurai struct ifreq reqbuf[32]; 3616059Samurai 3626059Samurai s = socket(AF_INET, SOCK_DGRAM, 0); 3636059Samurai if (s < 0) { 3646059Samurai perror("socket"); 3656059Samurai return(-1); 3666059Samurai } 3676059Samurai 3686059Samurai ifconfs.ifc_len = sizeof(reqbuf); 3696059Samurai ifconfs.ifc_buf = (caddr_t)reqbuf; 3706059Samurai if (ioctl(s, SIOCGIFCONF, &ifconfs) < 0) { 3716059Samurai perror("IFCONF"); 3726059Samurai return(-1); 3736059Samurai } 3746059Samurai 3756059Samurai ifrp = ifconfs.ifc_req; 3766059Samurai 3776059Samurai index = 1; 3786059Samurai for (len = ifconfs.ifc_len; len > 0; len -= sizeof(struct ifreq)) { 3796059Samurai elen = ifrp->ifr_addr.sa_len - sizeof(struct sockaddr); 3806059Samurai if (ifrp->ifr_addr.sa_family == AF_LINK) { 3816059Samurai#ifdef DEBUG 3826059Samurai logprintf("%d: %-*.*s, %d, %d\n", index, IFNAMSIZ, IFNAMSIZ, ifrp->ifr_name, 3836059Samurai ifrp->ifr_addr.sa_family, elen); 3846059Samurai#endif 3856059Samurai if (strcmp(ifrp->ifr_name, name) == 0) { 3866059Samurai IfIndex = index; 3876059Samurai return(index); 3886059Samurai } 3896059Samurai index++; 3906059Samurai } 3916059Samurai 3926059Samurai len -= elen; 3936059Samurai ifrp = (struct ifreq *)((char *)ifrp + elen); 3946059Samurai ifrp++; 3956059Samurai } 3966059Samurai 3976059Samurai close(s); 3986059Samurai return(-1); 3996059Samurai} 400