1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 *
5 * Copyright (c) 1983, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgment:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $FreeBSD: src/sbin/routed/if.c,v 1.8 2000/08/11 08:24:38 sheldonh Exp $
37 */
38
39 #include "defs.h"
40 #include "pathnames.h"
41 #include <sys/sockio.h>
42 #include <inet/ip.h>
43 #include <kstat.h>
44 #include <stropts.h>
45 #include <fcntl.h>
46 #include <stddef.h>
47 #include <assert.h>
48
49 /* linked list of all interfaces */
50 struct interface *ifnet;
51
52 /*
53 * Acceptable sizes (in number of interfaces) for the interface hash
54 * tables. These must all be prime. The interface hash tables all
55 * start with a size of hash_table_sizes[0], and increase as needed.
56 */
57 size_t hash_table_sizes[] = { 67, 131, 257, 521, 1031, 2053, 4099, 0 };
58
59 struct htbl {
60 void **htbl_ptrs;
61 uint_t (*htbl_hash)(const void *, size_t);
62 size_t htbl_link_off; /* offset of the linkage structure */
63 size_t htbl_key_off; /* offset of the key value (rehash) */
64 size_t htbl_size; /* size of the hash */
65 uint_t htbl_size_index;
66 uint_t htbl_ifcount; /* count of entries */
67 boolean_t htbl_grow; /* growth allowed */
68 };
69
70 /* Get first element -- for iteration */
71 #define HFIRST(htbl, arg) \
72 ((htbl)->htbl_ptrs[(htbl)->htbl_hash((arg), 0) % (htbl)->htbl_size])
73
74 /* Add an element to a hash */
75 #define HADD(htbl, strp) \
76 hash_link((htbl), (htbl)->htbl_hash((strp), (htbl)->htbl_key_off), \
77 (strp))
78
79 uint_t tot_interfaces; /* # of remote and local interfaces */
80 uint_t rip_interfaces; /* # of interfaces doing RIP */
81 uint_t ripout_interfaces; /* # of interfaces advertising RIP */
82 uint_t fwd_interfaces; /* # of interfaces ip_forwarding=1 */
83 static boolean_t foundloopback; /* valid flag for loopaddr */
84 in_addr_t loopaddr; /* our address on loopback */
85 static struct rt_spare loop_rts;
86
87 struct timeval ifscan_timer;
88 static struct timeval last_ifscan;
89 #define IF_RESCAN_DELAY() \
90 (last_ifscan.tv_sec == now.tv_sec && \
91 last_ifscan.tv_usec == now.tv_usec && \
92 timercmp(&ifscan_timer, &now, > /* */))
93
94 boolean_t have_ripv1_out; /* have a RIPv1 interface */
95 static boolean_t have_ripv1_in;
96
97 static void if_bad(struct interface *, boolean_t);
98 static boolean_t addrouteforif(struct interface *);
99 static int get_if_kstats(struct interface *, struct phyi_data *);
100 static uint_t ahash(const void *, uint_t);
101 static uint_t ihash(const void *, uint_t);
102 static uint_t nhash(const void *, uint_t);
103 static void htbl_grow(struct htbl *);
104
105 /*
106 * Table of all interfaces, hashed by interface address. For remote
107 * interfaces, the gateway address is used.
108 */
109 static struct htbl ahash_tbl = {
110 NULL, ahash, offsetof(struct interface, int_ahash),
111 offsetof(struct interface, int_addr),
112 0, 0, 0, _B_TRUE };
113 /*
114 * Table of broadcast capable interfaces, hashed by interface broadcast
115 * address.
116 */
117 static struct htbl bhash_tbl = {
118 NULL, ahash, offsetof(struct interface, int_bhash),
119 offsetof(struct interface, int_brdaddr),
120 0, 0, 0, _B_TRUE };
121 /*
122 * Table of physical_interface structures (lists of interfaces by ifIndex),
123 * hashed by interface index.
124 */
125 static struct htbl ihash_tbl = {
126 NULL, ihash, offsetof(struct physical_interface, phyi_link),
127 offsetof(struct physical_interface, phyi_index),
128 0, 0, 0, _B_TRUE };
129 /*
130 * Table of all interfaces, hashed by interface name.
131 */
132 static struct htbl nhash_tbl = {
133 NULL, nhash, offsetof(struct interface, int_nhash),
134 offsetof(struct interface, int_name),
135 0, 0, 0, _B_TRUE };
136
137 static struct physical_interface dummy_phyi;
138 struct interface dummy_ifp;
139
140 /* Hash based on an IP address. */
141 static uint_t
ahash(const void * arg,size_t voffs)142 ahash(const void *arg, size_t voffs)
143 {
144 /* LINTED */
145 return ((uint_t)*(const in_addr_t *)((const char *)arg + voffs));
146 }
147
148 static uint_t
ihash(const void * arg,size_t voffs)149 ihash(const void *arg, size_t voffs)
150 {
151 /* LINTED */
152 return ((uint_t)*(const uint32_t *)((const char *)arg + voffs));
153 }
154
155 static uint_t
nhash(const void * arg,size_t voffs)156 nhash(const void *arg, size_t voffs)
157 {
158 const char *cp = (const char *)arg + voffs;
159 uint_t i;
160
161 for (i = 0; *cp != '\0'; cp++) {
162 i = ((i<<1) & 0x7fffffff) | ((i>>30) & 0x00000003);
163 i ^= *cp;
164 }
165 return (i);
166 }
167
168 /*
169 * Add an element to the head of the list.
170 */
171 static void
link_in(void ** head,void * strp,size_t loffs)172 link_in(void **head, void *strp, size_t loffs)
173 {
174 struct hlinkage *hlp;
175
176 /* LINTED: alignment known to be good. */
177 hlp = (struct hlinkage *)((char *)strp + loffs);
178 hlp->hl_prev = head;
179 if ((hlp->hl_next = *head) != NULL) {
180 /* LINTED */
181 ((struct hlinkage *)((char *)*head + loffs))->hl_prev =
182 &hlp->hl_next;
183 }
184 *head = strp;
185 }
186
187 /* Remove from a list */
188 static void
link_out(void * strp,size_t loffs)189 link_out(void *strp, size_t loffs)
190 {
191 struct hlinkage *hlp;
192
193 /* LINTED: alignment known to be good. */
194 hlp = (struct hlinkage *)((char *)strp + loffs);
195 if ((*hlp->hl_prev = hlp->hl_next) != NULL) {
196 /* LINTED */
197 ((struct hlinkage *)((char *)hlp->hl_next + loffs))->hl_prev =
198 hlp->hl_prev;
199 }
200 }
201
202 /* Add to a hash */
203 static void
hash_link(struct htbl * htbl,uint_t hval,void * strp)204 hash_link(struct htbl *htbl, uint_t hval, void *strp)
205 {
206 void **hep;
207
208 if (htbl->htbl_grow && htbl->htbl_ifcount >= htbl->htbl_size * 5)
209 htbl_grow(htbl);
210
211 hep = &htbl->htbl_ptrs[hval % htbl->htbl_size];
212 link_in(hep, strp, htbl->htbl_link_off);
213 htbl->htbl_ifcount++;
214 }
215
216 /* Remove from a hash */
217 static void
hash_unlink(struct htbl * htbl,void * strp)218 hash_unlink(struct htbl *htbl, void *strp)
219 {
220 link_out(strp, htbl->htbl_link_off);
221 htbl->htbl_ifcount--;
222 }
223
224 static void
dummy_ifp_init(void)225 dummy_ifp_init(void)
226 {
227 dummy_phyi.phyi_interface = &dummy_ifp;
228 dummy_ifp.int_phys = &dummy_phyi;
229 (void) strcpy(dummy_phyi.phyi_name, "wildcard");
230 (void) strcpy(dummy_ifp.int_name, "wildcard");
231 dummy_ifp.int_dstaddr = dummy_ifp.int_addr = INADDR_NONE;
232 dummy_ifp.int_mask = IP_HOST_MASK;
233 dummy_ifp.int_metric = HOPCNT_INFINITY;
234 dummy_ifp.int_state = (IS_BROKE|IS_PASSIVE|IS_NO_RIP|IS_NO_RDISC);
235 dummy_ifp.int_std_mask = std_mask(dummy_ifp.int_addr);
236 dummy_ifp.int_std_net = dummy_ifp.int_net & dummy_ifp.int_std_mask;
237 dummy_ifp.int_std_addr = htonl(dummy_ifp.int_std_net);
238 }
239
240 /* allocate the interface hash tables */
241 void
iftbl_alloc(void)242 iftbl_alloc(void)
243 {
244 size_t initial_size = hash_table_sizes[0];
245
246 errno = 0;
247 ahash_tbl.htbl_ptrs = calloc(initial_size, sizeof (void *));
248 bhash_tbl.htbl_ptrs = calloc(initial_size, sizeof (void *));
249 ihash_tbl.htbl_ptrs = calloc(initial_size, sizeof (void *));
250 nhash_tbl.htbl_ptrs = calloc(initial_size, sizeof (void *));
251
252 if (errno != 0)
253 BADERR(_B_FALSE, "Unable to allocate interface tables");
254
255 ahash_tbl.htbl_size = initial_size;
256 bhash_tbl.htbl_size = initial_size;
257 ihash_tbl.htbl_size = initial_size;
258 nhash_tbl.htbl_size = initial_size;
259
260 dummy_ifp_init();
261 }
262
263
264 static void
htbl_grow(struct htbl * htbl)265 htbl_grow(struct htbl *htbl)
266 {
267 void *strp;
268 void **new_ptrs, **saved_old_ptrs, **old_ptrs;
269 size_t new_size, old_size;
270 static uint_t failed_count;
271
272 if ((new_size = hash_table_sizes[htbl->htbl_size_index + 1]) == 0)
273 return;
274
275 if ((new_ptrs = calloc(new_size, sizeof (void *))) == NULL) {
276 /*
277 * This is not fatal since we already have a
278 * functional, yet crowded, interface table.
279 */
280 if (++failed_count % 100 == 1)
281 msglog("%sunable to grow interface hash table: %s",
282 failed_count > 1 ? "Still " : "",
283 rip_strerror(errno));
284 return;
285 }
286
287 failed_count = 0;
288
289 saved_old_ptrs = old_ptrs = htbl->htbl_ptrs;
290 old_size = htbl->htbl_size;
291 htbl->htbl_ptrs = new_ptrs;
292 htbl->htbl_size = new_size;
293 htbl->htbl_size_index++;
294 htbl->htbl_ifcount = 0;
295
296 /*
297 * Go through the list of structures, and re-link each into
298 * this new table.
299 */
300 htbl->htbl_grow = _B_FALSE;
301 while (old_size-- > 0) {
302 strp = *old_ptrs++;
303 HADD(htbl, strp);
304 }
305
306 htbl->htbl_grow = _B_TRUE;
307 free(saved_old_ptrs);
308 }
309
310 /* Link a new interface into the lists and hash tables. */
311 void
if_link(struct interface * ifp,uint32_t ifindex)312 if_link(struct interface *ifp, uint32_t ifindex)
313 {
314 struct physical_interface *phyi;
315
316 link_in((void **)&ifnet, ifp, offsetof(struct interface, int_link));
317
318 HADD(&ahash_tbl, ifp);
319 HADD(&nhash_tbl, ifp);
320
321 if (ifp->int_if_flags & IFF_BROADCAST)
322 HADD(&bhash_tbl, ifp);
323
324 if (ifindex != 0) {
325 for (phyi = HFIRST(&ihash_tbl, &ifindex);
326 phyi != NULL; phyi = phyi->phyi_link.hl_next) {
327 if (phyi->phyi_index == ifindex)
328 break;
329 }
330 if (phyi == NULL) {
331 size_t size;
332
333 phyi = rtmalloc(sizeof (*phyi), "physical_interface");
334 (void) memset(phyi, 0, sizeof (*phyi));
335 phyi->phyi_index = ifindex;
336 /* LINTED */
337 assert(IF_NAME_LEN >= IF_NAMESIZE);
338
339 size = strcspn(ifp->int_name, ":");
340 (void) strncpy(phyi->phyi_name, ifp->int_name,
341 size);
342 phyi->phyi_name[size] = '\0';
343 HADD(&ihash_tbl, phyi);
344 }
345 link_in((void **)&phyi->phyi_interface, ifp,
346 offsetof(struct interface, int_ilist));
347 ifp->int_phys = phyi;
348 }
349 }
350
351 /* Find the interface with an address */
352 struct interface *
ifwithaddr(in_addr_t addr,boolean_t bcast,boolean_t remote)353 ifwithaddr(in_addr_t addr,
354 boolean_t bcast, /* notice IFF_BROADCAST address */
355 boolean_t remote) /* include IS_REMOTE interfaces */
356 {
357 struct interface *ifp, *possible = NULL;
358 uint32_t remote_state;
359
360 remote_state = (!remote ? IS_REMOTE : 0);
361
362 for (ifp = HFIRST(&ahash_tbl, &addr); ifp != NULL;
363 ifp = ifp->int_ahash.hl_next) {
364 if (ifp->int_addr != addr)
365 continue;
366 if (ifp->int_state & remote_state)
367 continue;
368 if (!(ifp->int_state & (IS_BROKE | IS_PASSIVE)))
369 return (ifp);
370 possible = ifp;
371 }
372
373 if (possible != NULL || !bcast)
374 return (possible);
375
376 for (ifp = HFIRST(&bhash_tbl, &addr); ifp != NULL;
377 ifp = ifp->int_bhash.hl_next) {
378 if (ifp->int_brdaddr != addr)
379 continue;
380 if (ifp->int_state & remote_state)
381 continue;
382 if (!(ifp->int_state & (IS_BROKE | IS_PASSIVE)))
383 return (ifp);
384 possible = ifp;
385 }
386
387 return (possible);
388 }
389
390
391 /* find the interface with the specified name ("hme0" for example) */
392 struct interface *
ifwithname(const char * name)393 ifwithname(const char *name)
394 {
395 struct interface *ifp;
396
397 for (;;) {
398 for (ifp = HFIRST(&nhash_tbl, name); ifp != NULL;
399 ifp = ifp->int_nhash.hl_next) {
400 if (strcmp(ifp->int_name, name) == 0)
401 return (ifp);
402 }
403
404 /*
405 * If there is no known interface, maybe there is a
406 * new interface. So just once look for new interfaces.
407 */
408 if (IF_RESCAN_DELAY())
409 return (NULL);
410 ifscan();
411 }
412 }
413
414 /* Return physical interface with the specified name */
415 struct physical_interface *
phys_byname(const char * name)416 phys_byname(const char *name)
417 {
418 int nlen;
419 size_t i;
420 struct physical_interface *phyi;
421
422 nlen = strcspn(name, ":");
423 for (i = 0; i < ihash_tbl.htbl_size; i++) {
424 for (phyi = ihash_tbl.htbl_ptrs[i]; phyi != NULL;
425 phyi = phyi->phyi_link.hl_next) {
426 if (strncmp(phyi->phyi_name, name, nlen) == 0 &&
427 phyi->phyi_name[nlen] == '\0')
428 return (phyi);
429 }
430 }
431 return (NULL);
432 }
433
434 struct interface *
findremoteif(in_addr_t addr)435 findremoteif(in_addr_t addr)
436 {
437 struct interface *ifp;
438
439 for (ifp = HFIRST(&ahash_tbl, &addr); ifp != NULL;
440 ifp = ifp->int_ahash.hl_next) {
441 if ((ifp->int_state & IS_REMOTE) && ifp->int_addr == addr)
442 return (ifp);
443 }
444
445 return (NULL);
446 }
447
448 struct interface *
findifaddr(in_addr_t addr)449 findifaddr(in_addr_t addr)
450 {
451 struct interface *ifp;
452
453 for (ifp = HFIRST(&ahash_tbl, &addr); ifp != NULL;
454 ifp = ifp->int_ahash.hl_next) {
455 if (ifp->int_addr == addr)
456 return (ifp);
457 }
458
459 return (NULL);
460 }
461
462 /*
463 * Return the first interface with the given index.
464 */
465 struct interface *
ifwithindex(ulong_t index,boolean_t rescan_ok)466 ifwithindex(ulong_t index,
467 boolean_t rescan_ok)
468 {
469 struct physical_interface *phyi;
470
471 for (;;) {
472 for (phyi = HFIRST(&ihash_tbl, &index); phyi != NULL;
473 phyi = phyi->phyi_link.hl_next) {
474 if (phyi->phyi_index == index)
475 return (phyi->phyi_interface);
476 }
477
478 /*
479 * If there is no known interface, maybe there is a
480 * new interface. So just once look for new interfaces.
481 */
482 if (!rescan_ok || IF_RESCAN_DELAY())
483 return (NULL);
484 rescan_ok = _B_FALSE;
485 ifscan();
486 }
487 }
488
489 /*
490 * Returns true only if given ifp has the exact address else returns
491 * false and sets best if an ifp matches partially and is a better
492 * match than the previous one passed via best.
493 */
494 boolean_t
addr_on_ifp(in_addr_t addr,struct interface * ifp,struct interface ** best)495 addr_on_ifp(in_addr_t addr, struct interface *ifp,
496 struct interface **best)
497 {
498 struct interface *p_best = *best;
499
500 /*
501 * Don't use a duplicate interface since it is unusable for output.
502 */
503 if (ifp->int_state & IS_DUP)
504 return (_B_FALSE);
505
506 if (ifp->int_if_flags & IFF_POINTOPOINT) {
507 if (ifp->int_dstaddr == addr) {
508 *best = NULL;
509 return (_B_TRUE);
510 }
511 } else {
512 if (ifp->int_addr == addr) {
513 if (IS_PASSIVE_IFP(ifp))
514 trace_misc("addr_on_ifp "
515 "returning passive intf %s",
516 ifp->int_name);
517 *best = NULL;
518 return (_B_TRUE);
519 }
520
521 /* Look for the longest approximate match. */
522 if (on_net(addr, ifp->int_net, ifp->int_mask) &&
523 (p_best == NULL ||
524 ifp->int_mask > p_best->int_mask)) {
525 *best = ifp;
526 }
527 }
528 return (_B_FALSE);
529 }
530
531 /*
532 * Find an interface which should be receiving packets sent from the
533 * given address. Used as a last ditch effort for figuring out which
534 * interface a packet came in on. Also used for finding out which
535 * interface points towards the gateway of static routes learned from
536 * the kernel.
537 */
538 struct interface *
iflookup(in_addr_t addr)539 iflookup(in_addr_t addr)
540 {
541 struct interface *ifp, *maybe;
542
543 maybe = NULL;
544 for (;;) {
545 for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) {
546
547 /* Exact match found */
548 if (addr_on_ifp(addr, ifp, &maybe))
549 return (ifp);
550 }
551
552 /*
553 * If there is no known interface, maybe there is a
554 * new interface. So just once look for new interfaces.
555 */
556 if (maybe == NULL && !IF_RESCAN_DELAY())
557 ifscan();
558 else
559 break;
560 }
561
562 if (maybe != NULL && IS_PASSIVE_IFP(maybe)) {
563 trace_misc("iflookup returning passive intf %s",
564 maybe->int_name);
565 }
566 return (maybe);
567 }
568
569 /*
570 * Find the netmask that would be inferred by RIPv1 listeners
571 * on the given interface for a given network.
572 * If no interface is specified, look for the best fitting interface.
573 */
574 in_addr_t
ripv1_mask_net(in_addr_t addr,const struct interface * ifp)575 ripv1_mask_net(in_addr_t addr, /* in network byte order */
576 const struct interface *ifp) /* as seen on this interface */
577 {
578 const struct r1net *r1p;
579 in_addr_t mask = 0;
580
581 if (addr == 0) /* default always has 0 mask */
582 return (mask);
583
584 if (ifp != NULL && ifp->int_ripv1_mask != HOST_MASK) {
585 /*
586 * If the target network is that of the associated interface
587 * on which it arrived, then use the netmask of the interface.
588 */
589 if (on_net(addr, ifp->int_net, ifp->int_std_mask))
590 mask = ifp->int_ripv1_mask;
591
592 } else {
593 /*
594 * Examine all interfaces, and if it the target seems
595 * to have the same network number of an interface, use the
596 * netmask of that interface. If there is more than one
597 * such interface, prefer the interface with the longest
598 * match.
599 */
600 for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) {
601 if (on_net(addr, ifp->int_std_net, ifp->int_std_mask) &&
602 ifp->int_ripv1_mask > mask &&
603 ifp->int_ripv1_mask != HOST_MASK)
604 mask = ifp->int_ripv1_mask;
605 }
606
607 }
608
609 if (mask == 0) {
610 /*
611 * Check to see if the user has supplied an applicable
612 * netmask as a ripv1_mask option in /etc/gateways.
613 */
614 for (r1p = r1nets; r1p != NULL; r1p = r1p->r1net_next) {
615 /*
616 * If the address is is on a matching network
617 * and we haven't already found a longer match,
618 * use the matching netmask.
619 */
620 if (on_net(addr, r1p->r1net_net, r1p->r1net_match) &&
621 r1p->r1net_mask > mask)
622 mask = r1p->r1net_mask;
623 }
624
625 /* Otherwise, make the classic A/B/C guess. */
626 if (mask == 0)
627 mask = std_mask(addr);
628 }
629
630 return (mask);
631 }
632
633
634 in_addr_t
ripv1_mask_host(in_addr_t addr,const struct interface * ifp)635 ripv1_mask_host(in_addr_t addr, /* in network byte order */
636 const struct interface *ifp) /* as seen on this interface */
637 {
638 in_addr_t mask = ripv1_mask_net(addr, ifp);
639
640
641 /*
642 * If the computed netmask does not mask all of the set bits
643 * in the address, then assume it is a host address
644 */
645 if ((ntohl(addr) & ~mask) != 0)
646 mask = HOST_MASK;
647 return (mask);
648 }
649
650
651 /* See if a IP address looks reasonable as a destination */
652 boolean_t /* _B_FALSE=bad _B_TRUE=good */
check_dst(in_addr_t addr)653 check_dst(in_addr_t addr)
654 {
655 addr = ntohl(addr);
656
657 if (IN_CLASSA(addr)) {
658 if (addr == 0)
659 return (_B_TRUE); /* default */
660
661 addr >>= IN_CLASSA_NSHIFT;
662 return (addr != 0 && addr != IN_LOOPBACKNET);
663 }
664
665 /* Must not allow destination to be link local address. */
666 if (IN_LINKLOCAL(addr))
667 return (_B_FALSE);
668
669 if (IN_CLASSB(addr) || IN_CLASSC(addr))
670 return (_B_TRUE);
671
672 if (IN_CLASSD(addr))
673 return (_B_FALSE);
674
675 return (_B_TRUE);
676
677 }
678
679 /*
680 * Find an existing interface which has the given parameters, but don't
681 * return the interface with name "name" if "name" is specified.
682 */
683 struct interface *
check_dup(const char * name,in_addr_t addr,in_addr_t dstaddr,in_addr_t mask,uint64_t if_flags,boolean_t allowdups)684 check_dup(const char *name, /* Don't return this interface */
685 in_addr_t addr, /* IP address, so network byte order */
686 in_addr_t dstaddr, /* ditto */
687 in_addr_t mask, /* mask, so host byte order */
688 uint64_t if_flags, /* set IFF_POINTOPOINT to ignore local int_addr */
689 boolean_t allowdups) /* set true to include duplicates */
690 {
691 struct interface *best_ifp = NULL;
692 struct interface *ifp;
693 in_addr_t dstaddr_h = ntohl(dstaddr);
694 int best_pref = 0;
695 int pref;
696
697 for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) {
698 /* This interface, not a duplicate. */
699 if (name != NULL && strcmp(name, ifp->int_name) == 0)
700 continue;
701
702 /*
703 * Find an interface which isn't already a duplicate to
704 * avoid cyclical duplication. (i.e. qfe0:1 is a duplicate
705 * of qfe0, and qfe0 is a duplicate of qfe0:1. That would
706 * be bad)
707 */
708 if (!allowdups && (ifp->int_state & IS_DUP))
709 continue;
710
711 if (ifp->int_mask != mask)
712 continue;
713
714 if (!IS_IFF_UP(ifp->int_if_flags))
715 continue;
716
717 /*
718 * The local address can only be shared with a point-to-point
719 * link.
720 */
721 if ((ifp->int_addr == addr &&
722 ((if_flags|ifp->int_if_flags) & IFF_POINTOPOINT) == 0) ||
723 on_net(ifp->int_dstaddr, dstaddr_h, mask)) {
724 pref = 0;
725 if (!(ifp->int_state & IS_ALIAS))
726 pref++;
727 if (!IS_RIP_OUT_OFF(ifp->int_state))
728 pref += 2;
729 if (IS_IFF_ROUTING(ifp->int_if_flags))
730 pref += 4;
731 if (pref > best_pref) {
732 best_pref = pref;
733 best_ifp = ifp;
734 }
735 }
736 }
737 return (best_ifp);
738 }
739
740
741 /*
742 * See that a remote gateway is reachable.
743 * Note that the answer can change as real interfaces come and go.
744 */
745 boolean_t /* _B_FALSE=bad _B_TRUE=good */
check_remote(struct interface * ifp)746 check_remote(struct interface *ifp)
747 {
748 struct rt_entry *rt;
749
750 /* do not worry about other kinds */
751 if (!(ifp->int_state & IS_REMOTE))
752 return (_B_TRUE);
753
754 rt = rtfind(ifp->int_addr);
755 if (rt != NULL &&
756 rt->rt_ifp != NULL &&
757 on_net(ifp->int_addr, rt->rt_ifp->int_net, rt->rt_ifp->int_mask)) {
758 return (_B_TRUE);
759 }
760
761 /*
762 * the gateway cannot be reached directly from one of our
763 * interfaces
764 */
765 if (!(ifp->int_state & IS_BROKE)) {
766 msglog("unreachable gateway %s in "PATH_GATEWAYS,
767 naddr_ntoa(ifp->int_addr));
768 if_bad(ifp, _B_FALSE);
769 }
770 return (_B_FALSE);
771 }
772
773 /* Delete an interface. */
774 static void
ifdel(struct interface * ifp)775 ifdel(struct interface *ifp)
776 {
777 struct rewire_data wire;
778 boolean_t resurrected;
779 struct physical_interface *phyi;
780
781 trace_if("Del", ifp);
782
783 ifp->int_state |= IS_BROKE;
784
785 /* unlink the interface */
786 link_out(ifp, offsetof(struct interface, int_link));
787 hash_unlink(&ahash_tbl, ifp);
788 hash_unlink(&nhash_tbl, ifp);
789 if (ifp->int_if_flags & IFF_BROADCAST)
790 hash_unlink(&bhash_tbl, ifp);
791
792 /* Remove from list of interfaces with this ifIndex */
793 if ((phyi = ifp->int_phys) != NULL) {
794 link_out(ifp, offsetof(struct interface, int_ilist));
795 if (phyi->phyi_interface == NULL) {
796 hash_unlink(&ihash_tbl, phyi);
797 free(phyi);
798 }
799 }
800
801 /*
802 * If this is a lead interface, then check first for
803 * duplicates of this interface with an eye towards promoting
804 * one of them.
805 */
806 resurrected = _B_FALSE;
807 if (!(ifp->int_state & IS_DUP) &&
808 (wire.if_new = check_dup(ifp->int_name, ifp->int_addr,
809 ifp->int_dstaddr, ifp->int_mask, ifp->int_if_flags,
810 _B_TRUE)) != NULL &&
811 !IS_IFF_QUIET(wire.if_new->int_if_flags)) {
812
813 trace_act("promoting duplicate %s in place of %s",
814 wire.if_new->int_name, ifp->int_name);
815
816 /* Rewire routes with the replacement interface */
817 wire.if_old = ifp;
818 wire.metric_delta = wire.if_new->int_metric - ifp->int_metric;
819 (void) rn_walktree(rhead, walk_rewire, &wire);
820 kern_rewire_ifp(wire.if_old, wire.if_new);
821 if_rewire_rdisc(wire.if_old, wire.if_new);
822
823 /* Mark the replacement as being no longer a duplicate */
824 wire.if_new->int_state &= ~IS_DUP;
825 tot_interfaces++;
826 if (!IS_RIP_OFF(wire.if_new->int_state))
827 rip_interfaces++;
828 if (!IS_RIP_OUT_OFF(wire.if_new->int_state))
829 ripout_interfaces++;
830 if (IS_IFF_ROUTING(wire.if_new->int_if_flags))
831 fwd_interfaces++;
832
833 set_rdisc_mg(wire.if_new, 1);
834 rip_mcast_on(wire.if_new);
835
836 /* We came out ok; no need to clobber routes over this. */
837 resurrected = _B_TRUE;
838 }
839
840 rip_mcast_off(ifp);
841 if (rip_sock_interface == ifp)
842 rip_sock_interface = NULL;
843
844 set_rdisc_mg(ifp, 0);
845
846 /*
847 * Note that duplicates are not counted in the total number of
848 * interfaces.
849 */
850 if (!(ifp->int_state & IS_DUP) && !IS_IFF_QUIET(ifp->int_if_flags)) {
851 tot_interfaces--;
852 if (!IS_RIP_OFF(ifp->int_state))
853 rip_interfaces--;
854 if (!IS_RIP_OUT_OFF(ifp->int_state))
855 ripout_interfaces--;
856 if (IS_IFF_ROUTING(ifp->int_if_flags))
857 fwd_interfaces--;
858 }
859
860 if (!resurrected) {
861 /*
862 * Zap all routes associated with this interface.
863 * Assume routes just using gateways beyond this interface
864 * will timeout naturally, and have probably already died.
865 */
866 (void) rn_walktree(rhead, walk_bad, ifp);
867 kern_flush_ifp(ifp);
868
869 if_bad_rdisc(ifp);
870 }
871
872 free(ifp);
873 }
874
875
876 /* Mark an interface ill. */
877 void
if_sick(struct interface * ifp,boolean_t recurse)878 if_sick(struct interface *ifp, boolean_t recurse)
879 {
880 struct interface *ifp1;
881
882 if (0 == (ifp->int_state & (IS_SICK | IS_BROKE))) {
883 ifp->int_state |= IS_SICK;
884 ifp->int_act_time = NEVER;
885 trace_if("Chg", ifp);
886
887 LIM_SEC(ifscan_timer, now.tv_sec+CHECK_BAD_INTERVAL);
888 if (recurse && ifp->int_phys != NULL) {
889 /* If an interface is sick, so are its aliases. */
890 for (ifp1 = ifp->int_phys->phyi_interface;
891 ifp1 != NULL; ifp1 = ifp1->int_ilist.hl_next) {
892 if (ifp1 != ifp)
893 if_sick(ifp1, _B_FALSE);
894 }
895 }
896 }
897 }
898
899
900 /* Mark an interface dead. */
901 static void
if_bad(struct interface * ifp,boolean_t recurse)902 if_bad(struct interface *ifp, boolean_t recurse)
903 {
904 struct interface *ifp1;
905 struct rewire_data wire;
906
907 if (ifp->int_state & IS_BROKE)
908 return;
909
910 LIM_SEC(ifscan_timer, now.tv_sec+CHECK_BAD_INTERVAL);
911
912 ifp->int_state |= (IS_BROKE | IS_SICK);
913 ifp->int_act_time = NEVER;
914 ifp->int_query_time = NEVER;
915 /* Note: don't reset the stats timestamp here */
916
917 trace_if("Chg", ifp);
918
919 if (recurse && ifp->int_phys != NULL) {
920 /* If an interface is bad, so are its aliases. */
921 for (ifp1 = ifp->int_phys->phyi_interface;
922 ifp1 != NULL; ifp1 = ifp1->int_ilist.hl_next) {
923 if (ifp1 != ifp)
924 if_bad(ifp1, _B_FALSE);
925 }
926 }
927
928 /* If we can find a replacement, then pick it up. */
929 if (!(ifp->int_state & IS_DUP) &&
930 (wire.if_new = check_dup(ifp->int_name, ifp->int_addr,
931 ifp->int_dstaddr, ifp->int_mask, ifp->int_if_flags,
932 _B_TRUE)) != NULL &&
933 !IS_IFF_QUIET(wire.if_new->int_if_flags)) {
934 trace_act("promoting duplicate %s in place of %s",
935 wire.if_new->int_name, ifp->int_name);
936 wire.if_old = ifp;
937 wire.metric_delta = wire.if_new->int_metric - ifp->int_metric;
938 (void) rn_walktree(rhead, walk_rewire, &wire);
939 if_rewire_rdisc(wire.if_old, wire.if_new);
940
941 /* The broken guy becomes the duplicate */
942 wire.if_new->int_state &= ~IS_DUP;
943 set_rdisc_mg(ifp, 0);
944 rip_mcast_off(ifp);
945 ifp->int_state |= IS_DUP;
946
947 /* join the mcast groups for the replacement */
948 set_rdisc_mg(wire.if_new, 1);
949 rip_mcast_on(wire.if_new);
950
951 if (rip_sock_interface == ifp)
952 rip_sock_interface = NULL;
953 } else {
954 (void) rn_walktree(rhead, walk_bad, ifp);
955 if_bad_rdisc(ifp);
956 }
957 }
958
959
960 /* Mark an interface alive */
961 void
if_ok(struct interface * ifp,const char * type,boolean_t recurse)962 if_ok(struct interface *ifp, const char *type, boolean_t recurse)
963 {
964 struct interface *ifp1;
965 boolean_t wasbroken = _B_FALSE;
966
967 if (ifp->int_state & IS_BROKE) {
968 writelog(LOG_WARNING, "%sinterface %s to %s restored",
969 type, ifp->int_name, naddr_ntoa(ifp->int_dstaddr));
970 ifp->int_state &= ~(IS_BROKE | IS_SICK);
971 wasbroken = _B_TRUE;
972 } else if (ifp->int_state & IS_SICK) {
973 trace_act("%sinterface %s to %s working better",
974 type, ifp->int_name, naddr_ntoa(ifp->int_dstaddr));
975 ifp->int_state &= ~IS_SICK;
976 }
977
978 if (recurse && ifp->int_phys != NULL && IS_IFF_UP(ifp->int_if_flags)) {
979 ifp->int_phys->phyi_data.ts = 0;
980
981 /* Also mark all aliases of this interface as ok */
982 for (ifp1 = ifp->int_phys->phyi_interface;
983 ifp1 != NULL; ifp1 = ifp1->int_ilist.hl_next) {
984 if (ifp1 != ifp)
985 if_ok(ifp1, type, _B_FALSE);
986 }
987 }
988
989 if (wasbroken) {
990 if (!(ifp->int_state & IS_DUP))
991 if_ok_rdisc(ifp);
992
993 if (ifp->int_state & IS_REMOTE)
994 (void) addrouteforif(ifp);
995 }
996 }
997
998 boolean_t
remote_address_ok(struct interface * ifp,in_addr_t addr)999 remote_address_ok(struct interface *ifp, in_addr_t addr)
1000 {
1001 if (ifp->int_if_flags & IFF_POINTOPOINT) {
1002 if (addr == ifp->int_dstaddr)
1003 return (_B_TRUE);
1004 } else if (on_net(addr, ifp->int_net, ifp->int_mask)) {
1005 return (_B_TRUE);
1006 }
1007 return (_B_FALSE);
1008 }
1009
1010 /*
1011 * Find the network interfaces which have configured themselves.
1012 * This must be done regularly, if only for extra addresses
1013 * that come and go on interfaces.
1014 */
1015 void
ifscan(void)1016 ifscan(void)
1017 {
1018 uint_t complaints = 0;
1019 static uint_t prev_complaints = 0;
1020 #define COMP_BADADDR 0x001
1021 #define COMP_NODST 0x002
1022 #define COMP_NOBADDR 0x004
1023 #define COMP_NOMASK 0x008
1024 #define COMP_BAD_METRIC 0x010
1025 #define COMP_NETMASK 0x020
1026 #define COMP_NO_INDEX 0x040
1027 #define COMP_BAD_FLAGS 0x080
1028 #define COMP_NO_KSTATS 0x100
1029 #define COMP_IPFORWARD 0x200
1030
1031 struct interface ifs, *ifp, *ifp1;
1032 struct rt_entry *rt;
1033 size_t needed;
1034 static size_t lastneeded = 0;
1035 char *buf;
1036 static char *lastbuf = NULL;
1037 int32_t in, ierr, out, oerr;
1038 struct intnet *intnetp;
1039 int sock;
1040 struct lifnum lifn;
1041 struct lifconf lifc;
1042 struct lifreq *lifrp, *lifrp_lim;
1043 struct sockaddr_in *sinp;
1044 in_addr_t haddr;
1045 static in_addr_t myaddr = 0;
1046 uint32_t ifindex;
1047 struct phyi_data newstats;
1048 struct physical_interface *phyi;
1049
1050 last_ifscan = now;
1051 ifscan_timer.tv_sec = now.tv_sec +
1052 (supplier || tot_interfaces != 1 ?
1053 CHECK_ACT_INTERVAL : CHECK_QUIET_INTERVAL);
1054
1055 /* mark all interfaces so we can get rid of those that disappear */
1056 for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next)
1057 ifp->int_state &= ~IS_CHECKED;
1058
1059 /* Fetch the size of the current interface list */
1060 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
1061 BADERR(_B_TRUE, "ifscan: socket(SOCK_DGRAM)");
1062 lifn.lifn_family = AF_INET; /* Only count IPv4 interfaces */
1063 /*
1064 * Include IFF_NOXMIT interfaces. Such interfaces are exluded
1065 * from protocol operations, but their inclusion in the
1066 * internal table enables us to know when packets arrive on
1067 * such interfaces.
1068 */
1069 lifn.lifn_flags = LIFC_NOXMIT;
1070 calculate_lifc_len:
1071 if (ioctl(sock, SIOCGLIFNUM, &lifn) == -1) {
1072 BADERR(_B_TRUE, "ifscan: ioctl(SIOCGLIFNUM)");
1073 }
1074
1075 /*
1076 * When calculating the buffer size needed, add a small number
1077 * of interfaces to those we counted. We do this to capture
1078 * the interface status of potential interfaces which may have
1079 * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF.
1080 * Try to reuse the buffer we already have to avoid heap
1081 * thrash.
1082 */
1083 needed = (lifn.lifn_count + 4) * sizeof (struct lifreq);
1084 if (needed > lastneeded || needed < lastneeded/2) {
1085 if (lastbuf != NULL)
1086 free(lastbuf);
1087 if ((buf = malloc(needed)) == NULL) {
1088 lastbuf = NULL;
1089 msglog("ifscan: malloc: %s", rip_strerror(errno));
1090 return;
1091 }
1092 } else {
1093 buf = lastbuf;
1094 }
1095 lastbuf = buf;
1096 lastneeded = needed;
1097
1098 /* Get the list */
1099 lifc.lifc_family = AF_INET; /* We only need IPv4 interfaces */
1100 lifc.lifc_flags = LIFC_NOXMIT;
1101 lifc.lifc_len = needed;
1102 lifc.lifc_buf = buf;
1103 if (ioctl(sock, SIOCGLIFCONF, &lifc) == -1) {
1104 /*
1105 * IP returns EINVAL if the lifc_len we passed in is
1106 * too small. If that's the case, we need to go back
1107 * and recalculate it.
1108 */
1109 if (errno == EINVAL)
1110 goto calculate_lifc_len;
1111 BADERR(_B_TRUE, "ifscan: ioctl(SIOCGLIFCONF)");
1112 }
1113
1114 /*
1115 * If the returned lifc_len is within one lifreq of the
1116 * requested ammount, we may have used a buffer which
1117 * was too small to hold all of the interfaces. In that
1118 * case go back and recalculate needed.
1119 */
1120 if (lifc.lifc_len >= needed - sizeof (struct lifreq))
1121 goto calculate_lifc_len;
1122
1123 lifrp = lifc.lifc_req;
1124 lifrp_lim = lifrp + lifc.lifc_len / sizeof (*lifrp);
1125 for (; lifrp < lifrp_lim; lifrp++) {
1126
1127 (void) memset(&ifs, 0, sizeof (ifs));
1128
1129 (void) strlcpy(ifs.int_name, lifrp->lifr_name,
1130 sizeof (ifs.int_name));
1131
1132 /* SIOCGLIFCONF fills in the lifr_addr of each lifreq */
1133 ifs.int_addr = ((struct sockaddr_in *)&lifrp->lifr_addr)->
1134 sin_addr.s_addr;
1135
1136 if (ioctl(sock, SIOCGLIFFLAGS, lifrp) == -1) {
1137 if (!(prev_complaints & COMP_BAD_FLAGS))
1138 writelog(LOG_NOTICE,
1139 "unable to get interface flags for %s: %s",
1140 ifs.int_name, rip_strerror(errno));
1141 complaints |= COMP_BAD_FLAGS;
1142 ifs.int_if_flags = 0;
1143 } else {
1144 ifs.int_if_flags = lifrp->lifr_flags;
1145 }
1146
1147 if (IN_CLASSD(ntohl(ifs.int_addr)) ||
1148 (ntohl(ifs.int_addr) & IN_CLASSA_NET) == 0) {
1149 if (IS_IFF_UP(ifs.int_if_flags)) {
1150 if (!(prev_complaints & COMP_BADADDR))
1151 writelog(LOG_NOTICE,
1152 "%s has a bad address %s",
1153 ifs.int_name,
1154 naddr_ntoa(ifs.int_addr));
1155 complaints |= COMP_BADADDR;
1156 }
1157 continue;
1158 }
1159
1160 /* Ignore interface with IPv4 link local address. */
1161 if (IN_LINKLOCAL(ntohl(ifs.int_addr)))
1162 continue;
1163
1164 /* Get the interface index. */
1165 if (ioctl(sock, SIOCGLIFINDEX, lifrp) == -1) {
1166 ifindex = 0;
1167 ifs.int_if_flags &= ~IFF_UP;
1168 if (!(prev_complaints & COMP_NO_INDEX))
1169 writelog(LOG_NOTICE, "%s has no ifIndex: %s",
1170 ifs.int_name, rip_strerror(errno));
1171 complaints |= COMP_NO_INDEX;
1172 } else {
1173 ifindex = lifrp->lifr_index;
1174 }
1175
1176 /*
1177 * Get the destination address for point-to-point
1178 * interfaces.
1179 */
1180 if (ifs.int_if_flags & IFF_POINTOPOINT) {
1181 sinp = (struct sockaddr_in *)&lifrp->lifr_dstaddr;
1182 if (ioctl(sock, SIOCGLIFDSTADDR, lifrp) == -1) {
1183 if (IS_IFF_UP(ifs.int_if_flags)) {
1184 if (!(prev_complaints & COMP_NODST))
1185 writelog(LOG_NOTICE,
1186 "%s has no destination "
1187 "address : %s",
1188 ifs.int_name,
1189 rip_strerror(errno));
1190 complaints |= COMP_NODST;
1191 }
1192 continue;
1193 }
1194 ifs.int_net = ntohl(sinp->sin_addr.s_addr);
1195 if (IN_CLASSD(ntohl(ifs.int_net)) ||
1196 (ifs.int_net != 0 &&
1197 (ifs.int_net & IN_CLASSA_NET) == 0)) {
1198 if (IS_IFF_UP(ifs.int_if_flags)) {
1199 if (!(prev_complaints & COMP_NODST))
1200 writelog(LOG_NOTICE,
1201 "%s has a bad "
1202 "destination address %s",
1203 ifs.int_name,
1204 naddr_ntoa(ifs.int_net));
1205 complaints |= COMP_NODST;
1206 }
1207 continue;
1208 }
1209 ifs.int_dstaddr = sinp->sin_addr.s_addr;
1210 }
1211
1212 /* Get the subnet mask */
1213 sinp = (struct sockaddr_in *)&lifrp->lifr_addr;
1214 if (ioctl(sock, SIOCGLIFNETMASK, lifrp) == -1) {
1215 if (IS_IFF_UP(ifs.int_if_flags)) {
1216 if (!(prev_complaints & COMP_NOMASK))
1217 writelog(LOG_NOTICE,
1218 "%s has no netmask: %s",
1219 ifs.int_name, rip_strerror(errno));
1220 complaints |= COMP_NOMASK;
1221 }
1222 continue;
1223 }
1224 if (sinp->sin_addr.s_addr == INADDR_ANY) {
1225 if (!(ifs.int_if_flags &
1226 (IFF_POINTOPOINT|IFF_LOOPBACK))) {
1227 if (IS_IFF_UP(ifs.int_if_flags)) {
1228 if (!(prev_complaints & COMP_NOMASK))
1229 writelog(LOG_NOTICE,
1230 "%s has all-zero netmask",
1231 ifs.int_name);
1232 complaints |= COMP_NOMASK;
1233 }
1234 continue;
1235 }
1236 ifs.int_mask = IP_HOST_MASK;
1237 } else {
1238 ifs.int_mask = ntohl(sinp->sin_addr.s_addr);
1239 }
1240
1241 /*
1242 * Get the broadcast address on broadcast capable
1243 * interfaces.
1244 */
1245 if (ifs.int_if_flags & IFF_BROADCAST) {
1246 if (ioctl(sock, SIOCGLIFBRDADDR, lifrp) == -1) {
1247 if (IS_IFF_UP(ifs.int_if_flags)) {
1248 if (!(prev_complaints & COMP_NOBADDR))
1249 writelog(LOG_NOTICE,
1250 "%s has no broadcast "
1251 "address: %s",
1252 ifs.int_name,
1253 rip_strerror(errno));
1254 complaints |= COMP_NOBADDR;
1255 }
1256 continue;
1257 }
1258 haddr = ntohl(sinp->sin_addr.s_addr);
1259 if (IN_CLASSD(haddr) ||
1260 (haddr & IN_CLASSA_NET) == 0) {
1261 if (IS_IFF_UP(ifs.int_if_flags)) {
1262 if (!(prev_complaints & COMP_NOBADDR))
1263 writelog(LOG_NOTICE,
1264 "%s has a bad broadcast "
1265 "address %s",
1266 ifs.int_name,
1267 naddr_ntoa(haddr));
1268 complaints |= COMP_NOBADDR;
1269 }
1270 continue;
1271 }
1272 }
1273 ifs.int_brdaddr = sinp->sin_addr.s_addr;
1274
1275 /* Get interface metric, if possible. */
1276 if (ioctl(sock, SIOCGLIFMETRIC, lifrp) == -1) {
1277 if (IS_IFF_UP(ifs.int_if_flags)) {
1278 if (!(prev_complaints & COMP_BAD_METRIC))
1279 writelog(LOG_NOTICE,
1280 "%s has no metric: %s",
1281 ifs.int_name, rip_strerror(errno));
1282 complaints |= COMP_BAD_METRIC;
1283 }
1284 } else {
1285 ifs.int_metric = lifrp->lifr_metric;
1286 if (ifs.int_metric > HOPCNT_INFINITY) {
1287 if (IS_IFF_UP(ifs.int_if_flags)) {
1288 if (!(prev_complaints &
1289 COMP_BAD_METRIC))
1290 writelog(LOG_NOTICE,
1291 "%s has a metric of %d, "
1292 "defaulting to %d",
1293 ifs.int_name,
1294 ifs.int_metric,
1295 HOPCNT_INFINITY);
1296 complaints |= COMP_BAD_METRIC;
1297 }
1298 ifs.int_metric = HOPCNT_INFINITY;
1299 }
1300 }
1301
1302 ifs.int_state |= IS_CHECKED;
1303 ifs.int_query_time = NEVER;
1304
1305 /*
1306 * If this is an alias, then mark it appropriately.
1307 * Do not output RIP or Router-Discovery packets via
1308 * aliases.
1309 */
1310 if (strchr(ifs.int_name, ':') != NULL)
1311 ifs.int_state |= IS_ALIAS;
1312
1313 if (ifs.int_if_flags & IFF_LOOPBACK) {
1314 ifs.int_state |= IS_PASSIVE | IS_NO_RIP | IS_NO_RDISC;
1315 ifs.int_dstaddr = ifs.int_addr;
1316 ifs.int_mask = HOST_MASK;
1317 ifs.int_ripv1_mask = HOST_MASK;
1318 ifs.int_std_mask = std_mask(ifs.int_dstaddr);
1319 ifs.int_net = ntohl(ifs.int_dstaddr);
1320 if (!foundloopback) {
1321 foundloopback = _B_TRUE;
1322 loopaddr = ifs.int_addr;
1323 loop_rts.rts_gate = loopaddr;
1324 loop_rts.rts_router = loopaddr;
1325 }
1326
1327 } else if (ifs.int_if_flags & IFF_POINTOPOINT) {
1328 ifs.int_ripv1_mask = ifs.int_mask;
1329 ifs.int_mask = HOST_MASK;
1330 ifs.int_std_mask = std_mask(ifs.int_dstaddr);
1331
1332 } else {
1333 ifs.int_dstaddr = ifs.int_addr;
1334 ifs.int_ripv1_mask = ifs.int_mask;
1335 ifs.int_std_mask = std_mask(ifs.int_addr);
1336 ifs.int_net = ntohl(ifs.int_addr) & ifs.int_mask;
1337 if (ifs.int_mask != ifs.int_std_mask)
1338 ifs.int_state |= IS_SUBNET;
1339 }
1340 ifs.int_std_net = ifs.int_net & ifs.int_std_mask;
1341 ifs.int_std_addr = htonl(ifs.int_std_net);
1342
1343 /*
1344 * If this interface duplicates another, mark it
1345 * appropriately so that we don't generate duplicate
1346 * packets.
1347 */
1348 ifp = check_dup(ifs.int_name, ifs.int_addr, ifs.int_dstaddr,
1349 ifs.int_mask, ifs.int_if_flags, _B_FALSE);
1350 if (ifp != NULL) {
1351 trace_misc("%s (%s%s%s) is a duplicate of %s (%s%s%s)",
1352 ifs.int_name,
1353 addrname(ifs.int_addr, ifs.int_mask, 1),
1354 ((ifs.int_if_flags & IFF_POINTOPOINT) ?
1355 "-->" : ""),
1356 ((ifs.int_if_flags & IFF_POINTOPOINT) ?
1357 naddr_ntoa(ifs.int_dstaddr) : ""),
1358 ifp->int_name,
1359 addrname(ifp->int_addr, ifp->int_mask, 1),
1360 ((ifp->int_if_flags & IFF_POINTOPOINT) ?
1361 "-->" : ""),
1362 ((ifp->int_if_flags & IFF_POINTOPOINT) ?
1363 naddr_ntoa(ifp->int_dstaddr) : ""));
1364 ifs.int_state |= IS_DUP;
1365 } else {
1366 ifs.int_state &= ~IS_DUP;
1367 }
1368
1369 /*
1370 * See if this is a familiar interface.
1371 * If so, stop worrying about it if it is the same.
1372 * Start it over if it now is to somewhere else, as happens
1373 * frequently with PPP and SLIP, or if its forwarding
1374 * status has changed.
1375 */
1376 ifp = ifwithname(ifs.int_name);
1377 if (ifp != NULL) {
1378 ifp->int_state |= IS_CHECKED;
1379 ifp->int_state = (ifp->int_state & ~IS_DUP) |
1380 (ifs.int_state & IS_DUP);
1381
1382 if ((ifp->int_phys == NULL && ifindex != 0) ||
1383 (ifp->int_phys != NULL &&
1384 ifp->int_phys->phyi_index != ifindex) ||
1385 0 != ((ifp->int_if_flags ^ ifs.int_if_flags)
1386 & (IFF_BROADCAST | IFF_LOOPBACK |
1387 IFF_POINTOPOINT | IFF_MULTICAST |
1388 IFF_ROUTER | IFF_NORTEXCH | IFF_NOXMIT)) ||
1389 ifp->int_addr != ifs.int_addr ||
1390 ifp->int_brdaddr != ifs.int_brdaddr ||
1391 ifp->int_dstaddr != ifs.int_dstaddr ||
1392 ifp->int_mask != ifs.int_mask ||
1393 ifp->int_metric != ifs.int_metric) {
1394 /*
1395 * Forget old information about
1396 * a changed interface.
1397 */
1398 trace_act("interface %s has changed",
1399 ifp->int_name);
1400 ifdel(ifp);
1401 ifp = NULL;
1402 }
1403 }
1404
1405 if (ifp != NULL) {
1406 /* note interfaces that have been turned off */
1407 if (!IS_IFF_UP(ifs.int_if_flags)) {
1408 if (IS_IFF_UP(ifp->int_if_flags)) {
1409 writelog(LOG_WARNING,
1410 "interface %s to %s turned off",
1411 ifp->int_name,
1412 naddr_ntoa(ifp->int_dstaddr));
1413 if_bad(ifp, _B_FALSE);
1414 ifp->int_if_flags &= ~IFF_UP;
1415 } else if (ifp->int_phys != NULL &&
1416 now.tv_sec > (ifp->int_phys->phyi_data.ts +
1417 CHECK_BAD_INTERVAL)) {
1418 trace_act("interface %s has been off"
1419 " %ld seconds; forget it",
1420 ifp->int_name,
1421 now.tv_sec -
1422 ifp->int_phys->phyi_data.ts);
1423 ifdel(ifp);
1424 }
1425 continue;
1426 }
1427 /* or that were off and are now ok */
1428 if (!IS_IFF_UP(ifp->int_if_flags)) {
1429 ifp->int_if_flags |= IFF_UP;
1430 if_ok(ifp, "", _B_FALSE);
1431 }
1432
1433 /*
1434 * If it has been long enough,
1435 * see if the interface is broken.
1436 */
1437 if ((phyi = ifp->int_phys) == NULL ||
1438 now.tv_sec < phyi->phyi_data.ts +
1439 CHECK_BAD_INTERVAL)
1440 continue;
1441
1442 (void) memset(&newstats, 0, sizeof (newstats));
1443 if (get_if_kstats(ifp, &newstats) == -1) {
1444 if (!(prev_complaints & COMP_NO_KSTATS))
1445 writelog(LOG_WARNING,
1446 "unable to obtain kstats for %s",
1447 phyi->phyi_name);
1448 complaints |= COMP_NO_KSTATS;
1449 }
1450
1451 /*
1452 * If the interface just awoke, restart the counters.
1453 */
1454 if (phyi->phyi_data.ts == 0) {
1455 phyi->phyi_data = newstats;
1456 continue;
1457 }
1458
1459 in = newstats.ipackets - phyi->phyi_data.ipackets;
1460 ierr = newstats.ierrors - phyi->phyi_data.ierrors;
1461 out = newstats.opackets - phyi->phyi_data.opackets;
1462 oerr = newstats.oerrors - phyi->phyi_data.oerrors;
1463 phyi->phyi_data = newstats;
1464
1465 /*
1466 * Withhold judgment when the short error counters
1467 * wrap, the interface is reset, or if there are
1468 * no kstats.
1469 */
1470 if (ierr < 0 || in < 0 || oerr < 0 || out < 0 ||
1471 newstats.ts == 0) {
1472 LIM_SEC(ifscan_timer,
1473 now.tv_sec + CHECK_BAD_INTERVAL);
1474 continue;
1475 }
1476
1477 /* Withhold judgement when there is no traffic */
1478 if (in == 0 && out == 0 && ierr == 0 && oerr == 0)
1479 continue;
1480
1481 /*
1482 * It is bad if at least 25% of input or output on
1483 * an interface results in errors. Require
1484 * presistent problems before marking it dead.
1485 */
1486 if ((ierr > 0 && ierr >= in/4) ||
1487 (oerr > 0 && oerr >= out/4)) {
1488 if (!(ifp->int_state & IS_SICK)) {
1489 trace_act("interface %s to %s"
1490 " sick: in=%d ierr=%d"
1491 " out=%d oerr=%d",
1492 ifp->int_name,
1493 naddr_ntoa(ifp->int_dstaddr),
1494 in, ierr, out, oerr);
1495 if_sick(ifp, _B_TRUE);
1496 continue;
1497 }
1498 if (!(ifp->int_state & IS_BROKE)) {
1499 writelog(LOG_WARNING,
1500 "interface %s to %s broken:"
1501 " in=%d ierr=%d out=%d oerr=%d",
1502 ifp->int_name,
1503 naddr_ntoa(ifp->int_dstaddr),
1504 in, ierr, out, oerr);
1505 if_bad(ifp, _B_TRUE);
1506 }
1507 continue;
1508 }
1509
1510 /* otherwise, it is active and healthy */
1511 ifp->int_act_time = now.tv_sec;
1512 if_ok(ifp, "", _B_TRUE);
1513 continue;
1514 }
1515
1516 /*
1517 * This is a new interface.
1518 * If it is dead, forget it.
1519 */
1520 if (!IS_IFF_UP(ifs.int_if_flags))
1521 continue;
1522
1523 if (0 == (ifs.int_if_flags & (IFF_POINTOPOINT |
1524 IFF_BROADCAST | IFF_LOOPBACK)) &&
1525 !(ifs.int_state & IS_PASSIVE)) {
1526 if (!(prev_complaints & COMP_BAD_FLAGS))
1527 trace_act("%s is neither broadcast, "
1528 "point-to-point, nor loopback",
1529 ifs.int_name);
1530 complaints |= COMP_BAD_FLAGS;
1531 if (!(ifs.int_if_flags & IFF_MULTICAST))
1532 ifs.int_state |= IS_NO_RDISC;
1533 }
1534
1535
1536 /*
1537 * It is new and ok. Add it to the list of interfaces
1538 */
1539 ifp = rtmalloc(sizeof (*ifp), "ifscan ifp");
1540 (void) memcpy(ifp, &ifs, sizeof (*ifp));
1541 get_parms(ifp);
1542 if_link(ifp, ifindex);
1543 trace_if("Add", ifp);
1544
1545 if (ifp->int_phys != NULL &&
1546 get_if_kstats(ifp, &ifp->int_phys->phyi_data) == -1) {
1547 if (!(prev_complaints & COMP_NO_KSTATS))
1548 writelog(LOG_NOTICE,
1549 "unable to obtain kstats for %s",
1550 ifp->int_phys->phyi_name);
1551 complaints |= COMP_NO_KSTATS;
1552 }
1553
1554 /* Detect interfaces that have conflicting netmasks. */
1555 if (!(ifp->int_if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK))) {
1556 for (ifp1 = ifnet; ifp1 != NULL;
1557 ifp1 = ifp1->int_next) {
1558 if (ifp1->int_mask == ifp->int_mask)
1559 continue;
1560
1561 /*
1562 * we don't care about point-to-point
1563 * or loopback aliases
1564 */
1565 if (ifp1->int_if_flags &
1566 (IFF_POINTOPOINT|IFF_LOOPBACK)) {
1567 continue;
1568 }
1569
1570 /* ignore aliases on the same network */
1571 if (ifp->int_phys == ifp1->int_phys)
1572 continue;
1573
1574 if (on_net(ifp->int_addr,
1575 ifp1->int_net, ifp1->int_mask) ||
1576 on_net(ifp1->int_addr,
1577 ifp->int_net, ifp->int_mask)) {
1578 writelog(LOG_INFO,
1579 "possible netmask problem"
1580 " between %s:%s and %s:%s",
1581 ifp->int_name,
1582 addrname(htonl(ifp->int_net),
1583 ifp->int_mask, 1),
1584 ifp1->int_name,
1585 addrname(htonl(ifp1->int_net),
1586 ifp1->int_mask, 1));
1587 complaints |= COMP_NETMASK;
1588 }
1589 }
1590 }
1591
1592 if (!(ifp->int_state & IS_DUP) &&
1593 !IS_IFF_QUIET(ifp->int_if_flags)) {
1594 /* Count the # of directly connected networks. */
1595 tot_interfaces++;
1596 if (!IS_RIP_OFF(ifp->int_state))
1597 rip_interfaces++;
1598 if (!IS_RIP_OUT_OFF(ifp->int_state))
1599 ripout_interfaces++;
1600 if (IS_IFF_ROUTING(ifp->int_if_flags))
1601 fwd_interfaces++;
1602
1603 if_ok_rdisc(ifp);
1604 rip_on(ifp);
1605 }
1606 }
1607
1608 (void) close(sock);
1609
1610 /*
1611 * If we are multi-homed and have at least two interfaces that
1612 * are able to forward, then output RIP by default.
1613 */
1614 if (!supplier_set)
1615 set_supplier();
1616
1617 /*
1618 * If we are multi-homed, optionally advertise a route to
1619 * our main address.
1620 */
1621 if (advertise_mhome || (tot_interfaces > 1 && mhome)) {
1622 /* lookup myaddr if we haven't done so already */
1623 if (myaddr == 0) {
1624 char myname[MAXHOSTNAMELEN+1];
1625
1626 /*
1627 * If we are unable to resolve our hostname, don't
1628 * bother trying again.
1629 */
1630 if (gethostname(myname, MAXHOSTNAMELEN) == -1) {
1631 msglog("gethostname: %s", rip_strerror(errno));
1632 advertise_mhome = _B_FALSE;
1633 mhome = _B_FALSE;
1634 } else if (gethost(myname, &myaddr) == 0) {
1635 writelog(LOG_WARNING,
1636 "unable to resolve local hostname %s",
1637 myname);
1638 advertise_mhome = _B_FALSE;
1639 mhome = _B_FALSE;
1640 }
1641 }
1642 if (myaddr != 0 &&
1643 (ifp = ifwithaddr(myaddr, _B_FALSE, _B_FALSE)) != NULL &&
1644 foundloopback) {
1645 advertise_mhome = _B_TRUE;
1646 rt = rtget(myaddr, HOST_MASK);
1647 if (rt != NULL) {
1648 if (rt->rt_ifp != ifp ||
1649 rt->rt_router != loopaddr) {
1650 rtdelete(rt);
1651 rt = NULL;
1652 } else {
1653 loop_rts.rts_ifp = ifp;
1654 loop_rts.rts_metric = 0;
1655 loop_rts.rts_time = rt->rt_time;
1656 loop_rts.rts_origin = RO_LOOPBCK;
1657 rtchange(rt, rt->rt_state | RS_MHOME,
1658 &loop_rts, NULL);
1659 }
1660 }
1661 if (rt == NULL) {
1662 loop_rts.rts_ifp = ifp;
1663 loop_rts.rts_metric = 0;
1664 loop_rts.rts_origin = RO_LOOPBCK;
1665 rtadd(myaddr, HOST_MASK, RS_MHOME, &loop_rts);
1666 }
1667 }
1668 }
1669
1670 for (ifp = ifnet; ifp != NULL; ifp = ifp1) {
1671 ifp1 = ifp->int_next; /* because we may delete it */
1672
1673 /* Forget any interfaces that have disappeared. */
1674 if (!(ifp->int_state & (IS_CHECKED | IS_REMOTE))) {
1675 trace_act("interface %s has disappeared",
1676 ifp->int_name);
1677 ifdel(ifp);
1678 continue;
1679 }
1680
1681 if ((ifp->int_state & IS_BROKE) &&
1682 !(ifp->int_state & IS_PASSIVE))
1683 LIM_SEC(ifscan_timer, now.tv_sec+CHECK_BAD_INTERVAL);
1684
1685 /*
1686 * If we ever have a RIPv1 interface, assume we always will.
1687 * It might come back if it ever goes away.
1688 */
1689 if (!(ifp->int_state & (IS_NO_RIPV1_OUT | IS_DUP)) &&
1690 should_supply(ifp))
1691 have_ripv1_out = _B_TRUE;
1692 if (!(ifp->int_state & IS_NO_RIPV1_IN))
1693 have_ripv1_in = _B_TRUE;
1694 }
1695
1696 for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) {
1697 /*
1698 * Ensure there is always a network route for interfaces,
1699 * after any dead interfaces have been deleted, which
1700 * might affect routes for point-to-point links.
1701 */
1702 if (addrouteforif(ifp) == 0)
1703 continue;
1704
1705 /*
1706 * Add routes to the local end of point-to-point interfaces
1707 * using loopback.
1708 */
1709 if ((ifp->int_if_flags & IFF_POINTOPOINT) &&
1710 !(ifp->int_state & IS_REMOTE) && foundloopback) {
1711 /*
1712 * Delete any routes to the network address through
1713 * foreign routers. Remove even static routes.
1714 */
1715 del_static(ifp->int_addr, HOST_MASK, 0, ifp, 0);
1716 rt = rtget(ifp->int_addr, HOST_MASK);
1717 if (rt != NULL && rt->rt_router != loopaddr) {
1718 rtdelete(rt);
1719 rt = NULL;
1720 }
1721 if (rt != NULL) {
1722 if (!(rt->rt_state & RS_LOCAL) ||
1723 rt->rt_metric > ifp->int_metric) {
1724 ifp1 = ifp;
1725 } else {
1726 ifp1 = rt->rt_ifp;
1727 }
1728 loop_rts.rts_ifp = ifp1;
1729 loop_rts.rts_metric = 0;
1730 loop_rts.rts_time = rt->rt_time;
1731 loop_rts.rts_origin = RO_LOOPBCK;
1732 rtchange(rt, ((rt->rt_state & ~RS_NET_SYN) |
1733 (RS_IF|RS_LOCAL)), &loop_rts, 0);
1734 } else {
1735 loop_rts.rts_ifp = ifp;
1736 loop_rts.rts_metric = 0;
1737 loop_rts.rts_origin = RO_LOOPBCK;
1738 rtadd(ifp->int_addr, HOST_MASK,
1739 (RS_IF | RS_LOCAL), &loop_rts);
1740 }
1741 }
1742 }
1743
1744 /* add the authority routes */
1745 for (intnetp = intnets; intnetp != NULL;
1746 intnetp = intnetp->intnet_next) {
1747 rt = rtget(intnetp->intnet_addr, intnetp->intnet_mask);
1748 if (rt != NULL &&
1749 !(rt->rt_state & RS_NO_NET_SYN) &&
1750 !(rt->rt_state & RS_NET_INT)) {
1751 rtdelete(rt);
1752 rt = NULL;
1753 }
1754 if (rt == NULL) {
1755 loop_rts.rts_ifp = NULL;
1756 loop_rts.rts_metric = intnetp->intnet_metric-1;
1757 loop_rts.rts_origin = RO_LOOPBCK;
1758 rtadd(intnetp->intnet_addr, intnetp->intnet_mask,
1759 RS_NET_SYN | RS_NET_INT, &loop_rts);
1760 }
1761 }
1762
1763 prev_complaints = complaints;
1764 }
1765
1766
1767 static void
check_net_syn(struct interface * ifp)1768 check_net_syn(struct interface *ifp)
1769 {
1770 struct rt_entry *rt;
1771 struct rt_spare new;
1772
1773 /*
1774 * Turn on the need to automatically synthesize a network route
1775 * for this interface only if we are running RIPv1 on some other
1776 * interface that is on a different class-A,B,or C network.
1777 */
1778 if (have_ripv1_out || have_ripv1_in) {
1779 ifp->int_state |= IS_NEED_NET_SYN;
1780 rt = rtget(ifp->int_std_addr, ifp->int_std_mask);
1781 if (rt != NULL &&
1782 0 == (rt->rt_state & RS_NO_NET_SYN) &&
1783 (!(rt->rt_state & RS_NET_SYN) ||
1784 rt->rt_metric > ifp->int_metric)) {
1785 rtdelete(rt);
1786 rt = NULL;
1787 }
1788 if (rt == NULL) {
1789 (void) memset(&new, 0, sizeof (new));
1790 new.rts_ifp = ifp;
1791 new.rts_gate = ifp->int_addr;
1792 new.rts_router = ifp->int_addr;
1793 new.rts_metric = ifp->int_metric;
1794 new.rts_origin = RO_NET_SYN;
1795 rtadd(ifp->int_std_addr, ifp->int_std_mask,
1796 RS_NET_SYN, &new);
1797 }
1798
1799 } else {
1800 ifp->int_state &= ~IS_NEED_NET_SYN;
1801
1802 rt = rtget(ifp->int_std_addr, ifp->int_std_mask);
1803 if (rt != NULL &&
1804 (rt->rt_state & RS_NET_SYN) &&
1805 rt->rt_ifp == ifp)
1806 rtbad_sub(rt, NULL);
1807 }
1808 }
1809
1810
1811 /*
1812 * Add route for interface if not currently installed.
1813 * Create route to other end if a point-to-point link,
1814 * otherwise a route to this (sub)network.
1815 */
1816 static boolean_t /* _B_FALSE=bad interface */
addrouteforif(struct interface * ifp)1817 addrouteforif(struct interface *ifp)
1818 {
1819 struct rt_entry *rt;
1820 struct rt_spare new;
1821 in_addr_t dst;
1822 uint16_t rt_newstate = RS_IF;
1823
1824
1825 /* skip sick interfaces */
1826 if (ifp->int_state & IS_BROKE)
1827 return (_B_FALSE);
1828
1829 /*
1830 * don't install routes for duplicate interfaces, or
1831 * unnumbered point-to-point interfaces.
1832 */
1833 if ((ifp->int_state & IS_DUP) ||
1834 ((ifp->int_if_flags & IFF_POINTOPOINT) && ifp->int_dstaddr == 0))
1835 return (_B_TRUE);
1836
1837 /*
1838 * If the interface on a subnet, then install a RIPv1 route to
1839 * the network as well (unless it is sick).
1840 */
1841 if (ifp->int_state & IS_SUBNET)
1842 check_net_syn(ifp);
1843
1844 dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) ?
1845 ifp->int_dstaddr : htonl(ifp->int_net));
1846
1847 (void) memset(&new, 0, sizeof (new));
1848 new.rts_ifp = ifp;
1849 new.rts_router = ifp->int_addr;
1850 new.rts_gate = ifp->int_addr;
1851 new.rts_metric = ifp->int_metric;
1852 new.rts_time = now.tv_sec;
1853 if (ifp->int_if_flags & IFF_POINTOPOINT)
1854 new.rts_origin = RO_PTOPT;
1855 else if (ifp->int_if_flags & IFF_LOOPBACK)
1856 new.rts_origin = RO_LOOPBCK;
1857 else
1858 new.rts_origin = RO_IF;
1859
1860 /*
1861 * If we are going to send packets to the gateway,
1862 * it must be reachable using our physical interfaces
1863 */
1864 if ((ifp->int_state & IS_REMOTE) &&
1865 !(ifp->int_state & IS_EXTERNAL) &&
1866 !check_remote(ifp))
1867 return (_B_FALSE);
1868
1869 /*
1870 * We are finished if the correct main interface route exists.
1871 * The right route must be for the right interface, not synthesized
1872 * from a subnet, be a "gateway" or not as appropriate, and so forth.
1873 */
1874 del_static(dst, ifp->int_mask, 0, ifp, 0);
1875 rt = rtget(dst, ifp->int_mask);
1876 if (!IS_IFF_ROUTING(ifp->int_if_flags))
1877 rt_newstate |= RS_NOPROPAGATE;
1878 if (rt != NULL) {
1879 if ((rt->rt_ifp != ifp || rt->rt_router != ifp->int_addr) &&
1880 (rt->rt_ifp == NULL ||
1881 (rt->rt_ifp->int_state & IS_BROKE))) {
1882 rtdelete(rt);
1883 rt = NULL;
1884 } else {
1885 rtchange(rt, ((rt->rt_state | rt_newstate) &
1886 ~(RS_NET_SYN | RS_LOCAL)), &new, 0);
1887 }
1888 }
1889 if (rt == NULL) {
1890 if (ifp->int_transitions++ > 0)
1891 trace_act("re-installing interface %s;"
1892 " went up %d times",
1893 ifp->int_name, ifp->int_transitions);
1894
1895 rtadd(dst, ifp->int_mask, rt_newstate, &new);
1896 }
1897
1898 return (_B_TRUE);
1899 }
1900
1901 /*
1902 * Obtains the named kstat, and places its value in *value. It
1903 * returns 0 for success, -1 for failure.
1904 */
1905 static int
kstat_named_value(kstat_t * ksp,char * name,uint32_t * value)1906 kstat_named_value(kstat_t *ksp, char *name, uint32_t *value)
1907 {
1908 kstat_named_t *knp;
1909
1910 if (ksp == NULL)
1911 return (-1);
1912
1913 if ((knp = kstat_data_lookup(ksp, name)) == NULL) {
1914 return (-1);
1915 } else if (knp->data_type != KSTAT_DATA_UINT32) {
1916 return (-1);
1917 } else {
1918 *value = knp->value.ui32;
1919 return (0);
1920 }
1921 }
1922
1923 static int
get_if_kstats(struct interface * ifp,struct phyi_data * newdata)1924 get_if_kstats(struct interface *ifp, struct phyi_data *newdata)
1925 {
1926 struct physical_interface *phyi = ifp->int_phys;
1927 kstat_ctl_t *kc;
1928 kstat_t *ksp;
1929
1930 /* We did this recently; don't do it again. */
1931 if (phyi->phyi_data.ts == now.tv_sec) {
1932 if (newdata != &phyi->phyi_data)
1933 *newdata = phyi->phyi_data;
1934 return (0);
1935 }
1936
1937 if ((kc = kstat_open()) == NULL)
1938 return (-1);
1939
1940 /*
1941 * First we try to query the "link" kstats in case the link is renamed.
1942 * If that fails, fallback to legacy ktats for those non-GLDv3 links.
1943 */
1944 if (((ksp = kstat_lookup(kc, "link", 0, phyi->phyi_name)) == NULL) &&
1945 ((ksp = kstat_lookup(kc, NULL, -1, phyi->phyi_name)) == NULL)) {
1946 (void) kstat_close(kc);
1947 return (-1);
1948 }
1949
1950 if (kstat_read(kc, ksp, NULL) == -1) {
1951 (void) kstat_close(kc);
1952 return (-1);
1953 }
1954
1955 if ((kstat_named_value(ksp, "ipackets", &newdata->ipackets) == -1) ||
1956 (kstat_named_value(ksp, "opackets", &newdata->opackets) == -1)) {
1957 newdata->ts = 0;
1958 (void) kstat_close(kc);
1959 return (-1);
1960 }
1961
1962 /* The loopback interface does not keep track of errors */
1963 if (!(ifp->int_if_flags & IFF_LOOPBACK)) {
1964 if ((kstat_named_value(ksp, "ierrors",
1965 &newdata->ierrors) == -1) ||
1966 (kstat_named_value(ksp, "oerrors",
1967 &newdata->oerrors) == -1)) {
1968 newdata->ts = 0;
1969 (void) kstat_close(kc);
1970 return (-1);
1971 }
1972 }
1973
1974 newdata->ts = now.tv_sec;
1975 (void) kstat_close(kc);
1976 return (0);
1977 }
1978
1979 /*
1980 * Returns true if we should supply routes to other systems. If the
1981 * user has forced us to be a supplier (by the command line) or if we
1982 * have more than one forwarding interface and this is one of the
1983 * forwarding interfaces, then behave as a RIP supplier (supply rdisc
1984 * advertisements and RIP responses).
1985 */
1986 boolean_t
should_supply(struct interface * ifp)1987 should_supply(struct interface *ifp)
1988 {
1989 if (ifp != NULL && !IS_IFF_ROUTING(ifp->int_if_flags))
1990 return (_B_FALSE);
1991 return ((supplier_set && supplier) ||
1992 (!supplier_set && fwd_interfaces > 1));
1993 }
1994