route.c revision 13389
1133808Spjd/* 2142727Spjd * PPP Routing related Module 3133808Spjd * 4133808Spjd * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5133808Spjd * 6133808Spjd * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 7133808Spjd * 8133808Spjd * Redistribution and use in source and binary forms are permitted 9133808Spjd * provided that the above copyright notice and this paragraph are 10133808Spjd * duplicated in all such forms and that any documentation, 11133808Spjd * advertising materials, and other materials related to such 12133808Spjd * distribution and use acknowledge that the software was developed 13155175Spjd * by the Internet Initiative Japan, Inc. The name of the 14133808Spjd * IIJ may not be used to endorse or promote products derived 15133808Spjd * from this software without specific prior written permission. 16133808Spjd * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17133808Spjd * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18133808Spjd * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19133808Spjd * 20133808Spjd * $Id: route.c,v 1.4 1995/07/08 06:08:52 amurai Exp $ 21133808Spjd * 22133808Spjd */ 23133808Spjd#include <sys/types.h> 24133808Spjd#include <machine/endian.h> 25133808Spjd#include <sys/param.h> 26133808Spjd#include <sys/socket.h> 27133808Spjd#include <net/route.h> 28133808Spjd#include <sys/ioctl.h> 29133808Spjd#include <net/if.h> 30133808Spjd#include <errno.h> 31133808Spjd#include <netinet/in_systm.h> 32133808Spjd#include <netinet/in.h> 33133808Spjd#include <arpa/inet.h> 34133808Spjd#if (BSD >= 199306) 35133808Spjd#include <sys/sysctl.h> 36133808Spjd#else 37133808Spjd#include <sys/kinfo.h> 38133808Spjd#endif 39133808Spjd#include <stdlib.h> 40133808Spjd#include <stdio.h> 41133808Spjd#include <string.h> 42133808Spjd#include <unistd.h> 43133808Spjd#include "log.h" 44133808Spjd 45133808Spjdstatic int IfIndex; 46133808Spjd 47133808Spjdstruct rtmsg { 48133808Spjd struct rt_msghdr m_rtm; 49133808Spjd char m_space[64]; 50133808Spjd}; 51133808Spjd 52133808Spjdstatic int seqno; 53133808Spjd 54143586Spjdvoid 55143586SpjdOsSetRoute(cmd, dst, gateway, mask) 56143586Spjdint cmd; 57133808Spjdstruct in_addr dst; 58133808Spjdstruct in_addr gateway; 59133808Spjdstruct in_addr mask; 60133808Spjd{ 61133808Spjd struct rtmsg rtmes; 62133808Spjd int s, nb, wb; 63134124Spjd char *cp; 64134124Spjd u_long *lp; 65134168Spjd struct sockaddr_in rtdata; 66134168Spjd 67133808Spjd s = socket(PF_ROUTE, SOCK_RAW, 0); 68143586Spjd if (s < 0) 69143586Spjd logprintf("socket\n"); 70133808Spjd 71143586Spjd bzero(&rtmes, sizeof(rtmes)); 72143586Spjd rtmes.m_rtm.rtm_version = RTM_VERSION; 73143586Spjd rtmes.m_rtm.rtm_type = cmd; 74133808Spjd rtmes.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK; 75133808Spjd if (cmd == RTM_ADD) rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY; 76133808Spjd rtmes.m_rtm.rtm_seq = ++seqno; 77133808Spjd rtmes.m_rtm.rtm_pid = getpid(); 78133808Spjd rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY; 79143586Spjd 80143586Spjd bzero(&rtdata, sizeof(rtdata)); 81133808Spjd rtdata.sin_len = 16; 82133808Spjd rtdata.sin_family = AF_INET; 83133808Spjd rtdata.sin_port = 0; 84133808Spjd rtdata.sin_addr = dst; 85133808Spjd 86134124Spjd cp = rtmes.m_space; 87134168Spjd bcopy(&rtdata, cp, 16); 88133808Spjd cp += 16; 89143586Spjd if (gateway.s_addr) { 90143586Spjd rtdata.sin_addr = gateway; 91133808Spjd bcopy(&rtdata, cp, 16); 92143586Spjd cp += 16; 93143586Spjd } 94143586Spjd 95133808Spjd if (dst.s_addr == INADDR_ANY) 96133808Spjd mask.s_addr = INADDR_ANY; 97133808Spjd 98133808Spjd lp = (u_long *)cp; 99143586Spjd 100143586Spjd if (mask.s_addr) { 101133808Spjd *lp++ = 8; 102133808Spjd cp += sizeof(int); 103133808Spjd *lp = mask.s_addr; 104133808Spjd } else 105133808Spjd *lp = 0; 106143586Spjd cp += sizeof(u_long); 107143586Spjd 108133808Spjd nb = cp - (char *)&rtmes; 109133808Spjd rtmes.m_rtm.rtm_msglen = nb; 110133808Spjd wb = write(s, &rtmes, nb); 111133808Spjd if (wb < 0) { 112133808Spjd LogPrintf(LOG_TCPIP, "Already set route addr dst=%x, gateway=%x\n" 113133808Spjd ,dst.s_addr, gateway.s_addr); 114133808Spjd } 115133808Spjd#ifdef DEBUG 116133808Spjd logprintf("wrote %d: dst = %x, gateway = %x\n", nb, dst.s_addr, gateway.s_addr); 117133808Spjd#endif 118133808Spjd close(s); 119133808Spjd} 120133808Spjd 121133808Spjdstatic void 122153190Spjdp_sockaddr(sa, width) 123133808Spjdstruct sockaddr *sa; 124133808Spjdint width; 125133808Spjd{ 126133808Spjd register char *cp; 127133808Spjd register struct sockaddr_in *sin = (struct sockaddr_in *)sa; 128133808Spjd 129133808Spjd cp = (sin->sin_addr.s_addr == 0) ? "default" : 130133808Spjd inet_ntoa(sin->sin_addr); 131133808Spjd printf("%-*.*s ", width, width, cp); 132133808Spjd} 133133808Spjd 134133808Spjdstruct bits { 135133808Spjd short b_mask; 136133808Spjd char b_val; 137133808Spjd} bits[] = { 138133808Spjd { RTF_UP, 'U' }, 139133808Spjd { RTF_GATEWAY, 'G' }, 140133808Spjd { RTF_HOST, 'H' }, 141133808Spjd { RTF_DYNAMIC, 'D' }, 142133808Spjd { RTF_MODIFIED, 'M' }, 143134420Spjd { RTF_CLONING, 'C' }, 144134420Spjd { RTF_XRESOLVE, 'X' }, 145153190Spjd { RTF_LLINFO, 'L' }, 146133808Spjd { RTF_REJECT, 'R' }, 147153190Spjd { 0 } 148153190Spjd}; 149133808Spjd 150133808Spjdstatic void 151133808Spjdp_flags(f, format) 152153190Spjdregister int f; 153133808Spjdchar *format; 154133808Spjd{ 155133808Spjd char name[33], *flags; 156133808Spjd register struct bits *p = bits; 157133808Spjd 158133808Spjd for (flags = name; p->b_mask; p++) 159153190Spjd if (p->b_mask & f) 160133808Spjd *flags++ = p->b_val; 161147947Spjd *flags = '\0'; 162153190Spjd printf(format, name); 163133808Spjd} 164133808Spjd 165139295Spjdint 166133808SpjdShowRoute() 167133808Spjd{ 168153190Spjd struct rt_msghdr *rtm; 169153190Spjd struct sockaddr *sa; 170133808Spjd char *sp, *ep, *cp; 171153190Spjd u_char *wp; 172153190Spjd int *lp; 173134124Spjd int needed, nb; 174153190Spjd u_long mask; 175153190Spjd#if (BSD >= 199306) 176134168Spjd int mib[6]; 177153190Spjd#endif 178134168Spjd 179134168Spjd#if (BSD >= 199306) 180134168Spjd mib[0] = CTL_NET; 181153190Spjd mib[1] = PF_ROUTE; 182133808Spjd mib[2] = 0; 183133808Spjd mib[3] = 0; 184133808Spjd mib[4] = NET_RT_DUMP; 185133808Spjd mib[5] = 0; 186133808Spjd if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 187133808Spjd perror("sysctl-estimate"); 188133808Spjd return(1); 189153190Spjd } 190153190Spjd#else 191133808Spjd needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0); 192133808Spjd#endif 193133808Spjd if (needed < 0) 194133808Spjd return(1); 195133808Spjd sp = malloc(needed); 196133808Spjd if (sp == NULL) 197133808Spjd return(1); 198133808Spjd#if (BSD >= 199306) 199133808Spjd if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 200133808Spjd perror("sysctl-getroute"); 201133808Spjd return(1); 202133808Spjd } 203133808Spjd#else 204133808Spjd if (getkerninfo(KINFO_RT_DUMP, sp, &needed, 0) < 0) 205133808Spjd return(1); 206153190Spjd#endif 207153190Spjd ep = sp + needed; 208133808Spjd 209133808Spjd for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 210133808Spjd rtm = (struct rt_msghdr *)cp; 211133808Spjd sa = (struct sockaddr *)(rtm + 1); 212153190Spjd mask = 0xffffffff; 213153190Spjd if (rtm->rtm_addrs == RTA_DST) 214133808Spjd p_sockaddr(sa, 36); 215133808Spjd else { 216133808Spjd wp = (u_char *)cp + rtm->rtm_msglen; 217133808Spjd p_sockaddr(sa, 16); 218133808Spjd if (sa->sa_len == 0) 219133808Spjd sa->sa_len = sizeof(long); 220133808Spjd sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 221133808Spjd p_sockaddr(sa, 18); 222133808Spjd lp = (int *)(sa->sa_len + (char *)sa); 223133808Spjd if ((char *)lp < (char *)wp && *lp) { 224133808Spjd#ifdef DEBUG 225153190Spjd logprintf(" flag = %x, rest = %d", rtm->rtm_flags, *lp); 226153190Spjd#endif 227142727Spjd wp = (u_char *)(lp + 1); 228142727Spjd mask = 0; 229142727Spjd for (nb = *lp; nb > 4; nb--) { 230134420Spjd mask <<= 8; 231134420Spjd mask |= *wp++; 232142727Spjd } 233134420Spjd for (nb = 8 - *lp; nb > 0; nb--) 234134420Spjd mask <<= 8; 235133808Spjd } 236142727Spjd } 237153190Spjd printf("%08lx ", mask); 238133808Spjd p_flags(rtm->rtm_flags & (RTF_UP|RTF_GATEWAY|RTF_HOST), "%-6.6s "); 239133808Spjd printf("(%d)\n", rtm->rtm_index); 240133808Spjd } 241133808Spjd 242133808Spjd return(1); 243133808Spjd} 244153190Spjd 245134539Spjd/* 246134539Spjd * Delete routes associated with our interface 247134539Spjd */ 248134539Spjdvoid 249134539SpjdDeleteIfRoutes(all) 250134539Spjdint all; 251133808Spjd{ 252133808Spjd struct rt_msghdr *rtm; 253133808Spjd struct sockaddr *sa; 254133808Spjd struct in_addr dstnet, gateway; 255133808Spjd int needed; 256133808Spjd char *sp, *cp, *ep; 257133808Spjd u_long mask; 258133808Spjd int *lp, nb; 259133808Spjd u_char *wp; 260133808Spjd#if (BSD >= 199306) 261133808Spjd int mib[6]; 262133808Spjd#endif 263133808Spjd 264133808Spjd#ifdef DEBUG 265133808Spjd logprintf("DeleteIfRoutes (%d)\n", IfIndex); 266133808Spjd#endif 267133808Spjd#if (BSD >= 199306) 268153190Spjd mib[0] = CTL_NET; 269133808Spjd mib[1] = PF_ROUTE; 270153190Spjd mib[2] = 0; 271153190Spjd mib[3] = 0; 272133808Spjd mib[4] = NET_RT_DUMP; 273133808Spjd mib[5] = 0; 274133808Spjd if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 275133808Spjd perror("sysctl-estimate"); 276153190Spjd return; 277153190Spjd } 278133808Spjd#else 279133808Spjd needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0); 280133808Spjd#endif 281133808Spjd 282133808Spjd if (needed < 0) 283133808Spjd return; 284133808Spjd 285133808Spjd sp = malloc(needed); 286155175Spjd if (sp == NULL) 287133808Spjd return; 288133808Spjd 289133808Spjd#if (BSD >= 199306) 290133808Spjd if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 291133808Spjd free(sp); 292133808Spjd perror("sysctl-getroute"); 293133808Spjd return; 294133808Spjd } 295153190Spjd#else 296133808Spjd if (getkerninfo(KINFO_RT_DUMP, sp, &needed, 0) < 0) { 297153190Spjd free(sp); 298153190Spjd return; 299133808Spjd } 300133808Spjd#endif 301133808Spjd ep = sp + needed; 302133808Spjd 303153190Spjd for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 304153190Spjd rtm = (struct rt_msghdr *)cp; 305133808Spjd sa = (struct sockaddr *)(rtm + 1); 306133808Spjd#ifdef DEBUG 307133808Spjd logprintf("addrs: %x, index: %d, flags: %x, dstnet: %x\n", 308133808Spjd rtm->rtm_addrs, rtm->rtm_index, rtm->rtm_flags, 309133808Spjd ((struct sockaddr_in *)sa)->sin_addr); 310133808Spjd#endif 311133808Spjd if (rtm->rtm_addrs != RTA_DST && 312133808Spjd (rtm->rtm_index == IfIndex) && 313133808Spjd (all || (rtm->rtm_flags & RTF_GATEWAY))) { 314133808Spjd dstnet = ((struct sockaddr_in *)sa)->sin_addr; 315133808Spjd wp = (u_char *)cp + rtm->rtm_msglen; 316133808Spjd if (sa->sa_len == 0) 317133808Spjd sa->sa_len = sizeof(long); 318133808Spjd sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 319133808Spjd gateway = ((struct sockaddr_in *)sa)->sin_addr; 320133808Spjd lp = (int *)(sa->sa_len + (char *)sa); 321133808Spjd mask = 0; 322133808Spjd if ((char *)lp < (char *)wp && *lp) { 323133808Spjd#ifdef DEBUG 324 printf(" flag = %x, rest = %d", rtm->rtm_flags, *lp); 325#endif 326 wp = (u_char *)(lp + 1); 327 for (nb = *lp; nb > 4; nb--) { 328 mask <<= 8; 329 mask |= *wp++; 330 } 331 for (nb = 8 - *lp; nb > 0; nb--) 332 mask <<= 8; 333 } 334#ifdef DEBUG 335 logprintf("## %s ", inet_ntoa(dstnet)); 336 logprintf(" %s %d\n", inet_ntoa(gateway), rtm->rtm_index); 337#endif 338 if (dstnet.s_addr == INADDR_ANY) { 339 gateway.s_addr = INADDR_ANY; 340 mask = INADDR_ANY; 341 } 342 OsSetRoute(RTM_DELETE, dstnet, gateway, htonl(mask)); 343 } 344#ifdef DEBUG 345 else if (rtm->rtm_index == IfIndex) { 346 logprintf("??? addrs: %x, flags = %x\n", rtm->rtm_addrs, rtm->rtm_flags); 347 } 348#endif 349 } 350 free(sp); 351} 352 353int 354GetIfIndex(name) 355char *name; 356{ 357 struct ifreq *ifrp; 358 int s, len, elen, index; 359 struct ifconf ifconfs; 360 struct ifreq reqbuf[32]; 361 362 s = socket(AF_INET, SOCK_DGRAM, 0); 363 if (s < 0) { 364 perror("socket"); 365 return(-1); 366 } 367 368 ifconfs.ifc_len = sizeof(reqbuf); 369 ifconfs.ifc_buf = (caddr_t)reqbuf; 370 if (ioctl(s, SIOCGIFCONF, &ifconfs) < 0) { 371 perror("IFCONF"); 372 return(-1); 373 } 374 375 ifrp = ifconfs.ifc_req; 376 377 index = 1; 378 for (len = ifconfs.ifc_len; len > 0; len -= sizeof(struct ifreq)) { 379 elen = ifrp->ifr_addr.sa_len - sizeof(struct sockaddr); 380 if (ifrp->ifr_addr.sa_family == AF_LINK) { 381#ifdef DEBUG 382 logprintf("%d: %-*.*s, %d, %d\n", index, IFNAMSIZ, IFNAMSIZ, ifrp->ifr_name, 383 ifrp->ifr_addr.sa_family, elen); 384#endif 385 if (strcmp(ifrp->ifr_name, name) == 0) { 386 IfIndex = index; 387 return(index); 388 } 389 index++; 390 } 391 392 len -= elen; 393 ifrp = (struct ifreq *)((char *)ifrp + elen); 394 ifrp++; 395 } 396 397 close(s); 398 return(-1); 399} 400