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 #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include "defs.h" 30*0Sstevel@tonic-gate #include "tables.h" 31*0Sstevel@tonic-gate #include <fcntl.h> 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate static void initlog(void); 34*0Sstevel@tonic-gate static void run_timeouts(void); 35*0Sstevel@tonic-gate static void check_fallback(void); 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate static void advertise(struct sockaddr_in6 *sin6, struct phyint *pi, 38*0Sstevel@tonic-gate boolean_t no_prefixes); 39*0Sstevel@tonic-gate static void solicit(struct sockaddr_in6 *sin6, struct phyint *pi); 40*0Sstevel@tonic-gate static void initifs(boolean_t first); 41*0Sstevel@tonic-gate static void check_if_removed(struct phyint *pi); 42*0Sstevel@tonic-gate static void loopback_ra_enqueue(struct phyint *pi, 43*0Sstevel@tonic-gate struct nd_router_advert *ra, int len); 44*0Sstevel@tonic-gate static void loopback_ra_dequeue(void); 45*0Sstevel@tonic-gate static void check_daemonize(void); 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate struct in6_addr all_nodes_mcast = { { 0xff, 0x2, 0x0, 0x0, 48*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 49*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 50*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x1 } }; 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate struct in6_addr all_routers_mcast = { { 0xff, 0x2, 0x0, 0x0, 53*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 54*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 55*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x2 } }; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate static struct sockaddr_in6 v6allnodes = { AF_INET6, 0, 0, 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, 0x1 } }; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate static struct sockaddr_in6 v6allrouters = { AF_INET6, 0, 0, 64*0Sstevel@tonic-gate { 0xff, 0x2, 0x0, 0x0, 65*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 66*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 67*0Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x2 } }; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate static char **argv0; /* Saved for re-exec on SIGHUP */ 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate static uint64_t packet[(IP_MAXPACKET + 1)/8]; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate static int show_ifs = 0; 74*0Sstevel@tonic-gate static boolean_t already_daemonized = _B_FALSE; 75*0Sstevel@tonic-gate int debug = 0; 76*0Sstevel@tonic-gate int no_loopback = 0; /* Do not send RA packets to ourselves */ 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate /* 79*0Sstevel@tonic-gate * Size of routing socket message used by in.ndpd which includes the header, 80*0Sstevel@tonic-gate * space for the RTA_DST, RTA_GATEWAY and RTA_NETMASK (each a sockaddr_in6) 81*0Sstevel@tonic-gate * plus space for the RTA_IFP (a sockaddr_dl). 82*0Sstevel@tonic-gate */ 83*0Sstevel@tonic-gate #define NDP_RTM_MSGLEN sizeof (struct rt_msghdr) + \ 84*0Sstevel@tonic-gate sizeof (struct sockaddr_in6) + \ 85*0Sstevel@tonic-gate sizeof (struct sockaddr_in6) + \ 86*0Sstevel@tonic-gate sizeof (struct sockaddr_in6) + \ 87*0Sstevel@tonic-gate sizeof (struct sockaddr_dl) 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate /* 90*0Sstevel@tonic-gate * These are referenced externally in tables.c in order to fill in the 91*0Sstevel@tonic-gate * dynamic portions of the routing socket message and then to send the message 92*0Sstevel@tonic-gate * itself. 93*0Sstevel@tonic-gate */ 94*0Sstevel@tonic-gate int rtsock = -1; /* Routing socket */ 95*0Sstevel@tonic-gate struct rt_msghdr *rt_msg; /* Routing socket message */ 96*0Sstevel@tonic-gate struct sockaddr_in6 *rta_gateway; /* RTA_GATEWAY sockaddr */ 97*0Sstevel@tonic-gate struct sockaddr_dl *rta_ifp; /* RTA_IFP sockaddr */ 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* 100*0Sstevel@tonic-gate * Return the current time in milliseconds truncated to 101*0Sstevel@tonic-gate * fit in an integer. 102*0Sstevel@tonic-gate */ 103*0Sstevel@tonic-gate uint_t 104*0Sstevel@tonic-gate getcurrenttime(void) 105*0Sstevel@tonic-gate { 106*0Sstevel@tonic-gate struct timeval tp; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate if (gettimeofday(&tp, NULL) < 0) { 109*0Sstevel@tonic-gate logperror("getcurrenttime: gettimeofday failed"); 110*0Sstevel@tonic-gate exit(1); 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate return (tp.tv_sec * 1000 + tp.tv_usec / 1000); 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate /* 116*0Sstevel@tonic-gate * Output a preformated packet from the packet[] buffer. 117*0Sstevel@tonic-gate */ 118*0Sstevel@tonic-gate static void 119*0Sstevel@tonic-gate sendpacket(struct sockaddr_in6 *sin6, int sock, int size, int flags) 120*0Sstevel@tonic-gate { 121*0Sstevel@tonic-gate int cc; 122*0Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate cc = sendto(sock, (char *)packet, size, flags, 125*0Sstevel@tonic-gate (struct sockaddr *)sin6, sizeof (*sin6)); 126*0Sstevel@tonic-gate if (cc < 0 || cc != size) { 127*0Sstevel@tonic-gate if (cc < 0) { 128*0Sstevel@tonic-gate logperror("sendpacket: sendto"); 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate logmsg(LOG_ERR, "sendpacket: wrote %s %d chars, ret=%d\n", 131*0Sstevel@tonic-gate inet_ntop(sin6->sin6_family, 132*0Sstevel@tonic-gate (void *)&sin6->sin6_addr, 133*0Sstevel@tonic-gate abuf, sizeof (abuf)), 134*0Sstevel@tonic-gate size, cc); 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate /* Send a Router Solicitation */ 139*0Sstevel@tonic-gate static void 140*0Sstevel@tonic-gate solicit(struct sockaddr_in6 *sin6, struct phyint *pi) 141*0Sstevel@tonic-gate { 142*0Sstevel@tonic-gate int packetlen = 0; 143*0Sstevel@tonic-gate struct nd_router_solicit *rs = (struct nd_router_solicit *)packet; 144*0Sstevel@tonic-gate char *pptr = (char *)packet; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate rs->nd_rs_type = ND_ROUTER_SOLICIT; 147*0Sstevel@tonic-gate rs->nd_rs_code = 0; 148*0Sstevel@tonic-gate rs->nd_rs_cksum = htons(0); 149*0Sstevel@tonic-gate rs->nd_rs_reserved = htonl(0); 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate packetlen += sizeof (*rs); 152*0Sstevel@tonic-gate pptr += sizeof (*rs); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* Attach any options */ 155*0Sstevel@tonic-gate if (pi->pi_hdw_addr_len != 0) { 156*0Sstevel@tonic-gate struct nd_opt_lla *lo = (struct nd_opt_lla *)pptr; 157*0Sstevel@tonic-gate int optlen; 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate /* roundup to multiple of 8 and make padding zero */ 160*0Sstevel@tonic-gate optlen = ((sizeof (struct nd_opt_hdr) + 161*0Sstevel@tonic-gate pi->pi_hdw_addr_len + 7) / 8) * 8; 162*0Sstevel@tonic-gate bzero(pptr, optlen); 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate lo->nd_opt_lla_type = ND_OPT_SOURCE_LINKADDR; 165*0Sstevel@tonic-gate lo->nd_opt_lla_len = optlen / 8; 166*0Sstevel@tonic-gate bcopy((char *)pi->pi_hdw_addr, 167*0Sstevel@tonic-gate (char *)lo->nd_opt_lla_hdw_addr, 168*0Sstevel@tonic-gate pi->pi_hdw_addr_len); 169*0Sstevel@tonic-gate packetlen += optlen; 170*0Sstevel@tonic-gate pptr += optlen; 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate if (debug & D_PKTOUT) { 174*0Sstevel@tonic-gate print_route_sol("Sending solicitation to ", pi, rs, packetlen, 175*0Sstevel@tonic-gate sin6); 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate sendpacket(sin6, pi->pi_sock, packetlen, 0); 178*0Sstevel@tonic-gate } 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* 181*0Sstevel@tonic-gate * Send a (set of) Router Advertisements and feed them back to ourselves 182*0Sstevel@tonic-gate * for processing. Unless no_prefixes is set all prefixes are included. 183*0Sstevel@tonic-gate * If there are too many prefix options to fit in one packet multiple 184*0Sstevel@tonic-gate * packets will be sent - each containing a subset of the prefix options. 185*0Sstevel@tonic-gate */ 186*0Sstevel@tonic-gate static void 187*0Sstevel@tonic-gate advertise(struct sockaddr_in6 *sin6, struct phyint *pi, boolean_t no_prefixes) 188*0Sstevel@tonic-gate { 189*0Sstevel@tonic-gate struct nd_opt_prefix_info *po; 190*0Sstevel@tonic-gate char *pptr = (char *)packet; 191*0Sstevel@tonic-gate struct nd_router_advert *ra; 192*0Sstevel@tonic-gate struct adv_prefix *adv_pr; 193*0Sstevel@tonic-gate int packetlen = 0; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate ra = (struct nd_router_advert *)pptr; 196*0Sstevel@tonic-gate ra->nd_ra_type = ND_ROUTER_ADVERT; 197*0Sstevel@tonic-gate ra->nd_ra_code = 0; 198*0Sstevel@tonic-gate ra->nd_ra_cksum = htons(0); 199*0Sstevel@tonic-gate ra->nd_ra_curhoplimit = pi->pi_AdvCurHopLimit; 200*0Sstevel@tonic-gate ra->nd_ra_flags_reserved = 0; 201*0Sstevel@tonic-gate if (pi->pi_AdvManagedFlag) 202*0Sstevel@tonic-gate ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED; 203*0Sstevel@tonic-gate if (pi->pi_AdvOtherConfigFlag) 204*0Sstevel@tonic-gate ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER; 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate if (pi->pi_adv_state == FINAL_ADV) 207*0Sstevel@tonic-gate ra->nd_ra_router_lifetime = htons(0); 208*0Sstevel@tonic-gate else 209*0Sstevel@tonic-gate ra->nd_ra_router_lifetime = htons(pi->pi_AdvDefaultLifetime); 210*0Sstevel@tonic-gate ra->nd_ra_reachable = htonl(pi->pi_AdvReachableTime); 211*0Sstevel@tonic-gate ra->nd_ra_retransmit = htonl(pi->pi_AdvRetransTimer); 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate packetlen = sizeof (*ra); 214*0Sstevel@tonic-gate pptr += sizeof (*ra); 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if (pi->pi_adv_state == FINAL_ADV) { 217*0Sstevel@tonic-gate if (debug & D_PKTOUT) { 218*0Sstevel@tonic-gate print_route_adv("Sending advert (FINAL) to ", pi, 219*0Sstevel@tonic-gate ra, packetlen, sin6); 220*0Sstevel@tonic-gate } 221*0Sstevel@tonic-gate sendpacket(sin6, pi->pi_sock, packetlen, 0); 222*0Sstevel@tonic-gate /* Feed packet back in for router operation */ 223*0Sstevel@tonic-gate loopback_ra_enqueue(pi, ra, packetlen); 224*0Sstevel@tonic-gate return; 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate /* Attach any options */ 228*0Sstevel@tonic-gate if (pi->pi_hdw_addr_len != 0) { 229*0Sstevel@tonic-gate struct nd_opt_lla *lo = (struct nd_opt_lla *)pptr; 230*0Sstevel@tonic-gate int optlen; 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate /* roundup to multiple of 8 and make padding zero */ 233*0Sstevel@tonic-gate optlen = ((sizeof (struct nd_opt_hdr) + 234*0Sstevel@tonic-gate pi->pi_hdw_addr_len + 7) / 8) * 8; 235*0Sstevel@tonic-gate bzero(pptr, optlen); 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate lo->nd_opt_lla_type = ND_OPT_SOURCE_LINKADDR; 238*0Sstevel@tonic-gate lo->nd_opt_lla_len = optlen / 8; 239*0Sstevel@tonic-gate bcopy((char *)pi->pi_hdw_addr, 240*0Sstevel@tonic-gate (char *)lo->nd_opt_lla_hdw_addr, 241*0Sstevel@tonic-gate pi->pi_hdw_addr_len); 242*0Sstevel@tonic-gate packetlen += optlen; 243*0Sstevel@tonic-gate pptr += optlen; 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate if (pi->pi_AdvLinkMTU != 0) { 247*0Sstevel@tonic-gate struct nd_opt_mtu *mo = (struct nd_opt_mtu *)pptr; 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate mo->nd_opt_mtu_type = ND_OPT_MTU; 250*0Sstevel@tonic-gate mo->nd_opt_mtu_len = sizeof (struct nd_opt_mtu) / 8; 251*0Sstevel@tonic-gate mo->nd_opt_mtu_reserved = 0; 252*0Sstevel@tonic-gate mo->nd_opt_mtu_mtu = htonl(pi->pi_AdvLinkMTU); 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate packetlen += sizeof (struct nd_opt_mtu); 255*0Sstevel@tonic-gate pptr += sizeof (struct nd_opt_mtu); 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate if (no_prefixes) { 259*0Sstevel@tonic-gate if (debug & D_PKTOUT) { 260*0Sstevel@tonic-gate print_route_adv("Sending advert to ", pi, 261*0Sstevel@tonic-gate ra, packetlen, sin6); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate sendpacket(sin6, pi->pi_sock, packetlen, 0); 264*0Sstevel@tonic-gate /* Feed packet back in for router operation */ 265*0Sstevel@tonic-gate loopback_ra_enqueue(pi, ra, packetlen); 266*0Sstevel@tonic-gate return; 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate po = (struct nd_opt_prefix_info *)pptr; 270*0Sstevel@tonic-gate for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL; 271*0Sstevel@tonic-gate adv_pr = adv_pr->adv_pr_next) { 272*0Sstevel@tonic-gate if (!adv_pr->adv_pr_AdvOnLinkFlag && 273*0Sstevel@tonic-gate !adv_pr->adv_pr_AdvAutonomousFlag) { 274*0Sstevel@tonic-gate continue; 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate /* 278*0Sstevel@tonic-gate * If the prefix doesn't fit in packet send 279*0Sstevel@tonic-gate * what we have so far and start with new packet. 280*0Sstevel@tonic-gate */ 281*0Sstevel@tonic-gate if (packetlen + sizeof (*po) > 282*0Sstevel@tonic-gate pi->pi_LinkMTU - sizeof (struct ip6_hdr)) { 283*0Sstevel@tonic-gate if (debug & D_PKTOUT) { 284*0Sstevel@tonic-gate print_route_adv("Sending advert " 285*0Sstevel@tonic-gate "(FRAG) to ", 286*0Sstevel@tonic-gate pi, ra, packetlen, sin6); 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate sendpacket(sin6, pi->pi_sock, packetlen, 0); 289*0Sstevel@tonic-gate /* Feed packet back in for router operation */ 290*0Sstevel@tonic-gate loopback_ra_enqueue(pi, ra, packetlen); 291*0Sstevel@tonic-gate packetlen = sizeof (*ra); 292*0Sstevel@tonic-gate pptr = (char *)packet + sizeof (*ra); 293*0Sstevel@tonic-gate po = (struct nd_opt_prefix_info *)pptr; 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate po->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; 296*0Sstevel@tonic-gate po->nd_opt_pi_len = sizeof (*po)/8; 297*0Sstevel@tonic-gate po->nd_opt_pi_flags_reserved = 0; 298*0Sstevel@tonic-gate if (adv_pr->adv_pr_AdvOnLinkFlag) { 299*0Sstevel@tonic-gate po->nd_opt_pi_flags_reserved |= 300*0Sstevel@tonic-gate ND_OPT_PI_FLAG_ONLINK; 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate if (adv_pr->adv_pr_AdvAutonomousFlag) { 303*0Sstevel@tonic-gate po->nd_opt_pi_flags_reserved |= 304*0Sstevel@tonic-gate ND_OPT_PI_FLAG_AUTO; 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate po->nd_opt_pi_prefix_len = adv_pr->adv_pr_prefix_len; 307*0Sstevel@tonic-gate /* 308*0Sstevel@tonic-gate * If both Adv*Expiration and Adv*Lifetime are 309*0Sstevel@tonic-gate * set we prefer the former and make the lifetime 310*0Sstevel@tonic-gate * decrement in real time. 311*0Sstevel@tonic-gate */ 312*0Sstevel@tonic-gate if (adv_pr->adv_pr_AdvValidRealTime) { 313*0Sstevel@tonic-gate po->nd_opt_pi_valid_time = 314*0Sstevel@tonic-gate htonl(adv_pr->adv_pr_AdvValidExpiration); 315*0Sstevel@tonic-gate } else { 316*0Sstevel@tonic-gate po->nd_opt_pi_valid_time = 317*0Sstevel@tonic-gate htonl(adv_pr->adv_pr_AdvValidLifetime); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate if (adv_pr->adv_pr_AdvPreferredRealTime) { 320*0Sstevel@tonic-gate po->nd_opt_pi_preferred_time = 321*0Sstevel@tonic-gate htonl(adv_pr->adv_pr_AdvPreferredExpiration); 322*0Sstevel@tonic-gate } else { 323*0Sstevel@tonic-gate po->nd_opt_pi_preferred_time = 324*0Sstevel@tonic-gate htonl(adv_pr->adv_pr_AdvPreferredLifetime); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate po->nd_opt_pi_reserved2 = htonl(0); 327*0Sstevel@tonic-gate po->nd_opt_pi_prefix = adv_pr->adv_pr_prefix; 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate po++; 330*0Sstevel@tonic-gate packetlen += sizeof (*po); 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate if (debug & D_PKTOUT) { 333*0Sstevel@tonic-gate print_route_adv("Sending advert to ", pi, 334*0Sstevel@tonic-gate ra, packetlen, sin6); 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate sendpacket(sin6, pi->pi_sock, packetlen, 0); 337*0Sstevel@tonic-gate /* Feed packet back in for router operation */ 338*0Sstevel@tonic-gate loopback_ra_enqueue(pi, ra, packetlen); 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate /* Poll support */ 342*0Sstevel@tonic-gate static int pollfd_num = 0; /* Allocated and initialized */ 343*0Sstevel@tonic-gate static struct pollfd *pollfds = NULL; 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate /* 346*0Sstevel@tonic-gate * Add fd to the set being polled. Returns 0 if ok; -1 if failed. 347*0Sstevel@tonic-gate */ 348*0Sstevel@tonic-gate int 349*0Sstevel@tonic-gate poll_add(int fd) 350*0Sstevel@tonic-gate { 351*0Sstevel@tonic-gate int i; 352*0Sstevel@tonic-gate int new_num; 353*0Sstevel@tonic-gate struct pollfd *newfds; 354*0Sstevel@tonic-gate retry: 355*0Sstevel@tonic-gate /* Check if already present */ 356*0Sstevel@tonic-gate for (i = 0; i < pollfd_num; i++) { 357*0Sstevel@tonic-gate if (pollfds[i].fd == fd) 358*0Sstevel@tonic-gate return (0); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate /* Check for empty spot already present */ 361*0Sstevel@tonic-gate for (i = 0; i < pollfd_num; i++) { 362*0Sstevel@tonic-gate if (pollfds[i].fd == -1) { 363*0Sstevel@tonic-gate pollfds[i].fd = fd; 364*0Sstevel@tonic-gate return (0); 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate /* Allocate space for 32 more fds and initialize to -1 */ 369*0Sstevel@tonic-gate new_num = pollfd_num + 32; 370*0Sstevel@tonic-gate newfds = realloc(pollfds, new_num * sizeof (struct pollfd)); 371*0Sstevel@tonic-gate if (newfds == NULL) { 372*0Sstevel@tonic-gate logperror("poll_add: realloc"); 373*0Sstevel@tonic-gate return (-1); 374*0Sstevel@tonic-gate } 375*0Sstevel@tonic-gate for (i = pollfd_num; i < new_num; i++) { 376*0Sstevel@tonic-gate newfds[i].fd = -1; 377*0Sstevel@tonic-gate newfds[i].events = POLLIN; 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate pollfd_num = new_num; 380*0Sstevel@tonic-gate pollfds = newfds; 381*0Sstevel@tonic-gate goto retry; 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * Remove fd from the set being polled. Returns 0 if ok; -1 if failed. 386*0Sstevel@tonic-gate */ 387*0Sstevel@tonic-gate int 388*0Sstevel@tonic-gate poll_remove(int fd) 389*0Sstevel@tonic-gate { 390*0Sstevel@tonic-gate int i; 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate /* Check if already present */ 393*0Sstevel@tonic-gate for (i = 0; i < pollfd_num; i++) { 394*0Sstevel@tonic-gate if (pollfds[i].fd == fd) { 395*0Sstevel@tonic-gate pollfds[i].fd = -1; 396*0Sstevel@tonic-gate return (0); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate return (-1); 400*0Sstevel@tonic-gate } 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate /* 403*0Sstevel@tonic-gate * Extract information about the ifname (either a physical interface and 404*0Sstevel@tonic-gate * the ":0" logical interface or just a logical interface). 405*0Sstevel@tonic-gate * If the interface (still) exists in kernel set pr_in_use 406*0Sstevel@tonic-gate * for caller to be able to detect interfaces that are removed. 407*0Sstevel@tonic-gate * Starts sending advertisements/solicitations when new physical interfaces 408*0Sstevel@tonic-gate * are detected. 409*0Sstevel@tonic-gate */ 410*0Sstevel@tonic-gate static void 411*0Sstevel@tonic-gate if_process(int s, char *ifname, boolean_t first) 412*0Sstevel@tonic-gate { 413*0Sstevel@tonic-gate struct lifreq lifr; 414*0Sstevel@tonic-gate struct phyint *pi; 415*0Sstevel@tonic-gate struct prefix *pr; 416*0Sstevel@tonic-gate char *cp; 417*0Sstevel@tonic-gate char phyintname[LIFNAMSIZ + 1]; 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate if (debug & D_IFSCAN) 420*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "if_process(%s)\n", ifname); 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate (void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 423*0Sstevel@tonic-gate lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 424*0Sstevel@tonic-gate if (ioctl(s, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 425*0Sstevel@tonic-gate if (errno == ENXIO) { 426*0Sstevel@tonic-gate /* 427*0Sstevel@tonic-gate * Interface has disappeared 428*0Sstevel@tonic-gate */ 429*0Sstevel@tonic-gate return; 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate logperror("if_process: ioctl (get interface flags)"); 432*0Sstevel@tonic-gate return; 433*0Sstevel@tonic-gate } 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate /* 436*0Sstevel@tonic-gate * Ignore loopback and point-to-multipoint interfaces. 437*0Sstevel@tonic-gate * Point-to-point interfaces always have IFF_MULTICAST set. 438*0Sstevel@tonic-gate */ 439*0Sstevel@tonic-gate if (!(lifr.lifr_flags & IFF_MULTICAST) || 440*0Sstevel@tonic-gate (lifr.lifr_flags & IFF_LOOPBACK)) { 441*0Sstevel@tonic-gate return; 442*0Sstevel@tonic-gate } 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate if (!(lifr.lifr_flags & IFF_IPV6)) 445*0Sstevel@tonic-gate return; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate (void) strncpy(phyintname, ifname, sizeof (phyintname)); 448*0Sstevel@tonic-gate phyintname[sizeof (phyintname) - 1] = '\0'; 449*0Sstevel@tonic-gate if ((cp = strchr(phyintname, IF_SEPARATOR)) != NULL) { 450*0Sstevel@tonic-gate *cp = '\0'; 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate pi = phyint_lookup(phyintname); 454*0Sstevel@tonic-gate if (pi == NULL) { 455*0Sstevel@tonic-gate /* 456*0Sstevel@tonic-gate * Do not add anything for new interfaces until they are UP. 457*0Sstevel@tonic-gate * For existing interfaces we track the up flag. 458*0Sstevel@tonic-gate */ 459*0Sstevel@tonic-gate if (!(lifr.lifr_flags & IFF_UP)) 460*0Sstevel@tonic-gate return; 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate pi = phyint_create(phyintname); 463*0Sstevel@tonic-gate if (pi == NULL) { 464*0Sstevel@tonic-gate logmsg(LOG_ERR, "if_process: out of memory\n"); 465*0Sstevel@tonic-gate return; 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate } 468*0Sstevel@tonic-gate (void) phyint_init_from_k(pi); 469*0Sstevel@tonic-gate if (pi->pi_sock == -1 && !(pi->pi_kernel_state & PI_PRESENT)) { 470*0Sstevel@tonic-gate /* Interface is not yet present */ 471*0Sstevel@tonic-gate if (debug & D_PHYINT) { 472*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "if_process: interface not yet " 473*0Sstevel@tonic-gate "present %s\n", pi->pi_name); 474*0Sstevel@tonic-gate } 475*0Sstevel@tonic-gate return; 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate if (pi->pi_sock != -1) { 479*0Sstevel@tonic-gate if (poll_add(pi->pi_sock) == -1) { 480*0Sstevel@tonic-gate /* 481*0Sstevel@tonic-gate * reset state. 482*0Sstevel@tonic-gate */ 483*0Sstevel@tonic-gate phyint_cleanup(pi); 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate /* 488*0Sstevel@tonic-gate * Check if IFF_ROUTER has been turned off in kernel in which 489*0Sstevel@tonic-gate * case we have to turn off AdvSendAdvertisements. 490*0Sstevel@tonic-gate * The kernel will automatically turn off IFF_ROUTER if 491*0Sstevel@tonic-gate * ip6_forwarding is turned off. 492*0Sstevel@tonic-gate * Note that we do not switch back should IFF_ROUTER be turned on. 493*0Sstevel@tonic-gate */ 494*0Sstevel@tonic-gate if (!first && 495*0Sstevel@tonic-gate pi->pi_AdvSendAdvertisements && !(pi->pi_flags & IFF_ROUTER)) { 496*0Sstevel@tonic-gate logmsg(LOG_INFO, "No longer a router on %s\n", pi->pi_name); 497*0Sstevel@tonic-gate check_to_advertise(pi, START_FINAL_ADV); 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate pi->pi_AdvSendAdvertisements = 0; 500*0Sstevel@tonic-gate pi->pi_sol_state = NO_SOLICIT; 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate /* 504*0Sstevel@tonic-gate * Send advertisments and solicitation only if the interface is 505*0Sstevel@tonic-gate * present in the kernel. 506*0Sstevel@tonic-gate */ 507*0Sstevel@tonic-gate if (pi->pi_kernel_state & PI_PRESENT) { 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate if (pi->pi_AdvSendAdvertisements) { 510*0Sstevel@tonic-gate if (pi->pi_adv_state == NO_ADV) 511*0Sstevel@tonic-gate check_to_advertise(pi, START_INIT_ADV); 512*0Sstevel@tonic-gate } else { 513*0Sstevel@tonic-gate if (pi->pi_sol_state == NO_SOLICIT) 514*0Sstevel@tonic-gate check_to_solicit(pi, START_INIT_SOLICIT); 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate } 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate /* 519*0Sstevel@tonic-gate * Track static kernel prefixes to prevent in.ndpd from clobbering 520*0Sstevel@tonic-gate * them by creating a struct prefix for each prefix detected in the 521*0Sstevel@tonic-gate * kernel. 522*0Sstevel@tonic-gate */ 523*0Sstevel@tonic-gate pr = prefix_lookup_name(pi, ifname); 524*0Sstevel@tonic-gate if (pr == NULL) { 525*0Sstevel@tonic-gate pr = prefix_create_name(pi, ifname); 526*0Sstevel@tonic-gate if (pr == NULL) { 527*0Sstevel@tonic-gate logmsg(LOG_ERR, "if_process: out of memory\n"); 528*0Sstevel@tonic-gate return; 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate if (prefix_init_from_k(pr) == -1) { 531*0Sstevel@tonic-gate prefix_delete(pr); 532*0Sstevel@tonic-gate return; 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate } 535*0Sstevel@tonic-gate /* Detect prefixes which are removed */ 536*0Sstevel@tonic-gate if (pr->pr_kernel_state != 0) 537*0Sstevel@tonic-gate pr->pr_in_use = _B_TRUE; 538*0Sstevel@tonic-gate } 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gate static int ifsock = -1; 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate /* 543*0Sstevel@tonic-gate * Scan all interfaces to detect changes as well as new and deleted intefaces 544*0Sstevel@tonic-gate * 'first' is set for the initial call only. Do not effect anything. 545*0Sstevel@tonic-gate */ 546*0Sstevel@tonic-gate static void 547*0Sstevel@tonic-gate initifs(boolean_t first) 548*0Sstevel@tonic-gate { 549*0Sstevel@tonic-gate char *buf; 550*0Sstevel@tonic-gate int bufsize; 551*0Sstevel@tonic-gate int numifs; 552*0Sstevel@tonic-gate int n; 553*0Sstevel@tonic-gate struct lifnum lifn; 554*0Sstevel@tonic-gate struct lifconf lifc; 555*0Sstevel@tonic-gate struct lifreq *lifr; 556*0Sstevel@tonic-gate struct phyint *pi; 557*0Sstevel@tonic-gate struct phyint *next_pi; 558*0Sstevel@tonic-gate struct prefix *pr; 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate if (debug & D_IFSCAN) 561*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "Reading interface configuration\n"); 562*0Sstevel@tonic-gate if (ifsock < 0) { 563*0Sstevel@tonic-gate ifsock = socket(AF_INET6, SOCK_DGRAM, 0); 564*0Sstevel@tonic-gate if (ifsock < 0) { 565*0Sstevel@tonic-gate logperror("initifs: socket"); 566*0Sstevel@tonic-gate return; 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate lifn.lifn_family = AF_INET6; 570*0Sstevel@tonic-gate lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY; 571*0Sstevel@tonic-gate if (ioctl(ifsock, SIOCGLIFNUM, (char *)&lifn) < 0) { 572*0Sstevel@tonic-gate logperror("initifs: ioctl (get interface numbers)"); 573*0Sstevel@tonic-gate return; 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate numifs = lifn.lifn_count; 576*0Sstevel@tonic-gate bufsize = numifs * sizeof (struct lifreq); 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate buf = (char *)malloc(bufsize); 579*0Sstevel@tonic-gate if (buf == NULL) { 580*0Sstevel@tonic-gate logmsg(LOG_ERR, "initifs: out of memory\n"); 581*0Sstevel@tonic-gate return; 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate /* 585*0Sstevel@tonic-gate * Mark the interfaces so that we can find phyints and prefixes 586*0Sstevel@tonic-gate * which have disappeared from the kernel. 587*0Sstevel@tonic-gate * if_process will set pr_in_use when it finds the interface 588*0Sstevel@tonic-gate * in the kernel. 589*0Sstevel@tonic-gate */ 590*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = pi->pi_next) { 591*0Sstevel@tonic-gate /* 592*0Sstevel@tonic-gate * Before re-examining the state of the interfaces, 593*0Sstevel@tonic-gate * PI_PRESENT should be cleared from pi_kernel_state. 594*0Sstevel@tonic-gate */ 595*0Sstevel@tonic-gate pi->pi_kernel_state &= ~PI_PRESENT; 596*0Sstevel@tonic-gate for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 597*0Sstevel@tonic-gate pr->pr_in_use = _B_FALSE; 598*0Sstevel@tonic-gate } 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate lifc.lifc_family = AF_INET6; 602*0Sstevel@tonic-gate lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY; 603*0Sstevel@tonic-gate lifc.lifc_len = bufsize; 604*0Sstevel@tonic-gate lifc.lifc_buf = buf; 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate if (ioctl(ifsock, SIOCGLIFCONF, (char *)&lifc) < 0) { 607*0Sstevel@tonic-gate logperror("initifs: ioctl (get interface configuration)"); 608*0Sstevel@tonic-gate free(buf); 609*0Sstevel@tonic-gate return; 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate lifr = (struct lifreq *)lifc.lifc_req; 613*0Sstevel@tonic-gate for (n = lifc.lifc_len / sizeof (struct lifreq); n > 0; n--, lifr++) 614*0Sstevel@tonic-gate if_process(ifsock, lifr->lifr_name, first); 615*0Sstevel@tonic-gate free(buf); 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate /* 618*0Sstevel@tonic-gate * Detect phyints that have been removed from the kernel. 619*0Sstevel@tonic-gate * Since we can't recreate it here (would require ifconfig plumb 620*0Sstevel@tonic-gate * logic) we just terminate use of that phyint. 621*0Sstevel@tonic-gate */ 622*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = next_pi) { 623*0Sstevel@tonic-gate next_pi = pi->pi_next; 624*0Sstevel@tonic-gate /* 625*0Sstevel@tonic-gate * If interface (still) exists in kernel, set 626*0Sstevel@tonic-gate * pi_state to indicate that. 627*0Sstevel@tonic-gate */ 628*0Sstevel@tonic-gate if (pi->pi_kernel_state & PI_PRESENT) { 629*0Sstevel@tonic-gate pi->pi_state |= PI_PRESENT; 630*0Sstevel@tonic-gate } 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate check_if_removed(pi); 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate if (show_ifs) 635*0Sstevel@tonic-gate phyint_print_all(); 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate /* 640*0Sstevel@tonic-gate * Router advertisement state machine. Used for everything but timer 641*0Sstevel@tonic-gate * events which use advertise_event directly. 642*0Sstevel@tonic-gate */ 643*0Sstevel@tonic-gate void 644*0Sstevel@tonic-gate check_to_advertise(struct phyint *pi, enum adv_events event) 645*0Sstevel@tonic-gate { 646*0Sstevel@tonic-gate uint_t delay; 647*0Sstevel@tonic-gate enum adv_states old_state = pi->pi_adv_state; 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate if (debug & D_STATE) { 650*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "check_to_advertise(%s, %d) state %d\n", 651*0Sstevel@tonic-gate pi->pi_name, (int)event, (int)old_state); 652*0Sstevel@tonic-gate } 653*0Sstevel@tonic-gate delay = advertise_event(pi, event, 0); 654*0Sstevel@tonic-gate if (delay != TIMER_INFINITY) { 655*0Sstevel@tonic-gate /* Make sure the global next event is updated */ 656*0Sstevel@tonic-gate timer_schedule(delay); 657*0Sstevel@tonic-gate } 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate if (debug & D_STATE) { 660*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "check_to_advertise(%s, %d) state %d -> %d\n", 661*0Sstevel@tonic-gate pi->pi_name, (int)event, (int)old_state, 662*0Sstevel@tonic-gate (int)pi->pi_adv_state); 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate } 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate /* 667*0Sstevel@tonic-gate * Router advertisement state machine. 668*0Sstevel@tonic-gate * Return the number of milliseconds until next timeout (TIMER_INFINITY 669*0Sstevel@tonic-gate * if never). 670*0Sstevel@tonic-gate * For the ADV_TIMER event the caller passes in the number of milliseconds 671*0Sstevel@tonic-gate * since the last timer event in the 'elapsed' parameter. 672*0Sstevel@tonic-gate */ 673*0Sstevel@tonic-gate uint_t 674*0Sstevel@tonic-gate advertise_event(struct phyint *pi, enum adv_events event, uint_t elapsed) 675*0Sstevel@tonic-gate { 676*0Sstevel@tonic-gate uint_t delay; 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate if (debug & D_STATE) { 679*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "advertise_event(%s, %d, %d) state %d\n", 680*0Sstevel@tonic-gate pi->pi_name, (int)event, elapsed, (int)pi->pi_adv_state); 681*0Sstevel@tonic-gate } 682*0Sstevel@tonic-gate check_daemonize(); 683*0Sstevel@tonic-gate if (!pi->pi_AdvSendAdvertisements) 684*0Sstevel@tonic-gate return (TIMER_INFINITY); 685*0Sstevel@tonic-gate if (pi->pi_flags & IFF_NORTEXCH) { 686*0Sstevel@tonic-gate if (debug & D_PKTOUT) { 687*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "Suppress sending RA packet on %s " 688*0Sstevel@tonic-gate "(no route exchange on interface)\n", 689*0Sstevel@tonic-gate pi->pi_name); 690*0Sstevel@tonic-gate } 691*0Sstevel@tonic-gate return (TIMER_INFINITY); 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate switch (event) { 695*0Sstevel@tonic-gate case ADV_OFF: 696*0Sstevel@tonic-gate pi->pi_adv_state = NO_ADV; 697*0Sstevel@tonic-gate return (TIMER_INFINITY); 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate case START_INIT_ADV: 700*0Sstevel@tonic-gate if (pi->pi_adv_state == INIT_ADV) 701*0Sstevel@tonic-gate return (pi->pi_adv_time_left); 702*0Sstevel@tonic-gate pi->pi_adv_count = ND_MAX_INITIAL_RTR_ADVERTISEMENTS; 703*0Sstevel@tonic-gate pi->pi_adv_time_left = 0; 704*0Sstevel@tonic-gate pi->pi_adv_state = INIT_ADV; 705*0Sstevel@tonic-gate break; /* send advertisement */ 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate case START_FINAL_ADV: 708*0Sstevel@tonic-gate if (pi->pi_adv_state == NO_ADV) 709*0Sstevel@tonic-gate return (TIMER_INFINITY); 710*0Sstevel@tonic-gate if (pi->pi_adv_state == FINAL_ADV) 711*0Sstevel@tonic-gate return (pi->pi_adv_time_left); 712*0Sstevel@tonic-gate pi->pi_adv_count = ND_MAX_FINAL_RTR_ADVERTISEMENTS; 713*0Sstevel@tonic-gate pi->pi_adv_time_left = 0; 714*0Sstevel@tonic-gate pi->pi_adv_state = FINAL_ADV; 715*0Sstevel@tonic-gate break; /* send advertisement */ 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate case RECEIVED_SOLICIT: 718*0Sstevel@tonic-gate if (pi->pi_adv_state == NO_ADV) 719*0Sstevel@tonic-gate return (TIMER_INFINITY); 720*0Sstevel@tonic-gate if (pi->pi_adv_state == SOLICIT_ADV) { 721*0Sstevel@tonic-gate if (pi->pi_adv_time_left != 0) 722*0Sstevel@tonic-gate return (pi->pi_adv_time_left); 723*0Sstevel@tonic-gate break; 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate delay = GET_RANDOM(0, ND_MAX_RA_DELAY_TIME); 726*0Sstevel@tonic-gate if (delay < pi->pi_adv_time_left) 727*0Sstevel@tonic-gate pi->pi_adv_time_left = delay; 728*0Sstevel@tonic-gate if (pi->pi_adv_time_since_sent < ND_MIN_DELAY_BETWEEN_RAS) { 729*0Sstevel@tonic-gate /* 730*0Sstevel@tonic-gate * Send an advertisement (ND_MIN_DELAY_BETWEEN_RAS 731*0Sstevel@tonic-gate * plus random delay) after the previous 732*0Sstevel@tonic-gate * advertisement was sent. 733*0Sstevel@tonic-gate */ 734*0Sstevel@tonic-gate pi->pi_adv_time_left = delay + 735*0Sstevel@tonic-gate ND_MIN_DELAY_BETWEEN_RAS - 736*0Sstevel@tonic-gate pi->pi_adv_time_since_sent; 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate pi->pi_adv_state = SOLICIT_ADV; 739*0Sstevel@tonic-gate break; 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate case ADV_TIMER: 742*0Sstevel@tonic-gate if (pi->pi_adv_state == NO_ADV) 743*0Sstevel@tonic-gate return (TIMER_INFINITY); 744*0Sstevel@tonic-gate /* Decrease time left */ 745*0Sstevel@tonic-gate if (pi->pi_adv_time_left >= elapsed) 746*0Sstevel@tonic-gate pi->pi_adv_time_left -= elapsed; 747*0Sstevel@tonic-gate else 748*0Sstevel@tonic-gate pi->pi_adv_time_left = 0; 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate /* Increase time since last advertisement was sent */ 751*0Sstevel@tonic-gate pi->pi_adv_time_since_sent += elapsed; 752*0Sstevel@tonic-gate break; 753*0Sstevel@tonic-gate default: 754*0Sstevel@tonic-gate logmsg(LOG_ERR, "advertise_event: Unknown event %d\n", 755*0Sstevel@tonic-gate (int)event); 756*0Sstevel@tonic-gate return (TIMER_INFINITY); 757*0Sstevel@tonic-gate } 758*0Sstevel@tonic-gate 759*0Sstevel@tonic-gate if (pi->pi_adv_time_left != 0) 760*0Sstevel@tonic-gate return (pi->pi_adv_time_left); 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate /* Send advertisement and calculate next time to send */ 763*0Sstevel@tonic-gate if (pi->pi_adv_state == FINAL_ADV) { 764*0Sstevel@tonic-gate /* Omit the prefixes */ 765*0Sstevel@tonic-gate advertise(&v6allnodes, pi, _B_TRUE); 766*0Sstevel@tonic-gate } else { 767*0Sstevel@tonic-gate advertise(&v6allnodes, pi, _B_FALSE); 768*0Sstevel@tonic-gate } 769*0Sstevel@tonic-gate pi->pi_adv_time_since_sent = 0; 770*0Sstevel@tonic-gate 771*0Sstevel@tonic-gate switch (pi->pi_adv_state) { 772*0Sstevel@tonic-gate case SOLICIT_ADV: 773*0Sstevel@tonic-gate /* 774*0Sstevel@tonic-gate * The solicited advertisement has been sent. 775*0Sstevel@tonic-gate * Revert to periodic advertisements. 776*0Sstevel@tonic-gate */ 777*0Sstevel@tonic-gate pi->pi_adv_state = REG_ADV; 778*0Sstevel@tonic-gate /* FALLTHRU */ 779*0Sstevel@tonic-gate case REG_ADV: 780*0Sstevel@tonic-gate pi->pi_adv_time_left = 781*0Sstevel@tonic-gate GET_RANDOM(1000 * pi->pi_MinRtrAdvInterval, 782*0Sstevel@tonic-gate 1000 * pi->pi_MaxRtrAdvInterval); 783*0Sstevel@tonic-gate break; 784*0Sstevel@tonic-gate 785*0Sstevel@tonic-gate case INIT_ADV: 786*0Sstevel@tonic-gate if (--pi->pi_adv_count > 0) { 787*0Sstevel@tonic-gate delay = GET_RANDOM(1000 * pi->pi_MinRtrAdvInterval, 788*0Sstevel@tonic-gate 1000 * pi->pi_MaxRtrAdvInterval); 789*0Sstevel@tonic-gate if (delay > ND_MAX_INITIAL_RTR_ADVERT_INTERVAL) 790*0Sstevel@tonic-gate delay = ND_MAX_INITIAL_RTR_ADVERT_INTERVAL; 791*0Sstevel@tonic-gate pi->pi_adv_time_left = delay; 792*0Sstevel@tonic-gate } else { 793*0Sstevel@tonic-gate pi->pi_adv_time_left = 794*0Sstevel@tonic-gate GET_RANDOM(1000 * pi->pi_MinRtrAdvInterval, 795*0Sstevel@tonic-gate 1000 * pi->pi_MaxRtrAdvInterval); 796*0Sstevel@tonic-gate pi->pi_adv_state = REG_ADV; 797*0Sstevel@tonic-gate } 798*0Sstevel@tonic-gate break; 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate case FINAL_ADV: 801*0Sstevel@tonic-gate if (--pi->pi_adv_count > 0) { 802*0Sstevel@tonic-gate pi->pi_adv_time_left = 803*0Sstevel@tonic-gate ND_MAX_INITIAL_RTR_ADVERT_INTERVAL; 804*0Sstevel@tonic-gate } else { 805*0Sstevel@tonic-gate pi->pi_adv_state = NO_ADV; 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate break; 808*0Sstevel@tonic-gate } 809*0Sstevel@tonic-gate if (pi->pi_adv_state != NO_ADV) 810*0Sstevel@tonic-gate return (pi->pi_adv_time_left); 811*0Sstevel@tonic-gate else 812*0Sstevel@tonic-gate return (TIMER_INFINITY); 813*0Sstevel@tonic-gate } 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate /* 816*0Sstevel@tonic-gate * Router solicitation state machine. Used for everything but timer 817*0Sstevel@tonic-gate * events which use solicit_event directly. 818*0Sstevel@tonic-gate */ 819*0Sstevel@tonic-gate void 820*0Sstevel@tonic-gate check_to_solicit(struct phyint *pi, enum solicit_events event) 821*0Sstevel@tonic-gate { 822*0Sstevel@tonic-gate uint_t delay; 823*0Sstevel@tonic-gate enum solicit_states old_state = pi->pi_sol_state; 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate if (debug & D_STATE) { 826*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "check_to_solicit(%s, %d) state %d\n", 827*0Sstevel@tonic-gate pi->pi_name, (int)event, (int)old_state); 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate delay = solicit_event(pi, event, 0); 830*0Sstevel@tonic-gate if (delay != TIMER_INFINITY) { 831*0Sstevel@tonic-gate /* Make sure the global next event is updated */ 832*0Sstevel@tonic-gate timer_schedule(delay); 833*0Sstevel@tonic-gate } 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate if (debug & D_STATE) { 836*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "check_to_solicit(%s, %d) state %d -> %d\n", 837*0Sstevel@tonic-gate pi->pi_name, (int)event, (int)old_state, 838*0Sstevel@tonic-gate (int)pi->pi_sol_state); 839*0Sstevel@tonic-gate } 840*0Sstevel@tonic-gate } 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate static void 843*0Sstevel@tonic-gate daemonize_ndpd(void) 844*0Sstevel@tonic-gate { 845*0Sstevel@tonic-gate FILE *pidfp; 846*0Sstevel@tonic-gate mode_t pidmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* 0644 */ 847*0Sstevel@tonic-gate struct itimerval it; 848*0Sstevel@tonic-gate boolean_t timerval = _B_TRUE; 849*0Sstevel@tonic-gate 850*0Sstevel@tonic-gate /* 851*0Sstevel@tonic-gate * Need to get current timer settings so they can be restored 852*0Sstevel@tonic-gate * after the fork(), as the it_value and it_interval values for 853*0Sstevel@tonic-gate * the ITIMER_REAL timer are reset to 0 in the child process. 854*0Sstevel@tonic-gate */ 855*0Sstevel@tonic-gate if (getitimer(ITIMER_REAL, &it) < 0) { 856*0Sstevel@tonic-gate if (debug & D_TIMER) 857*0Sstevel@tonic-gate logmsg(LOG_DEBUG, 858*0Sstevel@tonic-gate "daemonize_ndpd: failed to get itimerval\n"); 859*0Sstevel@tonic-gate timerval = _B_FALSE; 860*0Sstevel@tonic-gate } 861*0Sstevel@tonic-gate 862*0Sstevel@tonic-gate /* Daemonize. */ 863*0Sstevel@tonic-gate switch (fork()) { 864*0Sstevel@tonic-gate case 0: 865*0Sstevel@tonic-gate /* Child */ 866*0Sstevel@tonic-gate break; 867*0Sstevel@tonic-gate case -1: 868*0Sstevel@tonic-gate logperror("fork"); 869*0Sstevel@tonic-gate exit(1); 870*0Sstevel@tonic-gate default: 871*0Sstevel@tonic-gate /* Parent */ 872*0Sstevel@tonic-gate _exit(0); 873*0Sstevel@tonic-gate } 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate /* Store our process id, blow away any existing file if it exists. */ 876*0Sstevel@tonic-gate if ((pidfp = fopen(PATH_PID, "w")) == NULL) { 877*0Sstevel@tonic-gate (void) fprintf(stderr, "%s: unable to open " PATH_PID ": %s\n", 878*0Sstevel@tonic-gate argv0[0], strerror(errno)); 879*0Sstevel@tonic-gate } else { 880*0Sstevel@tonic-gate (void) fprintf(pidfp, "%ld\n", getpid()); 881*0Sstevel@tonic-gate (void) fclose(pidfp); 882*0Sstevel@tonic-gate (void) chmod(PATH_PID, pidmode); 883*0Sstevel@tonic-gate } 884*0Sstevel@tonic-gate 885*0Sstevel@tonic-gate (void) close(0); 886*0Sstevel@tonic-gate (void) close(1); 887*0Sstevel@tonic-gate (void) close(2); 888*0Sstevel@tonic-gate 889*0Sstevel@tonic-gate (void) chdir("/"); 890*0Sstevel@tonic-gate (void) open("/dev/null", O_RDWR); 891*0Sstevel@tonic-gate (void) dup2(0, 1); 892*0Sstevel@tonic-gate (void) dup2(0, 2); 893*0Sstevel@tonic-gate (void) setsid(); 894*0Sstevel@tonic-gate 895*0Sstevel@tonic-gate already_daemonized = _B_TRUE; 896*0Sstevel@tonic-gate 897*0Sstevel@tonic-gate /* 898*0Sstevel@tonic-gate * Restore timer values, if we were able to save them; if not, 899*0Sstevel@tonic-gate * check and set the right value by calling run_timeouts(). 900*0Sstevel@tonic-gate */ 901*0Sstevel@tonic-gate if (timerval) { 902*0Sstevel@tonic-gate if (setitimer(ITIMER_REAL, &it, NULL) < 0) { 903*0Sstevel@tonic-gate logperror("daemonize_ndpd: setitimer"); 904*0Sstevel@tonic-gate exit(2); 905*0Sstevel@tonic-gate } 906*0Sstevel@tonic-gate } else { 907*0Sstevel@tonic-gate run_timeouts(); 908*0Sstevel@tonic-gate } 909*0Sstevel@tonic-gate } 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate /* 912*0Sstevel@tonic-gate * Check to see if the time is right to daemonize. The right time is when: 913*0Sstevel@tonic-gate * 914*0Sstevel@tonic-gate * 1. We haven't already daemonized. 915*0Sstevel@tonic-gate * 2. We are not in debug mode. 916*0Sstevel@tonic-gate * 3. All interfaces are marked IFF_NOXMIT. 917*0Sstevel@tonic-gate * 4. All non-router interfaces have their prefixes set up and we're 918*0Sstevel@tonic-gate * done sending router solicitations on those interfaces without 919*0Sstevel@tonic-gate * prefixes. 920*0Sstevel@tonic-gate */ 921*0Sstevel@tonic-gate static void 922*0Sstevel@tonic-gate check_daemonize(void) 923*0Sstevel@tonic-gate { 924*0Sstevel@tonic-gate struct phyint *pi; 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate if (already_daemonized || debug != 0) 927*0Sstevel@tonic-gate return; 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = pi->pi_next) { 930*0Sstevel@tonic-gate if (!(pi->pi_flags & IFF_NOXMIT)) 931*0Sstevel@tonic-gate break; 932*0Sstevel@tonic-gate } 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate /* 935*0Sstevel@tonic-gate * If we can't transmit on any of the interfaces there is no reason 936*0Sstevel@tonic-gate * to hold up progress. 937*0Sstevel@tonic-gate */ 938*0Sstevel@tonic-gate if (pi == NULL) { 939*0Sstevel@tonic-gate daemonize_ndpd(); 940*0Sstevel@tonic-gate return; 941*0Sstevel@tonic-gate } 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate /* Check all interfaces. If any are still soliciting, just return. */ 944*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = pi->pi_next) { 945*0Sstevel@tonic-gate if (pi->pi_AdvSendAdvertisements || 946*0Sstevel@tonic-gate !(pi->pi_kernel_state & PI_PRESENT)) 947*0Sstevel@tonic-gate continue; 948*0Sstevel@tonic-gate 949*0Sstevel@tonic-gate if (pi->pi_sol_state == INIT_SOLICIT) 950*0Sstevel@tonic-gate return; 951*0Sstevel@tonic-gate } 952*0Sstevel@tonic-gate 953*0Sstevel@tonic-gate daemonize_ndpd(); 954*0Sstevel@tonic-gate } 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate /* 957*0Sstevel@tonic-gate * Router solicitation state machine. 958*0Sstevel@tonic-gate * Return the number of milliseconds until next timeout (TIMER_INFINITY 959*0Sstevel@tonic-gate * if never). 960*0Sstevel@tonic-gate * For the SOL_TIMER event the caller passes in the number of milliseconds 961*0Sstevel@tonic-gate * since the last timer event in the 'elapsed' parameter. 962*0Sstevel@tonic-gate */ 963*0Sstevel@tonic-gate uint_t 964*0Sstevel@tonic-gate solicit_event(struct phyint *pi, enum solicit_events event, uint_t elapsed) 965*0Sstevel@tonic-gate { 966*0Sstevel@tonic-gate if (debug & D_STATE) { 967*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "solicit_event(%s, %d, %d) state %d\n", 968*0Sstevel@tonic-gate pi->pi_name, (int)event, elapsed, (int)pi->pi_sol_state); 969*0Sstevel@tonic-gate } 970*0Sstevel@tonic-gate 971*0Sstevel@tonic-gate if (pi->pi_AdvSendAdvertisements) 972*0Sstevel@tonic-gate return (TIMER_INFINITY); 973*0Sstevel@tonic-gate if (pi->pi_flags & IFF_NORTEXCH) { 974*0Sstevel@tonic-gate if (debug & D_PKTOUT) { 975*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "Suppress sending RS packet on %s " 976*0Sstevel@tonic-gate "(no route exchange on interface)\n", 977*0Sstevel@tonic-gate pi->pi_name); 978*0Sstevel@tonic-gate } 979*0Sstevel@tonic-gate return (TIMER_INFINITY); 980*0Sstevel@tonic-gate } 981*0Sstevel@tonic-gate 982*0Sstevel@tonic-gate switch (event) { 983*0Sstevel@tonic-gate case SOLICIT_OFF: 984*0Sstevel@tonic-gate pi->pi_sol_state = NO_SOLICIT; 985*0Sstevel@tonic-gate check_daemonize(); 986*0Sstevel@tonic-gate return (TIMER_INFINITY); 987*0Sstevel@tonic-gate 988*0Sstevel@tonic-gate case SOLICIT_DONE: 989*0Sstevel@tonic-gate pi->pi_sol_state = DONE_SOLICIT; 990*0Sstevel@tonic-gate check_daemonize(); 991*0Sstevel@tonic-gate return (TIMER_INFINITY); 992*0Sstevel@tonic-gate 993*0Sstevel@tonic-gate case START_INIT_SOLICIT: 994*0Sstevel@tonic-gate if (pi->pi_sol_state == INIT_SOLICIT) 995*0Sstevel@tonic-gate return (pi->pi_sol_time_left); 996*0Sstevel@tonic-gate pi->pi_sol_count = ND_MAX_RTR_SOLICITATIONS; 997*0Sstevel@tonic-gate pi->pi_sol_time_left = 998*0Sstevel@tonic-gate GET_RANDOM(0, ND_MAX_RTR_SOLICITATION_DELAY); 999*0Sstevel@tonic-gate pi->pi_sol_state = INIT_SOLICIT; 1000*0Sstevel@tonic-gate break; 1001*0Sstevel@tonic-gate 1002*0Sstevel@tonic-gate case SOL_TIMER: 1003*0Sstevel@tonic-gate if (pi->pi_sol_state == NO_SOLICIT) 1004*0Sstevel@tonic-gate return (TIMER_INFINITY); 1005*0Sstevel@tonic-gate /* Decrease time left */ 1006*0Sstevel@tonic-gate if (pi->pi_sol_time_left >= elapsed) 1007*0Sstevel@tonic-gate pi->pi_sol_time_left -= elapsed; 1008*0Sstevel@tonic-gate else 1009*0Sstevel@tonic-gate pi->pi_sol_time_left = 0; 1010*0Sstevel@tonic-gate break; 1011*0Sstevel@tonic-gate default: 1012*0Sstevel@tonic-gate logmsg(LOG_ERR, "solicit_event: Unknown event %d\n", 1013*0Sstevel@tonic-gate (int)event); 1014*0Sstevel@tonic-gate return (TIMER_INFINITY); 1015*0Sstevel@tonic-gate } 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate if (pi->pi_sol_time_left != 0) 1018*0Sstevel@tonic-gate return (pi->pi_sol_time_left); 1019*0Sstevel@tonic-gate 1020*0Sstevel@tonic-gate /* Send solicitation and calculate next time */ 1021*0Sstevel@tonic-gate switch (pi->pi_sol_state) { 1022*0Sstevel@tonic-gate case INIT_SOLICIT: 1023*0Sstevel@tonic-gate solicit(&v6allrouters, pi); 1024*0Sstevel@tonic-gate if (--pi->pi_sol_count == 0) { 1025*0Sstevel@tonic-gate pi->pi_sol_state = DONE_SOLICIT; 1026*0Sstevel@tonic-gate /* check if default route needs to be installed */ 1027*0Sstevel@tonic-gate check_fallback(); 1028*0Sstevel@tonic-gate check_daemonize(); 1029*0Sstevel@tonic-gate return (TIMER_INFINITY); 1030*0Sstevel@tonic-gate } 1031*0Sstevel@tonic-gate pi->pi_sol_time_left = ND_RTR_SOLICITATION_INTERVAL; 1032*0Sstevel@tonic-gate return (pi->pi_sol_time_left); 1033*0Sstevel@tonic-gate case NO_SOLICIT: 1034*0Sstevel@tonic-gate case DONE_SOLICIT: 1035*0Sstevel@tonic-gate return (TIMER_INFINITY); 1036*0Sstevel@tonic-gate default: 1037*0Sstevel@tonic-gate return (pi->pi_sol_time_left); 1038*0Sstevel@tonic-gate } 1039*0Sstevel@tonic-gate } 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* 1042*0Sstevel@tonic-gate * If no interfaces are advertising and have gone to DONE_SOLICIT 1043*0Sstevel@tonic-gate * and there are no default routers: 1044*0Sstevel@tonic-gate * We add an "everything is on-link" default route if there 1045*0Sstevel@tonic-gate * is only one non-point-to-point phyint in the kernel. 1046*0Sstevel@tonic-gate * XXX What to do when there are multiple phyints? 1047*0Sstevel@tonic-gate * XXX The router_delete_onlink checks only operate on one phyint! 1048*0Sstevel@tonic-gate */ 1049*0Sstevel@tonic-gate void 1050*0Sstevel@tonic-gate check_fallback(void) 1051*0Sstevel@tonic-gate { 1052*0Sstevel@tonic-gate struct phyint *pi; 1053*0Sstevel@tonic-gate struct router *dr; 1054*0Sstevel@tonic-gate boolean_t add_default; 1055*0Sstevel@tonic-gate int num_phyints; 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate if (debug & D_PREFIX) { 1058*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "check_fallback()\n"); 1059*0Sstevel@tonic-gate } 1060*0Sstevel@tonic-gate add_default = _B_TRUE; 1061*0Sstevel@tonic-gate num_phyints = 0; 1062*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = pi->pi_next) { 1063*0Sstevel@tonic-gate if (pi->pi_AdvSendAdvertisements || 1064*0Sstevel@tonic-gate pi->pi_sol_state != DONE_SOLICIT) { 1065*0Sstevel@tonic-gate add_default = _B_FALSE; 1066*0Sstevel@tonic-gate break; 1067*0Sstevel@tonic-gate } 1068*0Sstevel@tonic-gate if (!(pi->pi_kernel_state & PI_PRESENT)) 1069*0Sstevel@tonic-gate continue; 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate if (!(pi->pi_flags & IFF_POINTOPOINT)) 1072*0Sstevel@tonic-gate num_phyints++; 1073*0Sstevel@tonic-gate for (dr = pi->pi_router_list; dr != NULL; dr = dr->dr_next) { 1074*0Sstevel@tonic-gate if (dr->dr_inkernel) { 1075*0Sstevel@tonic-gate add_default = _B_FALSE; 1076*0Sstevel@tonic-gate break; 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate if (!add_default) 1080*0Sstevel@tonic-gate break; 1081*0Sstevel@tonic-gate } 1082*0Sstevel@tonic-gate if (num_phyints == 1 && add_default) { 1083*0Sstevel@tonic-gate if (debug & D_ROUTER) { 1084*0Sstevel@tonic-gate logmsg(LOG_DEBUG, 1085*0Sstevel@tonic-gate "check_fallback: create default router\n"); 1086*0Sstevel@tonic-gate } 1087*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = pi->pi_next) { 1088*0Sstevel@tonic-gate if (!(pi->pi_kernel_state & PI_PRESENT)) 1089*0Sstevel@tonic-gate continue; 1090*0Sstevel@tonic-gate if (debug & D_ROUTER) { 1091*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "check_fallback: " 1092*0Sstevel@tonic-gate "%s default router\n", pi->pi_name); 1093*0Sstevel@tonic-gate } 1094*0Sstevel@tonic-gate if (!(pi->pi_flags & IFF_POINTOPOINT)) 1095*0Sstevel@tonic-gate (void) router_create_onlink(pi); 1096*0Sstevel@tonic-gate } 1097*0Sstevel@tonic-gate } 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate } 1100*0Sstevel@tonic-gate 1101*0Sstevel@tonic-gate /* 1102*0Sstevel@tonic-gate * Timer mechanism using relative time (in milliseconds) from the 1103*0Sstevel@tonic-gate * previous timer event. Timers exceeding TIMER_INFINITY milliseconds 1104*0Sstevel@tonic-gate * will fire after TIMER_INFINITY milliseconds. 1105*0Sstevel@tonic-gate */ 1106*0Sstevel@tonic-gate static uint_t timer_previous; /* When last SIGALRM occurred */ 1107*0Sstevel@tonic-gate static uint_t timer_next; /* Currently scheduled timeout */ 1108*0Sstevel@tonic-gate 1109*0Sstevel@tonic-gate static void 1110*0Sstevel@tonic-gate timer_init(void) 1111*0Sstevel@tonic-gate { 1112*0Sstevel@tonic-gate timer_previous = getcurrenttime(); 1113*0Sstevel@tonic-gate timer_next = TIMER_INFINITY; 1114*0Sstevel@tonic-gate run_timeouts(); 1115*0Sstevel@tonic-gate } 1116*0Sstevel@tonic-gate 1117*0Sstevel@tonic-gate /* 1118*0Sstevel@tonic-gate * Make sure the next SIGALRM occurs delay milliseconds from the current 1119*0Sstevel@tonic-gate * time if not earlier. 1120*0Sstevel@tonic-gate * Handles getcurrenttime (32 bit integer holding milliseconds) wraparound 1121*0Sstevel@tonic-gate * by treating differences greater than 0x80000000 as negative. 1122*0Sstevel@tonic-gate */ 1123*0Sstevel@tonic-gate void 1124*0Sstevel@tonic-gate timer_schedule(uint_t delay) 1125*0Sstevel@tonic-gate { 1126*0Sstevel@tonic-gate uint_t now; 1127*0Sstevel@tonic-gate struct itimerval itimerval; 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate now = getcurrenttime(); 1130*0Sstevel@tonic-gate if (debug & D_TIMER) { 1131*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "timer_schedule(%u): now %u next %u\n", 1132*0Sstevel@tonic-gate delay, now, timer_next); 1133*0Sstevel@tonic-gate } 1134*0Sstevel@tonic-gate /* Will this timer occur before the currently scheduled SIGALRM? */ 1135*0Sstevel@tonic-gate if (delay >= timer_next - now) { 1136*0Sstevel@tonic-gate if (debug & D_TIMER) { 1137*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "timer_schedule(%u): no action - " 1138*0Sstevel@tonic-gate "next in %u ms\n", 1139*0Sstevel@tonic-gate delay, timer_next - now); 1140*0Sstevel@tonic-gate } 1141*0Sstevel@tonic-gate return; 1142*0Sstevel@tonic-gate } 1143*0Sstevel@tonic-gate if (delay == 0) { 1144*0Sstevel@tonic-gate /* Minimum allowed delay */ 1145*0Sstevel@tonic-gate delay = 1; 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate timer_next = now + delay; 1148*0Sstevel@tonic-gate 1149*0Sstevel@tonic-gate itimerval.it_value.tv_sec = delay / 1000; 1150*0Sstevel@tonic-gate itimerval.it_value.tv_usec = (delay % 1000) * 1000; 1151*0Sstevel@tonic-gate itimerval.it_interval.tv_sec = 0; 1152*0Sstevel@tonic-gate itimerval.it_interval.tv_usec = 0; 1153*0Sstevel@tonic-gate if (debug & D_TIMER) { 1154*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "timer_schedule(%u): sec %lu usec %lu\n", 1155*0Sstevel@tonic-gate delay, 1156*0Sstevel@tonic-gate itimerval.it_value.tv_sec, itimerval.it_value.tv_usec); 1157*0Sstevel@tonic-gate } 1158*0Sstevel@tonic-gate if (setitimer(ITIMER_REAL, &itimerval, NULL) < 0) { 1159*0Sstevel@tonic-gate logperror("timer_schedule: setitimer"); 1160*0Sstevel@tonic-gate exit(2); 1161*0Sstevel@tonic-gate } 1162*0Sstevel@tonic-gate } 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate /* 1165*0Sstevel@tonic-gate * Conditional running of timer. If more than 'minimal_time' millseconds 1166*0Sstevel@tonic-gate * since the timer routines were last run we run them. 1167*0Sstevel@tonic-gate * Used when packets arrive. 1168*0Sstevel@tonic-gate */ 1169*0Sstevel@tonic-gate static void 1170*0Sstevel@tonic-gate conditional_run_timeouts(uint_t minimal_time) 1171*0Sstevel@tonic-gate { 1172*0Sstevel@tonic-gate uint_t now; 1173*0Sstevel@tonic-gate uint_t elapsed; 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate now = getcurrenttime(); 1176*0Sstevel@tonic-gate elapsed = now - timer_previous; 1177*0Sstevel@tonic-gate if (elapsed > minimal_time) { 1178*0Sstevel@tonic-gate if (debug & D_TIMER) { 1179*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "conditional_run_timeouts: " 1180*0Sstevel@tonic-gate "elapsed %d\n", elapsed); 1181*0Sstevel@tonic-gate } 1182*0Sstevel@tonic-gate run_timeouts(); 1183*0Sstevel@tonic-gate } 1184*0Sstevel@tonic-gate } 1185*0Sstevel@tonic-gate 1186*0Sstevel@tonic-gate /* 1187*0Sstevel@tonic-gate * Timer has fired. 1188*0Sstevel@tonic-gate * Determine when the next timer event will occur by asking all 1189*0Sstevel@tonic-gate * the timer routines. 1190*0Sstevel@tonic-gate * Should not be called from a timer routine but in some cases this is 1191*0Sstevel@tonic-gate * done because the code doesn't know that e.g. it was called from 1192*0Sstevel@tonic-gate * ifconfig_timer(). In this case the nested run_timeouts will just return but 1193*0Sstevel@tonic-gate * the running run_timeouts will ensure to call all the timer functions by 1194*0Sstevel@tonic-gate * looping once more. 1195*0Sstevel@tonic-gate */ 1196*0Sstevel@tonic-gate static void 1197*0Sstevel@tonic-gate run_timeouts(void) 1198*0Sstevel@tonic-gate { 1199*0Sstevel@tonic-gate uint_t now; 1200*0Sstevel@tonic-gate uint_t elapsed; 1201*0Sstevel@tonic-gate uint_t next; 1202*0Sstevel@tonic-gate uint_t nexti; 1203*0Sstevel@tonic-gate struct phyint *pi; 1204*0Sstevel@tonic-gate struct phyint *next_pi; 1205*0Sstevel@tonic-gate struct prefix *pr; 1206*0Sstevel@tonic-gate struct prefix *next_pr; 1207*0Sstevel@tonic-gate struct adv_prefix *adv_pr; 1208*0Sstevel@tonic-gate struct adv_prefix *next_adv_pr; 1209*0Sstevel@tonic-gate struct router *dr; 1210*0Sstevel@tonic-gate struct router *next_dr; 1211*0Sstevel@tonic-gate static boolean_t timeout_running; 1212*0Sstevel@tonic-gate static boolean_t do_retry; 1213*0Sstevel@tonic-gate 1214*0Sstevel@tonic-gate if (timeout_running) { 1215*0Sstevel@tonic-gate if (debug & D_TIMER) 1216*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts: nested call\n"); 1217*0Sstevel@tonic-gate do_retry = _B_TRUE; 1218*0Sstevel@tonic-gate return; 1219*0Sstevel@tonic-gate } 1220*0Sstevel@tonic-gate timeout_running = _B_TRUE; 1221*0Sstevel@tonic-gate retry: 1222*0Sstevel@tonic-gate /* How much time since the last time we were called? */ 1223*0Sstevel@tonic-gate now = getcurrenttime(); 1224*0Sstevel@tonic-gate elapsed = now - timer_previous; 1225*0Sstevel@tonic-gate timer_previous = now; 1226*0Sstevel@tonic-gate 1227*0Sstevel@tonic-gate if (debug & D_TIMER) 1228*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts: elapsed %d\n", elapsed); 1229*0Sstevel@tonic-gate 1230*0Sstevel@tonic-gate next = TIMER_INFINITY; 1231*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = next_pi) { 1232*0Sstevel@tonic-gate next_pi = pi->pi_next; 1233*0Sstevel@tonic-gate nexti = phyint_timer(pi, elapsed); 1234*0Sstevel@tonic-gate if (nexti != TIMER_INFINITY && nexti < next) 1235*0Sstevel@tonic-gate next = nexti; 1236*0Sstevel@tonic-gate if (debug & D_TIMER) { 1237*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts (pi %s): %d -> %u ms\n", 1238*0Sstevel@tonic-gate pi->pi_name, nexti, next); 1239*0Sstevel@tonic-gate } 1240*0Sstevel@tonic-gate for (pr = pi->pi_prefix_list; pr != NULL; pr = next_pr) { 1241*0Sstevel@tonic-gate next_pr = pr->pr_next; 1242*0Sstevel@tonic-gate nexti = prefix_timer(pr, elapsed); 1243*0Sstevel@tonic-gate if (nexti != TIMER_INFINITY && nexti < next) 1244*0Sstevel@tonic-gate next = nexti; 1245*0Sstevel@tonic-gate if (debug & D_TIMER) { 1246*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts (pr %s): " 1247*0Sstevel@tonic-gate "%d -> %u ms\n", pr->pr_name, nexti, next); 1248*0Sstevel@tonic-gate } 1249*0Sstevel@tonic-gate } 1250*0Sstevel@tonic-gate for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL; 1251*0Sstevel@tonic-gate adv_pr = next_adv_pr) { 1252*0Sstevel@tonic-gate next_adv_pr = adv_pr->adv_pr_next; 1253*0Sstevel@tonic-gate nexti = adv_prefix_timer(adv_pr, elapsed); 1254*0Sstevel@tonic-gate if (nexti != TIMER_INFINITY && nexti < next) 1255*0Sstevel@tonic-gate next = nexti; 1256*0Sstevel@tonic-gate if (debug & D_TIMER) { 1257*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts " 1258*0Sstevel@tonic-gate "(adv pr on %s): %d -> %u ms\n", 1259*0Sstevel@tonic-gate adv_pr->adv_pr_physical->pi_name, 1260*0Sstevel@tonic-gate nexti, next); 1261*0Sstevel@tonic-gate } 1262*0Sstevel@tonic-gate } 1263*0Sstevel@tonic-gate for (dr = pi->pi_router_list; dr != NULL; dr = next_dr) { 1264*0Sstevel@tonic-gate next_dr = dr->dr_next; 1265*0Sstevel@tonic-gate nexti = router_timer(dr, elapsed); 1266*0Sstevel@tonic-gate if (nexti != TIMER_INFINITY && nexti < next) 1267*0Sstevel@tonic-gate next = nexti; 1268*0Sstevel@tonic-gate if (debug & D_TIMER) { 1269*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts (dr): " 1270*0Sstevel@tonic-gate "%d -> %u ms\n", nexti, next); 1271*0Sstevel@tonic-gate } 1272*0Sstevel@tonic-gate } 1273*0Sstevel@tonic-gate if (pi->pi_TmpAddrsEnabled) { 1274*0Sstevel@tonic-gate nexti = tmptoken_timer(pi, elapsed); 1275*0Sstevel@tonic-gate if (nexti != TIMER_INFINITY && nexti < next) 1276*0Sstevel@tonic-gate next = nexti; 1277*0Sstevel@tonic-gate if (debug & D_TIMER) { 1278*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts (tmp on %s): " 1279*0Sstevel@tonic-gate "%d -> %u ms\n", pi->pi_name, nexti, next); 1280*0Sstevel@tonic-gate } 1281*0Sstevel@tonic-gate } 1282*0Sstevel@tonic-gate } 1283*0Sstevel@tonic-gate /* 1284*0Sstevel@tonic-gate * Make sure the timer functions are run at least once 1285*0Sstevel@tonic-gate * an hour. 1286*0Sstevel@tonic-gate */ 1287*0Sstevel@tonic-gate if (next == TIMER_INFINITY) 1288*0Sstevel@tonic-gate next = 3600 * 1000; /* 1 hour */ 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate if (debug & D_TIMER) 1291*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts: %u ms\n", next); 1292*0Sstevel@tonic-gate timer_schedule(next); 1293*0Sstevel@tonic-gate if (do_retry) { 1294*0Sstevel@tonic-gate if (debug & D_TIMER) 1295*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "run_timeouts: retry\n"); 1296*0Sstevel@tonic-gate do_retry = _B_FALSE; 1297*0Sstevel@tonic-gate goto retry; 1298*0Sstevel@tonic-gate } 1299*0Sstevel@tonic-gate timeout_running = _B_FALSE; 1300*0Sstevel@tonic-gate } 1301*0Sstevel@tonic-gate 1302*0Sstevel@tonic-gate static int eventpipe_read = -1; /* Used for synchronous signal delivery */ 1303*0Sstevel@tonic-gate static int eventpipe_write = -1; 1304*0Sstevel@tonic-gate 1305*0Sstevel@tonic-gate /* 1306*0Sstevel@tonic-gate * Ensure that signals are processed synchronously with the rest of 1307*0Sstevel@tonic-gate * the code by just writing a one character signal number on the pipe. 1308*0Sstevel@tonic-gate * The poll loop will pick this up and process the signal event. 1309*0Sstevel@tonic-gate */ 1310*0Sstevel@tonic-gate static void 1311*0Sstevel@tonic-gate sig_handler(int signo) 1312*0Sstevel@tonic-gate { 1313*0Sstevel@tonic-gate uchar_t buf = (uchar_t)signo; 1314*0Sstevel@tonic-gate 1315*0Sstevel@tonic-gate if (eventpipe_write == -1) { 1316*0Sstevel@tonic-gate logmsg(LOG_ERR, "sig_handler: no pipe\n"); 1317*0Sstevel@tonic-gate return; 1318*0Sstevel@tonic-gate } 1319*0Sstevel@tonic-gate if (write(eventpipe_write, &buf, sizeof (buf)) < 0) 1320*0Sstevel@tonic-gate logperror("sig_handler: write"); 1321*0Sstevel@tonic-gate } 1322*0Sstevel@tonic-gate 1323*0Sstevel@tonic-gate /* 1324*0Sstevel@tonic-gate * Pick up a signal "byte" from the pipe and process it. 1325*0Sstevel@tonic-gate */ 1326*0Sstevel@tonic-gate static void 1327*0Sstevel@tonic-gate in_signal(int fd) 1328*0Sstevel@tonic-gate { 1329*0Sstevel@tonic-gate uchar_t buf; 1330*0Sstevel@tonic-gate struct phyint *pi; 1331*0Sstevel@tonic-gate struct phyint *next_pi; 1332*0Sstevel@tonic-gate 1333*0Sstevel@tonic-gate switch (read(fd, &buf, sizeof (buf))) { 1334*0Sstevel@tonic-gate case -1: 1335*0Sstevel@tonic-gate logperror("in_signal: read"); 1336*0Sstevel@tonic-gate exit(1); 1337*0Sstevel@tonic-gate /* NOTREACHED */ 1338*0Sstevel@tonic-gate case 1: 1339*0Sstevel@tonic-gate break; 1340*0Sstevel@tonic-gate case 0: 1341*0Sstevel@tonic-gate logmsg(LOG_ERR, "in_signal: read eof\n"); 1342*0Sstevel@tonic-gate exit(1); 1343*0Sstevel@tonic-gate /* NOTREACHED */ 1344*0Sstevel@tonic-gate default: 1345*0Sstevel@tonic-gate logmsg(LOG_ERR, "in_signal: read > 1\n"); 1346*0Sstevel@tonic-gate exit(1); 1347*0Sstevel@tonic-gate } 1348*0Sstevel@tonic-gate 1349*0Sstevel@tonic-gate if (debug & D_TIMER) 1350*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "in_signal() got %d\n", buf); 1351*0Sstevel@tonic-gate 1352*0Sstevel@tonic-gate switch (buf) { 1353*0Sstevel@tonic-gate case SIGALRM: 1354*0Sstevel@tonic-gate if (debug & D_TIMER) { 1355*0Sstevel@tonic-gate uint_t now = getcurrenttime(); 1356*0Sstevel@tonic-gate 1357*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "in_signal(SIGALRM) delta %u\n", 1358*0Sstevel@tonic-gate now - timer_next); 1359*0Sstevel@tonic-gate } 1360*0Sstevel@tonic-gate timer_next = TIMER_INFINITY; 1361*0Sstevel@tonic-gate run_timeouts(); 1362*0Sstevel@tonic-gate break; 1363*0Sstevel@tonic-gate case SIGHUP: 1364*0Sstevel@tonic-gate /* Re-read config file by exec'ing ourselves */ 1365*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = next_pi) { 1366*0Sstevel@tonic-gate next_pi = pi->pi_next; 1367*0Sstevel@tonic-gate if (pi->pi_AdvSendAdvertisements) 1368*0Sstevel@tonic-gate check_to_advertise(pi, START_FINAL_ADV); 1369*0Sstevel@tonic-gate 1370*0Sstevel@tonic-gate phyint_delete(pi); 1371*0Sstevel@tonic-gate } 1372*0Sstevel@tonic-gate 1373*0Sstevel@tonic-gate /* 1374*0Sstevel@tonic-gate * Prevent fd leaks. Everything gets re-opened at start-up 1375*0Sstevel@tonic-gate * time. 0, 1, and 2 are closed and re-opened as 1376*0Sstevel@tonic-gate * /dev/null, so we'll leave those open. 1377*0Sstevel@tonic-gate */ 1378*0Sstevel@tonic-gate closefrom(3); 1379*0Sstevel@tonic-gate 1380*0Sstevel@tonic-gate logmsg(LOG_ERR, "SIGHUP: restart and reread config file\n"); 1381*0Sstevel@tonic-gate (void) execv(argv0[0], argv0); 1382*0Sstevel@tonic-gate (void) unlink(PATH_PID); 1383*0Sstevel@tonic-gate _exit(0177); 1384*0Sstevel@tonic-gate /* NOTREACHED */ 1385*0Sstevel@tonic-gate case SIGUSR1: 1386*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "Printing configuration:\n"); 1387*0Sstevel@tonic-gate phyint_print_all(); 1388*0Sstevel@tonic-gate break; 1389*0Sstevel@tonic-gate case SIGINT: 1390*0Sstevel@tonic-gate case SIGTERM: 1391*0Sstevel@tonic-gate case SIGQUIT: 1392*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = next_pi) { 1393*0Sstevel@tonic-gate next_pi = pi->pi_next; 1394*0Sstevel@tonic-gate if (pi->pi_AdvSendAdvertisements) 1395*0Sstevel@tonic-gate check_to_advertise(pi, START_FINAL_ADV); 1396*0Sstevel@tonic-gate 1397*0Sstevel@tonic-gate phyint_delete(pi); 1398*0Sstevel@tonic-gate } 1399*0Sstevel@tonic-gate (void) unlink(PATH_PID); 1400*0Sstevel@tonic-gate logmsg(LOG_ERR, "terminated\n"); 1401*0Sstevel@tonic-gate exit(0); 1402*0Sstevel@tonic-gate /* NOTREACHED */ 1403*0Sstevel@tonic-gate case 255: 1404*0Sstevel@tonic-gate /* 1405*0Sstevel@tonic-gate * Special "signal" from looback_ra_enqueue. 1406*0Sstevel@tonic-gate * Handle any queued loopback router advertisements. 1407*0Sstevel@tonic-gate */ 1408*0Sstevel@tonic-gate loopback_ra_dequeue(); 1409*0Sstevel@tonic-gate break; 1410*0Sstevel@tonic-gate default: 1411*0Sstevel@tonic-gate logmsg(LOG_ERR, "in_signal: unknown signal: %d\n", buf); 1412*0Sstevel@tonic-gate } 1413*0Sstevel@tonic-gate } 1414*0Sstevel@tonic-gate 1415*0Sstevel@tonic-gate /* 1416*0Sstevel@tonic-gate * Create pipe for signal delivery and set up signal handlers. 1417*0Sstevel@tonic-gate */ 1418*0Sstevel@tonic-gate static void 1419*0Sstevel@tonic-gate setup_eventpipe(void) 1420*0Sstevel@tonic-gate { 1421*0Sstevel@tonic-gate int fds[2]; 1422*0Sstevel@tonic-gate struct sigaction act; 1423*0Sstevel@tonic-gate 1424*0Sstevel@tonic-gate if ((pipe(fds)) < 0) { 1425*0Sstevel@tonic-gate logperror("setup_eventpipe: pipe"); 1426*0Sstevel@tonic-gate exit(1); 1427*0Sstevel@tonic-gate } 1428*0Sstevel@tonic-gate eventpipe_read = fds[0]; 1429*0Sstevel@tonic-gate eventpipe_write = fds[1]; 1430*0Sstevel@tonic-gate if (poll_add(eventpipe_read) == -1) { 1431*0Sstevel@tonic-gate exit(1); 1432*0Sstevel@tonic-gate } 1433*0Sstevel@tonic-gate act.sa_handler = sig_handler; 1434*0Sstevel@tonic-gate act.sa_flags = SA_RESTART; 1435*0Sstevel@tonic-gate (void) sigaction(SIGALRM, &act, NULL); 1436*0Sstevel@tonic-gate 1437*0Sstevel@tonic-gate (void) sigset(SIGHUP, sig_handler); 1438*0Sstevel@tonic-gate (void) sigset(SIGUSR1, sig_handler); 1439*0Sstevel@tonic-gate (void) sigset(SIGTERM, sig_handler); 1440*0Sstevel@tonic-gate (void) sigset(SIGINT, sig_handler); 1441*0Sstevel@tonic-gate (void) sigset(SIGQUIT, sig_handler); 1442*0Sstevel@tonic-gate } 1443*0Sstevel@tonic-gate 1444*0Sstevel@tonic-gate /* 1445*0Sstevel@tonic-gate * Create a routing socket for receiving RTM_IFINFO messages and initialize 1446*0Sstevel@tonic-gate * the routing socket message header and as much of the sockaddrs as possible. 1447*0Sstevel@tonic-gate */ 1448*0Sstevel@tonic-gate static int 1449*0Sstevel@tonic-gate setup_rtsock(void) 1450*0Sstevel@tonic-gate { 1451*0Sstevel@tonic-gate int s; 1452*0Sstevel@tonic-gate int ret; 1453*0Sstevel@tonic-gate char *cp; 1454*0Sstevel@tonic-gate struct sockaddr_in6 *sin6; 1455*0Sstevel@tonic-gate 1456*0Sstevel@tonic-gate s = socket(PF_ROUTE, SOCK_RAW, AF_INET6); 1457*0Sstevel@tonic-gate if (s == -1) { 1458*0Sstevel@tonic-gate logperror("socket(PF_ROUTE)"); 1459*0Sstevel@tonic-gate exit(1); 1460*0Sstevel@tonic-gate } 1461*0Sstevel@tonic-gate ret = fcntl(s, F_SETFL, O_NDELAY|O_NONBLOCK); 1462*0Sstevel@tonic-gate if (ret < 0) { 1463*0Sstevel@tonic-gate logperror("fcntl(O_NDELAY)"); 1464*0Sstevel@tonic-gate exit(1); 1465*0Sstevel@tonic-gate } 1466*0Sstevel@tonic-gate if (poll_add(s) == -1) { 1467*0Sstevel@tonic-gate exit(1); 1468*0Sstevel@tonic-gate } 1469*0Sstevel@tonic-gate 1470*0Sstevel@tonic-gate /* 1471*0Sstevel@tonic-gate * Allocate storage for the routing socket message. 1472*0Sstevel@tonic-gate */ 1473*0Sstevel@tonic-gate rt_msg = (struct rt_msghdr *)malloc(NDP_RTM_MSGLEN); 1474*0Sstevel@tonic-gate if (rt_msg == NULL) { 1475*0Sstevel@tonic-gate logperror("malloc"); 1476*0Sstevel@tonic-gate exit(1); 1477*0Sstevel@tonic-gate } 1478*0Sstevel@tonic-gate 1479*0Sstevel@tonic-gate /* 1480*0Sstevel@tonic-gate * Initialize the routing socket message by zero-filling it and then 1481*0Sstevel@tonic-gate * setting the fields where are constant through the lifetime of the 1482*0Sstevel@tonic-gate * process. 1483*0Sstevel@tonic-gate */ 1484*0Sstevel@tonic-gate bzero(rt_msg, NDP_RTM_MSGLEN); 1485*0Sstevel@tonic-gate rt_msg->rtm_msglen = NDP_RTM_MSGLEN; 1486*0Sstevel@tonic-gate rt_msg->rtm_version = RTM_VERSION; 1487*0Sstevel@tonic-gate rt_msg->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP; 1488*0Sstevel@tonic-gate rt_msg->rtm_pid = getpid(); 1489*0Sstevel@tonic-gate if (rt_msg->rtm_pid < 0) { 1490*0Sstevel@tonic-gate logperror("getpid"); 1491*0Sstevel@tonic-gate exit(1); 1492*0Sstevel@tonic-gate } 1493*0Sstevel@tonic-gate 1494*0Sstevel@tonic-gate /* 1495*0Sstevel@tonic-gate * The RTA_DST sockaddr does not change during the lifetime of the 1496*0Sstevel@tonic-gate * process so it can be completely initialized at this time. 1497*0Sstevel@tonic-gate */ 1498*0Sstevel@tonic-gate cp = (char *)rt_msg + sizeof (struct rt_msghdr); 1499*0Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)cp; 1500*0Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 1501*0Sstevel@tonic-gate sin6->sin6_addr = in6addr_any; 1502*0Sstevel@tonic-gate 1503*0Sstevel@tonic-gate /* 1504*0Sstevel@tonic-gate * Initialize the constant portion of the RTA_GATEWAY sockaddr. 1505*0Sstevel@tonic-gate */ 1506*0Sstevel@tonic-gate cp += sizeof (struct sockaddr_in6); 1507*0Sstevel@tonic-gate rta_gateway = (struct sockaddr_in6 *)cp; 1508*0Sstevel@tonic-gate rta_gateway->sin6_family = AF_INET6; 1509*0Sstevel@tonic-gate 1510*0Sstevel@tonic-gate /* 1511*0Sstevel@tonic-gate * The RTA_NETMASK sockaddr does not change during the lifetime of the 1512*0Sstevel@tonic-gate * process so it can be completely initialized at this time. 1513*0Sstevel@tonic-gate */ 1514*0Sstevel@tonic-gate cp += sizeof (struct sockaddr_in6); 1515*0Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)cp; 1516*0Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 1517*0Sstevel@tonic-gate sin6->sin6_addr = in6addr_any; 1518*0Sstevel@tonic-gate 1519*0Sstevel@tonic-gate /* 1520*0Sstevel@tonic-gate * Initialize the constant portion of the RTA_IFP sockaddr. 1521*0Sstevel@tonic-gate */ 1522*0Sstevel@tonic-gate cp += sizeof (struct sockaddr_in6); 1523*0Sstevel@tonic-gate rta_ifp = (struct sockaddr_dl *)cp; 1524*0Sstevel@tonic-gate rta_ifp->sdl_family = AF_LINK; 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate return (s); 1527*0Sstevel@tonic-gate } 1528*0Sstevel@tonic-gate 1529*0Sstevel@tonic-gate /* 1530*0Sstevel@tonic-gate * Retrieve one routing socket message. If RTM_IFINFO indicates 1531*0Sstevel@tonic-gate * new phyint do a full scan of the interfaces. If RTM_IFINFO 1532*0Sstevel@tonic-gate * indicates an existing phyint only scan that phyint and asociated 1533*0Sstevel@tonic-gate * prefixes. 1534*0Sstevel@tonic-gate */ 1535*0Sstevel@tonic-gate static void 1536*0Sstevel@tonic-gate process_rtsock(int rtsock) 1537*0Sstevel@tonic-gate { 1538*0Sstevel@tonic-gate int n; 1539*0Sstevel@tonic-gate #define MSG_SIZE 2048/8 1540*0Sstevel@tonic-gate int64_t msg[MSG_SIZE]; 1541*0Sstevel@tonic-gate struct rt_msghdr *rtm; 1542*0Sstevel@tonic-gate struct if_msghdr *ifm; 1543*0Sstevel@tonic-gate struct phyint *pi; 1544*0Sstevel@tonic-gate struct prefix *pr; 1545*0Sstevel@tonic-gate boolean_t need_initifs = _B_FALSE; 1546*0Sstevel@tonic-gate boolean_t need_ifscan = _B_FALSE; 1547*0Sstevel@tonic-gate int64_t ifscan_msg[10][MSG_SIZE]; 1548*0Sstevel@tonic-gate int ifscan_index = 0; 1549*0Sstevel@tonic-gate int i; 1550*0Sstevel@tonic-gate 1551*0Sstevel@tonic-gate /* Empty the rtsock and coealesce all the work that we have */ 1552*0Sstevel@tonic-gate while (ifscan_index < 10) { 1553*0Sstevel@tonic-gate n = read(rtsock, msg, sizeof (msg)); 1554*0Sstevel@tonic-gate if (n <= 0) { 1555*0Sstevel@tonic-gate /* No more messages */ 1556*0Sstevel@tonic-gate break; 1557*0Sstevel@tonic-gate } 1558*0Sstevel@tonic-gate rtm = (struct rt_msghdr *)msg; 1559*0Sstevel@tonic-gate if (rtm->rtm_version != RTM_VERSION) { 1560*0Sstevel@tonic-gate logmsg(LOG_ERR, 1561*0Sstevel@tonic-gate "process_rtsock: version %d not understood\n", 1562*0Sstevel@tonic-gate rtm->rtm_version); 1563*0Sstevel@tonic-gate return; 1564*0Sstevel@tonic-gate } 1565*0Sstevel@tonic-gate switch (rtm->rtm_type) { 1566*0Sstevel@tonic-gate case RTM_NEWADDR: 1567*0Sstevel@tonic-gate case RTM_DELADDR: 1568*0Sstevel@tonic-gate /* 1569*0Sstevel@tonic-gate * Some logical interface has changed - have to scan 1570*0Sstevel@tonic-gate * everything to determine what actually changed. 1571*0Sstevel@tonic-gate */ 1572*0Sstevel@tonic-gate if (debug & D_IFSCAN) { 1573*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "process_rtsock: " 1574*0Sstevel@tonic-gate "message %d\n", rtm->rtm_type); 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate need_initifs = _B_TRUE; 1577*0Sstevel@tonic-gate break; 1578*0Sstevel@tonic-gate case RTM_IFINFO: 1579*0Sstevel@tonic-gate need_ifscan = _B_TRUE; 1580*0Sstevel@tonic-gate (void) memcpy(ifscan_msg[ifscan_index], rtm, 1581*0Sstevel@tonic-gate sizeof (msg)); 1582*0Sstevel@tonic-gate ifscan_index++; 1583*0Sstevel@tonic-gate /* Handled below */ 1584*0Sstevel@tonic-gate break; 1585*0Sstevel@tonic-gate default: 1586*0Sstevel@tonic-gate /* Not interesting */ 1587*0Sstevel@tonic-gate break; 1588*0Sstevel@tonic-gate } 1589*0Sstevel@tonic-gate } 1590*0Sstevel@tonic-gate /* 1591*0Sstevel@tonic-gate * If we do full scan i.e initifs, we don't need to 1592*0Sstevel@tonic-gate * scan a particular interface as we should have 1593*0Sstevel@tonic-gate * done that as part of initifs. 1594*0Sstevel@tonic-gate */ 1595*0Sstevel@tonic-gate if (need_initifs) { 1596*0Sstevel@tonic-gate initifs(_B_FALSE); 1597*0Sstevel@tonic-gate return; 1598*0Sstevel@tonic-gate } 1599*0Sstevel@tonic-gate 1600*0Sstevel@tonic-gate if (!need_ifscan) 1601*0Sstevel@tonic-gate return; 1602*0Sstevel@tonic-gate 1603*0Sstevel@tonic-gate for (i = 0; i < ifscan_index; i++) { 1604*0Sstevel@tonic-gate ifm = (struct if_msghdr *)ifscan_msg[i]; 1605*0Sstevel@tonic-gate if (debug & D_IFSCAN) 1606*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "process_rtsock: index %d\n", 1607*0Sstevel@tonic-gate ifm->ifm_index); 1608*0Sstevel@tonic-gate 1609*0Sstevel@tonic-gate pi = phyint_lookup_on_index(ifm->ifm_index); 1610*0Sstevel@tonic-gate if (pi == NULL) { 1611*0Sstevel@tonic-gate /* 1612*0Sstevel@tonic-gate * A new physical interface. Do a full scan of the 1613*0Sstevel@tonic-gate * to catch any new logical interfaces. 1614*0Sstevel@tonic-gate */ 1615*0Sstevel@tonic-gate initifs(_B_FALSE); 1616*0Sstevel@tonic-gate return; 1617*0Sstevel@tonic-gate } 1618*0Sstevel@tonic-gate 1619*0Sstevel@tonic-gate if (ifm->ifm_flags != pi->pi_flags) { 1620*0Sstevel@tonic-gate if (debug & D_IFSCAN) { 1621*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "process_rtsock: clr for " 1622*0Sstevel@tonic-gate "%s old flags 0x%x new flags 0x%x\n", 1623*0Sstevel@tonic-gate pi->pi_name, pi->pi_flags, ifm->ifm_flags); 1624*0Sstevel@tonic-gate } 1625*0Sstevel@tonic-gate } 1626*0Sstevel@tonic-gate 1627*0Sstevel@tonic-gate 1628*0Sstevel@tonic-gate /* 1629*0Sstevel@tonic-gate * Mark the interfaces so that we can find phyints and prefixes 1630*0Sstevel@tonic-gate * which have disappeared from the kernel. 1631*0Sstevel@tonic-gate * if_process will set pr_in_use when it finds the 1632*0Sstevel@tonic-gate * interface in the kernel. 1633*0Sstevel@tonic-gate * Before re-examining the state of the interfaces, 1634*0Sstevel@tonic-gate * PI_PRESENT should be cleared from pi_kernel_state. 1635*0Sstevel@tonic-gate */ 1636*0Sstevel@tonic-gate pi->pi_kernel_state &= ~PI_PRESENT; 1637*0Sstevel@tonic-gate for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 1638*0Sstevel@tonic-gate pr->pr_in_use = _B_FALSE; 1639*0Sstevel@tonic-gate } 1640*0Sstevel@tonic-gate 1641*0Sstevel@tonic-gate if (ifsock < 0) { 1642*0Sstevel@tonic-gate ifsock = socket(AF_INET6, SOCK_DGRAM, 0); 1643*0Sstevel@tonic-gate if (ifsock < 0) { 1644*0Sstevel@tonic-gate logperror("process_rtsock: socket"); 1645*0Sstevel@tonic-gate return; 1646*0Sstevel@tonic-gate } 1647*0Sstevel@tonic-gate } 1648*0Sstevel@tonic-gate if_process(ifsock, pi->pi_name, _B_FALSE); 1649*0Sstevel@tonic-gate for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) { 1650*0Sstevel@tonic-gate if_process(ifsock, pr->pr_name, _B_FALSE); 1651*0Sstevel@tonic-gate } 1652*0Sstevel@tonic-gate /* 1653*0Sstevel@tonic-gate * If interface (still) exists in kernel, set 1654*0Sstevel@tonic-gate * pi_state to indicate that. 1655*0Sstevel@tonic-gate */ 1656*0Sstevel@tonic-gate if (pi->pi_kernel_state & PI_PRESENT) { 1657*0Sstevel@tonic-gate pi->pi_state |= PI_PRESENT; 1658*0Sstevel@tonic-gate } 1659*0Sstevel@tonic-gate check_if_removed(pi); 1660*0Sstevel@tonic-gate if (show_ifs) 1661*0Sstevel@tonic-gate phyint_print_all(); 1662*0Sstevel@tonic-gate } 1663*0Sstevel@tonic-gate } 1664*0Sstevel@tonic-gate 1665*0Sstevel@tonic-gate /* 1666*0Sstevel@tonic-gate * Check whether the address formed by pr->pr_prefix and pi_token 1667*0Sstevel@tonic-gate * exists in the kernel. Cannot call SIOCTMYADDR/ONLINK as it 1668*0Sstevel@tonic-gate * does not check for down addresses. This function should not 1669*0Sstevel@tonic-gate * be called for onlink prefixes. 1670*0Sstevel@tonic-gate */ 1671*0Sstevel@tonic-gate static boolean_t 1672*0Sstevel@tonic-gate is_address_present(struct phyint *pi, struct prefix *pr, uint64_t flags) 1673*0Sstevel@tonic-gate { 1674*0Sstevel@tonic-gate int s; 1675*0Sstevel@tonic-gate in6_addr_t addr, *token; 1676*0Sstevel@tonic-gate int i; 1677*0Sstevel@tonic-gate int ret; 1678*0Sstevel@tonic-gate struct sockaddr_in6 sin6; 1679*0Sstevel@tonic-gate 1680*0Sstevel@tonic-gate s = socket(AF_INET6, SOCK_DGRAM, 0); 1681*0Sstevel@tonic-gate if (s < 0) { 1682*0Sstevel@tonic-gate logperror("is_address_present: socket"); 1683*0Sstevel@tonic-gate /* 1684*0Sstevel@tonic-gate * By returning B_TRUE, we make the caller delete 1685*0Sstevel@tonic-gate * the prefix from the internal table. In the worst 1686*0Sstevel@tonic-gate * case the next RA will create the prefix. 1687*0Sstevel@tonic-gate */ 1688*0Sstevel@tonic-gate return (_B_TRUE); 1689*0Sstevel@tonic-gate } 1690*0Sstevel@tonic-gate if (flags & IFF_TEMPORARY) 1691*0Sstevel@tonic-gate token = &pi->pi_tmp_token; 1692*0Sstevel@tonic-gate else 1693*0Sstevel@tonic-gate token = &pi->pi_token; 1694*0Sstevel@tonic-gate for (i = 0; i < 16; i++) { 1695*0Sstevel@tonic-gate /* 1696*0Sstevel@tonic-gate * prefix_create ensures that pr_prefix has all-zero 1697*0Sstevel@tonic-gate * bits after prefixlen. 1698*0Sstevel@tonic-gate */ 1699*0Sstevel@tonic-gate addr.s6_addr[i] = pr->pr_prefix.s6_addr[i] | token->s6_addr[i]; 1700*0Sstevel@tonic-gate } 1701*0Sstevel@tonic-gate (void) memset(&sin6, 0, sizeof (struct sockaddr_in6)); 1702*0Sstevel@tonic-gate sin6.sin6_family = AF_INET6; 1703*0Sstevel@tonic-gate sin6.sin6_addr = addr; 1704*0Sstevel@tonic-gate ret = bind(s, (struct sockaddr *)&sin6, sizeof (struct sockaddr_in6)); 1705*0Sstevel@tonic-gate (void) close(s); 1706*0Sstevel@tonic-gate if (ret < 0 && errno == EADDRNOTAVAIL) 1707*0Sstevel@tonic-gate return (_B_FALSE); 1708*0Sstevel@tonic-gate else 1709*0Sstevel@tonic-gate return (_B_TRUE); 1710*0Sstevel@tonic-gate } 1711*0Sstevel@tonic-gate 1712*0Sstevel@tonic-gate /* 1713*0Sstevel@tonic-gate * Look if the phyint or one of its prefixes have been removed from 1714*0Sstevel@tonic-gate * the kernel and take appropriate action. 1715*0Sstevel@tonic-gate * Uses {pi,pr}_in_use. 1716*0Sstevel@tonic-gate */ 1717*0Sstevel@tonic-gate static void 1718*0Sstevel@tonic-gate check_if_removed(struct phyint *pi) 1719*0Sstevel@tonic-gate { 1720*0Sstevel@tonic-gate struct prefix *pr; 1721*0Sstevel@tonic-gate struct prefix *next_pr; 1722*0Sstevel@tonic-gate 1723*0Sstevel@tonic-gate /* 1724*0Sstevel@tonic-gate * Detect phyints that have been removed from the kernel. 1725*0Sstevel@tonic-gate * Since we can't recreate it here (would require ifconfig plumb 1726*0Sstevel@tonic-gate * logic) we just terminate use of that phyint. 1727*0Sstevel@tonic-gate */ 1728*0Sstevel@tonic-gate if (!(pi->pi_kernel_state & PI_PRESENT) && 1729*0Sstevel@tonic-gate (pi->pi_state & PI_PRESENT)) { 1730*0Sstevel@tonic-gate logmsg(LOG_ERR, "Interface %s has been removed from kernel. " 1731*0Sstevel@tonic-gate "in.ndpd will no longer use it\n", pi->pi_name); 1732*0Sstevel@tonic-gate /* 1733*0Sstevel@tonic-gate * Clear state so that should the phyint reappear 1734*0Sstevel@tonic-gate * we will start with initial advertisements or 1735*0Sstevel@tonic-gate * solicitations. 1736*0Sstevel@tonic-gate */ 1737*0Sstevel@tonic-gate phyint_cleanup(pi); 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate /* 1740*0Sstevel@tonic-gate * Detect prefixes which are removed. 1741*0Sstevel@tonic-gate * 1742*0Sstevel@tonic-gate * We remove the prefix in all of the following cases : 1743*0Sstevel@tonic-gate * 1744*0Sstevel@tonic-gate * 1) Static prefixes are not the ones we create. So, 1745*0Sstevel@tonic-gate * just remove it from our tables. 1746*0Sstevel@tonic-gate * 1747*0Sstevel@tonic-gate * 2) On-link prefixes potentially move to a different 1748*0Sstevel@tonic-gate * phyint during failover. As it does not have 1749*0Sstevel@tonic-gate * an address, we can't use the logic in is_address_present 1750*0Sstevel@tonic-gate * to detect whether it is present in the kernel or not. 1751*0Sstevel@tonic-gate * Thus when it is manually removed we don't recreate it. 1752*0Sstevel@tonic-gate * 1753*0Sstevel@tonic-gate * 3) If there is a token mis-match and this prefix is not 1754*0Sstevel@tonic-gate * in the kernel, it means we don't need this prefix on 1755*0Sstevel@tonic-gate * this interface anymore. It must have been moved to a 1756*0Sstevel@tonic-gate * different interface by in.mpathd. This normally 1757*0Sstevel@tonic-gate * happens after a failover followed by a failback (or 1758*0Sstevel@tonic-gate * another failover) and we re-read the network 1759*0Sstevel@tonic-gate * configuration. For the failover from A to B, we would 1760*0Sstevel@tonic-gate * have created state on B about A's address, which will 1761*0Sstevel@tonic-gate * not be in use after the subsequent failback. So, we 1762*0Sstevel@tonic-gate * remove that prefix here. 1763*0Sstevel@tonic-gate * 1764*0Sstevel@tonic-gate * 4) If the physical interface is not present, then remove 1765*0Sstevel@tonic-gate * the prefix. In the cases where we are advertising 1766*0Sstevel@tonic-gate * prefixes, the state is kept in advertisement prefix and 1767*0Sstevel@tonic-gate * hence we can delete the prefix. 1768*0Sstevel@tonic-gate * 1769*0Sstevel@tonic-gate * 5) Similar to case (3), when we failover from A to B, the 1770*0Sstevel@tonic-gate * prefix in A will not be in use as it has been moved to B. 1771*0Sstevel@tonic-gate * We will delete it from our tables and recreate it when 1772*0Sstevel@tonic-gate * it fails back. is_address_present makes sure that the 1773*0Sstevel@tonic-gate * address is still valid in kernel. 1774*0Sstevel@tonic-gate * 1775*0Sstevel@tonic-gate * If none of the above is true, we recreate the prefix as it 1776*0Sstevel@tonic-gate * has been manually removed. We do it only when the interface 1777*0Sstevel@tonic-gate * is not FAILED or INACTIVE or OFFLINE. 1778*0Sstevel@tonic-gate */ 1779*0Sstevel@tonic-gate for (pr = pi->pi_prefix_list; pr != NULL; pr = next_pr) { 1780*0Sstevel@tonic-gate next_pr = pr->pr_next; 1781*0Sstevel@tonic-gate if (!pr->pr_in_use) { 1782*0Sstevel@tonic-gate /* Clear PR_AUTO and PR_ONLINK */ 1783*0Sstevel@tonic-gate pr->pr_kernel_state &= PR_STATIC; 1784*0Sstevel@tonic-gate if ((pr->pr_state & PR_STATIC) || 1785*0Sstevel@tonic-gate !(pr->pr_state & PR_AUTO) || 1786*0Sstevel@tonic-gate !(prefix_token_match(pi, pr, pr->pr_flags)) || 1787*0Sstevel@tonic-gate (!(pi->pi_kernel_state & PI_PRESENT)) || 1788*0Sstevel@tonic-gate (is_address_present(pi, pr, pr->pr_flags))) { 1789*0Sstevel@tonic-gate prefix_delete(pr); 1790*0Sstevel@tonic-gate } else if (!(pi->pi_flags & 1791*0Sstevel@tonic-gate (IFF_FAILED|IFF_INACTIVE|IFF_OFFLINE)) && 1792*0Sstevel@tonic-gate pr->pr_state != pr->pr_kernel_state) { 1793*0Sstevel@tonic-gate pr->pr_name[0] = '\0'; 1794*0Sstevel@tonic-gate logmsg(LOG_INFO, "Prefix manually removed " 1795*0Sstevel@tonic-gate "on %s - recreating it!\n", 1796*0Sstevel@tonic-gate pi->pi_name); 1797*0Sstevel@tonic-gate prefix_update_k(pr); 1798*0Sstevel@tonic-gate } 1799*0Sstevel@tonic-gate } 1800*0Sstevel@tonic-gate } 1801*0Sstevel@tonic-gate } 1802*0Sstevel@tonic-gate 1803*0Sstevel@tonic-gate 1804*0Sstevel@tonic-gate /* 1805*0Sstevel@tonic-gate * Queuing mechanism for router advertisements that are sent by in.ndpd 1806*0Sstevel@tonic-gate * and that also need to be processed by in.ndpd. 1807*0Sstevel@tonic-gate * Uses "signal number" 255 to indicate to the main poll loop 1808*0Sstevel@tonic-gate * that there is something to dequeue and send to incomining_ra(). 1809*0Sstevel@tonic-gate */ 1810*0Sstevel@tonic-gate struct raq { 1811*0Sstevel@tonic-gate struct raq *raq_next; 1812*0Sstevel@tonic-gate struct phyint *raq_pi; 1813*0Sstevel@tonic-gate int raq_packetlen; 1814*0Sstevel@tonic-gate uchar_t *raq_packet; 1815*0Sstevel@tonic-gate }; 1816*0Sstevel@tonic-gate static struct raq *raq_head = NULL; 1817*0Sstevel@tonic-gate 1818*0Sstevel@tonic-gate /* 1819*0Sstevel@tonic-gate * Allocate a struct raq and memory for the packet. 1820*0Sstevel@tonic-gate * Send signal 255 to have poll dequeue. 1821*0Sstevel@tonic-gate */ 1822*0Sstevel@tonic-gate static void 1823*0Sstevel@tonic-gate loopback_ra_enqueue(struct phyint *pi, struct nd_router_advert *ra, int len) 1824*0Sstevel@tonic-gate { 1825*0Sstevel@tonic-gate struct raq *raq; 1826*0Sstevel@tonic-gate struct raq **raqp; 1827*0Sstevel@tonic-gate 1828*0Sstevel@tonic-gate if (no_loopback) 1829*0Sstevel@tonic-gate return; 1830*0Sstevel@tonic-gate 1831*0Sstevel@tonic-gate if (debug & D_PKTOUT) 1832*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "loopback_ra_enqueue for %s\n", pi->pi_name); 1833*0Sstevel@tonic-gate 1834*0Sstevel@tonic-gate raq = calloc(sizeof (struct raq), 1); 1835*0Sstevel@tonic-gate if (raq == NULL) { 1836*0Sstevel@tonic-gate logmsg(LOG_ERR, "loopback_ra_enqueue: out of memory\n"); 1837*0Sstevel@tonic-gate return; 1838*0Sstevel@tonic-gate } 1839*0Sstevel@tonic-gate raq->raq_packet = malloc(len); 1840*0Sstevel@tonic-gate if (raq->raq_packet == NULL) { 1841*0Sstevel@tonic-gate free(raq); 1842*0Sstevel@tonic-gate logmsg(LOG_ERR, "loopback_ra_enqueue: out of memory\n"); 1843*0Sstevel@tonic-gate return; 1844*0Sstevel@tonic-gate } 1845*0Sstevel@tonic-gate bcopy(ra, raq->raq_packet, len); 1846*0Sstevel@tonic-gate raq->raq_packetlen = len; 1847*0Sstevel@tonic-gate raq->raq_pi = pi; 1848*0Sstevel@tonic-gate 1849*0Sstevel@tonic-gate /* Tail insert */ 1850*0Sstevel@tonic-gate raqp = &raq_head; 1851*0Sstevel@tonic-gate while (*raqp != NULL) 1852*0Sstevel@tonic-gate raqp = &((*raqp)->raq_next); 1853*0Sstevel@tonic-gate *raqp = raq; 1854*0Sstevel@tonic-gate 1855*0Sstevel@tonic-gate /* Signal for poll loop */ 1856*0Sstevel@tonic-gate sig_handler(255); 1857*0Sstevel@tonic-gate } 1858*0Sstevel@tonic-gate 1859*0Sstevel@tonic-gate /* 1860*0Sstevel@tonic-gate * Dequeue and process all queued advertisements. 1861*0Sstevel@tonic-gate */ 1862*0Sstevel@tonic-gate static void 1863*0Sstevel@tonic-gate loopback_ra_dequeue(void) 1864*0Sstevel@tonic-gate { 1865*0Sstevel@tonic-gate struct sockaddr_in6 from = IN6ADDR_LOOPBACK_INIT; 1866*0Sstevel@tonic-gate struct raq *raq; 1867*0Sstevel@tonic-gate 1868*0Sstevel@tonic-gate if (debug & D_PKTIN) 1869*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "loopback_ra_dequeue()\n"); 1870*0Sstevel@tonic-gate 1871*0Sstevel@tonic-gate while ((raq = raq_head) != NULL) { 1872*0Sstevel@tonic-gate raq_head = raq->raq_next; 1873*0Sstevel@tonic-gate raq->raq_next = NULL; 1874*0Sstevel@tonic-gate 1875*0Sstevel@tonic-gate if (debug & D_PKTIN) { 1876*0Sstevel@tonic-gate logmsg(LOG_DEBUG, "loopback_ra_dequeue for %s\n", 1877*0Sstevel@tonic-gate raq->raq_pi->pi_name); 1878*0Sstevel@tonic-gate } 1879*0Sstevel@tonic-gate 1880*0Sstevel@tonic-gate incoming_ra(raq->raq_pi, 1881*0Sstevel@tonic-gate (struct nd_router_advert *)raq->raq_packet, 1882*0Sstevel@tonic-gate raq->raq_packetlen, &from, _B_TRUE); 1883*0Sstevel@tonic-gate free(raq->raq_packet); 1884*0Sstevel@tonic-gate free(raq); 1885*0Sstevel@tonic-gate } 1886*0Sstevel@tonic-gate } 1887*0Sstevel@tonic-gate 1888*0Sstevel@tonic-gate 1889*0Sstevel@tonic-gate static void 1890*0Sstevel@tonic-gate usage(char *cmd) 1891*0Sstevel@tonic-gate { 1892*0Sstevel@tonic-gate (void) fprintf(stderr, 1893*0Sstevel@tonic-gate "usage: %s [ -adt ] [-f <config file>]\n", cmd); 1894*0Sstevel@tonic-gate } 1895*0Sstevel@tonic-gate 1896*0Sstevel@tonic-gate int 1897*0Sstevel@tonic-gate main(int argc, char *argv[]) 1898*0Sstevel@tonic-gate { 1899*0Sstevel@tonic-gate int i; 1900*0Sstevel@tonic-gate struct phyint *pi; 1901*0Sstevel@tonic-gate int c; 1902*0Sstevel@tonic-gate char *config_file = PATH_NDPD_CONF; 1903*0Sstevel@tonic-gate boolean_t file_required = _B_FALSE; 1904*0Sstevel@tonic-gate 1905*0Sstevel@tonic-gate argv0 = argv; 1906*0Sstevel@tonic-gate srandom(gethostid()); 1907*0Sstevel@tonic-gate (void) umask(0022); 1908*0Sstevel@tonic-gate 1909*0Sstevel@tonic-gate while ((c = getopt(argc, argv, "adD:ntIf:")) != EOF) { 1910*0Sstevel@tonic-gate switch (c) { 1911*0Sstevel@tonic-gate case 'a': 1912*0Sstevel@tonic-gate /* 1913*0Sstevel@tonic-gate * The StatelessAddrConf variable in ndpd.conf, if 1914*0Sstevel@tonic-gate * present, will override this setting. 1915*0Sstevel@tonic-gate */ 1916*0Sstevel@tonic-gate ifdefaults[I_StatelessAddrConf].cf_value = 0; 1917*0Sstevel@tonic-gate break; 1918*0Sstevel@tonic-gate case 'd': 1919*0Sstevel@tonic-gate debug = D_ALL; 1920*0Sstevel@tonic-gate break; 1921*0Sstevel@tonic-gate case 'D': 1922*0Sstevel@tonic-gate i = strtol((char *)optarg, NULL, 0); 1923*0Sstevel@tonic-gate if (i == 0) { 1924*0Sstevel@tonic-gate (void) fprintf(stderr, "Bad debug flags: %s\n", 1925*0Sstevel@tonic-gate (char *)optarg); 1926*0Sstevel@tonic-gate exit(1); 1927*0Sstevel@tonic-gate } 1928*0Sstevel@tonic-gate debug |= i; 1929*0Sstevel@tonic-gate break; 1930*0Sstevel@tonic-gate case 'n': 1931*0Sstevel@tonic-gate no_loopback = 1; 1932*0Sstevel@tonic-gate break; 1933*0Sstevel@tonic-gate case 'I': 1934*0Sstevel@tonic-gate show_ifs = 1; 1935*0Sstevel@tonic-gate break; 1936*0Sstevel@tonic-gate case 't': 1937*0Sstevel@tonic-gate debug |= D_PKTIN | D_PKTOUT | D_PKTBAD; 1938*0Sstevel@tonic-gate break; 1939*0Sstevel@tonic-gate case 'f': 1940*0Sstevel@tonic-gate config_file = (char *)optarg; 1941*0Sstevel@tonic-gate file_required = _B_TRUE; 1942*0Sstevel@tonic-gate break; 1943*0Sstevel@tonic-gate case '?': 1944*0Sstevel@tonic-gate usage(argv[0]); 1945*0Sstevel@tonic-gate exit(1); 1946*0Sstevel@tonic-gate } 1947*0Sstevel@tonic-gate } 1948*0Sstevel@tonic-gate 1949*0Sstevel@tonic-gate if (parse_config(config_file, file_required) == -1) 1950*0Sstevel@tonic-gate exit(2); 1951*0Sstevel@tonic-gate 1952*0Sstevel@tonic-gate if (show_ifs) 1953*0Sstevel@tonic-gate phyint_print_all(); 1954*0Sstevel@tonic-gate 1955*0Sstevel@tonic-gate if (debug == 0) { 1956*0Sstevel@tonic-gate initlog(); 1957*0Sstevel@tonic-gate } 1958*0Sstevel@tonic-gate 1959*0Sstevel@tonic-gate setup_eventpipe(); 1960*0Sstevel@tonic-gate rtsock = setup_rtsock(); 1961*0Sstevel@tonic-gate timer_init(); 1962*0Sstevel@tonic-gate initifs(_B_TRUE); 1963*0Sstevel@tonic-gate 1964*0Sstevel@tonic-gate check_daemonize(); 1965*0Sstevel@tonic-gate 1966*0Sstevel@tonic-gate for (;;) { 1967*0Sstevel@tonic-gate if (poll(pollfds, pollfd_num, -1) < 0) { 1968*0Sstevel@tonic-gate if (errno == EINTR) 1969*0Sstevel@tonic-gate continue; 1970*0Sstevel@tonic-gate logperror("main: poll"); 1971*0Sstevel@tonic-gate exit(1); 1972*0Sstevel@tonic-gate } 1973*0Sstevel@tonic-gate for (i = 0; i < pollfd_num; i++) { 1974*0Sstevel@tonic-gate if (!(pollfds[i].revents & POLLIN)) 1975*0Sstevel@tonic-gate continue; 1976*0Sstevel@tonic-gate if (pollfds[i].fd == eventpipe_read) { 1977*0Sstevel@tonic-gate in_signal(eventpipe_read); 1978*0Sstevel@tonic-gate break; 1979*0Sstevel@tonic-gate } 1980*0Sstevel@tonic-gate if (pollfds[i].fd == rtsock) { 1981*0Sstevel@tonic-gate process_rtsock(rtsock); 1982*0Sstevel@tonic-gate break; 1983*0Sstevel@tonic-gate } 1984*0Sstevel@tonic-gate /* 1985*0Sstevel@tonic-gate * Run timer routine to advance clock if more than 1986*0Sstevel@tonic-gate * half a second since the clock was advanced. 1987*0Sstevel@tonic-gate * This limits CPU usage under severe packet 1988*0Sstevel@tonic-gate * arrival rates but it creates a slight inaccuracy 1989*0Sstevel@tonic-gate * in the timer mechanism. 1990*0Sstevel@tonic-gate */ 1991*0Sstevel@tonic-gate conditional_run_timeouts(500U); 1992*0Sstevel@tonic-gate for (pi = phyints; pi != NULL; pi = pi->pi_next) { 1993*0Sstevel@tonic-gate if (pollfds[i].fd == pi->pi_sock) { 1994*0Sstevel@tonic-gate in_data(pi); 1995*0Sstevel@tonic-gate break; 1996*0Sstevel@tonic-gate } 1997*0Sstevel@tonic-gate } 1998*0Sstevel@tonic-gate } 1999*0Sstevel@tonic-gate } 2000*0Sstevel@tonic-gate /* NOTREACHED */ 2001*0Sstevel@tonic-gate return (0); 2002*0Sstevel@tonic-gate } 2003*0Sstevel@tonic-gate 2004*0Sstevel@tonic-gate /* 2005*0Sstevel@tonic-gate * LOGGER 2006*0Sstevel@tonic-gate */ 2007*0Sstevel@tonic-gate 2008*0Sstevel@tonic-gate static boolean_t logging = _B_FALSE; 2009*0Sstevel@tonic-gate 2010*0Sstevel@tonic-gate static void 2011*0Sstevel@tonic-gate initlog(void) 2012*0Sstevel@tonic-gate { 2013*0Sstevel@tonic-gate logging = _B_TRUE; 2014*0Sstevel@tonic-gate openlog("in.ndpd", LOG_PID | LOG_CONS, LOG_DAEMON); 2015*0Sstevel@tonic-gate } 2016*0Sstevel@tonic-gate 2017*0Sstevel@tonic-gate /* Print the date/time without a trailing carridge return */ 2018*0Sstevel@tonic-gate static void 2019*0Sstevel@tonic-gate fprintdate(FILE *file) 2020*0Sstevel@tonic-gate { 2021*0Sstevel@tonic-gate char buf[BUFSIZ]; 2022*0Sstevel@tonic-gate struct tm tms; 2023*0Sstevel@tonic-gate time_t now; 2024*0Sstevel@tonic-gate 2025*0Sstevel@tonic-gate now = time(NULL); 2026*0Sstevel@tonic-gate (void) localtime_r(&now, &tms); 2027*0Sstevel@tonic-gate (void) strftime(buf, sizeof (buf), "%h %d %X", &tms); 2028*0Sstevel@tonic-gate (void) fprintf(file, "%s ", buf); 2029*0Sstevel@tonic-gate } 2030*0Sstevel@tonic-gate 2031*0Sstevel@tonic-gate /* PRINTFLIKE1 */ 2032*0Sstevel@tonic-gate void 2033*0Sstevel@tonic-gate logmsg(int level, char *fmt, ...) 2034*0Sstevel@tonic-gate { 2035*0Sstevel@tonic-gate va_list ap; 2036*0Sstevel@tonic-gate va_start(ap, fmt); 2037*0Sstevel@tonic-gate 2038*0Sstevel@tonic-gate if (logging) { 2039*0Sstevel@tonic-gate vsyslog(level, fmt, ap); 2040*0Sstevel@tonic-gate } else { 2041*0Sstevel@tonic-gate fprintdate(stderr); 2042*0Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap); 2043*0Sstevel@tonic-gate } 2044*0Sstevel@tonic-gate va_end(ap); 2045*0Sstevel@tonic-gate } 2046*0Sstevel@tonic-gate 2047*0Sstevel@tonic-gate void 2048*0Sstevel@tonic-gate logperror(char *str) 2049*0Sstevel@tonic-gate { 2050*0Sstevel@tonic-gate if (logging) { 2051*0Sstevel@tonic-gate syslog(LOG_ERR, "%s: %m\n", str); 2052*0Sstevel@tonic-gate } else { 2053*0Sstevel@tonic-gate fprintdate(stderr); 2054*0Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", str, strerror(errno)); 2055*0Sstevel@tonic-gate } 2056*0Sstevel@tonic-gate } 2057*0Sstevel@tonic-gate 2058*0Sstevel@tonic-gate void 2059*0Sstevel@tonic-gate logperror_pi(struct phyint *pi, char *str) 2060*0Sstevel@tonic-gate { 2061*0Sstevel@tonic-gate if (logging) { 2062*0Sstevel@tonic-gate syslog(LOG_ERR, "%s (interface %s): %m\n", 2063*0Sstevel@tonic-gate str, pi->pi_name); 2064*0Sstevel@tonic-gate } else { 2065*0Sstevel@tonic-gate fprintdate(stderr); 2066*0Sstevel@tonic-gate (void) fprintf(stderr, "%s (interface %s): %s\n", 2067*0Sstevel@tonic-gate str, pi->pi_name, strerror(errno)); 2068*0Sstevel@tonic-gate } 2069*0Sstevel@tonic-gate } 2070*0Sstevel@tonic-gate 2071*0Sstevel@tonic-gate void 2072*0Sstevel@tonic-gate logperror_pr(struct prefix *pr, char *str) 2073*0Sstevel@tonic-gate { 2074*0Sstevel@tonic-gate if (logging) { 2075*0Sstevel@tonic-gate syslog(LOG_ERR, "%s (prefix %s if %s): %m\n", 2076*0Sstevel@tonic-gate str, pr->pr_name, pr->pr_physical->pi_name); 2077*0Sstevel@tonic-gate } else { 2078*0Sstevel@tonic-gate fprintdate(stderr); 2079*0Sstevel@tonic-gate (void) fprintf(stderr, "%s (prefix %s if %s): %s\n", 2080*0Sstevel@tonic-gate str, pr->pr_name, pr->pr_physical->pi_name, 2081*0Sstevel@tonic-gate strerror(errno)); 2082*0Sstevel@tonic-gate } 2083*0Sstevel@tonic-gate } 2084