route.c revision 13389
159290Sjlemon/* 259290Sjlemon * PPP Routing related Module 359290Sjlemon * 459290Sjlemon * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 559290Sjlemon * 659290Sjlemon * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 759290Sjlemon * 859290Sjlemon * Redistribution and use in source and binary forms are permitted 959290Sjlemon * provided that the above copyright notice and this paragraph are 1059290Sjlemon * duplicated in all such forms and that any documentation, 1159290Sjlemon * advertising materials, and other materials related to such 1259290Sjlemon * distribution and use acknowledge that the software was developed 1359290Sjlemon * by the Internet Initiative Japan, Inc. The name of the 1459290Sjlemon * IIJ may not be used to endorse or promote products derived 1559290Sjlemon * from this software without specific prior written permission. 1659290Sjlemon * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1759290Sjlemon * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1859290Sjlemon * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1959290Sjlemon * 2059290Sjlemon * $Id: route.c,v 1.4 1995/07/08 06:08:52 amurai Exp $ 2159290Sjlemon * 2259290Sjlemon */ 2359290Sjlemon#include <sys/types.h> 2459290Sjlemon#include <machine/endian.h> 2559290Sjlemon#include <sys/param.h> 2659290Sjlemon#include <sys/socket.h> 2759290Sjlemon#include <net/route.h> 2859290Sjlemon#include <sys/ioctl.h> 2959290Sjlemon#include <net/if.h> 3059290Sjlemon#include <errno.h> 3159290Sjlemon#include <netinet/in_systm.h> 3259290Sjlemon#include <netinet/in.h> 3359290Sjlemon#include <arpa/inet.h> 3459290Sjlemon#if (BSD >= 199306) 3559290Sjlemon#include <sys/sysctl.h> 3659290Sjlemon#else 3759290Sjlemon#include <sys/kinfo.h> 3859290Sjlemon#endif 3959290Sjlemon#include <stdlib.h> 4059290Sjlemon#include <stdio.h> 4159290Sjlemon#include <string.h> 4259290Sjlemon#include <unistd.h> 4359290Sjlemon#include "log.h" 4459290Sjlemon 4559290Sjlemonstatic int IfIndex; 4659290Sjlemon 4759290Sjlemonstruct rtmsg { 4859290Sjlemon struct rt_msghdr m_rtm; 4959290Sjlemon char m_space[64]; 5059290Sjlemon}; 5159290Sjlemon 5259290Sjlemonstatic int seqno; 5359290Sjlemon 5459290Sjlemonvoid 5559290SjlemonOsSetRoute(cmd, dst, gateway, mask) 5659290Sjlemonint cmd; 5759290Sjlemonstruct in_addr dst; 5859290Sjlemonstruct in_addr gateway; 5959290Sjlemonstruct in_addr mask; 6059290Sjlemon{ 6159290Sjlemon struct rtmsg rtmes; 6259290Sjlemon int s, nb, wb; 6359290Sjlemon char *cp; 6459290Sjlemon u_long *lp; 6559290Sjlemon struct sockaddr_in rtdata; 6659290Sjlemon 6759290Sjlemon s = socket(PF_ROUTE, SOCK_RAW, 0); 6859290Sjlemon if (s < 0) 6959290Sjlemon logprintf("socket\n"); 7059290Sjlemon 7159290Sjlemon bzero(&rtmes, sizeof(rtmes)); 7259290Sjlemon rtmes.m_rtm.rtm_version = RTM_VERSION; 7359290Sjlemon rtmes.m_rtm.rtm_type = cmd; 7459290Sjlemon rtmes.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK; 7559290Sjlemon if (cmd == RTM_ADD) rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 7659290Sjlemon rtmes.m_rtm.rtm_seq = ++seqno; 7759290Sjlemon rtmes.m_rtm.rtm_pid = getpid(); 7859290Sjlemon rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY; 7959290Sjlemon 8059290Sjlemon bzero(&rtdata, sizeof(rtdata)); 8159290Sjlemon rtdata.sin_len = 16; 8259290Sjlemon rtdata.sin_family = AF_INET; 8359290Sjlemon rtdata.sin_port = 0; 8459290Sjlemon rtdata.sin_addr = dst; 8559290Sjlemon 8659290Sjlemon cp = rtmes.m_space; 8759290Sjlemon bcopy(&rtdata, cp, 16); 8859290Sjlemon cp += 16; 8959290Sjlemon if (gateway.s_addr) { 9059290Sjlemon rtdata.sin_addr = gateway; 9159290Sjlemon bcopy(&rtdata, cp, 16); 9259290Sjlemon cp += 16; 9359290Sjlemon } 9459290Sjlemon 9559290Sjlemon if (dst.s_addr == INADDR_ANY) 9659290Sjlemon mask.s_addr = INADDR_ANY; 9759290Sjlemon 9859290Sjlemon lp = (u_long *)cp; 9959290Sjlemon 10059290Sjlemon if (mask.s_addr) { 10159290Sjlemon *lp++ = 8; 10259290Sjlemon cp += sizeof(int); 10359290Sjlemon *lp = mask.s_addr; 10459290Sjlemon } else 10559290Sjlemon *lp = 0; 10659290Sjlemon cp += sizeof(u_long); 10759290Sjlemon 10859290Sjlemon nb = cp - (char *)&rtmes; 10959290Sjlemon rtmes.m_rtm.rtm_msglen = nb; 11059290Sjlemon wb = write(s, &rtmes, nb); 11159290Sjlemon if (wb < 0) { 11259290Sjlemon LogPrintf(LOG_TCPIP, "Already set route addr dst=%x, gateway=%x\n" 11359290Sjlemon ,dst.s_addr, gateway.s_addr); 11459290Sjlemon } 11559290Sjlemon#ifdef DEBUG 11659290Sjlemon logprintf("wrote %d: dst = %x, gateway = %x\n", nb, dst.s_addr, gateway.s_addr); 11759290Sjlemon#endif 11859290Sjlemon close(s); 11959290Sjlemon} 12059290Sjlemon 12159290Sjlemonstatic void 12259290Sjlemonp_sockaddr(sa, width) 12359290Sjlemonstruct sockaddr *sa; 12459290Sjlemonint width; 12559290Sjlemon{ 12659290Sjlemon register char *cp; 12759290Sjlemon register struct sockaddr_in *sin = (struct sockaddr_in *)sa; 12859290Sjlemon 12959290Sjlemon cp = (sin->sin_addr.s_addr == 0) ? "default" : 13059290Sjlemon inet_ntoa(sin->sin_addr); 13159290Sjlemon printf("%-*.*s ", width, width, cp); 13259290Sjlemon} 13359290Sjlemon 13459290Sjlemonstruct bits { 13559290Sjlemon short b_mask; 13659290Sjlemon char b_val; 13759290Sjlemon} bits[] = { 13859290Sjlemon { RTF_UP, 'U' }, 13959290Sjlemon { RTF_GATEWAY, 'G' }, 14059290Sjlemon { RTF_HOST, 'H' }, 14159290Sjlemon { RTF_DYNAMIC, 'D' }, 14259290Sjlemon { RTF_MODIFIED, 'M' }, 14359290Sjlemon { RTF_CLONING, 'C' }, 14459290Sjlemon { RTF_XRESOLVE, 'X' }, 14559290Sjlemon { RTF_LLINFO, 'L' }, 14659290Sjlemon { RTF_REJECT, 'R' }, 14759290Sjlemon { 0 } 14859290Sjlemon}; 14959290Sjlemon 15059290Sjlemonstatic void 15159290Sjlemonp_flags(f, format) 15259290Sjlemonregister int f; 15359290Sjlemonchar *format; 15459290Sjlemon{ 15559290Sjlemon char name[33], *flags; 15659290Sjlemon register struct bits *p = bits; 15759290Sjlemon 15859290Sjlemon for (flags = name; p->b_mask; p++) 15959290Sjlemon if (p->b_mask & f) 16059290Sjlemon *flags++ = p->b_val; 16159290Sjlemon *flags = '\0'; 16259290Sjlemon printf(format, name); 16359290Sjlemon} 16459290Sjlemon 16559290Sjlemonint 16659290SjlemonShowRoute() 16759290Sjlemon{ 16859290Sjlemon struct rt_msghdr *rtm; 16959290Sjlemon struct sockaddr *sa; 17059290Sjlemon char *sp, *ep, *cp; 17159290Sjlemon u_char *wp; 17259290Sjlemon int *lp; 17359290Sjlemon int needed, nb; 17459290Sjlemon u_long mask; 17559290Sjlemon#if (BSD >= 199306) 17659290Sjlemon int mib[6]; 17759290Sjlemon#endif 17859290Sjlemon 17959290Sjlemon#if (BSD >= 199306) 18059290Sjlemon mib[0] = CTL_NET; 18159290Sjlemon mib[1] = PF_ROUTE; 18259290Sjlemon mib[2] = 0; 18359290Sjlemon mib[3] = 0; 18459290Sjlemon mib[4] = NET_RT_DUMP; 18559290Sjlemon mib[5] = 0; 18659290Sjlemon if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 18759290Sjlemon perror("sysctl-estimate"); 18859290Sjlemon return(1); 18959290Sjlemon } 19059290Sjlemon#else 19159290Sjlemon needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0); 19259290Sjlemon#endif 19359290Sjlemon if (needed < 0) 19459290Sjlemon return(1); 19559290Sjlemon sp = malloc(needed); 19659290Sjlemon if (sp == NULL) 19759290Sjlemon return(1); 19859290Sjlemon#if (BSD >= 199306) 19959290Sjlemon if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 20059290Sjlemon perror("sysctl-getroute"); 20159290Sjlemon return(1); 20259290Sjlemon } 20359290Sjlemon#else 20459290Sjlemon if (getkerninfo(KINFO_RT_DUMP, sp, &needed, 0) < 0) 20559290Sjlemon return(1); 20659290Sjlemon#endif 20759290Sjlemon ep = sp + needed; 20859290Sjlemon 20959290Sjlemon for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 21059290Sjlemon rtm = (struct rt_msghdr *)cp; 21159290Sjlemon sa = (struct sockaddr *)(rtm + 1); 21259290Sjlemon mask = 0xffffffff; 21359290Sjlemon if (rtm->rtm_addrs == RTA_DST) 21459290Sjlemon p_sockaddr(sa, 36); 21559290Sjlemon else { 21659290Sjlemon wp = (u_char *)cp + rtm->rtm_msglen; 21759290Sjlemon p_sockaddr(sa, 16); 21859290Sjlemon if (sa->sa_len == 0) 21959290Sjlemon sa->sa_len = sizeof(long); 22059290Sjlemon sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 22159290Sjlemon p_sockaddr(sa, 18); 22259290Sjlemon lp = (int *)(sa->sa_len + (char *)sa); 22359290Sjlemon if ((char *)lp < (char *)wp && *lp) { 22459290Sjlemon#ifdef DEBUG 22559290Sjlemon logprintf(" flag = %x, rest = %d", rtm->rtm_flags, *lp); 22659290Sjlemon#endif 22759290Sjlemon wp = (u_char *)(lp + 1); 22859290Sjlemon mask = 0; 22959290Sjlemon for (nb = *lp; nb > 4; nb--) { 23059290Sjlemon mask <<= 8; 23159290Sjlemon mask |= *wp++; 23259290Sjlemon } 23359290Sjlemon for (nb = 8 - *lp; nb > 0; nb--) 23459290Sjlemon mask <<= 8; 23559290Sjlemon } 23659290Sjlemon } 23759290Sjlemon printf("%08lx ", mask); 23859290Sjlemon p_flags(rtm->rtm_flags & (RTF_UP|RTF_GATEWAY|RTF_HOST), "%-6.6s "); 23959290Sjlemon printf("(%d)\n", rtm->rtm_index); 24059290Sjlemon } 24159290Sjlemon 24259290Sjlemon return(1); 24359290Sjlemon} 24459290Sjlemon 24559290Sjlemon/* 24659290Sjlemon * Delete routes associated with our interface 24759290Sjlemon */ 24859290Sjlemonvoid 24959290SjlemonDeleteIfRoutes(all) 25059290Sjlemonint all; 25159290Sjlemon{ 25259290Sjlemon struct rt_msghdr *rtm; 25359290Sjlemon struct sockaddr *sa; 25459290Sjlemon struct in_addr dstnet, gateway; 25559290Sjlemon int needed; 25659290Sjlemon char *sp, *cp, *ep; 25759290Sjlemon u_long mask; 25859290Sjlemon int *lp, nb; 25959290Sjlemon u_char *wp; 26059290Sjlemon#if (BSD >= 199306) 26159290Sjlemon int mib[6]; 26259290Sjlemon#endif 26359290Sjlemon 26459290Sjlemon#ifdef DEBUG 26559290Sjlemon logprintf("DeleteIfRoutes (%d)\n", IfIndex); 26659290Sjlemon#endif 26759290Sjlemon#if (BSD >= 199306) 26859290Sjlemon mib[0] = CTL_NET; 26959290Sjlemon mib[1] = PF_ROUTE; 27059290Sjlemon mib[2] = 0; 27159290Sjlemon mib[3] = 0; 27259290Sjlemon mib[4] = NET_RT_DUMP; 27359290Sjlemon mib[5] = 0; 27459290Sjlemon if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 27559290Sjlemon perror("sysctl-estimate"); 27659290Sjlemon return; 27759290Sjlemon } 27859290Sjlemon#else 27959290Sjlemon needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0); 28059290Sjlemon#endif 28159290Sjlemon 28259290Sjlemon if (needed < 0) 28359290Sjlemon return; 28459290Sjlemon 28559290Sjlemon sp = malloc(needed); 28659290Sjlemon if (sp == NULL) 28759290Sjlemon return; 28859290Sjlemon 28959290Sjlemon#if (BSD >= 199306) 29059290Sjlemon if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 29159290Sjlemon free(sp); 29259290Sjlemon perror("sysctl-getroute"); 29359290Sjlemon return; 29459290Sjlemon } 29559290Sjlemon#else 29659290Sjlemon if (getkerninfo(KINFO_RT_DUMP, sp, &needed, 0) < 0) { 29759290Sjlemon free(sp); 29859290Sjlemon return; 29959290Sjlemon } 30059290Sjlemon#endif 30159290Sjlemon ep = sp + needed; 30259290Sjlemon 30359290Sjlemon for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 30459290Sjlemon rtm = (struct rt_msghdr *)cp; 30559290Sjlemon sa = (struct sockaddr *)(rtm + 1); 30659290Sjlemon#ifdef DEBUG 30759290Sjlemon logprintf("addrs: %x, index: %d, flags: %x, dstnet: %x\n", 30859290Sjlemon rtm->rtm_addrs, rtm->rtm_index, rtm->rtm_flags, 30959290Sjlemon ((struct sockaddr_in *)sa)->sin_addr); 31059290Sjlemon#endif 31159290Sjlemon if (rtm->rtm_addrs != RTA_DST && 31259290Sjlemon (rtm->rtm_index == IfIndex) && 31359290Sjlemon (all || (rtm->rtm_flags & RTF_GATEWAY))) { 31459290Sjlemon dstnet = ((struct sockaddr_in *)sa)->sin_addr; 31559290Sjlemon wp = (u_char *)cp + rtm->rtm_msglen; 31659290Sjlemon if (sa->sa_len == 0) 31759290Sjlemon sa->sa_len = sizeof(long); 31859290Sjlemon sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 31959290Sjlemon gateway = ((struct sockaddr_in *)sa)->sin_addr; 32059290Sjlemon lp = (int *)(sa->sa_len + (char *)sa); 32159290Sjlemon mask = 0; 32259290Sjlemon if ((char *)lp < (char *)wp && *lp) { 32359290Sjlemon#ifdef DEBUG 32459290Sjlemon printf(" flag = %x, rest = %d", rtm->rtm_flags, *lp); 32559290Sjlemon#endif 32659290Sjlemon wp = (u_char *)(lp + 1); 32759290Sjlemon for (nb = *lp; nb > 4; nb--) { 32859290Sjlemon mask <<= 8; 32959290Sjlemon mask |= *wp++; 33059290Sjlemon } 33159290Sjlemon for (nb = 8 - *lp; nb > 0; nb--) 33259290Sjlemon mask <<= 8; 33359290Sjlemon } 33459290Sjlemon#ifdef DEBUG 33559290Sjlemon logprintf("## %s ", inet_ntoa(dstnet)); 33659290Sjlemon logprintf(" %s %d\n", inet_ntoa(gateway), rtm->rtm_index); 33759290Sjlemon#endif 33859290Sjlemon if (dstnet.s_addr == INADDR_ANY) { 33959290Sjlemon gateway.s_addr = INADDR_ANY; 34059290Sjlemon mask = INADDR_ANY; 34159290Sjlemon } 34259290Sjlemon OsSetRoute(RTM_DELETE, dstnet, gateway, htonl(mask)); 34359290Sjlemon } 34459290Sjlemon#ifdef DEBUG 34559290Sjlemon else if (rtm->rtm_index == IfIndex) { 34659290Sjlemon logprintf("??? addrs: %x, flags = %x\n", rtm->rtm_addrs, rtm->rtm_flags); 34759290Sjlemon } 34859290Sjlemon#endif 34959290Sjlemon } 35059290Sjlemon free(sp); 35159290Sjlemon} 35259290Sjlemon 35359290Sjlemonint 35459290SjlemonGetIfIndex(name) 35559290Sjlemonchar *name; 35659290Sjlemon{ 35759290Sjlemon struct ifreq *ifrp; 35859290Sjlemon int s, len, elen, index; 35959290Sjlemon struct ifconf ifconfs; 36059290Sjlemon struct ifreq reqbuf[32]; 36159290Sjlemon 36259290Sjlemon s = socket(AF_INET, SOCK_DGRAM, 0); 36359290Sjlemon if (s < 0) { 36459290Sjlemon perror("socket"); 36559290Sjlemon return(-1); 36659290Sjlemon } 36759290Sjlemon 36859290Sjlemon ifconfs.ifc_len = sizeof(reqbuf); 36959290Sjlemon ifconfs.ifc_buf = (caddr_t)reqbuf; 37059290Sjlemon if (ioctl(s, SIOCGIFCONF, &ifconfs) < 0) { 37159290Sjlemon perror("IFCONF"); 37259290Sjlemon return(-1); 37359290Sjlemon } 37459290Sjlemon 37559290Sjlemon ifrp = ifconfs.ifc_req; 37659290Sjlemon 37759290Sjlemon index = 1; 37859290Sjlemon for (len = ifconfs.ifc_len; len > 0; len -= sizeof(struct ifreq)) { 37959290Sjlemon elen = ifrp->ifr_addr.sa_len - sizeof(struct sockaddr); 38059290Sjlemon if (ifrp->ifr_addr.sa_family == AF_LINK) { 38159290Sjlemon#ifdef DEBUG 38259290Sjlemon logprintf("%d: %-*.*s, %d, %d\n", index, IFNAMSIZ, IFNAMSIZ, ifrp->ifr_name, 38359290Sjlemon ifrp->ifr_addr.sa_family, elen); 38459290Sjlemon#endif 38559290Sjlemon if (strcmp(ifrp->ifr_name, name) == 0) { 38659290Sjlemon IfIndex = index; 38759290Sjlemon return(index); 38859290Sjlemon } 38959290Sjlemon index++; 39059290Sjlemon } 39159290Sjlemon 39259290Sjlemon len -= elen; 39359290Sjlemon ifrp = (struct ifreq *)((char *)ifrp + elen); 39459290Sjlemon ifrp++; 39559290Sjlemon } 39659290Sjlemon 39759290Sjlemon close(s); 39859290Sjlemon return(-1); 39959290Sjlemon} 40059290Sjlemon