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