1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 32*7c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include "defs.h" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #define IF_SEPARATOR ':' 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate struct interface *ifnet; 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate static int setup_listen_sock(int ifindex); 44*7c478bd9Sstevel@tonic-gate static void addrouteforif(struct interface *ifp); 45*7c478bd9Sstevel@tonic-gate static void resetup_listen_sock(struct interface *, int); 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * This is called at startup and after that, every CHECK_INTERVAL seconds or 49*7c478bd9Sstevel@tonic-gate * when a SIGHUP is received. 50*7c478bd9Sstevel@tonic-gate */ 51*7c478bd9Sstevel@tonic-gate void 52*7c478bd9Sstevel@tonic-gate initifs(void) 53*7c478bd9Sstevel@tonic-gate { 54*7c478bd9Sstevel@tonic-gate static char *buf = NULL; 55*7c478bd9Sstevel@tonic-gate static uint_t maxbufsize = 0; 56*7c478bd9Sstevel@tonic-gate int bufsize; 57*7c478bd9Sstevel@tonic-gate int numifs; 58*7c478bd9Sstevel@tonic-gate struct lifnum lifn; 59*7c478bd9Sstevel@tonic-gate struct lifconf lifc; 60*7c478bd9Sstevel@tonic-gate struct lifreq lifr; 61*7c478bd9Sstevel@tonic-gate struct lifreq *lifrp; 62*7c478bd9Sstevel@tonic-gate int n; 63*7c478bd9Sstevel@tonic-gate struct interface ifs; 64*7c478bd9Sstevel@tonic-gate struct interface *ifp; 65*7c478bd9Sstevel@tonic-gate int netmaskchange = 0; 66*7c478bd9Sstevel@tonic-gate boolean_t changes = _B_FALSE; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate lifn.lifn_family = AF_INET6; 69*7c478bd9Sstevel@tonic-gate lifn.lifn_flags = 0; 70*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFNUM, (char *)&lifn) < 0) { 71*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "initifs: ioctl (get interface numbers): %m"); 72*7c478bd9Sstevel@tonic-gate return; 73*7c478bd9Sstevel@tonic-gate } 74*7c478bd9Sstevel@tonic-gate numifs = lifn.lifn_count; 75*7c478bd9Sstevel@tonic-gate bufsize = numifs * sizeof (struct lifreq); 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate if (buf == NULL || bufsize > maxbufsize) { 78*7c478bd9Sstevel@tonic-gate if (buf != NULL) 79*7c478bd9Sstevel@tonic-gate free(buf); 80*7c478bd9Sstevel@tonic-gate maxbufsize = bufsize; 81*7c478bd9Sstevel@tonic-gate buf = (char *)malloc(maxbufsize); 82*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 83*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "initifs: out of memory"); 84*7c478bd9Sstevel@tonic-gate return; 85*7c478bd9Sstevel@tonic-gate } 86*7c478bd9Sstevel@tonic-gate } 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate lifc.lifc_family = AF_INET6; 89*7c478bd9Sstevel@tonic-gate lifc.lifc_flags = 0; 90*7c478bd9Sstevel@tonic-gate lifc.lifc_len = bufsize; 91*7c478bd9Sstevel@tonic-gate lifc.lifc_buf = buf; 92*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFCONF, (char *)&lifc) < 0) { 93*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 94*7c478bd9Sstevel@tonic-gate "initifs: ioctl (get interface configuration): %m"); 95*7c478bd9Sstevel@tonic-gate return; 96*7c478bd9Sstevel@tonic-gate } 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* 99*7c478bd9Sstevel@tonic-gate * Mark all of the currently known interfaces in order to determine 100*7c478bd9Sstevel@tonic-gate * which of the these interfaces no longer exist. 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) 103*7c478bd9Sstevel@tonic-gate ifp->int_flags |= RIP6_IFF_MARKED; 104*7c478bd9Sstevel@tonic-gate lifrp = lifc.lifc_req; 105*7c478bd9Sstevel@tonic-gate for (n = lifc.lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) { 106*7c478bd9Sstevel@tonic-gate bzero((char *)&ifs, sizeof (ifs)); 107*7c478bd9Sstevel@tonic-gate (void) strncpy(lifr.lifr_name, lifrp->lifr_name, 108*7c478bd9Sstevel@tonic-gate sizeof (lifr.lifr_name)); 109*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 110*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 111*7c478bd9Sstevel@tonic-gate "initifs: ioctl (get interface flags): %m"); 112*7c478bd9Sstevel@tonic-gate continue; 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate if (!(lifr.lifr_flags & IFF_IPV6) || 115*7c478bd9Sstevel@tonic-gate !(lifr.lifr_flags & IFF_MULTICAST) || 116*7c478bd9Sstevel@tonic-gate (lifr.lifr_flags & IFF_LOOPBACK)) 117*7c478bd9Sstevel@tonic-gate continue; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate ifp = if_ifwithname(lifr.lifr_name); 120*7c478bd9Sstevel@tonic-gate if (ifp != NULL) 121*7c478bd9Sstevel@tonic-gate ifp->int_flags &= ~RIP6_IFF_MARKED; 122*7c478bd9Sstevel@tonic-gate if (lifr.lifr_flags & IFF_POINTOPOINT) 123*7c478bd9Sstevel@tonic-gate ifs.int_flags |= RIP6_IFF_POINTOPOINT; 124*7c478bd9Sstevel@tonic-gate if (lifr.lifr_flags & IFF_NORTEXCH) 125*7c478bd9Sstevel@tonic-gate ifs.int_flags |= RIP6_IFF_NORTEXCH; 126*7c478bd9Sstevel@tonic-gate if (lifr.lifr_flags & IFF_PRIVATE) 127*7c478bd9Sstevel@tonic-gate ifs.int_flags |= RIP6_IFF_PRIVATE; 128*7c478bd9Sstevel@tonic-gate if (lifr.lifr_flags & IFF_UP) { 129*7c478bd9Sstevel@tonic-gate ifs.int_flags |= RIP6_IFF_UP; 130*7c478bd9Sstevel@tonic-gate } else { 131*7c478bd9Sstevel@tonic-gate if (ifp != NULL) { 132*7c478bd9Sstevel@tonic-gate if (ifp->int_flags & RIP6_IFF_UP) { 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * If there is an transition from up to 135*7c478bd9Sstevel@tonic-gate * down for an exisiting interface, 136*7c478bd9Sstevel@tonic-gate * increment the counter. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate ifp->int_transitions++; 139*7c478bd9Sstevel@tonic-gate changes = _B_TRUE; 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate if_purge(ifp); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate continue; 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate if (ifs.int_flags & RIP6_IFF_POINTOPOINT) { 147*7c478bd9Sstevel@tonic-gate /* 148*7c478bd9Sstevel@tonic-gate * For point-to-point interfaces, retrieve both the 149*7c478bd9Sstevel@tonic-gate * local and the remote addresses. 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFADDR, (char *)&lifr) < 0) { 152*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 153*7c478bd9Sstevel@tonic-gate "initifs: ioctl (get interface address): " 154*7c478bd9Sstevel@tonic-gate "%m"); 155*7c478bd9Sstevel@tonic-gate continue; 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate ifs.int_addr = 158*7c478bd9Sstevel@tonic-gate ((struct sockaddr_in6 *)&lifr.lifr_addr)->sin6_addr; 159*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFDSTADDR, (char *)&lifr) < 0) { 160*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 161*7c478bd9Sstevel@tonic-gate "initifs: ioctl (get destination address): " 162*7c478bd9Sstevel@tonic-gate "%m"); 163*7c478bd9Sstevel@tonic-gate continue; 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate ifs.int_dstaddr = ((struct sockaddr_in6 *) 166*7c478bd9Sstevel@tonic-gate &lifr.lifr_dstaddr)->sin6_addr; 167*7c478bd9Sstevel@tonic-gate ifs.int_prefix_length = IPV6_ABITS; 168*7c478bd9Sstevel@tonic-gate } else { 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * For other interfaces, retreieve the prefix (including 171*7c478bd9Sstevel@tonic-gate * the prefix length. 172*7c478bd9Sstevel@tonic-gate */ 173*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFSUBNET, (char *)&lifr) < 0) { 174*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 175*7c478bd9Sstevel@tonic-gate "initifs: ioctl (get subnet prefix): %m"); 176*7c478bd9Sstevel@tonic-gate continue; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate /* 179*7c478bd9Sstevel@tonic-gate * This should never happen but check for it in any case 180*7c478bd9Sstevel@tonic-gate * since the kernel stores it as an signed integer. 181*7c478bd9Sstevel@tonic-gate */ 182*7c478bd9Sstevel@tonic-gate if (lifr.lifr_addrlen < 0 || 183*7c478bd9Sstevel@tonic-gate lifr.lifr_addrlen > IPV6_ABITS) { 184*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 185*7c478bd9Sstevel@tonic-gate "initifs: ioctl (get subnet prefix) " 186*7c478bd9Sstevel@tonic-gate "returned invalid prefix length of %d", 187*7c478bd9Sstevel@tonic-gate lifr.lifr_addrlen); 188*7c478bd9Sstevel@tonic-gate continue; 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate ifs.int_prefix_length = lifr.lifr_addrlen; 191*7c478bd9Sstevel@tonic-gate ifs.int_addr = ((struct sockaddr_in6 *) 192*7c478bd9Sstevel@tonic-gate &lifr.lifr_subnet)->sin6_addr; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFMETRIC, (char *)&lifr) < 0 || 196*7c478bd9Sstevel@tonic-gate lifr.lifr_metric < 0) 197*7c478bd9Sstevel@tonic-gate ifs.int_metric = 1; 198*7c478bd9Sstevel@tonic-gate else 199*7c478bd9Sstevel@tonic-gate ifs.int_metric = lifr.lifr_metric + 1; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFINDEX, (char *)&lifr) < 0) { 202*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "initifs: ioctl (get index): %m"); 203*7c478bd9Sstevel@tonic-gate continue; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate ifs.int_ifindex = lifr.lifr_index; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate if (ioctl(iocsoc, SIOCGLIFMTU, (char *)&lifr) < 0) { 208*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "initifs: ioctl (get mtu): %m"); 209*7c478bd9Sstevel@tonic-gate continue; 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * If the interface's recorded MTU doesn't make sense, use 214*7c478bd9Sstevel@tonic-gate * IPV6_MIN_MTU instead. 215*7c478bd9Sstevel@tonic-gate */ 216*7c478bd9Sstevel@tonic-gate if (lifr.lifr_mtu < IPV6_MIN_MTU) 217*7c478bd9Sstevel@tonic-gate ifs.int_mtu = IPV6_MIN_MTU; 218*7c478bd9Sstevel@tonic-gate else 219*7c478bd9Sstevel@tonic-gate ifs.int_mtu = lifr.lifr_mtu; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate if (ifp != NULL) { 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * RIP6_IFF_NORTEXCH flag change by itself shouldn't 224*7c478bd9Sstevel@tonic-gate * cause an if_purge() call, which also purges all the 225*7c478bd9Sstevel@tonic-gate * routes heard off this interface. So, let's suppress 226*7c478bd9Sstevel@tonic-gate * changes of RIP6_IFF_NORTEXCH in the following 227*7c478bd9Sstevel@tonic-gate * comparisons. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate if (ifp->int_prefix_length == ifs.int_prefix_length && 230*7c478bd9Sstevel@tonic-gate ((ifp->int_flags | RIP6_IFF_NORTEXCH) == 231*7c478bd9Sstevel@tonic-gate (ifs.int_flags | RIP6_IFF_NORTEXCH)) && 232*7c478bd9Sstevel@tonic-gate ifp->int_metric == ifs.int_metric && 233*7c478bd9Sstevel@tonic-gate ifp->int_ifindex == ifs.int_ifindex) { 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * Now let's make sure we capture the latest 236*7c478bd9Sstevel@tonic-gate * value of RIP6_IFF_NORTEXCH flag. 237*7c478bd9Sstevel@tonic-gate */ 238*7c478bd9Sstevel@tonic-gate if (ifs.int_flags & RIP6_IFF_NORTEXCH) 239*7c478bd9Sstevel@tonic-gate ifp->int_flags |= RIP6_IFF_NORTEXCH; 240*7c478bd9Sstevel@tonic-gate else 241*7c478bd9Sstevel@tonic-gate ifp->int_flags &= ~RIP6_IFF_NORTEXCH; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate if (!(ifp->int_flags & RIP6_IFF_POINTOPOINT) && 244*7c478bd9Sstevel@tonic-gate IN6_ARE_ADDR_EQUAL(&ifp->int_addr, 245*7c478bd9Sstevel@tonic-gate &ifs.int_addr)) 246*7c478bd9Sstevel@tonic-gate continue; 247*7c478bd9Sstevel@tonic-gate if ((ifp->int_flags & RIP6_IFF_POINTOPOINT) && 248*7c478bd9Sstevel@tonic-gate IN6_ARE_ADDR_EQUAL(&ifp->int_dstaddr, 249*7c478bd9Sstevel@tonic-gate &ifs.int_dstaddr)) 250*7c478bd9Sstevel@tonic-gate continue; 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate if_purge(ifp); 253*7c478bd9Sstevel@tonic-gate if (ifp->int_prefix_length != ifs.int_prefix_length) 254*7c478bd9Sstevel@tonic-gate netmaskchange = 1; 255*7c478bd9Sstevel@tonic-gate ifp->int_addr = ifs.int_addr; 256*7c478bd9Sstevel@tonic-gate ifp->int_dstaddr = ifs.int_dstaddr; 257*7c478bd9Sstevel@tonic-gate ifp->int_metric = ifs.int_metric; 258*7c478bd9Sstevel@tonic-gate /* 259*7c478bd9Sstevel@tonic-gate * If there is an transition from down to up for an 260*7c478bd9Sstevel@tonic-gate * exisiting interface, increment the counter. 261*7c478bd9Sstevel@tonic-gate */ 262*7c478bd9Sstevel@tonic-gate if (!(ifp->int_flags & RIP6_IFF_UP) && 263*7c478bd9Sstevel@tonic-gate (ifs.int_flags & RIP6_IFF_UP)) 264*7c478bd9Sstevel@tonic-gate ifp->int_transitions++; 265*7c478bd9Sstevel@tonic-gate ifp->int_flags |= ifs.int_flags; 266*7c478bd9Sstevel@tonic-gate ifp->int_prefix_length = ifs.int_prefix_length; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * If the interface index has changed, we may need to 270*7c478bd9Sstevel@tonic-gate * set up the listen socket again. 271*7c478bd9Sstevel@tonic-gate */ 272*7c478bd9Sstevel@tonic-gate if (ifp->int_ifindex != ifs.int_ifindex) { 273*7c478bd9Sstevel@tonic-gate if (ifp->int_sock != -1) { 274*7c478bd9Sstevel@tonic-gate resetup_listen_sock(ifp, 275*7c478bd9Sstevel@tonic-gate ifs.int_ifindex); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate ifp->int_ifindex = ifs.int_ifindex; 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate ifp->int_mtu = ifs.int_mtu; 281*7c478bd9Sstevel@tonic-gate } else { 282*7c478bd9Sstevel@tonic-gate char *cp; 283*7c478bd9Sstevel@tonic-gate int log_num; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate ifp = (struct interface *) 286*7c478bd9Sstevel@tonic-gate malloc(sizeof (struct interface)); 287*7c478bd9Sstevel@tonic-gate if (ifp == NULL) { 288*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "initifs: out of memory"); 289*7c478bd9Sstevel@tonic-gate return; 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate *ifp = ifs; 292*7c478bd9Sstevel@tonic-gate ifp->int_name = ifp->int_ifbase = NULL; 293*7c478bd9Sstevel@tonic-gate ifp->int_name = 294*7c478bd9Sstevel@tonic-gate (char *)malloc((size_t)strlen(lifr.lifr_name) + 1); 295*7c478bd9Sstevel@tonic-gate if (ifp->int_name == NULL) { 296*7c478bd9Sstevel@tonic-gate free(ifp); 297*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "initifs: out of memory"); 298*7c478bd9Sstevel@tonic-gate return; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate (void) strcpy(ifp->int_name, lifr.lifr_name); 301*7c478bd9Sstevel@tonic-gate ifp->int_ifbase = 302*7c478bd9Sstevel@tonic-gate (char *)malloc((size_t)strlen(lifr.lifr_name) + 1); 303*7c478bd9Sstevel@tonic-gate if (ifp->int_ifbase == NULL) { 304*7c478bd9Sstevel@tonic-gate free(ifp->int_name); 305*7c478bd9Sstevel@tonic-gate free(ifp); 306*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "initifs: out of memory"); 307*7c478bd9Sstevel@tonic-gate return; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate (void) strcpy(ifp->int_ifbase, lifr.lifr_name); 310*7c478bd9Sstevel@tonic-gate cp = (char *)index(ifp->int_ifbase, IF_SEPARATOR); 311*7c478bd9Sstevel@tonic-gate if (cp != NULL) { 312*7c478bd9Sstevel@tonic-gate /* 313*7c478bd9Sstevel@tonic-gate * Verify that the value following the separator 314*7c478bd9Sstevel@tonic-gate * is an integer greater than zero (the only 315*7c478bd9Sstevel@tonic-gate * possible value for a logical interface). 316*7c478bd9Sstevel@tonic-gate */ 317*7c478bd9Sstevel@tonic-gate log_num = atoi((char *)(cp + 1)); 318*7c478bd9Sstevel@tonic-gate if (log_num <= 0) { 319*7c478bd9Sstevel@tonic-gate free(ifp->int_ifbase); 320*7c478bd9Sstevel@tonic-gate free(ifp->int_name); 321*7c478bd9Sstevel@tonic-gate free(ifp); 322*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 323*7c478bd9Sstevel@tonic-gate "initifs: interface name %s could " 324*7c478bd9Sstevel@tonic-gate "not be parsed", ifp->int_name); 325*7c478bd9Sstevel@tonic-gate return; 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate *cp = '\0'; 328*7c478bd9Sstevel@tonic-gate } else { 329*7c478bd9Sstevel@tonic-gate log_num = 0; 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate if (log_num == 0) { 332*7c478bd9Sstevel@tonic-gate ifp->int_sock = 333*7c478bd9Sstevel@tonic-gate setup_listen_sock(ifp->int_ifindex); 334*7c478bd9Sstevel@tonic-gate } else { 335*7c478bd9Sstevel@tonic-gate ifp->int_sock = -1; 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate ifp->int_next = ifnet; 338*7c478bd9Sstevel@tonic-gate ifnet = ifp; 339*7c478bd9Sstevel@tonic-gate traceinit(ifp); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate addrouteforif(ifp); 342*7c478bd9Sstevel@tonic-gate changes = _B_TRUE; 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate /* 346*7c478bd9Sstevel@tonic-gate * Any remaining interfaces that are still marked and which were in an 347*7c478bd9Sstevel@tonic-gate * up state (RIP6_IFF_UP) need to removed from the routing table. 348*7c478bd9Sstevel@tonic-gate */ 349*7c478bd9Sstevel@tonic-gate for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) { 350*7c478bd9Sstevel@tonic-gate if ((ifp->int_flags & (RIP6_IFF_MARKED | RIP6_IFF_UP)) == 351*7c478bd9Sstevel@tonic-gate (RIP6_IFF_MARKED | RIP6_IFF_UP)) { 352*7c478bd9Sstevel@tonic-gate if_purge(ifp); 353*7c478bd9Sstevel@tonic-gate ifp->int_flags &= ~RIP6_IFF_MARKED; 354*7c478bd9Sstevel@tonic-gate changes = _B_TRUE; 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate if (netmaskchange) 358*7c478bd9Sstevel@tonic-gate rtchangeall(); 359*7c478bd9Sstevel@tonic-gate if (supplier & changes) 360*7c478bd9Sstevel@tonic-gate dynamic_update((struct interface *)NULL); 361*7c478bd9Sstevel@tonic-gate } 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate static void 364*7c478bd9Sstevel@tonic-gate addrouteforif(struct interface *ifp) 365*7c478bd9Sstevel@tonic-gate { 366*7c478bd9Sstevel@tonic-gate struct rt_entry *rt; 367*7c478bd9Sstevel@tonic-gate struct in6_addr *dst; 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate if (ifp->int_flags & RIP6_IFF_POINTOPOINT) 370*7c478bd9Sstevel@tonic-gate dst = &ifp->int_dstaddr; 371*7c478bd9Sstevel@tonic-gate else 372*7c478bd9Sstevel@tonic-gate dst = &ifp->int_addr; 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate rt = rtlookup(dst, ifp->int_prefix_length); 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate if (rt != NULL) { 377*7c478bd9Sstevel@tonic-gate if (rt->rt_state & RTS_INTERFACE) 378*7c478bd9Sstevel@tonic-gate return; 379*7c478bd9Sstevel@tonic-gate rtdelete(rt); 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate rtadd(dst, &ifp->int_addr, ifp->int_prefix_length, ifp->int_metric, 0, 382*7c478bd9Sstevel@tonic-gate _B_TRUE, ifp); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate static int 386*7c478bd9Sstevel@tonic-gate setup_listen_sock(int ifindex) 387*7c478bd9Sstevel@tonic-gate { 388*7c478bd9Sstevel@tonic-gate int sock; 389*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 sin6; 390*7c478bd9Sstevel@tonic-gate uint_t hops; 391*7c478bd9Sstevel@tonic-gate struct ipv6_mreq allrouters_mreq; 392*7c478bd9Sstevel@tonic-gate int on = 1; 393*7c478bd9Sstevel@tonic-gate int off = 0; 394*7c478bd9Sstevel@tonic-gate int recvsize; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate sock = socket(AF_INET6, SOCK_DGRAM, 0); 397*7c478bd9Sstevel@tonic-gate if (sock == -1) 398*7c478bd9Sstevel@tonic-gate goto sock_fail; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, IPPROTO_IPV6, IPV6_BOUND_IF, (char *)&ifindex, 401*7c478bd9Sstevel@tonic-gate sizeof (ifindex)) < 0) { 402*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 403*7c478bd9Sstevel@tonic-gate "setup_listen_sock: setsockopt: IPV6_BOUND_IF: %m"); 404*7c478bd9Sstevel@tonic-gate goto sock_fail; 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate hops = IPV6_MAX_HOPS; 408*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *)&hops, 409*7c478bd9Sstevel@tonic-gate sizeof (hops)) < 0) { 410*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 411*7c478bd9Sstevel@tonic-gate "setup_listen_sock: setsockopt: IPV6_UNICAST_HOPS: %m"); 412*7c478bd9Sstevel@tonic-gate goto sock_fail; 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hops, 416*7c478bd9Sstevel@tonic-gate sizeof (hops)) < 0) { 417*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 418*7c478bd9Sstevel@tonic-gate "setup_listen_sock: setsockopt: IPV6_MULTICAST_HOPS: %m"); 419*7c478bd9Sstevel@tonic-gate goto sock_fail; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&off, 423*7c478bd9Sstevel@tonic-gate sizeof (off)) < 0) { 424*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 425*7c478bd9Sstevel@tonic-gate "setup_listen_sock: setsockopt: IPV6_MULTICAST_LOOP: %m"); 426*7c478bd9Sstevel@tonic-gate goto sock_fail; 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate allrouters_mreq.ipv6mr_multiaddr = allrouters_in6; 430*7c478bd9Sstevel@tonic-gate allrouters_mreq.ipv6mr_interface = ifindex; 431*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, 432*7c478bd9Sstevel@tonic-gate (char *)&allrouters_mreq, sizeof (allrouters_mreq)) < 0) { 433*7c478bd9Sstevel@tonic-gate if (errno != EADDRINUSE) { 434*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 435*7c478bd9Sstevel@tonic-gate "setup_listen_sock: setsockopt: " 436*7c478bd9Sstevel@tonic-gate "IPV6_JOIN_GROUP: %m"); 437*7c478bd9Sstevel@tonic-gate goto sock_fail; 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, (char *)&on, 442*7c478bd9Sstevel@tonic-gate sizeof (off)) < 0) { 443*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 444*7c478bd9Sstevel@tonic-gate "setup_listen_sock: setsockopt: IPV6_RECVHOPLIMIT: %m"); 445*7c478bd9Sstevel@tonic-gate goto sock_fail; 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, 449*7c478bd9Sstevel@tonic-gate sizeof (on)) < 0) { 450*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 451*7c478bd9Sstevel@tonic-gate "setup_listen_sock: setsockopt: SO_REUSEADDR: %m"); 452*7c478bd9Sstevel@tonic-gate goto sock_fail; 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate recvsize = RCVBUFSIZ; 456*7c478bd9Sstevel@tonic-gate if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&recvsize, 457*7c478bd9Sstevel@tonic-gate sizeof (int)) < 0) { 458*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "setup_listen_sock: setsockopt: SO_RCVBUF: %m"); 459*7c478bd9Sstevel@tonic-gate goto sock_fail; 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate bzero((char *)&sin6, sizeof (sin6)); 463*7c478bd9Sstevel@tonic-gate sin6.sin6_family = AF_INET6; 464*7c478bd9Sstevel@tonic-gate sin6.sin6_port = rip6_port; 465*7c478bd9Sstevel@tonic-gate if (bind(sock, (struct sockaddr *)&sin6, sizeof (sin6)) < 0) { 466*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "setup_listen_sock: bind: %m"); 467*7c478bd9Sstevel@tonic-gate goto sock_fail; 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate poll_ifs_num++; 471*7c478bd9Sstevel@tonic-gate if (poll_ifs == NULL) { 472*7c478bd9Sstevel@tonic-gate poll_ifs = (struct pollfd *) 473*7c478bd9Sstevel@tonic-gate malloc(max_poll_ifs * sizeof (struct pollfd)); 474*7c478bd9Sstevel@tonic-gate } else if (poll_ifs_num > max_poll_ifs) { 475*7c478bd9Sstevel@tonic-gate max_poll_ifs *= 2; 476*7c478bd9Sstevel@tonic-gate poll_ifs = (struct pollfd *)realloc((char *)poll_ifs, 477*7c478bd9Sstevel@tonic-gate max_poll_ifs * sizeof (struct pollfd)); 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate if (poll_ifs == NULL) { 480*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "setup_listen_sock: out of memory"); 481*7c478bd9Sstevel@tonic-gate goto sock_fail; 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate poll_ifs[poll_ifs_num - 1].fd = sock; 485*7c478bd9Sstevel@tonic-gate poll_ifs[poll_ifs_num - 1].events = POLLIN; 486*7c478bd9Sstevel@tonic-gate return (sock); 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate sock_fail: 489*7c478bd9Sstevel@tonic-gate if (sock > 0) 490*7c478bd9Sstevel@tonic-gate (void) close(sock); 491*7c478bd9Sstevel@tonic-gate return (-1); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate /* 495*7c478bd9Sstevel@tonic-gate * resetup_listen_sock is primarily used in the case where a tunnel was 496*7c478bd9Sstevel@tonic-gate * plumbed, unplumbed, then plumbed again. This would cause the binding set by 497*7c478bd9Sstevel@tonic-gate * IPV6_BOUND_IF to be useless, and sends to the associated socket will be 498*7c478bd9Sstevel@tonic-gate * transmitted on the wrong interface. resetup_listen_sock 499*7c478bd9Sstevel@tonic-gate * closes the socket, 500*7c478bd9Sstevel@tonic-gate * removes the socket from poll_ifs[] 501*7c478bd9Sstevel@tonic-gate * plugs the hole in poll_ifs[] 502*7c478bd9Sstevel@tonic-gate * calls setup_listen_sock to set up the socket again 503*7c478bd9Sstevel@tonic-gate */ 504*7c478bd9Sstevel@tonic-gate void 505*7c478bd9Sstevel@tonic-gate resetup_listen_sock(struct interface *ifp, int newindex) 506*7c478bd9Sstevel@tonic-gate { 507*7c478bd9Sstevel@tonic-gate int i; 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate (void) close(ifp->int_sock); 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate /* Remove socket from poll_ifs[]. */ 512*7c478bd9Sstevel@tonic-gate for (i = poll_ifs_num - 1; i >= 0; i--) { 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate if (poll_ifs[i].fd == ifp->int_sock) { 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate poll_ifs[i].fd = 0; 517*7c478bd9Sstevel@tonic-gate poll_ifs[i].events = 0; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * Remove hole in poll_ifs. Possibly exchange 521*7c478bd9Sstevel@tonic-gate * poll_ifs[i] with poll_ifs[poll_ifs_num-1]. 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate if (i != poll_ifs_num - 1) { 524*7c478bd9Sstevel@tonic-gate poll_ifs[i] = poll_ifs[poll_ifs_num - 1]; 525*7c478bd9Sstevel@tonic-gate poll_ifs[poll_ifs_num - 1].fd = 0; 526*7c478bd9Sstevel@tonic-gate poll_ifs[poll_ifs_num - 1].events = 0; 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate poll_ifs_num--; 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate /* Now set everything up again. */ 531*7c478bd9Sstevel@tonic-gate ifp->int_sock = setup_listen_sock(newindex); 532*7c478bd9Sstevel@tonic-gate break; 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate } 536