route.c revision 28679
1230557Sjimharris/* 2230557Sjimharris * PPP Routing related Module 3230557Sjimharris * 4230557Sjimharris * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5230557Sjimharris * 6230557Sjimharris * Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd. 7230557Sjimharris * 8230557Sjimharris * Redistribution and use in source and binary forms are permitted 9230557Sjimharris * provided that the above copyright notice and this paragraph are 10230557Sjimharris * duplicated in all such forms and that any documentation, 11230557Sjimharris * advertising materials, and other materials related to such 12230557Sjimharris * distribution and use acknowledge that the software was developed 13230557Sjimharris * by the Internet Initiative Japan, Inc. The name of the 14230557Sjimharris * IIJ may not be used to endorse or promote products derived 15230557Sjimharris * from this software without specific prior written permission. 16230557Sjimharris * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17230557Sjimharris * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18230557Sjimharris * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19230557Sjimharris * 20230557Sjimharris * $Id: route.c,v 1.17 1997/07/28 01:02:27 brian Exp $ 21230557Sjimharris * 22230557Sjimharris */ 23230557Sjimharris#include <sys/types.h> 24230557Sjimharris#include <machine/endian.h> 25230557Sjimharris#include <sys/ioctl.h> 26230557Sjimharris#include <sys/param.h> 27230557Sjimharris#include <sys/socket.h> 28230557Sjimharris#include <sys/sysctl.h> 29230557Sjimharris#include <sys/time.h> 30230557Sjimharris 31230557Sjimharris#include <errno.h> 32230557Sjimharris#include <stdlib.h> 33230557Sjimharris#include <stdio.h> 34230557Sjimharris#include <string.h> 35230557Sjimharris#include <unistd.h> 36230557Sjimharris 37230557Sjimharris#include <net/route.h> 38230557Sjimharris#include <net/if.h> 39230557Sjimharris#include <netinet/in_systm.h> 40230557Sjimharris#include <netinet/in.h> 41230557Sjimharris#include <arpa/inet.h> 42230557Sjimharris 43230557Sjimharris#include "log.h" 44230557Sjimharris#include "loadalias.h" 45230557Sjimharris#include "vars.h" 46230557Sjimharris 47230557Sjimharrisstatic int IfIndex; 48230557Sjimharris 49230557Sjimharrisstruct rtmsg { 50230557Sjimharris struct rt_msghdr m_rtm; 51230557Sjimharris char m_space[64]; 52230557Sjimharris}; 53230557Sjimharris 54230557Sjimharrisstatic int seqno; 55230557Sjimharris 56230557Sjimharrisvoid 57230557SjimharrisOsSetRoute(int cmd, 58230557Sjimharris struct in_addr dst, 59230557Sjimharris struct in_addr gateway, 60230557Sjimharris struct in_addr mask) 61230557Sjimharris{ 62230557Sjimharris struct rtmsg rtmes; 63230557Sjimharris int s, nb, wb; 64230557Sjimharris char *cp; 65230557Sjimharris u_long *lp; 66230557Sjimharris struct sockaddr_in rtdata; 67230557Sjimharris 68230557Sjimharris s = socket(PF_ROUTE, SOCK_RAW, 0); 69230557Sjimharris if (s < 0) { 70230557Sjimharris LogPrintf(LogERROR, "OsSetRoute: socket: %s", strerror(errno)); 71230557Sjimharris return; 72230557Sjimharris } 73230557Sjimharris bzero(&rtmes, sizeof(rtmes)); 74230557Sjimharris rtmes.m_rtm.rtm_version = RTM_VERSION; 75230557Sjimharris rtmes.m_rtm.rtm_type = cmd; 76230557Sjimharris rtmes.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK | RTA_GATEWAY; 77230557Sjimharris rtmes.m_rtm.rtm_seq = ++seqno; 78230557Sjimharris rtmes.m_rtm.rtm_pid = getpid(); 79230557Sjimharris rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 80230557Sjimharris 81230557Sjimharris bzero(&rtdata, sizeof(rtdata)); 82230557Sjimharris rtdata.sin_len = 16; 83230557Sjimharris rtdata.sin_family = AF_INET; 84230557Sjimharris rtdata.sin_port = 0; 85230557Sjimharris rtdata.sin_addr = dst; 86230557Sjimharris 87230557Sjimharris cp = rtmes.m_space; 88230557Sjimharris bcopy(&rtdata, cp, 16); 89230557Sjimharris cp += 16; 90230557Sjimharris if (gateway.s_addr) { 91230557Sjimharris rtdata.sin_addr = gateway; 92230557Sjimharris bcopy(&rtdata, cp, 16); 93230557Sjimharris cp += 16; 94230557Sjimharris } 95230557Sjimharris if (dst.s_addr == INADDR_ANY) 96230557Sjimharris mask.s_addr = INADDR_ANY; 97230557Sjimharris 98230557Sjimharris lp = (u_long *) cp; 99230557Sjimharris 100230557Sjimharris if (mask.s_addr) { 101230557Sjimharris *lp++ = 8; 102230557Sjimharris cp += sizeof(int); 103230557Sjimharris *lp = mask.s_addr; 104230557Sjimharris } else 105230557Sjimharris *lp = 0; 106230557Sjimharris cp += sizeof(u_long); 107230557Sjimharris 108230557Sjimharris nb = cp - (char *) &rtmes; 109230557Sjimharris rtmes.m_rtm.rtm_msglen = nb; 110230557Sjimharris wb = write(s, &rtmes, nb); 111230557Sjimharris if (wb < 0) { 112230557Sjimharris LogPrintf(LogTCPIP, "OsSetRoute: Dst = %s\n", inet_ntoa(dst)); 113230557Sjimharris LogPrintf(LogTCPIP, "OsSetRoute: Gateway = %s\n", inet_ntoa(gateway)); 114230557Sjimharris LogPrintf(LogTCPIP, "OsSetRoute: Mask = %s\n", inet_ntoa(mask)); 115230557Sjimharris switch (rtmes.m_rtm.rtm_errno) { 116230557Sjimharris case EEXIST: 117230557Sjimharris LogPrintf(LogTCPIP, "Add route failed: Already exists\n"); 118230557Sjimharris break; 119230557Sjimharris case ESRCH: 120230557Sjimharris LogPrintf(LogTCPIP, "Del route failed: Non-existent\n"); 121230557Sjimharris break; 122230557Sjimharris case ENOBUFS: 123230557Sjimharris default: 124230557Sjimharris LogPrintf(LogTCPIP, "Add/Del route failed: %s\n", 125230557Sjimharris strerror(rtmes.m_rtm.rtm_errno)); 126230557Sjimharris break; 127230557Sjimharris } 128230557Sjimharris } 129230557Sjimharris LogPrintf(LogDEBUG, "wrote %d: dst = %x, gateway = %x\n", nb, 130230557Sjimharris dst.s_addr, gateway.s_addr); 131230557Sjimharris close(s); 132230557Sjimharris} 133230557Sjimharris 134230557Sjimharrisstatic void 135230557Sjimharrisp_sockaddr(struct sockaddr * sa, int width) 136230557Sjimharris{ 137230557Sjimharris if (VarTerm) { 138230557Sjimharris register char *cp; 139230557Sjimharris register struct sockaddr_in *sin = (struct sockaddr_in *) sa; 140230557Sjimharris 141230557Sjimharris cp = (sin->sin_addr.s_addr == 0) ? "default" : 142230557Sjimharris inet_ntoa(sin->sin_addr); 143230557Sjimharris fprintf(VarTerm, "%-*.*s ", width, width, cp); 144230557Sjimharris } 145230557Sjimharris} 146230557Sjimharris 147230557Sjimharrisstruct bits { 148230557Sjimharris short b_mask; 149230557Sjimharris char b_val; 150230557Sjimharris} bits[] = { 151230557Sjimharris 152230557Sjimharris { 153230557Sjimharris RTF_UP, 'U' 154230557Sjimharris }, 155230557Sjimharris { 156240518Seadler RTF_GATEWAY, 'G' 157230557Sjimharris }, 158230557Sjimharris { 159230557Sjimharris RTF_HOST, 'H' 160230557Sjimharris }, 161230557Sjimharris { 162230557Sjimharris RTF_DYNAMIC, 'D' 163230557Sjimharris }, 164230557Sjimharris { 165230557Sjimharris RTF_MODIFIED, 'M' 166230557Sjimharris }, 167230557Sjimharris { 168230557Sjimharris RTF_CLONING, 'C' 169230557Sjimharris }, 170230557Sjimharris { 171230557Sjimharris RTF_XRESOLVE, 'X' 172230557Sjimharris }, 173230557Sjimharris { 174230557Sjimharris RTF_LLINFO, 'L' 175230557Sjimharris }, 176230557Sjimharris { 177230557Sjimharris RTF_REJECT, 'R' 178230557Sjimharris }, 179230557Sjimharris { 180230557Sjimharris 0 181230557Sjimharris } 182230557Sjimharris}; 183230557Sjimharris 184230557Sjimharrisstatic void 185230557Sjimharrisp_flags(int f, char *format) 186230557Sjimharris{ 187230557Sjimharris if (VarTerm) { 188230557Sjimharris char name[33], *flags; 189230557Sjimharris register struct bits *p = bits; 190230557Sjimharris 191230557Sjimharris for (flags = name; p->b_mask; p++) 192230557Sjimharris if (p->b_mask & f) 193230557Sjimharris *flags++ = p->b_val; 194230557Sjimharris *flags = '\0'; 195230557Sjimharris fprintf(VarTerm, format, name); 196230557Sjimharris } 197230557Sjimharris} 198230557Sjimharris 199230557Sjimharrisint 200230557SjimharrisShowRoute() 201230557Sjimharris{ 202230557Sjimharris struct rt_msghdr *rtm; 203230557Sjimharris struct sockaddr *sa; 204230557Sjimharris char *sp, *ep, *cp; 205230557Sjimharris u_char *wp; 206230557Sjimharris int *lp; 207230557Sjimharris int needed, nb; 208230557Sjimharris u_long mask; 209230557Sjimharris int mib[6]; 210230557Sjimharris 211230557Sjimharris if (!VarTerm) 212230557Sjimharris return 1; 213230557Sjimharris 214230557Sjimharris mib[0] = CTL_NET; 215230557Sjimharris mib[1] = PF_ROUTE; 216230557Sjimharris mib[2] = 0; 217230557Sjimharris mib[3] = 0; 218230557Sjimharris mib[4] = NET_RT_DUMP; 219230557Sjimharris mib[5] = 0; 220230557Sjimharris if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 221230557Sjimharris LogPrintf(LogERROR, "sysctl: estimate: %s", strerror(errno)); 222230557Sjimharris return (1); 223230557Sjimharris } 224230557Sjimharris if (needed < 0) 225230557Sjimharris return (1); 226230557Sjimharris sp = malloc(needed); 227230557Sjimharris if (sp == NULL) 228230557Sjimharris return (1); 229230557Sjimharris if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 230230557Sjimharris LogPrintf(LogERROR, "sysctl: getroute: %s", strerror(errno)); 231230557Sjimharris free(sp); 232230557Sjimharris return (1); 233230557Sjimharris } 234230557Sjimharris ep = sp + needed; 235230557Sjimharris 236230557Sjimharris for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 237230557Sjimharris rtm = (struct rt_msghdr *) cp; 238230557Sjimharris sa = (struct sockaddr *) (rtm + 1); 239230557Sjimharris mask = 0xffffffff; 240230557Sjimharris if (rtm->rtm_addrs == RTA_DST) 241230557Sjimharris p_sockaddr(sa, 36); 242230557Sjimharris else { 243230557Sjimharris wp = (u_char *) cp + rtm->rtm_msglen; 244230557Sjimharris p_sockaddr(sa, 16); 245230557Sjimharris if (sa->sa_len == 0) 246230557Sjimharris sa->sa_len = sizeof(long); 247230557Sjimharris sa = (struct sockaddr *) (sa->sa_len + (char *) sa); 248230557Sjimharris p_sockaddr(sa, 18); 249230557Sjimharris lp = (int *) (sa->sa_len + (char *) sa); 250230557Sjimharris if ((char *) lp < (char *) wp && *lp) { 251230557Sjimharris LogPrintf(LogDEBUG, " flag = %x, rest = %d", rtm->rtm_flags, *lp); 252230557Sjimharris wp = (u_char *) (lp + 1); 253230557Sjimharris mask = 0; 254230557Sjimharris for (nb = *(char *) lp; nb > 4; nb--) { 255230557Sjimharris mask <<= 8; 256230557Sjimharris mask |= *wp++; 257230557Sjimharris } 258230557Sjimharris for (nb = 8 - *(char *) lp; nb > 0; nb--) 259230557Sjimharris mask <<= 8; 260230557Sjimharris } 261230557Sjimharris } 262230557Sjimharris fprintf(VarTerm, "%08lx ", mask); 263230557Sjimharris p_flags(rtm->rtm_flags & (RTF_UP | RTF_GATEWAY | RTF_HOST), "%-6.6s "); 264230557Sjimharris fprintf(VarTerm, "(%d)\n", rtm->rtm_index); 265230557Sjimharris } 266230557Sjimharris free(sp); 267230557Sjimharris return 0; 268230557Sjimharris} 269230557Sjimharris 270230557Sjimharris/* 271230557Sjimharris * Delete routes associated with our interface 272230557Sjimharris */ 273230557Sjimharrisvoid 274230557SjimharrisDeleteIfRoutes(int all) 275230557Sjimharris{ 276230557Sjimharris struct rt_msghdr *rtm; 277230557Sjimharris struct sockaddr *sa; 278230557Sjimharris struct in_addr dstnet, gateway, maddr; 279230557Sjimharris int needed; 280230557Sjimharris char *sp, *cp, *ep; 281230557Sjimharris u_long mask; 282230557Sjimharris int *lp, nb; 283230557Sjimharris u_char *wp; 284230557Sjimharris int mib[6]; 285230557Sjimharris 286230557Sjimharris LogPrintf(LogDEBUG, "DeleteIfRoutes (%d)\n", IfIndex); 287230557Sjimharris 288230557Sjimharris mib[0] = CTL_NET; 289230557Sjimharris mib[1] = PF_ROUTE; 290230557Sjimharris mib[2] = 0; 291230557Sjimharris mib[3] = 0; 292230557Sjimharris mib[4] = NET_RT_DUMP; 293230557Sjimharris mib[5] = 0; 294230557Sjimharris if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 295230557Sjimharris LogPrintf(LogERROR, "sysctl: estimate: %s", strerror(errno)); 296230557Sjimharris return; 297230557Sjimharris } 298230557Sjimharris if (needed < 0) 299230557Sjimharris return; 300230557Sjimharris 301230557Sjimharris sp = malloc(needed); 302230557Sjimharris if (sp == NULL) 303230557Sjimharris return; 304230557Sjimharris 305230557Sjimharris if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { 306230557Sjimharris LogPrintf(LogERROR, "sysctl: getroute: %s", strerror(errno)); 307230557Sjimharris free(sp); 308230557Sjimharris return; 309230557Sjimharris } 310230557Sjimharris ep = sp + needed; 311230557Sjimharris 312230557Sjimharris for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { 313230557Sjimharris rtm = (struct rt_msghdr *) cp; 314230557Sjimharris sa = (struct sockaddr *) (rtm + 1); 315230557Sjimharris LogPrintf(LogDEBUG, "DeleteIfRoutes: addrs: %x, index: %d, flags: %x," 316230557Sjimharris " dstnet: %s\n", 317230557Sjimharris rtm->rtm_addrs, rtm->rtm_index, rtm->rtm_flags, 318230557Sjimharris inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); 319230557Sjimharris if (rtm->rtm_addrs != RTA_DST && 320230557Sjimharris (rtm->rtm_index == IfIndex) && 321230557Sjimharris (all || (rtm->rtm_flags & RTF_GATEWAY))) { 322230557Sjimharris LogPrintf(LogDEBUG, "DeleteIfRoutes: Remove it\n"); 323230557Sjimharris dstnet = ((struct sockaddr_in *) sa)->sin_addr; 324230557Sjimharris wp = (u_char *) cp + rtm->rtm_msglen; 325230557Sjimharris if (sa->sa_len == 0) 326230557Sjimharris sa->sa_len = sizeof(long); 327230557Sjimharris sa = (struct sockaddr *) (sa->sa_len + (char *) sa); 328230557Sjimharris gateway = ((struct sockaddr_in *) sa)->sin_addr; 329230557Sjimharris lp = (int *) (sa->sa_len + (char *) sa); 330230557Sjimharris mask = 0; 331230557Sjimharris if ((char *) lp < (char *) wp && *lp) { 332230557Sjimharris LogPrintf(LogDEBUG, "DeleteIfRoutes: flag = %x, rest = %d", 333230557Sjimharris rtm->rtm_flags, *lp); 334230557Sjimharris wp = (u_char *) (lp + 1); 335230557Sjimharris for (nb = *lp; nb > 4; nb--) { 336230557Sjimharris mask <<= 8; 337230557Sjimharris mask |= *wp++; 338230557Sjimharris } 339230557Sjimharris for (nb = 8 - *lp; nb > 0; nb--) 340230557Sjimharris mask <<= 8; 341230557Sjimharris } 342230557Sjimharris LogPrintf(LogDEBUG, "DeleteIfRoutes: Dst: %s\n", inet_ntoa(dstnet)); 343230557Sjimharris LogPrintf(LogDEBUG, "DeleteIfRoutes: Gw: %s\n", inet_ntoa(gateway)); 344230557Sjimharris LogPrintf(LogDEBUG, "DeleteIfRoutes: Index: %d\n", rtm->rtm_index); 345230557Sjimharris if (dstnet.s_addr == INADDR_ANY) 346230557Sjimharris mask = INADDR_ANY; 347230557Sjimharris maddr.s_addr = htonl(mask); 348230557Sjimharris OsSetRoute(RTM_DELETE, dstnet, gateway, maddr); 349230557Sjimharris } 350230557Sjimharris } 351230557Sjimharris free(sp); 352230557Sjimharris} 353230557Sjimharris 354230557Sjimharris /* 355230557Sjimharris * 960603 - Modified to use dynamic buffer allocator as in ifconfig 356230557Sjimharris */ 357230557Sjimharris 358230557Sjimharrisint 359230557SjimharrisGetIfIndex(char *name) 360230557Sjimharris{ 361230557Sjimharris char *buffer; 362230557Sjimharris struct ifreq *ifrp; 363230557Sjimharris int s, len, elen, index; 364230557Sjimharris struct ifconf ifconfs; 365230557Sjimharris 366230557Sjimharris /* struct ifreq reqbuf[256]; -- obsoleted :) */ 367230557Sjimharris int oldbufsize, bufsize = sizeof(struct ifreq); 368230557Sjimharris 369230557Sjimharris s = socket(AF_INET, SOCK_DGRAM, 0); 370230557Sjimharris if (s < 0) { 371230557Sjimharris LogPrintf(LogERROR, "GetIfIndex: socket: %s", strerror(errno)); 372230557Sjimharris return (-1); 373230557Sjimharris } 374230557Sjimharris buffer = malloc(bufsize); /* allocate first buffer */ 375230557Sjimharris ifconfs.ifc_len = bufsize; /* Initial setting */ 376230557Sjimharris 377230557Sjimharris /* 378230557Sjimharris * Iterate through here until we don't get many more data 379230557Sjimharris */ 380230557Sjimharris 381230557Sjimharris do { 382230557Sjimharris oldbufsize = ifconfs.ifc_len; 383230557Sjimharris bufsize += 1 + sizeof(struct ifreq); 384230557Sjimharris buffer = realloc((void *) buffer, bufsize); /* Make it bigger */ 385230557Sjimharris LogPrintf(LogDEBUG, "GetIfIndex: Growing buffer to %d\n", bufsize); 386230557Sjimharris ifconfs.ifc_len = bufsize; 387230557Sjimharris ifconfs.ifc_buf = buffer; 388230557Sjimharris if (ioctl(s, SIOCGIFCONF, &ifconfs) < 0) { 389230557Sjimharris LogPrintf(LogERROR, "ioctl(SIOCGIFCONF): %s", strerror(errno)); 390230557Sjimharris close(s); 391230557Sjimharris free(buffer); 392230557Sjimharris return (-1); 393230557Sjimharris } 394230557Sjimharris } while (ifconfs.ifc_len > oldbufsize); 395230557Sjimharris 396230557Sjimharris ifrp = ifconfs.ifc_req; 397230557Sjimharris 398230557Sjimharris index = 1; 399230557Sjimharris for (len = ifconfs.ifc_len; len > 0; len -= sizeof(struct ifreq)) { 400230557Sjimharris elen = ifrp->ifr_addr.sa_len - sizeof(struct sockaddr); 401230557Sjimharris if (ifrp->ifr_addr.sa_family == AF_LINK) { 402230557Sjimharris LogPrintf(LogDEBUG, "GetIfIndex: %d: %-*.*s, %d, %d\n", 403230557Sjimharris index, IFNAMSIZ, IFNAMSIZ, ifrp->ifr_name, 404230557Sjimharris ifrp->ifr_addr.sa_family, elen); 405230557Sjimharris if (strcmp(ifrp->ifr_name, name) == 0) { 406230557Sjimharris IfIndex = index; 407230557Sjimharris close(s); 408230557Sjimharris free(buffer); 409230557Sjimharris return (index); 410230557Sjimharris } 411230557Sjimharris index++; 412230557Sjimharris } 413230557Sjimharris len -= elen; 414230557Sjimharris ifrp = (struct ifreq *) ((char *) ifrp + elen); 415230557Sjimharris ifrp++; 416230557Sjimharris } 417230557Sjimharris 418230557Sjimharris close(s); 419230557Sjimharris free(buffer); 420230557Sjimharris return (-1); 421230557Sjimharris} 422230557Sjimharris