1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2024 Oxide Computer Company
26 */
27
28 #include "defs.h"
29 #include "tables.h"
30
31 #include <time.h>
32 #include <assert.h>
33
34 struct phyint *phyints = NULL;
35 int num_of_phyints = 0;
36
37 static void phyint_print(struct phyint *pi);
38 static void phyint_insert(struct phyint *pi);
39
40 static boolean_t tmptoken_isvalid(struct in6_addr *token);
41
42 static void prefix_print(struct prefix *pr);
43 static void prefix_insert(struct phyint *pi, struct prefix *pr);
44 static char *prefix_print_state(int state, char *buf, int buflen);
45 static void prefix_set(struct in6_addr *prefix, struct in6_addr addr,
46 int bits);
47
48 static void adv_prefix_print(struct adv_prefix *adv_pr);
49 static void adv_prefix_insert(struct phyint *pi, struct adv_prefix *adv_pr);
50 static void adv_prefix_delete(struct adv_prefix *adv_pr);
51
52 static void router_print(struct router *dr);
53 static void router_insert(struct phyint *pi, struct router *dr);
54 static void router_delete(struct router *dr);
55 static void router_add_k(struct router *dr);
56 static void router_delete_k(struct router *dr);
57
58 static int rtmseq; /* rtm_seq sequence number */
59
60 /* 1 week in ms */
61 #define NDP_PREFIX_DEFAULT_LIFETIME (7*24*60*60*1000)
62 struct phyint *
phyint_lookup(char * name)63 phyint_lookup(char *name)
64 {
65 struct phyint *pi;
66
67 if (debug & D_PHYINT)
68 logmsg(LOG_DEBUG, "phyint_lookup(%s)\n", name);
69
70 for (pi = phyints; pi != NULL; pi = pi->pi_next) {
71 if (strcmp(pi->pi_name, name) == 0)
72 break;
73 }
74 return (pi);
75 }
76
77 struct phyint *
phyint_lookup_on_index(uint_t ifindex)78 phyint_lookup_on_index(uint_t ifindex)
79 {
80 struct phyint *pi;
81
82 if (debug & D_PHYINT)
83 logmsg(LOG_DEBUG, "phyint_lookup_on_index(%d)\n", ifindex);
84
85 for (pi = phyints; pi != NULL; pi = pi->pi_next) {
86 if (pi->pi_index == ifindex)
87 break;
88 }
89 return (pi);
90 }
91
92 struct phyint *
phyint_create(char * name)93 phyint_create(char *name)
94 {
95 struct phyint *pi;
96 int i;
97
98 if (debug & D_PHYINT)
99 logmsg(LOG_DEBUG, "phyint_create(%s)\n", name);
100
101 pi = (struct phyint *)calloc(sizeof (struct phyint), 1);
102 if (pi == NULL) {
103 logmsg(LOG_ERR, "phyint_create: out of memory\n");
104 return (NULL);
105 }
106 (void) strncpy(pi->pi_name, name, sizeof (pi->pi_name));
107 pi->pi_name[sizeof (pi->pi_name) - 1] = '\0';
108
109 /*
110 * Copy the defaults from the defaults array.
111 * Do not copy the cf_notdefault fields since these have not
112 * been explicitly set for the phyint.
113 */
114 for (i = 0; i < I_IFSIZE; i++)
115 pi->pi_config[i].cf_value = ifdefaults[i].cf_value;
116
117 /*
118 * TmpDesyncFactor is used to desynchronize temporary token
119 * generation among systems; the actual preferred lifetime value
120 * of a temporary address will be (TmpPreferredLifetime -
121 * TmpDesyncFactor). It's a random value, with a user-configurable
122 * maximum value. The value is constant throughout the lifetime
123 * of the in.ndpd process, but can change if the daemon is restarted,
124 * per RFC3041.
125 */
126 if (pi->pi_TmpMaxDesyncFactor != 0) {
127 time_t seed = time(NULL);
128 srand((uint_t)seed);
129 pi->pi_TmpDesyncFactor = rand() % pi->pi_TmpMaxDesyncFactor;
130 /* we actually want [1,max], not [0,(max-1)] */
131 pi->pi_TmpDesyncFactor++;
132 }
133 pi->pi_TmpRegenCountdown = TIMER_INFINITY;
134
135 pi->pi_sock = -1;
136 pi->pi_stateless = pi->pi_StatelessAddrConf;
137 pi->pi_stateful = pi->pi_StatefulAddrConf;
138 pi->pi_autoconf = _B_TRUE;
139 pi->pi_default_token = _B_TRUE;
140 if (phyint_init_from_k(pi) == -1) {
141 free(pi);
142 return (NULL);
143 }
144 phyint_insert(pi);
145 if (pi->pi_sock != -1) {
146 if (poll_add(pi->pi_sock) == -1) {
147 phyint_delete(pi);
148 return (NULL);
149 }
150 }
151 return (pi);
152 }
153
154 /* Insert in linked list */
155 static void
phyint_insert(struct phyint * pi)156 phyint_insert(struct phyint *pi)
157 {
158 /* Insert in list */
159 pi->pi_next = phyints;
160 pi->pi_prev = NULL;
161 if (phyints)
162 phyints->pi_prev = pi;
163 phyints = pi;
164 num_of_phyints++;
165 }
166
167 /*
168 * Initialize both the phyint data structure and the pi_sock for
169 * sending and receving on the interface.
170 * Extract information from the kernel (if present) and set pi_kernel_state.
171 */
172 int
phyint_init_from_k(struct phyint * pi)173 phyint_init_from_k(struct phyint *pi)
174 {
175 struct ipv6_mreq v6mcastr;
176 struct lifreq lifr;
177 int fd;
178 int save_errno;
179 boolean_t newsock;
180 uint_t ttl;
181 struct sockaddr_in6 *sin6;
182
183 if (debug & D_PHYINT)
184 logmsg(LOG_DEBUG, "phyint_init_from_k(%s)\n", pi->pi_name);
185
186 start_over:
187
188 if (pi->pi_sock < 0) {
189 pi->pi_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
190 if (pi->pi_sock < 0) {
191 logperror_pi(pi, "phyint_init_from_k: socket");
192 return (-1);
193 }
194 newsock = _B_TRUE;
195 } else {
196 newsock = _B_FALSE;
197 }
198 fd = pi->pi_sock;
199
200 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name));
201 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
202 if (ioctl(fd, SIOCGLIFINDEX, (char *)&lifr) < 0) {
203 if (errno == ENXIO) {
204 if (newsock) {
205 (void) close(pi->pi_sock);
206 pi->pi_sock = -1;
207 }
208 if (debug & D_PHYINT) {
209 logmsg(LOG_DEBUG, "phyint_init_from_k(%s): "
210 "not exist\n", pi->pi_name);
211 }
212 return (0);
213 }
214 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFINDEX");
215 goto error;
216 }
217
218 if (!newsock && (pi->pi_index != lifr.lifr_index)) {
219 /*
220 * Interface has been re-plumbed, lets open a new socket.
221 * This situation can occur if plumb/unplumb are happening
222 * quite frequently.
223 */
224
225 phyint_cleanup(pi);
226 goto start_over;
227 }
228
229 pi->pi_index = lifr.lifr_index;
230
231 if (ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
232 logperror_pi(pi, "phyint_init_from_k: ioctl (get flags)");
233 goto error;
234 }
235 pi->pi_flags = lifr.lifr_flags;
236
237 /*
238 * If the link local interface is not up yet or it's IFF_UP and the
239 * IFF_NOLOCAL flag is set, then ignore the interface.
240 */
241 if (!(pi->pi_flags & IFF_UP) || (pi->pi_flags & IFF_NOLOCAL)) {
242 if (newsock) {
243 (void) close(pi->pi_sock);
244 pi->pi_sock = -1;
245 }
246
247 if (debug & D_PHYINT) {
248 logmsg(LOG_DEBUG, "phyint_init_from_k(%s): "
249 "IFF_NOLOCAL or not IFF_UP\n", pi->pi_name);
250 }
251 return (0);
252 }
253 pi->pi_kernel_state |= PI_PRESENT;
254
255 if (ioctl(fd, SIOCGLIFMTU, (caddr_t)&lifr) < 0) {
256 logperror_pi(pi, "phyint_init_from_k: ioctl (get mtu)");
257 goto error;
258 }
259 pi->pi_mtu = lifr.lifr_mtu;
260
261 if (ioctl(fd, SIOCGLIFADDR, (char *)&lifr) < 0) {
262 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFADDR");
263 goto error;
264 }
265 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
266 pi->pi_ifaddr = sin6->sin6_addr;
267
268 if (pi->pi_autoconf && pi->pi_default_token) {
269 if (ioctl(fd, SIOCGLIFTOKEN, (char *)&lifr) < 0) {
270 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFTOKEN");
271 goto error;
272 }
273 /* Ignore interface if the token is all zeros */
274 sin6 = (struct sockaddr_in6 *)&lifr.lifr_token;
275 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
276 logmsg(LOG_ERR, "ignoring interface %s: zero token\n",
277 pi->pi_name);
278 goto error;
279 }
280 pi->pi_token = sin6->sin6_addr;
281 pi->pi_token_length = lifr.lifr_addrlen;
282 }
283
284 /*
285 * Guess a remote token for POINTOPOINT by looking at
286 * the link-local destination address.
287 */
288 if (pi->pi_flags & IFF_POINTOPOINT) {
289 if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifr) < 0) {
290 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFDSTADDR");
291 goto error;
292 }
293 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
294 if (sin6->sin6_family != AF_INET6 ||
295 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
296 !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
297 pi->pi_dst_token = in6addr_any;
298 } else {
299 pi->pi_dst_token = sin6->sin6_addr;
300 /* Clear link-local prefix (first 10 bits) */
301 pi->pi_dst_token.s6_addr[0] = 0;
302 pi->pi_dst_token.s6_addr[1] &= 0x3f;
303 }
304 } else {
305 pi->pi_dst_token = in6addr_any;
306 }
307
308 if (newsock) {
309 icmp6_filter_t filter;
310 int on = 1;
311
312 /* Set default values */
313 pi->pi_LinkMTU = pi->pi_mtu;
314 pi->pi_CurHopLimit = 0;
315 pi->pi_BaseReachableTime = ND_REACHABLE_TIME;
316 phyint_reach_random(pi, _B_FALSE);
317 pi->pi_RetransTimer = ND_RETRANS_TIMER;
318
319 /* Setup socket for transmission and reception */
320 if (setsockopt(fd, IPPROTO_IPV6,
321 IPV6_BOUND_IF, (char *)&pi->pi_index,
322 sizeof (pi->pi_index)) < 0) {
323 logperror_pi(pi, "phyint_init_from_k: setsockopt "
324 "IPV6_BOUND_IF");
325 goto error;
326 }
327
328 ttl = IPV6_MAX_HOPS;
329 if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
330 (char *)&ttl, sizeof (ttl)) < 0) {
331 logperror_pi(pi, "phyint_init_from_k: setsockopt "
332 "IPV6_UNICAST_HOPS");
333 goto error;
334 }
335
336 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
337 (char *)&ttl, sizeof (ttl)) < 0) {
338 logperror_pi(pi, "phyint_init_from_k: setsockopt "
339 "IPV6_MULTICAST_HOPS");
340 goto error;
341 }
342
343 v6mcastr.ipv6mr_multiaddr = all_nodes_mcast;
344 v6mcastr.ipv6mr_interface = pi->pi_index;
345 if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
346 (char *)&v6mcastr, sizeof (v6mcastr)) < 0) {
347 /*
348 * One benign reason IPV6_JOIN_GROUP could fail is
349 * when `pi' has been placed into an IPMP group and we
350 * haven't yet processed the routing socket message
351 * informing us of its disappearance. As such, if
352 * it's now in a group, don't print an error.
353 */
354 save_errno = errno;
355 (void) strlcpy(lifr.lifr_name, pi->pi_name, LIFNAMSIZ);
356 if (ioctl(fd, SIOCGLIFGROUPNAME, &lifr) == -1 ||
357 lifr.lifr_groupname[0] == '\0') {
358 errno = save_errno;
359 logperror_pi(pi, "phyint_init_from_k: "
360 "setsockopt IPV6_JOIN_GROUP");
361 }
362 goto error;
363 }
364 pi->pi_state |= PI_JOINED_ALLNODES;
365 pi->pi_kernel_state |= PI_JOINED_ALLNODES;
366
367 /*
368 * Filter out so that we only receive router advertisements and
369 * router solicitations.
370 */
371 ICMP6_FILTER_SETBLOCKALL(&filter);
372 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
373 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
374
375 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER,
376 (char *)&filter, sizeof (filter)) < 0) {
377 logperror_pi(pi, "phyint_init_from_k: setsockopt "
378 "ICMP6_FILTER");
379 goto error;
380 }
381
382 /* Enable receipt of ancillary data */
383 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
384 (char *)&on, sizeof (on)) < 0) {
385 logperror_pi(pi, "phyint_init_from_k: setsockopt "
386 "IPV6_RECVHOPLIMIT");
387 goto error;
388 }
389 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDR,
390 (char *)&on, sizeof (on)) < 0) {
391 logperror_pi(pi, "phyint_init_from_k: setsockopt "
392 "IPV6_RECVRTHDR");
393 goto error;
394 }
395 }
396
397 if (pi->pi_AdvSendAdvertisements &&
398 !(pi->pi_kernel_state & PI_JOINED_ALLROUTERS)) {
399 v6mcastr.ipv6mr_multiaddr = all_routers_mcast;
400 v6mcastr.ipv6mr_interface = pi->pi_index;
401 if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
402 (char *)&v6mcastr, sizeof (v6mcastr)) < 0) {
403 /*
404 * See IPV6_JOIN_GROUP comment above.
405 */
406 save_errno = errno;
407 (void) strlcpy(lifr.lifr_name, pi->pi_name, LIFNAMSIZ);
408 if (ioctl(fd, SIOCGLIFGROUPNAME, &lifr) == -1 ||
409 lifr.lifr_groupname[0] == '\0') {
410 errno = save_errno;
411 logperror_pi(pi, "phyint_init_from_k: "
412 "setsockopt IPV6_JOIN_GROUP");
413 }
414 goto error;
415 }
416 pi->pi_state |= PI_JOINED_ALLROUTERS;
417 pi->pi_kernel_state |= PI_JOINED_ALLROUTERS;
418 }
419 /*
420 * If not already set, set the IFF_ROUTER interface flag based on
421 * AdvSendAdvertisements. Note that this will also enable IPv6
422 * forwarding on the interface. We don't clear IFF_ROUTER if we're
423 * not advertising on an interface, because we could still be
424 * forwarding on those interfaces.
425 */
426 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name));
427 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
428 if (ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
429 logperror_pi(pi, "phyint_init_from_k: SIOCGLIFFLAGS");
430 goto error;
431 }
432 if (!(lifr.lifr_flags & IFF_ROUTER) && pi->pi_AdvSendAdvertisements) {
433 lifr.lifr_flags |= IFF_ROUTER;
434
435 if (ioctl(fd, SIOCSLIFFLAGS, (char *)&lifr) < 0) {
436 logperror_pi(pi, "phyint_init_from_k: SIOCSLIFFLAGS");
437 goto error;
438 }
439 pi->pi_flags = lifr.lifr_flags;
440 }
441
442 /* Set linkinfo parameters */
443 (void) strncpy(lifr.lifr_name, pi->pi_name, sizeof (lifr.lifr_name));
444 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
445 lifr.lifr_ifinfo.lir_maxhops = pi->pi_CurHopLimit;
446 lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime;
447 lifr.lifr_ifinfo.lir_reachretrans = pi->pi_RetransTimer;
448 /* Setting maxmtu to 0 means that we're leaving the MTU alone */
449 lifr.lifr_ifinfo.lir_maxmtu = 0;
450 if (ioctl(fd, SIOCSLIFLNKINFO, (char *)&lifr) < 0) {
451 logperror_pi(pi, "phyint_init_from_k: SIOCSLIFLNKINFO");
452 goto error;
453 }
454 if (debug & D_PHYINT) {
455 logmsg(LOG_DEBUG, "phyint_init_from_k(%s): done\n",
456 pi->pi_name);
457 }
458 return (0);
459
460 error:
461 /* Pretend the interface does not exist in the kernel */
462 pi->pi_kernel_state &= ~PI_PRESENT;
463 if (newsock) {
464 (void) close(pi->pi_sock);
465 pi->pi_sock = -1;
466 }
467 return (-1);
468 }
469
470 /*
471 * Delete (unlink and free).
472 * Handles delete of things that have not yet been inserted in the list.
473 */
474 void
phyint_delete(struct phyint * pi)475 phyint_delete(struct phyint *pi)
476 {
477 if (debug & D_PHYINT)
478 logmsg(LOG_DEBUG, "phyint_delete(%s)\n", pi->pi_name);
479
480 assert(num_of_phyints > 0);
481
482 while (pi->pi_router_list)
483 router_delete(pi->pi_router_list);
484 while (pi->pi_prefix_list) {
485 prefix_update_ipadm_addrobj(pi->pi_prefix_list, _B_FALSE);
486 prefix_delete(pi->pi_prefix_list);
487 }
488 while (pi->pi_adv_prefix_list)
489 adv_prefix_delete(pi->pi_adv_prefix_list);
490
491 if (pi->pi_sock != -1) {
492 (void) poll_remove(pi->pi_sock);
493 if (close(pi->pi_sock) < 0) {
494 logperror_pi(pi, "phyint_delete: close");
495 }
496 pi->pi_sock = -1;
497 }
498
499 if (pi->pi_prev == NULL) {
500 if (phyints == pi)
501 phyints = pi->pi_next;
502 } else {
503 pi->pi_prev->pi_next = pi->pi_next;
504 }
505 if (pi->pi_next != NULL)
506 pi->pi_next->pi_prev = pi->pi_prev;
507 pi->pi_next = pi->pi_prev = NULL;
508 free(pi);
509 num_of_phyints--;
510 }
511
512 /*
513 * Called with the number of milliseconds elapsed since the last call.
514 * Determines if any timeout event has occurred and
515 * returns the number of milliseconds until the next timeout event
516 * for the phyint itself (excluding prefixes and routers).
517 * Returns TIMER_INFINITY for "never".
518 */
519 uint_t
phyint_timer(struct phyint * pi,uint_t elapsed)520 phyint_timer(struct phyint *pi, uint_t elapsed)
521 {
522 uint_t next = TIMER_INFINITY;
523
524 if (pi->pi_AdvSendAdvertisements) {
525 if (pi->pi_adv_state != NO_ADV) {
526 int old_state = pi->pi_adv_state;
527
528 if (debug & (D_STATE|D_PHYINT)) {
529 logmsg(LOG_DEBUG, "phyint_timer ADV(%s) "
530 "state %d\n", pi->pi_name, (int)old_state);
531 }
532 next = advertise_event(pi, ADV_TIMER, elapsed);
533 if (debug & D_STATE) {
534 logmsg(LOG_DEBUG, "phyint_timer ADV(%s) "
535 "state %d -> %d\n",
536 pi->pi_name, (int)old_state,
537 (int)pi->pi_adv_state);
538 }
539 }
540 } else {
541 if (pi->pi_sol_state != NO_SOLICIT) {
542 int old_state = pi->pi_sol_state;
543
544 if (debug & (D_STATE|D_PHYINT)) {
545 logmsg(LOG_DEBUG, "phyint_timer SOL(%s) "
546 "state %d\n", pi->pi_name, (int)old_state);
547 }
548 next = solicit_event(pi, SOL_TIMER, elapsed);
549 if (debug & D_STATE) {
550 logmsg(LOG_DEBUG, "phyint_timer SOL(%s) "
551 "state %d -> %d\n",
552 pi->pi_name, (int)old_state,
553 (int)pi->pi_sol_state);
554 }
555 }
556 }
557
558 /*
559 * If the phyint has been unplumbed, we don't want to call
560 * phyint_reach_random. We will be in the NO_ADV or NO_SOLICIT state.
561 */
562 if ((pi->pi_AdvSendAdvertisements && (pi->pi_adv_state != NO_ADV)) ||
563 (!pi->pi_AdvSendAdvertisements &&
564 (pi->pi_sol_state != NO_SOLICIT))) {
565 pi->pi_reach_time_since_random += elapsed;
566 if (pi->pi_reach_time_since_random >= MAX_REACH_RANDOM_INTERVAL)
567 phyint_reach_random(pi, _B_TRUE);
568 }
569
570 return (next);
571 }
572
573 static void
phyint_print(struct phyint * pi)574 phyint_print(struct phyint *pi)
575 {
576 struct prefix *pr;
577 struct adv_prefix *adv_pr;
578 struct router *dr;
579 char abuf[INET6_ADDRSTRLEN];
580
581 logmsg(LOG_DEBUG, "Phyint %s index %d state %x, kernel %x, "
582 "num routers %d\n",
583 pi->pi_name, pi->pi_index, pi->pi_state, pi->pi_kernel_state,
584 pi->pi_num_k_routers);
585 logmsg(LOG_DEBUG, "\taddress: %s flags %llx\n",
586 inet_ntop(AF_INET6, (void *)&pi->pi_ifaddr,
587 abuf, sizeof (abuf)), pi->pi_flags);
588 logmsg(LOG_DEBUG, "\tsock %d mtu %d\n", pi->pi_sock, pi->pi_mtu);
589 logmsg(LOG_DEBUG, "\ttoken: len %d %s\n", pi->pi_token_length,
590 inet_ntop(AF_INET6, (void *)&pi->pi_token,
591 abuf, sizeof (abuf)));
592 if (pi->pi_TmpAddrsEnabled) {
593 logmsg(LOG_DEBUG, "\ttmp_token: %s\n",
594 inet_ntop(AF_INET6, (void *)&pi->pi_tmp_token,
595 abuf, sizeof (abuf)));
596 logmsg(LOG_DEBUG, "\ttmp config: pref %d valid %d "
597 "maxdesync %d desync %d regen %d\n",
598 pi->pi_TmpPreferredLifetime, pi->pi_TmpValidLifetime,
599 pi->pi_TmpMaxDesyncFactor, pi->pi_TmpDesyncFactor,
600 pi->pi_TmpRegenAdvance);
601 }
602 if (pi->pi_flags & IFF_POINTOPOINT) {
603 logmsg(LOG_DEBUG, "\tdst_token: %s\n",
604 inet_ntop(AF_INET6, (void *)&pi->pi_dst_token,
605 abuf, sizeof (abuf)));
606 }
607 logmsg(LOG_DEBUG, "\tLinkMTU %d CurHopLimit %d "
608 "BaseReachableTime %d\n\tReachableTime %d RetransTimer %d\n",
609 pi->pi_LinkMTU, pi->pi_CurHopLimit, pi->pi_BaseReachableTime,
610 pi->pi_ReachableTime, pi->pi_RetransTimer);
611 if (!pi->pi_AdvSendAdvertisements) {
612 /* Solicit state */
613 logmsg(LOG_DEBUG, "\tSOLICIT: time_left %d state %d count %d\n",
614 pi->pi_sol_time_left, pi->pi_sol_state, pi->pi_sol_count);
615 } else {
616 /* Advertise state */
617 logmsg(LOG_DEBUG, "\tADVERT: time_left %d state %d count %d "
618 "since last %d\n",
619 pi->pi_adv_time_left, pi->pi_adv_state, pi->pi_adv_count,
620 pi->pi_adv_time_since_sent);
621 print_iflist(pi->pi_config);
622 }
623 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next)
624 prefix_print(pr);
625
626 for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL;
627 adv_pr = adv_pr->adv_pr_next) {
628 adv_prefix_print(adv_pr);
629 }
630
631 for (dr = pi->pi_router_list; dr != NULL; dr = dr->dr_next)
632 router_print(dr);
633
634 logmsg(LOG_DEBUG, "\n");
635 }
636
637
638 /*
639 * Store the LLA for the phyint `pi' `lifrp'. Returns 0 on success, or
640 * -1 on failure.
641 *
642 * Note that we do not cache the hardware address since there's no reliable
643 * mechanism to determine when it's become stale.
644 */
645 int
phyint_get_lla(struct phyint * pi,struct lifreq * lifrp)646 phyint_get_lla(struct phyint *pi, struct lifreq *lifrp)
647 {
648 struct sockaddr_in6 *sin6;
649
650 /* If this phyint doesn't have a link-layer address, bail */
651 if (!(pi->pi_flags & IFF_MULTICAST) ||
652 (pi->pi_flags & IFF_POINTOPOINT)) {
653 return (-1);
654 }
655
656 (void) strlcpy(lifrp->lifr_name, pi->pi_name, LIFNAMSIZ);
657 sin6 = (struct sockaddr_in6 *)&(lifrp->lifr_nd.lnr_addr);
658 sin6->sin6_family = AF_INET6;
659 sin6->sin6_addr = pi->pi_ifaddr;
660 if (ioctl(pi->pi_sock, SIOCLIFGETND, lifrp) < 0) {
661 /*
662 * For IPMP interfaces, don't report ESRCH errors since that
663 * merely indicates that there are no active interfaces in the
664 * IPMP group (and thus there's no working hardware address),
665 * and the packet will thus never make it out anyway.
666 */
667 if (!(pi->pi_flags & IFF_IPMP) || errno != ESRCH)
668 logperror_pi(pi, "phyint_get_lla: SIOCLIFGETND");
669 return (-1);
670 }
671 return (0);
672 }
673
674 /*
675 * Randomize pi->pi_ReachableTime.
676 * Done periodically when there are no RAs and at a maximum frequency when
677 * RA's arrive.
678 * Assumes that caller has determined that it is time to generate
679 * a new random ReachableTime.
680 */
681 void
phyint_reach_random(struct phyint * pi,boolean_t set_needed)682 phyint_reach_random(struct phyint *pi, boolean_t set_needed)
683 {
684 struct lifreq lifr;
685
686 pi->pi_ReachableTime = GET_RANDOM(
687 (int)(ND_MIN_RANDOM_FACTOR * pi->pi_BaseReachableTime),
688 (int)(ND_MAX_RANDOM_FACTOR * pi->pi_BaseReachableTime));
689 if (set_needed) {
690 bzero(&lifr, sizeof (lifr));
691 (void) strlcpy(lifr.lifr_name, pi->pi_name, LIFNAMSIZ);
692 lifr.lifr_ifinfo.lir_reachtime = pi->pi_ReachableTime;
693 if (ioctl(pi->pi_sock, SIOCSLIFLNKINFO, (char *)&lifr) < 0) {
694 logperror_pi(pi,
695 "phyint_reach_random: SIOCSLIFLNKINFO");
696 return;
697 }
698 }
699 pi->pi_reach_time_since_random = 0;
700 }
701
702 /*
703 * Validate a temporary token against a list of known bad values.
704 * Currently assumes that token is 8 bytes long! Current known
705 * bad values include 0, reserved anycast tokens (RFC 2526), tokens
706 * used by ISATAP (draft-ietf-ngtrans-isatap-N), any token already
707 * assigned to this interface, or any token for which the global
708 * bit is set.
709 *
710 * Called by tmptoken_create().
711 *
712 * Return _B_TRUE if token is valid (no match), _B_FALSE if not.
713 */
714 static boolean_t
tmptoken_isvalid(struct in6_addr * token)715 tmptoken_isvalid(struct in6_addr *token)
716 {
717 struct phyint *pi;
718 struct in6_addr mask;
719 struct in6_addr isatap = { 0, 0, 0, 0, 0, 0, 0, 0, \
720 0, 0, 0x5e, 0xfe, 0, 0, 0, 0 };
721 struct in6_addr anycast = { 0, 0, 0, 0, \
722 0, 0, 0, 0, \
723 0xfd, 0xff, 0xff, 0xff, \
724 0xff, 0xff, 0xff, 0x80 };
725
726 if (IN6_IS_ADDR_UNSPECIFIED(token))
727 return (_B_FALSE);
728
729 if (token->s6_addr[8] & 0x2)
730 return (_B_FALSE);
731
732 (void) memcpy(&mask, token, sizeof (mask));
733 mask._S6_un._S6_u32[3] = 0;
734 if (IN6_ARE_ADDR_EQUAL(&isatap, token))
735 return (_B_FALSE);
736
737 mask._S6_un._S6_u32[3] = token->_S6_un._S6_u32[3] & 0xffffff80;
738 if (IN6_ARE_ADDR_EQUAL(&anycast, token))
739 return (_B_FALSE);
740
741 for (pi = phyints; pi != NULL; pi = pi->pi_next) {
742 if (((pi->pi_token_length == TMP_TOKEN_BITS) &&
743 IN6_ARE_ADDR_EQUAL(&pi->pi_token, token)) ||
744 IN6_ARE_ADDR_EQUAL(&pi->pi_tmp_token, token))
745 return (_B_FALSE);
746 }
747
748 /* none of our tests failed, must be a good one! */
749 return (_B_TRUE);
750 }
751
752 /*
753 * Generate a temporary token and set up its timer
754 *
755 * Called from incoming_prefix_addrconf_process() (when token is first
756 * needed) and from tmptoken_timer() (when current token expires).
757 *
758 * Returns _B_TRUE if a token was successfully generated, _B_FALSE if not.
759 */
760 boolean_t
tmptoken_create(struct phyint * pi)761 tmptoken_create(struct phyint *pi)
762 {
763 int fd, i = 0, max_tries = 15;
764 struct in6_addr token;
765 uint32_t *tokenp = &(token._S6_un._S6_u32[2]);
766 char buf[INET6_ADDRSTRLEN];
767
768 if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
769 perror("open /dev/urandom");
770 goto no_token;
771 }
772
773 bzero((char *)&token, sizeof (token));
774 do {
775 if (read(fd, (void *)tokenp, TMP_TOKEN_BYTES) == -1) {
776 perror("read /dev/urandom");
777 (void) close(fd);
778 goto no_token;
779 }
780
781 /*
782 * Assume EUI-64 formatting, and thus 64-bit
783 * token len; need to clear global bit.
784 */
785 token.s6_addr[8] &= 0xfd;
786
787 i++;
788
789 } while (!tmptoken_isvalid(&token) && i < max_tries);
790
791 (void) close(fd);
792
793 if (i == max_tries) {
794 no_token:
795 logmsg(LOG_WARNING, "tmptoken_create(%s): failed to create "
796 "token; disabling temporary addresses on %s\n",
797 pi->pi_name, pi->pi_name);
798 pi->pi_TmpAddrsEnabled = 0;
799 return (_B_FALSE);
800 }
801
802 pi->pi_tmp_token = token;
803
804 if (debug & D_TMP)
805 logmsg(LOG_DEBUG, "tmptoken_create(%s): created temporary "
806 "token %s\n", pi->pi_name,
807 inet_ntop(AF_INET6, &pi->pi_tmp_token, buf, sizeof (buf)));
808
809 pi->pi_TmpRegenCountdown = (pi->pi_TmpPreferredLifetime -
810 pi->pi_TmpDesyncFactor - pi->pi_TmpRegenAdvance) * MILLISEC;
811 if (pi->pi_TmpRegenCountdown != 0)
812 timer_schedule(pi->pi_TmpRegenCountdown);
813
814 return (_B_TRUE);
815 }
816
817 /*
818 * Delete a temporary token. This is outside the normal timeout process,
819 * so mark any existing addresses based on this token DEPRECATED and set
820 * their preferred lifetime to 0. Don't tamper with valid lifetime, that
821 * will be used to eventually remove the address. Also reset the current
822 * pi_tmp_token value to 0.
823 *
824 * Called from incoming_prefix_addrconf_process() if DAD fails on a temp
825 * addr.
826 */
827 void
tmptoken_delete(struct phyint * pi)828 tmptoken_delete(struct phyint *pi)
829 {
830 struct prefix *pr;
831
832 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
833 if (!(pr->pr_flags & IFF_TEMPORARY) ||
834 (pr->pr_flags & IFF_DEPRECATED) ||
835 (!token_equal(pr->pr_address, pi->pi_tmp_token,
836 TMP_TOKEN_BITS))) {
837 continue;
838 }
839 pr->pr_PreferredLifetime = 0;
840 pr->pr_state |= PR_DEPRECATED;
841 prefix_update_k(pr);
842 }
843
844 (void) memset(&pi->pi_tmp_token, 0, sizeof (pi->pi_tmp_token));
845 }
846
847 /*
848 * Called from run_timeouts() with the number of milliseconds elapsed
849 * since the last call. Determines if any timeout event has occurred
850 * and returns the number of milliseconds until the next timeout event
851 * for the tmp token. Returns TIMER_INFINITY for "never".
852 */
853 uint_t
tmptoken_timer(struct phyint * pi,uint_t elapsed)854 tmptoken_timer(struct phyint *pi, uint_t elapsed)
855 {
856 struct nd_opt_prefix_info opt;
857 struct sockaddr_in6 sin6;
858 struct prefix *pr, *newpr;
859
860 if (debug & D_TMP) {
861 logmsg(LOG_DEBUG, "tmptoken_timer(%s, %d) regencountdown %d\n",
862 pi->pi_name, (int)elapsed, pi->pi_TmpRegenCountdown);
863 }
864 if (!pi->pi_TmpAddrsEnabled ||
865 (pi->pi_TmpRegenCountdown == TIMER_INFINITY))
866 return (TIMER_INFINITY);
867
868 if (pi->pi_TmpRegenCountdown > elapsed) {
869 pi->pi_TmpRegenCountdown -= elapsed;
870 return (pi->pi_TmpRegenCountdown);
871 }
872
873 /*
874 * Tmp token timer has expired. Start by generating a new token.
875 * If we can't get a new token, tmp addrs are disabled on this
876 * interface, so there's no need to continue, or to set a timer.
877 */
878 if (!tmptoken_create(pi))
879 return (TIMER_INFINITY);
880
881 /*
882 * Now that we have a new token, walk the list of prefixes to
883 * find which ones need a corresponding tmp addr generated.
884 */
885 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
886
887 if (!(pr->pr_state & PR_AUTO) || pr->pr_state & PR_STATIC ||
888 pr->pr_state & PR_DEPRECATED ||
889 pr->pr_flags & IFF_TEMPORARY)
890 continue;
891
892 newpr = prefix_create(pi, pr->pr_prefix, pr->pr_prefix_len,
893 IFF_TEMPORARY);
894 if (newpr == NULL) {
895 char pbuf[INET6_ADDRSTRLEN];
896 char tbuf[INET6_ADDRSTRLEN];
897 (void) inet_ntop(AF_INET6, &pr->pr_prefix, pbuf,
898 sizeof (pbuf));
899 (void) inet_ntop(AF_INET6, &pi->pi_tmp_token, tbuf,
900 sizeof (tbuf));
901 logmsg(LOG_ERR, "can't create new tmp addr "
902 "(%s, %s, %s)\n", pi->pi_name, pbuf, tbuf);
903 continue;
904 }
905
906 /*
907 * We want to use incoming_prefix_*_process() functions to
908 * set up the new tmp addr, so cobble together a prefix
909 * info option struct based on the existing prefix to pass
910 * in. The lifetimes will be based on the current time
911 * remaining.
912 *
913 * The "from" param is only used for messages; pass in
914 * ::0 for that.
915 */
916 opt.nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
917 opt.nd_opt_pi_len = sizeof (opt) / 8;
918 opt.nd_opt_pi_prefix_len = pr->pr_prefix_len;
919 opt.nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_AUTO;
920 opt.nd_opt_pi_valid_time =
921 htonl(pr->pr_ValidLifetime / 1000);
922 opt.nd_opt_pi_preferred_time =
923 htonl(pr->pr_PreferredLifetime / 1000);
924 if (pr->pr_state & PR_ONLINK)
925 opt.nd_opt_pi_flags_reserved &= ND_OPT_PI_FLAG_ONLINK;
926 opt.nd_opt_pi_prefix = pr->pr_prefix;
927
928 (void) memset(&sin6, 0, sizeof (sin6));
929
930 if (!incoming_prefix_addrconf_process(pi, newpr,
931 (uchar_t *)&opt, &sin6, _B_FALSE, _B_TRUE)) {
932 char pbuf[INET6_ADDRSTRLEN];
933 char tbuf[INET6_ADDRSTRLEN];
934 (void) inet_ntop(AF_INET6, &pr->pr_prefix, pbuf,
935 sizeof (pbuf));
936 (void) inet_ntop(AF_INET6, &pi->pi_tmp_token, tbuf,
937 sizeof (tbuf));
938 logmsg(LOG_ERR, "can't create new tmp addr "
939 "(%s, %s, %s)\n", pi->pi_name, pbuf, tbuf);
940 continue;
941 }
942
943 if (pr->pr_state & PR_ONLINK) {
944 incoming_prefix_onlink_process(newpr, (uchar_t *)&opt);
945 }
946 }
947
948 /*
949 * appropriate timers were scheduled when
950 * the token and addresses were created.
951 */
952 return (TIMER_INFINITY);
953 }
954
955 /*
956 * tlen specifies the token length in bits. Compares the lower
957 * tlen bits of the two addresses provided and returns _B_TRUE if
958 * they match, _B_FALSE if not. Also returns _B_FALSE for invalid
959 * values of tlen.
960 */
961 boolean_t
token_equal(struct in6_addr t1,struct in6_addr t2,int tlen)962 token_equal(struct in6_addr t1, struct in6_addr t2, int tlen)
963 {
964 uchar_t mask;
965 int j, abytes, tbytes, tbits;
966
967 if (tlen < 0 || tlen > IPV6_ABITS)
968 return (_B_FALSE);
969
970 abytes = IPV6_ABITS >> 3;
971 tbytes = tlen >> 3;
972 tbits = tlen & 7;
973
974 for (j = abytes - 1; j >= abytes - tbytes; j--)
975 if (t1.s6_addr[j] != t2.s6_addr[j])
976 return (_B_FALSE);
977
978 if (tbits == 0)
979 return (_B_TRUE);
980
981 /* We only care about the tbits rightmost bits */
982 mask = 0xff >> (8 - tbits);
983 if ((t1.s6_addr[j] & mask) != (t2.s6_addr[j] & mask))
984 return (_B_FALSE);
985
986 return (_B_TRUE);
987 }
988
989 /*
990 * Lookup prefix structure that matches the prefix and prefix length.
991 * Assumes that the bits after prefixlen might not be zero.
992 */
993 static struct prefix *
prefix_lookup(struct phyint * pi,struct in6_addr prefix,int prefixlen)994 prefix_lookup(struct phyint *pi, struct in6_addr prefix, int prefixlen)
995 {
996 struct prefix *pr;
997 char abuf[INET6_ADDRSTRLEN];
998
999 if (debug & D_PREFIX) {
1000 logmsg(LOG_DEBUG, "prefix_lookup(%s, %s/%u)\n", pi->pi_name,
1001 inet_ntop(AF_INET6, (void *)&prefix,
1002 abuf, sizeof (abuf)), prefixlen);
1003 }
1004
1005 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
1006 if (pr->pr_prefix_len == prefixlen &&
1007 prefix_equal(prefix, pr->pr_prefix, prefixlen))
1008 return (pr);
1009 }
1010 return (NULL);
1011 }
1012
1013 /*
1014 * Compare two prefixes that have the same prefix length.
1015 * Fails if the prefix length is unreasonable.
1016 */
1017 boolean_t
prefix_equal(struct in6_addr p1,struct in6_addr p2,int plen)1018 prefix_equal(struct in6_addr p1, struct in6_addr p2, int plen)
1019 {
1020 uchar_t mask;
1021 int j, pbytes, pbits;
1022
1023 if (plen < 0 || plen > IPV6_ABITS)
1024 return (_B_FALSE);
1025
1026 pbytes = plen >> 3;
1027 pbits = plen & 7;
1028
1029 for (j = 0; j < pbytes; j++)
1030 if (p1.s6_addr[j] != p2.s6_addr[j])
1031 return (_B_FALSE);
1032
1033 if (pbits == 0)
1034 return (_B_TRUE);
1035
1036 /* Make the N leftmost bits one */
1037 mask = 0xff << (8 - pbits);
1038 if ((p1.s6_addr[j] & mask) != (p2.s6_addr[j] & mask))
1039 return (_B_FALSE);
1040
1041 return (_B_TRUE);
1042 }
1043
1044 /*
1045 * Set a prefix from an address and a prefix length.
1046 * Force all the bits after the prefix length to be zero.
1047 */
1048 void
prefix_set(struct in6_addr * prefix,struct in6_addr addr,int prefix_len)1049 prefix_set(struct in6_addr *prefix, struct in6_addr addr, int prefix_len)
1050 {
1051 uchar_t mask;
1052 int j;
1053
1054 if (prefix_len < 0 || prefix_len > IPV6_ABITS)
1055 return;
1056
1057 bzero((char *)prefix, sizeof (*prefix));
1058
1059 for (j = 0; prefix_len > 8; prefix_len -= 8, j++)
1060 prefix->s6_addr[j] = addr.s6_addr[j];
1061
1062 /* Make the N leftmost bits one */
1063 mask = 0xff << (8 - prefix_len);
1064 prefix->s6_addr[j] = addr.s6_addr[j] & mask;
1065 }
1066
1067 /*
1068 * Lookup a prefix based on the kernel's interface name.
1069 */
1070 struct prefix *
prefix_lookup_name(struct phyint * pi,char * name)1071 prefix_lookup_name(struct phyint *pi, char *name)
1072 {
1073 struct prefix *pr;
1074
1075 if (debug & D_PREFIX) {
1076 logmsg(LOG_DEBUG, "prefix_lookup_name(%s, %s)\n",
1077 pi->pi_name, name);
1078 }
1079 if (name[0] == '\0')
1080 return (NULL);
1081
1082 for (pr = pi->pi_prefix_list; pr != NULL; pr = pr->pr_next) {
1083 if (strcmp(name, pr->pr_name) == 0)
1084 return (pr);
1085 }
1086 return (NULL);
1087 }
1088
1089 /*
1090 * Search the phyints list to make sure that this new prefix does
1091 * not already exist in any other physical interfaces that have
1092 * the same address as this one
1093 */
1094 struct prefix *
prefix_lookup_addr_match(struct prefix * pr)1095 prefix_lookup_addr_match(struct prefix *pr)
1096 {
1097 char abuf[INET6_ADDRSTRLEN];
1098 struct phyint *pi;
1099 struct prefix *otherpr = NULL;
1100 struct in6_addr prefix;
1101 int prefixlen;
1102
1103 if (debug & D_PREFIX) {
1104 logmsg(LOG_DEBUG, "prefix_lookup_addr_match(%s/%u)\n",
1105 inet_ntop(AF_INET6, (void *)&pr->pr_address,
1106 abuf, sizeof (abuf)), pr->pr_prefix_len);
1107 }
1108 prefix = pr->pr_prefix;
1109 prefixlen = pr->pr_prefix_len;
1110 for (pi = phyints; pi != NULL; pi = pi->pi_next) {
1111 otherpr = prefix_lookup(pi, prefix, prefixlen);
1112 if (otherpr == pr)
1113 continue;
1114 if (otherpr != NULL && (otherpr->pr_state & PR_AUTO) &&
1115 IN6_ARE_ADDR_EQUAL(&pr->pr_address,
1116 &otherpr->pr_address))
1117 return (otherpr);
1118 }
1119 return (NULL);
1120 }
1121
1122 /*
1123 * Initialize a new prefix without setting lifetimes etc.
1124 */
1125 struct prefix *
prefix_create(struct phyint * pi,struct in6_addr prefix,int prefixlen,uint64_t flags)1126 prefix_create(struct phyint *pi, struct in6_addr prefix, int prefixlen,
1127 uint64_t flags)
1128 {
1129 struct prefix *pr;
1130 char abuf[INET6_ADDRSTRLEN];
1131
1132 if (debug & D_PREFIX) {
1133 logmsg(LOG_DEBUG, "prefix_create(%s, %s/%u, 0x%llx)\n",
1134 pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix,
1135 abuf, sizeof (abuf)), prefixlen, flags);
1136 }
1137 pr = (struct prefix *)calloc(sizeof (struct prefix), 1);
1138 if (pr == NULL) {
1139 logmsg(LOG_ERR, "prefix_create: out of memory\n");
1140 return (NULL);
1141 }
1142 /*
1143 * The prefix might have non-zero bits after the prefix len bits.
1144 * Force them to be zero.
1145 */
1146 prefix_set(&pr->pr_prefix, prefix, prefixlen);
1147 pr->pr_prefix_len = prefixlen;
1148 pr->pr_PreferredLifetime = PREFIX_INFINITY;
1149 pr->pr_ValidLifetime = PREFIX_INFINITY;
1150 pr->pr_OnLinkLifetime = PREFIX_INFINITY;
1151 pr->pr_kernel_state = 0;
1152 pr->pr_flags |= flags;
1153 prefix_insert(pi, pr);
1154 return (pr);
1155 }
1156
1157 /*
1158 * Create a new named prefix. Caller should use prefix_init_from_k
1159 * to initialize the content.
1160 */
1161 struct prefix *
prefix_create_name(struct phyint * pi,char * name)1162 prefix_create_name(struct phyint *pi, char *name)
1163 {
1164 struct prefix *pr;
1165
1166 if (debug & D_PREFIX) {
1167 logmsg(LOG_DEBUG, "prefix_create_name(%s, %s)\n",
1168 pi->pi_name, name);
1169 }
1170 pr = (struct prefix *)calloc(sizeof (struct prefix), 1);
1171 if (pr == NULL) {
1172 logmsg(LOG_ERR, "prefix_create_name: out of memory\n");
1173 return (NULL);
1174 }
1175 (void) strncpy(pr->pr_name, name, sizeof (pr->pr_name));
1176 pr->pr_name[sizeof (pr->pr_name) - 1] = '\0';
1177 prefix_insert(pi, pr);
1178 return (pr);
1179 }
1180
1181 /* Insert in linked list */
1182 static void
prefix_insert(struct phyint * pi,struct prefix * pr)1183 prefix_insert(struct phyint *pi, struct prefix *pr)
1184 {
1185 pr->pr_next = pi->pi_prefix_list;
1186 pr->pr_prev = NULL;
1187 if (pi->pi_prefix_list != NULL)
1188 pi->pi_prefix_list->pr_prev = pr;
1189 pi->pi_prefix_list = pr;
1190 pr->pr_physical = pi;
1191 }
1192
1193 /*
1194 * Initialize the prefix from the content of the kernel.
1195 * If IFF_ADDRCONF is set we treat it as PR_AUTO (i.e. an addrconf
1196 * prefix). However, we cannot derive the lifetime from
1197 * the kernel, thus it is set to 1 week.
1198 * Ignore the prefix if the interface is not IFF_UP.
1199 * If it's from DHCPv6, then we set the netmask.
1200 */
1201 int
prefix_init_from_k(struct prefix * pr)1202 prefix_init_from_k(struct prefix *pr)
1203 {
1204 struct lifreq lifr;
1205 struct sockaddr_in6 *sin6;
1206 int sock = pr->pr_physical->pi_sock;
1207
1208 (void) strncpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name));
1209 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1210 if (ioctl(sock, SIOCGLIFADDR, (char *)&lifr) < 0) {
1211 logperror_pr(pr, "prefix_init_from_k: ioctl (get addr)");
1212 goto error;
1213 }
1214 if (lifr.lifr_addr.ss_family != AF_INET6) {
1215 logmsg(LOG_ERR, "ignoring interface %s: not AF_INET6\n",
1216 pr->pr_name);
1217 goto error;
1218 }
1219 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1220 pr->pr_address = sin6->sin6_addr;
1221
1222 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
1223 logperror_pr(pr, "prefix_init_from_k: ioctl (get flags)");
1224 goto error;
1225 }
1226 pr->pr_flags = lifr.lifr_flags;
1227
1228 /*
1229 * If this is a DHCPv6 interface, then we control the netmask.
1230 */
1231 if (lifr.lifr_flags & IFF_DHCPRUNNING) {
1232 struct phyint *pi = pr->pr_physical;
1233 struct prefix *pr2;
1234
1235 pr->pr_prefix_len = IPV6_ABITS;
1236 if (!(lifr.lifr_flags & IFF_UP) ||
1237 IN6_IS_ADDR_UNSPECIFIED(&pr->pr_address) ||
1238 IN6_IS_ADDR_LINKLOCAL(&pr->pr_address)) {
1239 if (debug & D_DHCP)
1240 logmsg(LOG_DEBUG, "prefix_init_from_k: "
1241 "ignoring DHCP %s not ready\n",
1242 pr->pr_name);
1243 return (0);
1244 }
1245
1246 for (pr2 = pi->pi_prefix_list; pr2 != NULL;
1247 pr2 = pr2->pr_next) {
1248 /*
1249 * Examine any non-static (autoconfigured) prefixes as
1250 * well as existing DHCP-controlled prefixes for valid
1251 * prefix length information.
1252 */
1253 if (pr2->pr_prefix_len != IPV6_ABITS &&
1254 (!(pr2->pr_state & PR_STATIC) ||
1255 (pr2->pr_flags & IFF_DHCPRUNNING)) &&
1256 prefix_equal(pr->pr_prefix, pr2->pr_prefix,
1257 pr2->pr_prefix_len)) {
1258 pr->pr_prefix_len = pr2->pr_prefix_len;
1259 break;
1260 }
1261 }
1262 if (pr2 == NULL) {
1263 if (debug & D_DHCP)
1264 logmsg(LOG_DEBUG, "prefix_init_from_k: no "
1265 "saved mask for DHCP %s; need to "
1266 "resolicit\n", pr->pr_name);
1267 (void) check_to_solicit(pi, RESTART_INIT_SOLICIT);
1268 } else {
1269 if (debug & D_DHCP)
1270 logmsg(LOG_DEBUG, "prefix_init_from_k: using "
1271 "%s mask for DHCP %s\n",
1272 pr2->pr_name[0] == '\0' ? "saved" :
1273 pr2->pr_name, pr->pr_name);
1274 prefix_update_dhcp(pr);
1275 }
1276 /*
1277 * If this interface was created using ipadm, store the
1278 * addrobj for the DHCPv6 interface in ipmgmtd daemon's
1279 * in-memory aobjmap.
1280 */
1281 prefix_update_ipadm_addrobj(pr, _B_TRUE);
1282 } else {
1283 if (ioctl(sock, SIOCGLIFSUBNET, (char *)&lifr) < 0) {
1284 logperror_pr(pr,
1285 "prefix_init_from_k: ioctl (get subnet)");
1286 goto error;
1287 }
1288 if (lifr.lifr_subnet.ss_family != AF_INET6) {
1289 logmsg(LOG_ERR,
1290 "ignoring interface %s: not AF_INET6\n",
1291 pr->pr_name);
1292 goto error;
1293 }
1294 /*
1295 * Guard against the prefix having non-zero bits after the
1296 * prefix len bits.
1297 */
1298 sin6 = (struct sockaddr_in6 *)&lifr.lifr_subnet;
1299 pr->pr_prefix_len = lifr.lifr_addrlen;
1300 prefix_set(&pr->pr_prefix, sin6->sin6_addr, pr->pr_prefix_len);
1301
1302 if (pr->pr_prefix_len != IPV6_ABITS &&
1303 (pr->pr_flags & IFF_UP) &&
1304 IN6_ARE_ADDR_EQUAL(&pr->pr_address, &pr->pr_prefix)) {
1305 char abuf[INET6_ADDRSTRLEN];
1306
1307 logmsg(LOG_ERR, "ignoring interface %s: it appears to "
1308 "be configured with an invalid interface id "
1309 "(%s/%u)\n",
1310 pr->pr_name,
1311 inet_ntop(AF_INET6, (void *)&pr->pr_address,
1312 abuf, sizeof (abuf)), pr->pr_prefix_len);
1313 goto error;
1314 }
1315 }
1316 pr->pr_kernel_state = 0;
1317 if (pr->pr_prefix_len != IPV6_ABITS)
1318 pr->pr_kernel_state |= PR_ONLINK;
1319 if (!(pr->pr_flags & (IFF_NOLOCAL | IFF_DHCPRUNNING)))
1320 pr->pr_kernel_state |= PR_AUTO;
1321 if ((pr->pr_flags & IFF_DEPRECATED) && (pr->pr_kernel_state & PR_AUTO))
1322 pr->pr_kernel_state |= PR_DEPRECATED;
1323 if (!(pr->pr_flags & IFF_ADDRCONF)) {
1324 /* Prevent ndpd from stepping on this prefix */
1325 pr->pr_kernel_state |= PR_STATIC;
1326 }
1327 pr->pr_state = pr->pr_kernel_state;
1328 /* Adjust pr_prefix_len based if PR_AUTO is set */
1329 if (pr->pr_state & PR_AUTO) {
1330 pr->pr_prefix_len =
1331 IPV6_ABITS - pr->pr_physical->pi_token_length;
1332 prefix_set(&pr->pr_prefix, pr->pr_prefix, pr->pr_prefix_len);
1333 }
1334
1335 /* Can't extract lifetimes from the kernel - use 1 week */
1336 pr->pr_ValidLifetime = NDP_PREFIX_DEFAULT_LIFETIME;
1337 pr->pr_PreferredLifetime = NDP_PREFIX_DEFAULT_LIFETIME;
1338 pr->pr_OnLinkLifetime = NDP_PREFIX_DEFAULT_LIFETIME;
1339
1340 /*
1341 * If this is a temp addr, the creation time needs to be set.
1342 * Though it won't be entirely accurate, the current time is
1343 * an okay approximation.
1344 */
1345 if (pr->pr_flags & IFF_TEMPORARY)
1346 pr->pr_CreateTime = getcurrenttime() / MILLISEC;
1347
1348 if (pr->pr_kernel_state == 0)
1349 pr->pr_name[0] = '\0';
1350 return (0);
1351
1352 error:
1353 /* Pretend that the prefix does not exist in the kernel */
1354 pr->pr_kernel_state = 0;
1355 pr->pr_name[0] = '\0';
1356 return (-1);
1357 }
1358
1359 /*
1360 * Delete (unlink and free) and remove from kernel if the prefix
1361 * was added by in.ndpd (i.e. PR_STATIC is not set).
1362 * Handles delete of things that have not yet been inserted in the list
1363 * i.e. pr_physical is NULL.
1364 * Removes the ipadm addrobj created for the prefix.
1365 */
1366 void
prefix_delete(struct prefix * pr)1367 prefix_delete(struct prefix *pr)
1368 {
1369 struct phyint *pi;
1370 char abuf[INET6_ADDRSTRLEN];
1371
1372 if (debug & D_PREFIX) {
1373 logmsg(LOG_DEBUG, "prefix_delete(%s, %s, %s/%u)\n",
1374 pr->pr_physical->pi_name, pr->pr_name,
1375 inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1376 abuf, sizeof (abuf)), pr->pr_prefix_len);
1377 }
1378 pi = pr->pr_physical;
1379
1380 /* Remove non-static prefixes from the kernel. */
1381 pr->pr_state &= PR_STATIC;
1382 if (pr->pr_kernel_state != pr->pr_state)
1383 prefix_update_k(pr);
1384
1385 if (pr->pr_prev == NULL) {
1386 if (pi != NULL)
1387 pi->pi_prefix_list = pr->pr_next;
1388 } else {
1389 pr->pr_prev->pr_next = pr->pr_next;
1390 }
1391 if (pr->pr_next != NULL)
1392 pr->pr_next->pr_prev = pr->pr_prev;
1393 pr->pr_next = pr->pr_prev = NULL;
1394
1395 free(pr);
1396 }
1397
1398 /*
1399 * Toggle one or more IFF_ flags for a prefix. Turn on 'onflags' and
1400 * turn off 'offflags'.
1401 */
1402 static int
prefix_modify_flags(struct prefix * pr,uint64_t onflags,uint64_t offflags)1403 prefix_modify_flags(struct prefix *pr, uint64_t onflags, uint64_t offflags)
1404 {
1405 struct lifreq lifr;
1406 struct phyint *pi = pr->pr_physical;
1407 uint64_t old_flags;
1408 char abuf[INET6_ADDRSTRLEN];
1409
1410 if (debug & D_PREFIX) {
1411 logmsg(LOG_DEBUG, "prefix_modify_flags(%s, %s, %s/%u) "
1412 "flags %llx on %llx off %llx\n",
1413 pr->pr_physical->pi_name,
1414 pr->pr_name,
1415 inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1416 abuf, sizeof (abuf)), pr->pr_prefix_len,
1417 pr->pr_flags, onflags, offflags);
1418 }
1419 /* Assumes that only the PR_STATIC link-local matches the pi_name */
1420 if (!(pr->pr_state & PR_STATIC) &&
1421 strcmp(pr->pr_name, pi->pi_name) == 0) {
1422 logmsg(LOG_ERR, "prefix_modify_flags(%s, on %llx, off %llx): "
1423 "name matches interface name\n",
1424 pi->pi_name, onflags, offflags);
1425 return (-1);
1426 }
1427
1428 (void) strncpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name));
1429 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1430 if (ioctl(pi->pi_sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
1431 if (errno != ENXIO) {
1432 logperror_pr(pr, "prefix_modify_flags: SIOCGLIFFLAGS");
1433 logmsg(LOG_ERR, "prefix_modify_flags(%s, %s) old 0x%llx"
1434 " on 0x%llx off 0x%llx\n", pr->pr_physical->pi_name,
1435 pr->pr_name, pr->pr_flags, onflags, offflags);
1436 }
1437 return (-1);
1438 }
1439 old_flags = lifr.lifr_flags;
1440 lifr.lifr_flags |= onflags;
1441 lifr.lifr_flags &= ~offflags;
1442 pr->pr_flags = lifr.lifr_flags;
1443 if (ioctl(pi->pi_sock, SIOCSLIFFLAGS, (char *)&lifr) < 0) {
1444 if (errno != ENXIO) {
1445 logperror_pr(pr, "prefix_modify_flags: SIOCSLIFFLAGS");
1446 logmsg(LOG_ERR, "prefix_modify_flags(%s, %s) old 0x%llx"
1447 " new 0x%llx on 0x%llx off 0x%llx\n",
1448 pr->pr_physical->pi_name, pr->pr_name,
1449 old_flags, lifr.lifr_flags, onflags, offflags);
1450 }
1451 return (-1);
1452 }
1453 return (0);
1454 }
1455
1456 /*
1457 * Update the subnet mask for this interface under DHCPv6 control.
1458 */
1459 void
prefix_update_dhcp(struct prefix * pr)1460 prefix_update_dhcp(struct prefix *pr)
1461 {
1462 struct lifreq lifr;
1463
1464 (void) memset(&lifr, 0, sizeof (lifr));
1465 (void) strlcpy(lifr.lifr_name, pr->pr_name, sizeof (lifr.lifr_name));
1466 lifr.lifr_addr.ss_family = AF_INET6;
1467 prefix_set(&((struct sockaddr_in6 *)&lifr.lifr_addr)->sin6_addr,
1468 pr->pr_address, pr->pr_prefix_len);
1469 lifr.lifr_addrlen = pr->pr_prefix_len;
1470 /*
1471 * Ignore ENXIO, as the dhcpagent process is responsible for plumbing
1472 * and unplumbing these.
1473 */
1474 if (ioctl(pr->pr_physical->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) ==
1475 -1 && errno != ENXIO)
1476 logperror_pr(pr, "prefix_update_dhcp: ioctl (set subnet)");
1477 }
1478
1479 /*
1480 * Make the kernel state match what is in the prefix structure.
1481 * This includes creating the prefix (allocating a new interface name)
1482 * as well as setting the local address and on-link subnet prefix
1483 * and controlling the IFF_ADDRCONF and IFF_DEPRECATED flags.
1484 */
1485 void
prefix_update_k(struct prefix * pr)1486 prefix_update_k(struct prefix *pr)
1487 {
1488 struct lifreq lifr;
1489 char abuf[INET6_ADDRSTRLEN];
1490 char buf1[PREFIX_STATESTRLEN], buf2[PREFIX_STATESTRLEN];
1491 struct phyint *pi = pr->pr_physical;
1492 struct sockaddr_in6 *sin6;
1493
1494 if (debug & D_PREFIX) {
1495 logmsg(LOG_DEBUG, "prefix_update_k(%s, %s, %s/%u) "
1496 "from %s to %s\n", pr->pr_physical->pi_name, pr->pr_name,
1497 inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1498 abuf, sizeof (abuf)), pr->pr_prefix_len,
1499 prefix_print_state(pr->pr_kernel_state, buf1,
1500 sizeof (buf1)),
1501 prefix_print_state(pr->pr_state, buf2, sizeof (buf2)));
1502 }
1503
1504 if (pr->pr_kernel_state == pr->pr_state)
1505 return; /* No changes */
1506
1507 /* Skip static prefixes */
1508 if (pr->pr_state & PR_STATIC)
1509 return;
1510
1511 if (pr->pr_kernel_state == 0) {
1512 uint64_t onflags;
1513 /*
1514 * Create a new logical interface name and store in pr_name.
1515 * Set IFF_ADDRCONF. Do not set an address (yet).
1516 */
1517 if (pr->pr_name[0] != '\0') {
1518 /* Name already set! */
1519 logmsg(LOG_ERR, "prefix_update_k(%s, %s, %s/%u) "
1520 "from %s to %s name is already allocated\n",
1521 pr->pr_physical->pi_name, pr->pr_name,
1522 inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1523 abuf, sizeof (abuf)), pr->pr_prefix_len,
1524 prefix_print_state(pr->pr_kernel_state, buf1,
1525 sizeof (buf1)),
1526 prefix_print_state(pr->pr_state, buf2,
1527 sizeof (buf2)));
1528 return;
1529 }
1530
1531 (void) strncpy(lifr.lifr_name, pi->pi_name,
1532 sizeof (lifr.lifr_name));
1533 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1534 lifr.lifr_addr.ss_family = AF_UNSPEC;
1535 if (ioctl(pi->pi_sock, SIOCLIFADDIF, (char *)&lifr) < 0) {
1536 logperror_pr(pr, "prefix_update_k: SIOCLIFADDIF");
1537 return;
1538 }
1539 (void) strncpy(pr->pr_name, lifr.lifr_name,
1540 sizeof (pr->pr_name));
1541 pr->pr_name[sizeof (pr->pr_name) - 1] = '\0';
1542 if (debug & D_PREFIX) {
1543 logmsg(LOG_DEBUG, "prefix_update_k: new name %s\n",
1544 pr->pr_name);
1545 }
1546 /*
1547 * The IFF_TEMPORARY flag might have already been set; if
1548 * so, it needs to be or'd into the flags we're turning on.
1549 * But be careful, we might be re-creating a manually
1550 * removed interface, in which case we don't want to try
1551 * to set *all* the flags we might have in our copy of the
1552 * flags yet.
1553 */
1554 onflags = IFF_ADDRCONF;
1555 if (pr->pr_flags & IFF_TEMPORARY)
1556 onflags |= IFF_TEMPORARY;
1557 if (prefix_modify_flags(pr, onflags, 0) == -1)
1558 return;
1559 }
1560 if ((pr->pr_state & (PR_ONLINK|PR_AUTO)) == 0) {
1561 /* Remove the interface */
1562 if (prefix_modify_flags(pr, 0, IFF_UP|IFF_DEPRECATED) == -1)
1563 return;
1564 (void) strncpy(lifr.lifr_name, pr->pr_name,
1565 sizeof (lifr.lifr_name));
1566 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1567
1568 if (debug & D_PREFIX) {
1569 logmsg(LOG_DEBUG, "prefix_update_k: remove name %s\n",
1570 pr->pr_name);
1571 }
1572
1573 /*
1574 * Assumes that only the PR_STATIC link-local matches
1575 * the pi_name
1576 */
1577 if (!(pr->pr_state & PR_STATIC) &&
1578 strcmp(pr->pr_name, pi->pi_name) == 0) {
1579 logmsg(LOG_ERR, "prefix_update_k(%s): "
1580 "name matches if\n", pi->pi_name);
1581 return;
1582 }
1583
1584 /* Remove logical interface based on pr_name */
1585 lifr.lifr_addr.ss_family = AF_UNSPEC;
1586 if (ioctl(pi->pi_sock, SIOCLIFREMOVEIF, (char *)&lifr) < 0 &&
1587 errno != ENXIO) {
1588 logperror_pr(pr, "prefix_update_k: SIOCLIFREMOVEIF");
1589 }
1590 pr->pr_kernel_state = 0;
1591 pr->pr_name[0] = '\0';
1592 return;
1593 }
1594 if ((pr->pr_state & PR_AUTO) && !(pr->pr_kernel_state & PR_AUTO)) {
1595 /*
1596 * Set local address and set the prefix length to 128.
1597 * Turn off IFF_NOLOCAL in case it was set.
1598 * Turn on IFF_UP.
1599 */
1600 (void) strncpy(lifr.lifr_name, pr->pr_name,
1601 sizeof (lifr.lifr_name));
1602 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1603 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1604 bzero(sin6, sizeof (struct sockaddr_in6));
1605 sin6->sin6_family = AF_INET6;
1606 sin6->sin6_addr = pr->pr_address;
1607 if (debug & D_PREFIX) {
1608 logmsg(LOG_DEBUG, "prefix_update_k(%s) set addr %s "
1609 "for PR_AUTO on\n",
1610 pr->pr_name,
1611 inet_ntop(AF_INET6, (void *)&pr->pr_address,
1612 abuf, sizeof (abuf)));
1613 }
1614 if (ioctl(pi->pi_sock, SIOCSLIFADDR, (char *)&lifr) < 0) {
1615 logperror_pr(pr, "prefix_update_k: SIOCSLIFADDR");
1616 return;
1617 }
1618 /*
1619 * If this interface was created using ipadm, store the
1620 * addrobj for the prefix in ipmgmtd daemon's aobjmap.
1621 */
1622 prefix_update_ipadm_addrobj(pr, _B_TRUE);
1623 if (pr->pr_state & PR_ONLINK) {
1624 sin6->sin6_addr = pr->pr_prefix;
1625 lifr.lifr_addrlen = pr->pr_prefix_len;
1626 } else {
1627 sin6->sin6_addr = pr->pr_address;
1628 lifr.lifr_addrlen = IPV6_ABITS;
1629 }
1630 if (debug & D_PREFIX) {
1631 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet "
1632 "%s/%u for PR_AUTO on\n", pr->pr_name,
1633 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
1634 abuf, sizeof (abuf)), lifr.lifr_addrlen);
1635 }
1636 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) {
1637 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET");
1638 return;
1639 }
1640 /*
1641 * For ptp interfaces, create a destination based on
1642 * prefix and prefix len together with the remote token
1643 * extracted from the remote pt-pt address. This is used by
1644 * ip to choose a proper source for outgoing packets.
1645 */
1646 if (pi->pi_flags & IFF_POINTOPOINT) {
1647 int i;
1648
1649 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1650 bzero(sin6, sizeof (struct sockaddr_in6));
1651 sin6->sin6_family = AF_INET6;
1652 sin6->sin6_addr = pr->pr_prefix;
1653 for (i = 0; i < 16; i++) {
1654 sin6->sin6_addr.s6_addr[i] |=
1655 pi->pi_dst_token.s6_addr[i];
1656 }
1657 if (debug & D_PREFIX) {
1658 logmsg(LOG_DEBUG, "prefix_update_k(%s) "
1659 "set dstaddr %s for PR_AUTO on\n",
1660 pr->pr_name, inet_ntop(AF_INET6,
1661 (void *)&sin6->sin6_addr,
1662 abuf, sizeof (abuf)));
1663 }
1664 if (ioctl(pi->pi_sock, SIOCSLIFDSTADDR,
1665 (char *)&lifr) < 0) {
1666 logperror_pr(pr,
1667 "prefix_update_k: SIOCSLIFDSTADDR");
1668 return;
1669 }
1670 }
1671 if (prefix_modify_flags(pr, IFF_UP, IFF_NOLOCAL) == -1)
1672 return;
1673 pr->pr_kernel_state |= PR_AUTO;
1674 if (pr->pr_state & PR_ONLINK)
1675 pr->pr_kernel_state |= PR_ONLINK;
1676 else
1677 pr->pr_kernel_state &= ~PR_ONLINK;
1678 }
1679 if (!(pr->pr_state & PR_AUTO) && (pr->pr_kernel_state & PR_AUTO)) {
1680 /* Turn on IFF_NOLOCAL and set the local address to all zero */
1681 if (prefix_modify_flags(pr, IFF_NOLOCAL, 0) == -1)
1682 return;
1683 (void) strncpy(lifr.lifr_name, pr->pr_name,
1684 sizeof (lifr.lifr_name));
1685 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1686 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1687 bzero(sin6, sizeof (struct sockaddr_in6));
1688 sin6->sin6_family = AF_INET6;
1689 if (debug & D_PREFIX) {
1690 logmsg(LOG_DEBUG, "prefix_update_k(%s) set addr %s "
1691 "for PR_AUTO off\n", pr->pr_name,
1692 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
1693 abuf, sizeof (abuf)));
1694 }
1695 if (ioctl(pi->pi_sock, SIOCSLIFADDR, (char *)&lifr) < 0) {
1696 logperror_pr(pr, "prefix_update_k: SIOCSLIFADDR");
1697 return;
1698 }
1699 pr->pr_kernel_state &= ~PR_AUTO;
1700 }
1701 if ((pr->pr_state & PR_DEPRECATED) &&
1702 !(pr->pr_kernel_state & PR_DEPRECATED) &&
1703 (pr->pr_kernel_state & PR_AUTO)) {
1704 /* Only applies if PR_AUTO */
1705 if (prefix_modify_flags(pr, IFF_DEPRECATED, 0) == -1)
1706 return;
1707 pr->pr_kernel_state |= PR_DEPRECATED;
1708 }
1709 if (!(pr->pr_state & PR_DEPRECATED) &&
1710 (pr->pr_kernel_state & PR_DEPRECATED)) {
1711 if (prefix_modify_flags(pr, 0, IFF_DEPRECATED) == -1)
1712 return;
1713 pr->pr_kernel_state &= ~PR_DEPRECATED;
1714 }
1715 if ((pr->pr_state & PR_ONLINK) && !(pr->pr_kernel_state & PR_ONLINK)) {
1716 /* Set the subnet and set IFF_UP */
1717 (void) strncpy(lifr.lifr_name, pr->pr_name,
1718 sizeof (lifr.lifr_name));
1719 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1720 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1721 bzero(sin6, sizeof (struct sockaddr_in6));
1722 sin6->sin6_family = AF_INET6;
1723 sin6->sin6_addr = pr->pr_prefix;
1724 lifr.lifr_addrlen = pr->pr_prefix_len;
1725 if (debug & D_PREFIX) {
1726 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet "
1727 "%s/%d for PR_ONLINK on\n", pr->pr_name,
1728 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
1729 abuf, sizeof (abuf)), lifr.lifr_addrlen);
1730 }
1731 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) {
1732 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET");
1733 return;
1734 }
1735 /*
1736 * If we've previously marked the interface "up" while
1737 * processing the PR_AUTO flag -- via incoming_prefix_addrconf
1738 * -- then there's no need to set it "up" again. We're done;
1739 * just set PR_ONLINK to indicate that we've set the subnet.
1740 */
1741 if (!(pr->pr_state & PR_AUTO) &&
1742 prefix_modify_flags(pr, IFF_UP | IFF_NOLOCAL, 0) == -1)
1743 return;
1744 pr->pr_kernel_state |= PR_ONLINK;
1745 }
1746 if (!(pr->pr_state & PR_ONLINK) && (pr->pr_kernel_state & PR_ONLINK)) {
1747 /* Set the prefixlen to 128 */
1748 (void) strncpy(lifr.lifr_name, pr->pr_name,
1749 sizeof (lifr.lifr_name));
1750 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0';
1751 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1752 bzero(sin6, sizeof (struct sockaddr_in6));
1753 sin6->sin6_family = AF_INET6;
1754 sin6->sin6_addr = pr->pr_address;
1755 lifr.lifr_addrlen = IPV6_ABITS;
1756 if (debug & D_PREFIX) {
1757 logmsg(LOG_DEBUG, "prefix_update_k(%s) set subnet "
1758 "%s/%d for PR_ONLINK off\n", pr->pr_name,
1759 inet_ntop(AF_INET6, (void *)&sin6->sin6_addr,
1760 abuf, sizeof (abuf)), lifr.lifr_addrlen);
1761 }
1762 if (ioctl(pi->pi_sock, SIOCSLIFSUBNET, (char *)&lifr) < 0) {
1763 logperror_pr(pr, "prefix_update_k: SIOCSLIFSUBNET");
1764 return;
1765 }
1766 pr->pr_kernel_state &= ~PR_ONLINK;
1767 }
1768 }
1769
1770 /*
1771 * Called with the number of millseconds elapsed since the last call.
1772 * Determines if any timeout event has occurred and
1773 * returns the number of milliseconds until the next timeout event.
1774 * Returns TIMER_INFINITY for "never".
1775 */
1776 uint_t
prefix_timer(struct prefix * pr,uint_t elapsed)1777 prefix_timer(struct prefix *pr, uint_t elapsed)
1778 {
1779 uint_t next = TIMER_INFINITY;
1780 char abuf[INET6_ADDRSTRLEN];
1781
1782 if (debug & (D_PREFIX|D_TMP)) {
1783 logmsg(LOG_DEBUG, "prefix_timer(%s, %s/%u, %d) "
1784 "valid %d pref %d onlink %d\n",
1785 pr->pr_name,
1786 inet_ntop(AF_INET6, (void *)&pr->pr_prefix,
1787 abuf, sizeof (abuf)), pr->pr_prefix_len,
1788 elapsed, pr->pr_ValidLifetime, pr->pr_PreferredLifetime,
1789 pr->pr_OnLinkLifetime);
1790 }
1791
1792 /* Exclude static prefixes */
1793 if (pr->pr_state & PR_STATIC)
1794 return (next);
1795
1796 if (pr->pr_AutonomousFlag &&
1797 (pr->pr_PreferredLifetime != PREFIX_INFINITY)) {
1798 if (pr->pr_PreferredLifetime <= elapsed) {
1799 pr->pr_PreferredLifetime = 0;
1800 } else {
1801 pr->pr_PreferredLifetime -= elapsed;
1802 if (pr->pr_PreferredLifetime < next)
1803 next = pr->pr_PreferredLifetime;
1804 }
1805 }
1806 if (pr->pr_AutonomousFlag &&
1807 (pr->pr_ValidLifetime != PREFIX_INFINITY)) {
1808 if (pr->pr_ValidLifetime <= elapsed) {
1809 pr->pr_ValidLifetime = 0;
1810 } else {
1811 pr->pr_ValidLifetime -= elapsed;
1812 if (pr->pr_ValidLifetime < next)
1813 next = pr->pr_ValidLifetime;
1814 }
1815 }
1816 if (pr->pr_OnLinkFlag &&
1817 (pr->pr_OnLinkLifetime != PREFIX_INFINITY)) {
1818 if (pr->pr_OnLinkLifetime <= elapsed) {
1819 pr->pr_OnLinkLifetime = 0;
1820 } else {
1821 pr->pr_OnLinkLifetime -= elapsed;
1822 if (pr->pr_OnLinkLifetime < next)
1823 next = pr->pr_OnLinkLifetime;
1824 }
1825 }
1826 if (pr->pr_AutonomousFlag && pr->pr_ValidLifetime == 0)
1827 pr->pr_state &= ~(PR_AUTO|PR_DEPRECATED);
1828 if (pr->pr_AutonomousFlag && pr->pr_PreferredLifetime == 0 &&
1829 (pr->pr_state & PR_AUTO)) {
1830 pr->pr_state |= PR_DEPRECATED;
1831 if (debug & D_TMP)
1832 logmsg(LOG_WARNING, "prefix_timer: deprecated "
1833 "prefix(%s)\n", pr->pr_name);
1834 }
1835 if (pr->pr_OnLinkFlag && pr->pr_OnLinkLifetime == 0)
1836 pr->pr_state &= ~PR_ONLINK;
1837
1838 if (pr->pr_state != pr->pr_kernel_state) {
1839 /* Might cause prefix to be deleted! */
1840
1841 /* Log a message when an addrconf prefix goes away */
1842 if ((pr->pr_kernel_state & PR_AUTO) &&
1843 !(pr->pr_state & PR_AUTO)) {
1844 char abuf[INET6_ADDRSTRLEN];
1845
1846 logmsg(LOG_WARNING,
1847 "Address removed due to timeout %s\n",
1848 inet_ntop(AF_INET6, (void *)&pr->pr_address,
1849 abuf, sizeof (abuf)));
1850 }
1851 prefix_update_k(pr);
1852 }
1853
1854 return (next);
1855 }
1856
1857 static char *
prefix_print_state(int state,char * buf,int buflen)1858 prefix_print_state(int state, char *buf, int buflen)
1859 {
1860 char *cp;
1861 int cplen = buflen;
1862
1863 cp = buf;
1864 cp[0] = '\0';
1865
1866 if (state & PR_ONLINK) {
1867 if (strlcat(cp, "ONLINK ", cplen) >= cplen)
1868 return (buf);
1869 cp += strlen(cp);
1870 cplen = buflen - (cp - buf);
1871 }
1872 if (state & PR_AUTO) {
1873 if (strlcat(cp, "AUTO ", cplen) >= cplen)
1874 return (buf);
1875 cp += strlen(cp);
1876 cplen = buflen - (cp - buf);
1877 }
1878 if (state & PR_DEPRECATED) {
1879 if (strlcat(cp, "DEPRECATED ", cplen) >= cplen)
1880 return (buf);
1881 cp += strlen(cp);
1882 cplen = buflen - (cp - buf);
1883 }
1884 if (state & PR_STATIC) {
1885 if (strlcat(cp, "STATIC ", cplen) >= cplen)
1886 return (buf);
1887 cp += strlen(cp);
1888 cplen = buflen - (cp - buf);
1889 }
1890 return (buf);
1891 }
1892
1893 static void
prefix_print(struct prefix * pr)1894 prefix_print(struct prefix *pr)
1895 {
1896 char abuf[INET6_ADDRSTRLEN];
1897 char buf1[PREFIX_STATESTRLEN], buf2[PREFIX_STATESTRLEN];
1898
1899 logmsg(LOG_DEBUG, "Prefix name: %s prefix %s/%u state %s "
1900 "kernel_state %s\n", pr->pr_name,
1901 inet_ntop(AF_INET6, (void *)&pr->pr_prefix, abuf, sizeof (abuf)),
1902 pr->pr_prefix_len,
1903 prefix_print_state(pr->pr_state, buf2, sizeof (buf2)),
1904 prefix_print_state(pr->pr_kernel_state, buf1, sizeof (buf1)));
1905 logmsg(LOG_DEBUG, "\tAddress: %s flags %llx in_use %d\n",
1906 inet_ntop(AF_INET6, (void *)&pr->pr_address, abuf, sizeof (abuf)),
1907 pr->pr_flags, pr->pr_in_use);
1908 logmsg(LOG_DEBUG, "\tValidLifetime %u PreferredLifetime %u "
1909 "OnLinkLifetime %u\n", pr->pr_ValidLifetime,
1910 pr->pr_PreferredLifetime, pr->pr_OnLinkLifetime);
1911 logmsg(LOG_DEBUG, "\tOnLink %d Auto %d\n",
1912 pr->pr_OnLinkFlag, pr->pr_AutonomousFlag);
1913 logmsg(LOG_DEBUG, "\n");
1914 }
1915
1916 /*
1917 * Lookup advertisement prefix structure that matches the prefix and
1918 * prefix length.
1919 * Assumes that the bits after prefixlen might not be zero.
1920 */
1921 struct adv_prefix *
adv_prefix_lookup(struct phyint * pi,struct in6_addr prefix,int prefixlen)1922 adv_prefix_lookup(struct phyint *pi, struct in6_addr prefix, int prefixlen)
1923 {
1924 struct adv_prefix *adv_pr;
1925 char abuf[INET6_ADDRSTRLEN];
1926
1927 if (debug & D_PREFIX) {
1928 logmsg(LOG_DEBUG, "adv_prefix_lookup(%s, %s/%u)\n",
1929 pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix,
1930 abuf, sizeof (abuf)), prefixlen);
1931 }
1932
1933 for (adv_pr = pi->pi_adv_prefix_list; adv_pr != NULL;
1934 adv_pr = adv_pr->adv_pr_next) {
1935 if (adv_pr->adv_pr_prefix_len == prefixlen &&
1936 prefix_equal(prefix, adv_pr->adv_pr_prefix, prefixlen))
1937 return (adv_pr);
1938 }
1939 return (NULL);
1940 }
1941
1942 /*
1943 * Initialize a new advertisement prefix.
1944 */
1945 struct adv_prefix *
adv_prefix_create(struct phyint * pi,struct in6_addr prefix,int prefixlen)1946 adv_prefix_create(struct phyint *pi, struct in6_addr prefix, int prefixlen)
1947 {
1948 struct adv_prefix *adv_pr;
1949 char abuf[INET6_ADDRSTRLEN];
1950
1951 if (debug & D_PREFIX) {
1952 logmsg(LOG_DEBUG, "adv_prefix_create(%s, %s/%u)\n",
1953 pi->pi_name, inet_ntop(AF_INET6, (void *)&prefix,
1954 abuf, sizeof (abuf)), prefixlen);
1955 }
1956 adv_pr = (struct adv_prefix *)calloc(sizeof (struct adv_prefix), 1);
1957 if (adv_pr == NULL) {
1958 logmsg(LOG_ERR, "adv_prefix_create: calloc\n");
1959 return (NULL);
1960 }
1961 /*
1962 * The prefix might have non-zero bits after the prefix len bits.
1963 * Force them to be zero.
1964 */
1965 prefix_set(&adv_pr->adv_pr_prefix, prefix, prefixlen);
1966 adv_pr->adv_pr_prefix_len = prefixlen;
1967 adv_prefix_insert(pi, adv_pr);
1968 return (adv_pr);
1969 }
1970
1971 /* Insert in linked list */
1972 static void
adv_prefix_insert(struct phyint * pi,struct adv_prefix * adv_pr)1973 adv_prefix_insert(struct phyint *pi, struct adv_prefix *adv_pr)
1974 {
1975 adv_pr->adv_pr_next = pi->pi_adv_prefix_list;
1976 adv_pr->adv_pr_prev = NULL;
1977 if (pi->pi_adv_prefix_list != NULL)
1978 pi->pi_adv_prefix_list->adv_pr_prev = adv_pr;
1979 pi->pi_adv_prefix_list = adv_pr;
1980 adv_pr->adv_pr_physical = pi;
1981 }
1982
1983 /*
1984 * Delete (unlink and free) from our tables. There should be
1985 * a corresponding "struct prefix *" which will clean up the kernel
1986 * if necessary. adv_prefix is just used for sending out advertisements.
1987 */
1988 static void
adv_prefix_delete(struct adv_prefix * adv_pr)1989 adv_prefix_delete(struct adv_prefix *adv_pr)
1990 {
1991 struct phyint *pi;
1992 char abuf[INET6_ADDRSTRLEN];
1993
1994 if (debug & D_PREFIX) {
1995 logmsg(LOG_DEBUG, "adv_prefix_delete(%s, %s/%u)\n",
1996 adv_pr->adv_pr_physical->pi_name,
1997 inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix,
1998 abuf, sizeof (abuf)), adv_pr->adv_pr_prefix_len);
1999 }
2000 pi = adv_pr->adv_pr_physical;
2001
2002 if (adv_pr->adv_pr_prev == NULL) {
2003 if (pi != NULL)
2004 pi->pi_adv_prefix_list = adv_pr->adv_pr_next;
2005 } else {
2006 adv_pr->adv_pr_prev->adv_pr_next = adv_pr->adv_pr_next;
2007 }
2008 if (adv_pr->adv_pr_next != NULL)
2009 adv_pr->adv_pr_next->adv_pr_prev = adv_pr->adv_pr_prev;
2010 adv_pr->adv_pr_next = adv_pr->adv_pr_prev = NULL;
2011 free(adv_pr);
2012 }
2013
2014 /*
2015 * Called with the number of millseconds elapsed since the last call.
2016 * Determines if any timeout event has occurred and
2017 * returns the number of milliseconds until the next timeout event.
2018 * Returns TIMER_INFINITY for "never".
2019 */
2020 uint_t
adv_prefix_timer(struct adv_prefix * adv_pr,uint_t elapsed)2021 adv_prefix_timer(struct adv_prefix *adv_pr, uint_t elapsed)
2022 {
2023 int seconds_elapsed = (elapsed + 500) / 1000; /* Rounded */
2024 char abuf[INET6_ADDRSTRLEN];
2025
2026 if (debug & D_PREFIX) {
2027 logmsg(LOG_DEBUG, "adv_prefix_timer(%s, %s/%u, %d)\n",
2028 adv_pr->adv_pr_physical->pi_name,
2029 inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix,
2030 abuf, sizeof (abuf)), adv_pr->adv_pr_prefix_len,
2031 elapsed);
2032 }
2033
2034 /* Decrement Expire time left for real-time lifetimes */
2035 if (adv_pr->adv_pr_AdvValidRealTime) {
2036 if (adv_pr->adv_pr_AdvValidExpiration > seconds_elapsed)
2037 adv_pr->adv_pr_AdvValidExpiration -= seconds_elapsed;
2038 else
2039 adv_pr->adv_pr_AdvValidExpiration = 0;
2040 }
2041 if (adv_pr->adv_pr_AdvPreferredRealTime) {
2042 if (adv_pr->adv_pr_AdvPreferredExpiration > seconds_elapsed) {
2043 adv_pr->adv_pr_AdvPreferredExpiration -=
2044 seconds_elapsed;
2045 } else {
2046 adv_pr->adv_pr_AdvPreferredExpiration = 0;
2047 }
2048 }
2049 return (TIMER_INFINITY);
2050 }
2051
2052 static void
adv_prefix_print(struct adv_prefix * adv_pr)2053 adv_prefix_print(struct adv_prefix *adv_pr)
2054 {
2055 print_prefixlist(adv_pr->adv_pr_config);
2056 }
2057
2058 /* Lookup router on its link-local IPv6 address */
2059 struct router *
router_lookup(struct phyint * pi,struct in6_addr addr)2060 router_lookup(struct phyint *pi, struct in6_addr addr)
2061 {
2062 struct router *dr;
2063 char abuf[INET6_ADDRSTRLEN];
2064
2065 if (debug & D_ROUTER) {
2066 logmsg(LOG_DEBUG, "router_lookup(%s, %s)\n", pi->pi_name,
2067 inet_ntop(AF_INET6, (void *)&addr,
2068 abuf, sizeof (abuf)));
2069 }
2070
2071 for (dr = pi->pi_router_list; dr != NULL; dr = dr->dr_next) {
2072 if (bcmp((char *)&addr, (char *)&dr->dr_address,
2073 sizeof (addr)) == 0)
2074 return (dr);
2075 }
2076 return (NULL);
2077 }
2078
2079 /*
2080 * Create a default router entry.
2081 * The lifetime parameter is in seconds.
2082 */
2083 struct router *
router_create(struct phyint * pi,struct in6_addr addr,uint_t lifetime)2084 router_create(struct phyint *pi, struct in6_addr addr, uint_t lifetime)
2085 {
2086 struct router *dr;
2087 char abuf[INET6_ADDRSTRLEN];
2088
2089 if (debug & D_ROUTER) {
2090 logmsg(LOG_DEBUG, "router_create(%s, %s, %u)\n", pi->pi_name,
2091 inet_ntop(AF_INET6, (void *)&addr,
2092 abuf, sizeof (abuf)), lifetime);
2093 }
2094
2095 dr = (struct router *)calloc(sizeof (struct router), 1);
2096 if (dr == NULL) {
2097 logmsg(LOG_ERR, "router_create: out of memory\n");
2098 return (NULL);
2099 }
2100 dr->dr_address = addr;
2101 dr->dr_lifetime = lifetime;
2102 router_insert(pi, dr);
2103 if (dr->dr_lifetime != 0)
2104 router_add_k(dr);
2105 return (dr);
2106 }
2107
2108 /* Insert in linked list */
2109 static void
router_insert(struct phyint * pi,struct router * dr)2110 router_insert(struct phyint *pi, struct router *dr)
2111 {
2112 dr->dr_next = pi->pi_router_list;
2113 dr->dr_prev = NULL;
2114 if (pi->pi_router_list != NULL)
2115 pi->pi_router_list->dr_prev = dr;
2116 pi->pi_router_list = dr;
2117 dr->dr_physical = pi;
2118 }
2119
2120 /*
2121 * Delete (unlink and free).
2122 * Handles delete of things that have not yet been inserted in the list
2123 * i.e. dr_physical is NULL.
2124 */
2125 static void
router_delete(struct router * dr)2126 router_delete(struct router *dr)
2127 {
2128 struct phyint *pi;
2129 char abuf[INET6_ADDRSTRLEN];
2130
2131 if (debug & D_ROUTER) {
2132 logmsg(LOG_DEBUG, "router_delete(%s, %s, %u)\n",
2133 dr->dr_physical->pi_name,
2134 inet_ntop(AF_INET6, (void *)&dr->dr_address,
2135 abuf, sizeof (abuf)), dr->dr_lifetime);
2136 }
2137 pi = dr->dr_physical;
2138 if (dr->dr_inkernel && (pi->pi_kernel_state & PI_PRESENT))
2139 router_delete_k(dr);
2140
2141 if (dr->dr_prev == NULL) {
2142 if (pi != NULL)
2143 pi->pi_router_list = dr->dr_next;
2144 } else {
2145 dr->dr_prev->dr_next = dr->dr_next;
2146 }
2147 if (dr->dr_next != NULL)
2148 dr->dr_next->dr_prev = dr->dr_prev;
2149 dr->dr_next = dr->dr_prev = NULL;
2150 free(dr);
2151 }
2152
2153 /*
2154 * Update the kernel to match dr_lifetime
2155 */
2156 void
router_update_k(struct router * dr)2157 router_update_k(struct router *dr)
2158 {
2159 char abuf[INET6_ADDRSTRLEN];
2160
2161 if (debug & D_ROUTER) {
2162 logmsg(LOG_DEBUG, "router_update_k(%s, %s, %u)\n",
2163 dr->dr_physical->pi_name,
2164 inet_ntop(AF_INET6, (void *)&dr->dr_address,
2165 abuf, sizeof (abuf)), dr->dr_lifetime);
2166 }
2167
2168 if (dr->dr_lifetime == 0 && dr->dr_inkernel) {
2169 /* Log a message when last router goes away */
2170 if (dr->dr_physical->pi_num_k_routers == 1) {
2171 logmsg(LOG_WARNING,
2172 "Last default router (%s) removed on %s\n",
2173 inet_ntop(AF_INET6, (void *)&dr->dr_address,
2174 abuf, sizeof (abuf)), dr->dr_physical->pi_name);
2175 }
2176 router_delete(dr);
2177 } else if (dr->dr_lifetime != 0 && !dr->dr_inkernel)
2178 router_add_k(dr);
2179 }
2180
2181 /*
2182 * Called with the number of millseconds elapsed since the last call.
2183 * Determines if any timeout event has occurred and
2184 * returns the number of milliseconds until the next timeout event.
2185 * Returns TIMER_INFINITY for "never".
2186 */
2187 uint_t
router_timer(struct router * dr,uint_t elapsed)2188 router_timer(struct router *dr, uint_t elapsed)
2189 {
2190 uint_t next = TIMER_INFINITY;
2191 char abuf[INET6_ADDRSTRLEN];
2192
2193 if (debug & D_ROUTER) {
2194 logmsg(LOG_DEBUG, "router_timer(%s, %s, %u, %d)\n",
2195 dr->dr_physical->pi_name,
2196 inet_ntop(AF_INET6, (void *)&dr->dr_address,
2197 abuf, sizeof (abuf)), dr->dr_lifetime, elapsed);
2198 }
2199 if (dr->dr_lifetime <= elapsed) {
2200 dr->dr_lifetime = 0;
2201 } else {
2202 dr->dr_lifetime -= elapsed;
2203 if (dr->dr_lifetime < next)
2204 next = dr->dr_lifetime;
2205 }
2206
2207 if (dr->dr_lifetime == 0) {
2208 /* Log a message when last router goes away */
2209 if (dr->dr_physical->pi_num_k_routers == 1) {
2210 logmsg(LOG_WARNING,
2211 "Last default router (%s) timed out on %s\n",
2212 inet_ntop(AF_INET6, (void *)&dr->dr_address,
2213 abuf, sizeof (abuf)), dr->dr_physical->pi_name);
2214 }
2215 router_delete(dr);
2216 }
2217 return (next);
2218 }
2219
2220 /*
2221 * Add a default route to the kernel (unless the lifetime is zero)
2222 * Handles onlink default routes.
2223 */
2224 static void
router_add_k(struct router * dr)2225 router_add_k(struct router *dr)
2226 {
2227 struct phyint *pi = dr->dr_physical;
2228 char abuf[INET6_ADDRSTRLEN];
2229 int rlen;
2230
2231 if (debug & D_ROUTER) {
2232 logmsg(LOG_DEBUG, "router_add_k(%s, %s, %u)\n",
2233 dr->dr_physical->pi_name,
2234 inet_ntop(AF_INET6, (void *)&dr->dr_address,
2235 abuf, sizeof (abuf)), dr->dr_lifetime);
2236 }
2237
2238 rta_gateway->sin6_addr = dr->dr_address;
2239
2240 rta_ifp->sdl_index = if_nametoindex(pi->pi_name);
2241 if (rta_ifp->sdl_index == 0) {
2242 logperror_pi(pi, "router_add_k: if_nametoindex");
2243 return;
2244 }
2245
2246 rt_msg->rtm_flags = RTF_GATEWAY;
2247 rt_msg->rtm_type = RTM_ADD;
2248 rt_msg->rtm_seq = ++rtmseq;
2249 rlen = write(rtsock, rt_msg, rt_msg->rtm_msglen);
2250 if (rlen < 0) {
2251 if (errno != EEXIST) {
2252 logperror_pi(pi, "router_add_k: RTM_ADD");
2253 return;
2254 }
2255 } else if (rlen < rt_msg->rtm_msglen) {
2256 logmsg(LOG_ERR, "router_add_k: write to routing socket got "
2257 "only %d for rlen (interface %s)\n", rlen, pi->pi_name);
2258 return;
2259 }
2260 dr->dr_inkernel = _B_TRUE;
2261 pi->pi_num_k_routers++;
2262 }
2263
2264 /*
2265 * Delete a route from the kernel.
2266 * Handles onlink default routes.
2267 */
2268 static void
router_delete_k(struct router * dr)2269 router_delete_k(struct router *dr)
2270 {
2271 struct phyint *pi = dr->dr_physical;
2272 char abuf[INET6_ADDRSTRLEN];
2273 int rlen;
2274
2275 if (debug & D_ROUTER) {
2276 logmsg(LOG_DEBUG, "router_delete_k(%s, %s, %u)\n",
2277 dr->dr_physical->pi_name,
2278 inet_ntop(AF_INET6, (void *)&dr->dr_address,
2279 abuf, sizeof (abuf)), dr->dr_lifetime);
2280 }
2281
2282 rta_gateway->sin6_addr = dr->dr_address;
2283
2284 rta_ifp->sdl_index = if_nametoindex(pi->pi_name);
2285 if (rta_ifp->sdl_index == 0) {
2286 logperror_pi(pi, "router_delete_k: if_nametoindex");
2287 return;
2288 }
2289
2290 rt_msg->rtm_flags = RTF_GATEWAY;
2291 rt_msg->rtm_type = RTM_DELETE;
2292 rt_msg->rtm_seq = ++rtmseq;
2293 rlen = write(rtsock, rt_msg, rt_msg->rtm_msglen);
2294 if (rlen < 0) {
2295 if (errno != ESRCH) {
2296 logperror_pi(pi, "router_delete_k: RTM_DELETE");
2297 }
2298 } else if (rlen < rt_msg->rtm_msglen) {
2299 logmsg(LOG_ERR, "router_delete_k: write to routing socket got "
2300 "only %d for rlen (interface %s)\n", rlen, pi->pi_name);
2301 }
2302 dr->dr_inkernel = _B_FALSE;
2303 pi->pi_num_k_routers--;
2304 }
2305
2306 static void
router_print(struct router * dr)2307 router_print(struct router *dr)
2308 {
2309 char abuf[INET6_ADDRSTRLEN];
2310
2311 logmsg(LOG_DEBUG, "Router %s on %s inkernel %d lifetime %u\n",
2312 inet_ntop(AF_INET6, (void *)&dr->dr_address, abuf, sizeof (abuf)),
2313 dr->dr_physical->pi_name, dr->dr_inkernel, dr->dr_lifetime);
2314 }
2315
2316 void
phyint_print_all(void)2317 phyint_print_all(void)
2318 {
2319 struct phyint *pi;
2320
2321 for (pi = phyints; pi != NULL; pi = pi->pi_next) {
2322 phyint_print(pi);
2323 }
2324 }
2325
2326 void
phyint_cleanup(struct phyint * pi)2327 phyint_cleanup(struct phyint *pi)
2328 {
2329 pi->pi_state = 0;
2330 pi->pi_kernel_state = 0;
2331
2332 if (pi->pi_AdvSendAdvertisements) {
2333 check_to_advertise(pi, ADV_OFF);
2334 } else {
2335 check_to_solicit(pi, SOLICIT_OFF);
2336 }
2337
2338 while (pi->pi_router_list)
2339 router_delete(pi->pi_router_list);
2340 (void) poll_remove(pi->pi_sock);
2341 (void) close(pi->pi_sock);
2342 pi->pi_sock = -1;
2343 pi->pi_stateless = pi->pi_StatelessAddrConf;
2344 pi->pi_stateful = pi->pi_StatefulAddrConf;
2345 pi->pi_ipadm_aobjname[0] = '\0';
2346 pi->pi_ifaddr = in6addr_any;
2347 }
2348
2349 /*
2350 * Sets/removes the ipadm address object name for the given prefix.
2351 */
2352 void
prefix_update_ipadm_addrobj(struct prefix * pr,boolean_t add)2353 prefix_update_ipadm_addrobj(struct prefix *pr, boolean_t add)
2354 {
2355 struct phyint *pi = pr->pr_physical;
2356 int lnum = 0;
2357 char *cp;
2358 ipadm_handle_t iph;
2359 ipadm_status_t status;
2360
2361 /*
2362 * If ipadm was used to autoconfigure this interface,
2363 * pi_ipadm_aobjname will contain the address object name
2364 * that is used to identify the addresses. Use the same
2365 * address object name for this prefix.
2366 */
2367 if (pi->pi_ipadm_aobjname[0] == '\0' ||
2368 pr->pr_name[0] == '\0' || IN6_IS_ADDR_LINKLOCAL(&pr->pr_address) ||
2369 (!(pr->pr_flags & IFF_ADDRCONF) &&
2370 !(pr->pr_flags & IFF_DHCPRUNNING))) {
2371 return;
2372 }
2373 if ((status = ipadm_open(&iph, 0)) != IPADM_SUCCESS) {
2374 logmsg(LOG_ERR, "Could not open handle to libipadm: %s\n",
2375 ipadm_status2str(status));
2376 return;
2377 }
2378 cp = strrchr(pr->pr_name, ':');
2379 if (cp != NULL)
2380 lnum = atoi(++cp);
2381 if (add) {
2382 status = ipadm_add_aobjname(iph, pi->pi_name, AF_INET6,
2383 pi->pi_ipadm_aobjname, IPADM_ADDR_IPV6_ADDRCONF, lnum);
2384 } else {
2385 status = ipadm_delete_aobjname(iph, pi->pi_name, AF_INET6,
2386 pi->pi_ipadm_aobjname, IPADM_ADDR_IPV6_ADDRCONF, lnum);
2387 }
2388 /* Ignore the error if the ipmgmtd daemon is not running */
2389 if (status != IPADM_SUCCESS && status != IPADM_IPC_ERROR) {
2390 logmsg(LOG_ERR, "ipadm error in %s '%s' : %s\n",
2391 (add ? "adding" : "deleting"), pi->pi_ipadm_aobjname,
2392 ipadm_status2str(status));
2393 }
2394 ipadm_close(iph);
2395 }
2396