1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate /* 31*0Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 32*0Sstevel@tonic-gate * under license from the Regents of the University of California. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #include "defs.h" 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate struct sockaddr_in6 allrouters; 40*0Sstevel@tonic-gate char *control; 41*0Sstevel@tonic-gate boolean_t dopoison = _B_TRUE; /* Do poison reverse */ 42*0Sstevel@tonic-gate int iocsoc; 43*0Sstevel@tonic-gate struct timeval lastfullupdate; /* last time full table multicast */ 44*0Sstevel@tonic-gate struct timeval lastmcast; /* last time all/changes multicast */ 45*0Sstevel@tonic-gate int max_poll_ifs = START_POLL_SIZE; 46*0Sstevel@tonic-gate struct rip6 *msg; 47*0Sstevel@tonic-gate boolean_t needupdate; /* true if need update at nextmcast */ 48*0Sstevel@tonic-gate struct timeval nextmcast; /* time to wait before changes mcast */ 49*0Sstevel@tonic-gate struct timeval now; /* current idea of time */ 50*0Sstevel@tonic-gate char *packet; 51*0Sstevel@tonic-gate struct pollfd *poll_ifs = NULL; 52*0Sstevel@tonic-gate int poll_ifs_num = 0; 53*0Sstevel@tonic-gate int rip6_port; 54*0Sstevel@tonic-gate boolean_t supplier = _B_TRUE; /* process should supply updates */ 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate struct in6_addr allrouters_in6 = { 57*0Sstevel@tonic-gate /* BEGIN CSTYLED */ 58*0Sstevel@tonic-gate { 0xff, 0x2, 0x0, 0x0, 59*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 60*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 61*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x9 } 62*0Sstevel@tonic-gate /* END CSTYLED */ 63*0Sstevel@tonic-gate }; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate static void timevalsub(struct timeval *t1, struct timeval *t2); 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate static void 68*0Sstevel@tonic-gate usage(char *fname) 69*0Sstevel@tonic-gate { 70*0Sstevel@tonic-gate (void) fprintf(stderr, 71*0Sstevel@tonic-gate "usage: " 72*0Sstevel@tonic-gate "%s [ -P ] [ -p port ] [ -q ] [ -s ] [ -t ] [ -v ] [<logfile>]\n", 73*0Sstevel@tonic-gate fname); 74*0Sstevel@tonic-gate exit(EXIT_FAILURE); 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate void 78*0Sstevel@tonic-gate main(int argc, char *argv[]) 79*0Sstevel@tonic-gate { 80*0Sstevel@tonic-gate int i, n; 81*0Sstevel@tonic-gate struct interface *ifp; 82*0Sstevel@tonic-gate int c; 83*0Sstevel@tonic-gate struct timeval waittime; 84*0Sstevel@tonic-gate int timeout; 85*0Sstevel@tonic-gate boolean_t daemon = _B_TRUE; /* Fork off a detached daemon */ 86*0Sstevel@tonic-gate FILE *pidfp; 87*0Sstevel@tonic-gate mode_t pidmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* 0644 */ 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate rip6_port = htons(IPPORT_ROUTESERVER6); 90*0Sstevel@tonic-gate allrouters.sin6_family = AF_INET6; 91*0Sstevel@tonic-gate allrouters.sin6_port = rip6_port; 92*0Sstevel@tonic-gate allrouters.sin6_addr = allrouters_in6; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "nsqvTtdgPp:")) != EOF) { 95*0Sstevel@tonic-gate switch (c) { 96*0Sstevel@tonic-gate case 'n': 97*0Sstevel@tonic-gate install = _B_FALSE; 98*0Sstevel@tonic-gate break; 99*0Sstevel@tonic-gate case 's': 100*0Sstevel@tonic-gate supplier = _B_TRUE; 101*0Sstevel@tonic-gate break; 102*0Sstevel@tonic-gate case 'q': 103*0Sstevel@tonic-gate supplier = _B_FALSE; 104*0Sstevel@tonic-gate break; 105*0Sstevel@tonic-gate case 'v': 106*0Sstevel@tonic-gate tracing |= ACTION_BIT; 107*0Sstevel@tonic-gate break; 108*0Sstevel@tonic-gate case 'T': 109*0Sstevel@tonic-gate daemon = _B_FALSE; 110*0Sstevel@tonic-gate break; 111*0Sstevel@tonic-gate case 't': 112*0Sstevel@tonic-gate tracepackets = _B_TRUE; 113*0Sstevel@tonic-gate daemon = _B_FALSE; 114*0Sstevel@tonic-gate tracing |= (INPUT_BIT | OUTPUT_BIT); 115*0Sstevel@tonic-gate break; 116*0Sstevel@tonic-gate case 'd': 117*0Sstevel@tonic-gate break; 118*0Sstevel@tonic-gate case 'P': 119*0Sstevel@tonic-gate dopoison = _B_FALSE; 120*0Sstevel@tonic-gate break; 121*0Sstevel@tonic-gate case 'p': 122*0Sstevel@tonic-gate rip6_port = htons(atoi(optarg)); 123*0Sstevel@tonic-gate allrouters.sin6_port = rip6_port; 124*0Sstevel@tonic-gate break; 125*0Sstevel@tonic-gate default: 126*0Sstevel@tonic-gate usage(argv[0]); 127*0Sstevel@tonic-gate /* NOTREACHED */ 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate /* 132*0Sstevel@tonic-gate * Any extra argument is considered 133*0Sstevel@tonic-gate * a tracing log file. 134*0Sstevel@tonic-gate */ 135*0Sstevel@tonic-gate if (optind < argc) { 136*0Sstevel@tonic-gate traceon(argv[optind]); 137*0Sstevel@tonic-gate } else if (tracing && !daemon) { 138*0Sstevel@tonic-gate traceonfp(stdout); 139*0Sstevel@tonic-gate } else if (tracing) { 140*0Sstevel@tonic-gate (void) fprintf(stderr, "Need logfile with -v\n"); 141*0Sstevel@tonic-gate usage(argv[0]); 142*0Sstevel@tonic-gate /* NOTREACHED */ 143*0Sstevel@tonic-gate } 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate if (daemon) { 146*0Sstevel@tonic-gate int t; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (fork()) 149*0Sstevel@tonic-gate exit(EXIT_SUCCESS); 150*0Sstevel@tonic-gate for (t = 0; t < 20; t++) { 151*0Sstevel@tonic-gate if (!tracing || (t != fileno(ftrace))) 152*0Sstevel@tonic-gate (void) close(t); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate (void) open("/", 0); 155*0Sstevel@tonic-gate (void) dup2(0, 1); 156*0Sstevel@tonic-gate (void) dup2(0, 2); 157*0Sstevel@tonic-gate (void) setsid(); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* Store our process id, blow away any existing file if it exists. */ 161*0Sstevel@tonic-gate if ((pidfp = fopen(PATH_PID, "w")) == NULL) { 162*0Sstevel@tonic-gate (void) fprintf(stderr, "%s: unable to open " PATH_PID ": %s\n", 163*0Sstevel@tonic-gate argv[0], strerror(errno)); 164*0Sstevel@tonic-gate } else { 165*0Sstevel@tonic-gate (void) fprintf(pidfp, "%ld\n", getpid()); 166*0Sstevel@tonic-gate (void) fclose(pidfp); 167*0Sstevel@tonic-gate (void) chmod(PATH_PID, pidmode); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate iocsoc = socket(AF_INET6, SOCK_DGRAM, 0); 172*0Sstevel@tonic-gate if (iocsoc < 0) { 173*0Sstevel@tonic-gate syslog(LOG_ERR, "main: socket: %m"); 174*0Sstevel@tonic-gate exit(EXIT_FAILURE); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate setup_rtsock(); 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate /* 180*0Sstevel@tonic-gate * Allocate the buffer to hold the RIPng packet. In reality, it will be 181*0Sstevel@tonic-gate * smaller than IPV6_MAX_PACKET octets due to (at least) the IPv6 and 182*0Sstevel@tonic-gate * UDP headers but IPV6_MAX_PACKET is a convenient size. 183*0Sstevel@tonic-gate */ 184*0Sstevel@tonic-gate packet = (char *)malloc(IPV6_MAX_PACKET); 185*0Sstevel@tonic-gate if (packet == NULL) { 186*0Sstevel@tonic-gate syslog(LOG_ERR, "main: malloc: %m"); 187*0Sstevel@tonic-gate exit(EXIT_FAILURE); 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate msg = (struct rip6 *)packet; 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate /* 192*0Sstevel@tonic-gate * Allocate the buffer to hold the ancillary data. This data is used to 193*0Sstevel@tonic-gate * insure that the incoming hop count of a RIPCMD6_RESPONSE message is 194*0Sstevel@tonic-gate * IPV6_MAX_HOPS which indicates that it came from a direct neighbor 195*0Sstevel@tonic-gate * (namely, no intervening router decremented it). 196*0Sstevel@tonic-gate */ 197*0Sstevel@tonic-gate control = (char *)malloc(IPV6_MAX_PACKET); 198*0Sstevel@tonic-gate if (control == NULL) { 199*0Sstevel@tonic-gate syslog(LOG_ERR, "main: malloc: %m"); 200*0Sstevel@tonic-gate exit(EXIT_FAILURE); 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate openlog("in.ripngd", LOG_PID | LOG_CONS, LOG_DAEMON); 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate (void) gettimeofday(&now, (struct timezone *)NULL); 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate initifs(); 208*0Sstevel@tonic-gate solicitall(&allrouters); 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate if (supplier) 211*0Sstevel@tonic-gate supplyall(&allrouters, 0, (struct interface *)NULL, _B_TRUE); 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate (void) sigset(SIGALRM, (void (*)(int))timer); 214*0Sstevel@tonic-gate (void) sigset(SIGHUP, (void (*)(int))initifs); 215*0Sstevel@tonic-gate (void) sigset(SIGTERM, (void (*)(int))term); 216*0Sstevel@tonic-gate (void) sigset(SIGUSR1, (void (*)(int))if_dump); 217*0Sstevel@tonic-gate (void) sigset(SIGUSR2, (void (*)(int))rtdump); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* 220*0Sstevel@tonic-gate * Seed the pseudo-random number generator for GET_RANDOM(). 221*0Sstevel@tonic-gate */ 222*0Sstevel@tonic-gate srandom((uint_t)gethostid()); 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate timer(); 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate for (;;) { 227*0Sstevel@tonic-gate if (needupdate) { 228*0Sstevel@tonic-gate waittime = nextmcast; 229*0Sstevel@tonic-gate timevalsub(&waittime, &now); 230*0Sstevel@tonic-gate if (waittime.tv_sec < 0) { 231*0Sstevel@tonic-gate timeout = 0; 232*0Sstevel@tonic-gate } else { 233*0Sstevel@tonic-gate timeout = TIME_TO_MSECS(waittime); 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate if (tracing & ACTION_BIT) { 236*0Sstevel@tonic-gate (void) fprintf(ftrace, 237*0Sstevel@tonic-gate "poll until dynamic update in %d msec\n", 238*0Sstevel@tonic-gate timeout); 239*0Sstevel@tonic-gate (void) fflush(ftrace); 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate } else { 242*0Sstevel@tonic-gate timeout = INFTIM; 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate if ((n = poll(poll_ifs, poll_ifs_num, timeout)) < 0) { 246*0Sstevel@tonic-gate if (errno == EINTR) 247*0Sstevel@tonic-gate continue; 248*0Sstevel@tonic-gate syslog(LOG_ERR, "main: poll: %m"); 249*0Sstevel@tonic-gate exit(EXIT_FAILURE); 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate (void) sighold(SIGALRM); 252*0Sstevel@tonic-gate (void) sighold(SIGHUP); 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * Poll timed out. 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate if (n == 0) { 257*0Sstevel@tonic-gate if (needupdate) { 258*0Sstevel@tonic-gate TRACE_ACTION("send delayed dynamic update", 259*0Sstevel@tonic-gate (struct rt_entry *)NULL); 260*0Sstevel@tonic-gate (void) gettimeofday(&now, 261*0Sstevel@tonic-gate (struct timezone *)NULL); 262*0Sstevel@tonic-gate supplyall(&allrouters, RTS_CHANGED, 263*0Sstevel@tonic-gate (struct interface *)NULL, _B_TRUE); 264*0Sstevel@tonic-gate lastmcast = now; 265*0Sstevel@tonic-gate needupdate = _B_FALSE; 266*0Sstevel@tonic-gate nextmcast.tv_sec = 0; 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate (void) sigrelse(SIGHUP); 269*0Sstevel@tonic-gate (void) sigrelse(SIGALRM); 270*0Sstevel@tonic-gate continue; 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate (void) gettimeofday(&now, (struct timezone *)NULL); 273*0Sstevel@tonic-gate for (i = 0; i < poll_ifs_num; i++) { 274*0Sstevel@tonic-gate /* 275*0Sstevel@tonic-gate * This case should never happen. 276*0Sstevel@tonic-gate */ 277*0Sstevel@tonic-gate if (poll_ifs[i].revents & POLLERR) { 278*0Sstevel@tonic-gate syslog(LOG_ERR, 279*0Sstevel@tonic-gate "main: poll returned a POLLERR event"); 280*0Sstevel@tonic-gate continue; 281*0Sstevel@tonic-gate } 282*0Sstevel@tonic-gate if (poll_ifs[i].revents & POLLIN) { 283*0Sstevel@tonic-gate for (ifp = ifnet; ifp != NULL; 284*0Sstevel@tonic-gate ifp = ifp->int_next) { 285*0Sstevel@tonic-gate if (poll_ifs[i].fd == ifp->int_sock) 286*0Sstevel@tonic-gate in_data(ifp); 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate } 290*0Sstevel@tonic-gate (void) sigrelse(SIGHUP); 291*0Sstevel@tonic-gate (void) sigrelse(SIGALRM); 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate void 296*0Sstevel@tonic-gate timevaladd(struct timeval *t1, struct timeval *t2) 297*0Sstevel@tonic-gate { 298*0Sstevel@tonic-gate t1->tv_sec += t2->tv_sec; 299*0Sstevel@tonic-gate if ((t1->tv_usec += t2->tv_usec) > 1000000) { 300*0Sstevel@tonic-gate t1->tv_sec++; 301*0Sstevel@tonic-gate t1->tv_usec -= 1000000; 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate } 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate void 306*0Sstevel@tonic-gate timevalsub(struct timeval *t1, struct timeval *t2) 307*0Sstevel@tonic-gate { 308*0Sstevel@tonic-gate t1->tv_sec -= t2->tv_sec; 309*0Sstevel@tonic-gate if ((t1->tv_usec -= t2->tv_usec) < 0) { 310*0Sstevel@tonic-gate t1->tv_sec--; 311*0Sstevel@tonic-gate t1->tv_usec += 1000000; 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate } 314