1: /*
2: * BIRD -- OSPF
3: *
4: * (c) 1999--2005 Ondrej Filip <feela@network.cz>
5: * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
6: * (c) 2009--2014 CZ.NIC z.s.p.o.
7: *
8: * Can be freely distributed and used under the terms of the GNU GPL.
9: */
10:
11: #include "ospf.h"
12: #include "nest/password.h"
13:
14:
15: const char *ospf_is_names[] = {
16: "Down", "Loopback", "Waiting", "PtP", "DROther", "Backup", "DR"
17: };
18:
19: const char *ospf_ism_names[] = {
20: "InterfaceUp", "WaitTimer", "BackupSeen", "NeighborChange",
21: "LoopInd", "UnloopInd", "InterfaceDown"
22: };
23:
24: const char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" };
25:
26:
27: static void
28: poll_timer_hook(timer * timer)
29: {
30: ospf_send_hello(timer->data, OHS_POLL, NULL);
31: }
32:
33: static void
34: hello_timer_hook(timer * timer)
35: {
36: ospf_send_hello(timer->data, OHS_HELLO, NULL);
37: }
38:
39: static void
40: wait_timer_hook(timer * timer)
41: {
42: struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
43: struct ospf_proto *p = ifa->oa->po;
44:
45: OSPF_TRACE(D_EVENTS, "Wait timer fired on %s", ifa->ifname);
46: ospf_iface_sm(ifa, ISM_WAITF);
47: }
48:
49: static inline uint
50: ifa_tx_length(struct ospf_iface *ifa)
51: {
52: return ifa->cf->tx_length ?: ifa->iface->mtu;
53: }
54:
55: static inline uint
56: ifa_tx_hdrlen(struct ospf_iface *ifa)
57: {
58: struct ospf_proto *p = ifa->oa->po;
59:
60: uint hlen = ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
61:
62: /* Relevant just for OSPFv2 */
63: if (ifa->autype == OSPF_AUTH_CRYPT)
64: {
65: hlen += ospf_is_v2(p) ? 0 : sizeof(struct ospf_auth3);
66: hlen += max_mac_length(ifa->passwords);
67: }
68:
69: return hlen;
70: }
71:
72: static inline uint
73: ifa_bufsize(struct ospf_iface *ifa)
74: {
75: uint bsize = ifa->cf->rx_buffer ?: ifa->iface->mtu;
76: return MAX(bsize, ifa->tx_length);
77: }
78:
79: static inline uint
80: ifa_flood_queue_size(struct ospf_iface *ifa)
81: {
82: return ifa->tx_length / 24;
83: }
84:
85: int
86: ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
87: {
88: plen += ifa->tx_hdrlen;
89:
90: if (plen <= ifa->sk->tbsize)
91: return 0;
92:
93: if (ifa->cf->rx_buffer || (plen > 0xffff))
94: return -1;
95:
96: plen = BIRD_ALIGN(plen, 1024);
97: plen = MIN(plen, 0xffff);
98: sk_set_tbsize(ifa->sk, plen);
99: return 1;
100: }
101:
102:
103: struct nbma_node *
104: find_nbma_node_(list *nnl, ip_addr ip)
105: {
106: struct nbma_node *nn;
107:
108: WALK_LIST(nn, *nnl)
109: if (ipa_equal(nn->ip, ip))
110: return nn;
111:
112: return NULL;
113: }
114:
115:
116: static int
117: ospf_sk_open(struct ospf_iface *ifa)
118: {
119: struct ospf_proto *p = ifa->oa->po;
120:
121: sock *sk = sk_new(ifa->pool);
122: sk->type = SK_IP;
123: sk->subtype = ospf_is_v2(p) ? SK_IPV4 : SK_IPV6;
124: sk->dport = OSPF_PROTO;
125: sk->saddr = ifa->addr->ip;
126: sk->iface = ifa->iface;
127: sk->vrf = p->p.vrf;
128:
129: sk->tos = ifa->cf->tx_tos;
130: sk->priority = ifa->cf->tx_priority;
131: sk->rx_hook = ospf_rx_hook;
132: // sk->tx_hook = ospf_tx_hook;
133: sk->err_hook = ospf_err_hook;
134: sk->rbsize = sk->tbsize = ifa_bufsize(ifa);
135: sk->data = (void *) ifa;
136: sk->flags = SKF_LADDR_RX | (ifa->check_ttl ? SKF_TTL_RX : 0);
137: sk->ttl = ifa->cf->ttl_security ? 255 : 1;
138:
139: if (sk_open(sk) < 0)
140: goto err;
141:
142: /* 12 is an offset of the checksum in an OSPFv3 packet */
143: if (ospf_is_v3(p) && !ifa->autype)
144: if (sk_set_ipv6_checksum(sk, 12) < 0)
145: goto err;
146:
147: if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
148: {
149: if (ifa->cf->real_bcast)
150: {
151: ifa->all_routers = ifa->addr->brd;
152: ifa->des_routers = IPA_NONE;
153:
154: if (sk_setup_broadcast(sk) < 0)
155: goto err;
156: }
157: else
158: {
159: ifa->all_routers = ospf_is_v2(p) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS;
160: ifa->des_routers = ospf_is_v2(p) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS;
161:
162: if (sk_setup_multicast(sk) < 0)
163: goto err;
164:
165: if (sk_join_group(sk, ifa->all_routers) < 0)
166: goto err;
167: }
168: }
169:
170: ifa->sk = sk;
171: ifa->sk_dr = 0;
172: return 1;
173:
174: err:
175: sk_log_error(sk, p->p.name);
176: rfree(sk);
177: return 0;
178: }
179:
180: static inline void
181: ospf_sk_join_dr(struct ospf_iface *ifa)
182: {
183: if (ifa->sk_dr)
184: return;
185:
186: if (sk_join_group(ifa->sk, ifa->des_routers) < 0)
187: sk_log_error(ifa->sk, ifa->oa->po->p.name);
188:
189: ifa->sk_dr = 1;
190: }
191:
192: static inline void
193: ospf_sk_leave_dr(struct ospf_iface *ifa)
194: {
195: if (!ifa->sk_dr)
196: return;
197:
198: if (sk_leave_group(ifa->sk, ifa->des_routers) < 0)
199: sk_log_error(ifa->sk, ifa->oa->po->p.name);
200:
201: ifa->sk_dr = 0;
202: }
203:
204: void
205: ospf_open_vlink_sk(struct ospf_proto *p)
206: {
207: sock *sk = sk_new(p->p.pool);
208: sk->type = SK_IP;
209: sk->subtype = ospf_is_v2(p) ? SK_IPV4 : SK_IPV6;
210: sk->dport = OSPF_PROTO;
211: sk->vrf = p->p.vrf;
212:
213: /* FIXME: configurable tos/priority ? */
214: sk->tos = IP_PREC_INTERNET_CONTROL;
215: sk->priority = sk_priority_control;
216: sk->err_hook = ospf_verr_hook;
217:
218: sk->rbsize = 0;
219: sk->tbsize = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
220: sk->data = (void *) p;
221: sk->flags = 0;
222:
223: if (sk_open(sk) < 0)
224: goto err;
225:
226: /* 12 is an offset of the checksum in an OSPFv3 packet */
227: if (ospf_is_v3(p))
228: if (sk_set_ipv6_checksum(sk, 12) < 0)
229: goto err;
230:
231: p->vlink_sk = sk;
232: return;
233:
234: err:
235: sk_log_error(sk, p->p.name);
236: log(L_ERR "%s: Cannot open virtual link socket", p->p.name);
237: rfree(sk);
238: }
239:
240: static void
241: ospf_iface_down(struct ospf_iface *ifa)
242: {
243: struct ospf_proto *p = ifa->oa->po;
244: struct ospf_neighbor *n, *nx;
245: struct ospf_iface *iff;
246:
247: if (ifa->type != OSPF_IT_VLINK)
248: {
249: if (ospf_is_v3(ifa->oa->po))
250: OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
251: ifa->ifname, ifa->instance_id, ifa->oa->areaid);
252: else if (ifa->addr->flags & IA_PEER)
253: OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R",
254: ifa->ifname, ifa->addr->opposite, ifa->oa->areaid);
255: else
256: OSPF_TRACE(D_EVENTS, "Removing interface %s (%N) from area %R",
257: ifa->ifname, &ifa->addr->prefix, ifa->oa->areaid);
258:
259: /* First of all kill all the related vlinks */
260: WALK_LIST(iff, p->iface_list)
261: {
262: if ((iff->type == OSPF_IT_VLINK) && (iff->vifa == ifa))
263: ospf_iface_sm(iff, ISM_DOWN);
264: }
265: }
266:
267: WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
268: ospf_neigh_sm(n, INM_KILLNBR);
269:
270: if (ifa->hello_timer)
271: tm_stop(ifa->hello_timer);
272:
273: if (ifa->poll_timer)
274: tm_stop(ifa->poll_timer);
275:
276: if (ifa->wait_timer)
277: tm_stop(ifa->wait_timer);
278:
279: ospf_flush2_lsa(p, &ifa->link_lsa);
280: ospf_flush2_lsa(p, &ifa->net_lsa);
281: ospf_flush2_lsa(p, &ifa->pxn_lsa);
282:
283: if (ifa->type == OSPF_IT_VLINK)
284: {
285: ifa->vifa = NULL;
286: ifa->addr = NULL;
287: ifa->cost = 0;
288: ifa->vip = IPA_NONE;
289: }
290:
291: ifa->rt_pos_beg = 0;
292: ifa->rt_pos_end = 0;
293: ifa->px_pos_beg = 0;
294: ifa->px_pos_end = 0;
295: }
296:
297:
298: void
299: ospf_iface_remove(struct ospf_iface *ifa)
300: {
301: struct ospf_proto *p = ifa->oa->po;
302: int i;
303:
304: if (ifa->type == OSPF_IT_VLINK)
305: OSPF_TRACE(D_EVENTS, "Removing vlink to %R via area %R", ifa->vid, ifa->voa->areaid);
306:
307: /* Release LSAs from flood queue */
308: if (!ifa->stub)
309: for (i = 0; i < ifa->flood_queue_used; i++)
310: ifa->flood_queue[i]->ret_count--;
311:
312: ospf_iface_sm(ifa, ISM_DOWN);
313: rem_node(NODE ifa);
314: rfree(ifa->pool);
315: }
316:
317: void
318: ospf_iface_shutdown(struct ospf_iface *ifa)
319: {
320: if (ifa->state > OSPF_IS_DOWN)
321: ospf_send_hello(ifa, OHS_SHUTDOWN, NULL);
322: }
323:
324: /**
325: * ospf_iface_chstate - handle changes of interface state
326: * @ifa: OSPF interface
327: * @state: new state
328: *
329: * Many actions must be taken according to interface state changes. New network
330: * LSAs must be originated, flushed, new multicast sockets to listen for messages for
331: * %ALLDROUTERS have to be opened, etc.
332: */
333: void
334: ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
335: {
336: struct ospf_proto *p = ifa->oa->po;
337: u8 oldstate = ifa->state;
338:
339: if (state == oldstate)
340: return;
341:
342: OSPF_TRACE(D_EVENTS, "Interface %s changed state from %s to %s",
343: ifa->ifname, ospf_is_names[oldstate], ospf_is_names[state]);
344:
345: ifa->state = state;
346:
347: if ((ifa->type == OSPF_IT_BCAST) && ipa_nonzero(ifa->des_routers) && ifa->sk)
348: {
349: if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
350: ospf_sk_join_dr(ifa);
351: else
352: ospf_sk_leave_dr(ifa);
353: }
354:
355: if ((oldstate > OSPF_IS_LOOP) && (state <= OSPF_IS_LOOP))
356: ospf_iface_down(ifa);
357:
358: /* RFC 2328 12.4 Event 2 - iface state change */
359: ospf_notify_rt_lsa(ifa->oa);
360:
361: /* RFC 5340 4.4.3 Event 1 - iface state change */
362: ospf_notify_link_lsa(ifa);
363:
364: /* RFC 2328 12.4 Event 3 - iface enters/leaves DR state */
365: ospf_notify_net_lsa(ifa);
366: }
367:
368: /**
369: * ospf_iface_sm - OSPF interface state machine
370: * @ifa: OSPF interface
371: * @event: event comming to state machine
372: *
373: * This fully respects 9.3 of RFC 2328 except we have slightly
374: * different handling of %DOWN and %LOOP state. We remove intefaces
375: * that are %DOWN. %DOWN state is used when an interface is waiting
376: * for a lock. %LOOP state is used when an interface does not have a
377: * link.
378: */
379: void
380: ospf_iface_sm(struct ospf_iface *ifa, int event)
381: {
382: DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism_names[event]);
383:
384: switch (event)
385: {
386: case ISM_UP:
387: if (ifa->state <= OSPF_IS_LOOP)
388: {
389: /* Now, nothing should be adjacent */
390: if ((ifa->type == OSPF_IT_PTP) ||
391: (ifa->type == OSPF_IT_PTMP) ||
392: (ifa->type == OSPF_IT_VLINK))
393: {
394: ospf_iface_chstate(ifa, OSPF_IS_PTP);
395: }
396: else
397: {
398: if (ifa->priority == 0)
399: ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
400: else
401: {
402: ospf_iface_chstate(ifa, OSPF_IS_WAITING);
403: if (ifa->wait_timer)
404: tm_start(ifa->wait_timer, ifa->waitint S);
405: }
406: }
407:
408: if (ifa->hello_timer)
409: tm_start(ifa->hello_timer, ifa->helloint S);
410:
411: if (ifa->poll_timer)
412: tm_start(ifa->poll_timer, ifa->pollint S);
413:
414: ospf_send_hello(ifa, OHS_HELLO, NULL);
415: }
416: break;
417:
418: case ISM_BACKS:
419: case ISM_WAITF:
420: if (ifa->state == OSPF_IS_WAITING)
421: ospf_dr_election(ifa);
422: break;
423:
424: case ISM_NEICH:
425: if (ifa->state >= OSPF_IS_DROTHER)
426: ospf_dr_election(ifa);
427: break;
428:
429: case ISM_LOOP:
430: if ((ifa->state > OSPF_IS_LOOP) && ifa->check_link)
431: ospf_iface_chstate(ifa, OSPF_IS_LOOP);
432: break;
433:
434: case ISM_UNLOOP:
435: /* Immediate go UP */
436: if (ifa->state == OSPF_IS_LOOP)
437: ospf_iface_sm(ifa, ISM_UP);
438: break;
439:
440: case ISM_DOWN:
441: ospf_iface_chstate(ifa, OSPF_IS_DOWN);
442: break;
443:
444: default:
445: bug("OSPF_I_SM - Unknown event?");
446: break;
447: }
448:
449: }
450:
451: static u8
452: ospf_iface_classify_(struct iface *ifa, struct ifa *addr)
453: {
454: if (ipa_nonzero(addr->opposite))
455: return (ifa->flags & IF_MULTICAST) ? OSPF_IT_PTP : OSPF_IT_PTMP;
456:
457: if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
458: (IF_MULTIACCESS | IF_MULTICAST))
459: return OSPF_IT_BCAST;
460:
461: if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS)
462: return OSPF_IT_NBMA;
463:
464: return OSPF_IT_PTP;
465: }
466:
467: static inline u8
468: ospf_iface_classify(u8 type, struct ifa *addr)
469: {
470: return (type != OSPF_IT_UNDEF) ? type : ospf_iface_classify_(addr->iface, addr);
471: }
472:
473:
474: struct ospf_iface *
475: ospf_iface_find(struct ospf_proto *p, struct iface *what)
476: {
477: struct ospf_iface *ifa;
478:
479: WALK_LIST(ifa, p->iface_list)
480: if ((ifa->iface == what) && (ifa->type != OSPF_IT_VLINK))
481: return ifa;
482:
483: return NULL;
484: }
485:
486: static void
487: ospf_iface_add(struct object_lock *lock)
488: {
489: struct ospf_iface *ifa = lock->data;
490: struct ospf_proto *p = ifa->oa->po;
491:
492: /* Open socket if interface is not stub */
493: if (! ifa->stub && ! ospf_sk_open(ifa))
494: {
495: log(L_ERR "%s: Cannot open socket for %s, declaring as stub", p->p.name, ifa->ifname);
496: ifa->ioprob = OSPF_I_SK;
497: ifa->stub = 1;
498: }
499:
500: if (! ifa->stub)
501: {
502: ifa->hello_timer = tm_new_init(ifa->pool, hello_timer_hook, ifa, ifa->helloint S, 0);
503:
504: if (ifa->type == OSPF_IT_NBMA)
505: ifa->poll_timer = tm_new_init(ifa->pool, poll_timer_hook, ifa, ifa->pollint S, 0);
506:
507: if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
508: ifa->wait_timer = tm_new_init(ifa->pool, wait_timer_hook, ifa, 0, 0);
509:
510: ifa->flood_queue_size = ifa_flood_queue_size(ifa);
511: ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
512: }
513:
514: /* Do iface UP, unless there is no link (then wait in LOOP state) */
515: if (!ifa->check_link || (ifa->iface->flags & IF_LINK_UP))
516: ospf_iface_sm(ifa, ISM_UP);
517: else
518: ospf_iface_chstate(ifa, OSPF_IS_LOOP);
519: }
520:
521: static inline void
522: add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
523: {
524: struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node));
525: add_tail(&ifa->nbma_list, NODE n);
526: n->ip = src->ip;
527: n->eligible = src->eligible;
528: n->found = found;
529: }
530:
531: static int
532: ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
533: {
534: /* vlink cannot be stub */
535: if (ip->type == OSPF_IT_VLINK)
536: return 0;
537:
538: /* a host address */
539: if (addr->flags & IA_HOST)
540: return 1;
541:
542: /* a loopback iface */
543: if (addr->iface->flags & IF_LOOPBACK)
544: return 1;
545:
546: return ip->stub;
547: }
548:
549: void
550: ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip)
551: {
552: struct ospf_proto *p = oa->po;
553: struct iface *iface = addr->iface;
554: struct ospf_iface *ifa;
555: struct pool *pool;
556:
557: if (ospf_is_v3(p))
558: OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
559: iface->name, ip->instance_id, oa->areaid);
560: else if (addr->flags & IA_PEER)
561: OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R",
562: iface->name, addr->opposite, oa->areaid);
563: else
564: OSPF_TRACE(D_EVENTS, "Adding interface %s (%N) to area %R",
565: iface->name, &addr->prefix, oa->areaid);
566:
567: pool = rp_new(p->p.pool, "OSPF Interface");
568: ifa = mb_allocz(pool, sizeof(struct ospf_iface));
569: ifa->iface = iface;
570: ifa->addr = addr;
571: ifa->oa = oa;
572: ifa->cf = ip;
573: ifa->pool = pool;
574:
575: ifa->iface_id = iface->index;
576: ifa->ifname = iface->name;
577:
578: ifa->cost = ip->cost;
579: ifa->rxmtint = ip->rxmtint;
580: ifa->inftransdelay = ip->inftransdelay;
581: ifa->priority = ip->priority;
582: ifa->helloint = ip->helloint;
583: ifa->pollint = ip->pollint;
584: ifa->strictnbma = ip->strictnbma;
585: ifa->waitint = ip->waitint;
586: ifa->deadint = ip->deadint;
587: ifa->stub = ospf_iface_stubby(ip, addr);
588: ifa->ioprob = OSPF_I_OK;
589: ifa->tx_length = ifa_tx_length(ifa);
590: ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
591: ifa->check_link = ip->check_link;
592: ifa->ecmp_weight = ip->ecmp_weight;
593: ifa->check_ttl = (ip->ttl_security == 1);
594: ifa->bfd = ip->bfd;
595: ifa->autype = ip->autype;
596: ifa->passwords = ip->passwords;
597: ifa->instance_id = ip->instance_id;
598:
599: ifa->ptp_netmask = !(addr->flags & IA_PEER);
600: if (ip->ptp_netmask < 2)
601: ifa->ptp_netmask = ip->ptp_netmask;
602:
603: ifa->drip = ifa->bdrip = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6;
604:
605: ifa->type = ospf_iface_classify(ip->type, addr);
606:
607: /* Check validity of interface type */
608: int old_type = ifa->type;
609: u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
610:
611: if (ospf_is_v2(p) && (ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
612: ifa->type = OSPF_IT_PTP;
613:
614: if (ospf_is_v2(p) && (ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
615: ifa->type = OSPF_IT_PTMP;
616:
617: if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag) && !ifa->stub)
618: ifa->type = OSPF_IT_NBMA;
619:
620: if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag) && !ifa->stub)
621: ifa->type = OSPF_IT_PTMP;
622:
623: if (ifa->type != old_type)
624: log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
625: p->p.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
626:
627:
628: if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP))
629: ifa->link_lsa_suppression = ip->link_lsa_suppression;
630:
631: ifa->state = OSPF_IS_DOWN;
632: init_list(&ifa->neigh_list);
633: init_list(&ifa->nbma_list);
634:
635: struct nbma_node *nb;
636: WALK_LIST(nb, ip->nbma_list)
637: {
638: /* In OSPFv3, addr is link-local while configured neighbors could
639: have global IP (although RFC 5340 C.5 says link-local addresses
640: should be used). Because OSPFv3 iface is not subnet-specific,
641: there is no need for ipa_in_net() check */
642:
643: if (ospf_is_v2(p) && !ipa_in_netX(nb->ip, &addr->prefix))
644: continue;
645:
646: if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
647: log(L_WARN "%s: Configured neighbor address (%I) should be link-local",
648: p->p.name, nb->ip);
649:
650: add_nbma_node(ifa, nb, 0);
651: }
652:
653: add_tail(&oa->po->iface_list, NODE ifa);
654:
655: struct object_lock *lock = olock_new(pool);
656: lock->addr = ospf_is_v2(p) ? ipa_from_ip4(net4_prefix(&ifa->addr->prefix)) : IPA_NONE;
657: lock->type = OBJLOCK_IP;
658: lock->port = OSPF_PROTO;
659: lock->inst = ifa->instance_id;
660: lock->iface = iface;
661: lock->data = ifa;
662: lock->hook = ospf_iface_add;
663:
664: olock_acquire(lock);
665: }
666:
667: void
668: ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
669: {
670: struct ospf_iface *ifa;
671: struct pool *pool;
672:
673: if (!p->vlink_sk)
674: return;
675:
676: OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
677:
678: /* Vlink ifname is stored just after the ospf_iface structure */
679:
680: pool = rp_new(p->p.pool, "OSPF Vlink");
681: ifa = mb_allocz(pool, sizeof(struct ospf_iface) + 16);
682: ifa->oa = p->backbone;
683: ifa->cf = ip;
684: ifa->pool = pool;
685:
686: /* Assign iface ID, for vlinks, this is ugly hack */
687: u32 vlink_id = p->last_vlink_id++;
688: ifa->iface_id = vlink_id + OSPF_VLINK_ID_OFFSET;
689: ifa->ifname = (void *) (ifa + 1);
690: bsprintf(ifa->ifname, "vlink%d", vlink_id);
691:
692: ifa->voa = ospf_find_area(p, ip->voa);
693: ifa->vid = ip->vid;
694: ifa->sk = p->vlink_sk;
695:
696: ifa->helloint = ip->helloint;
697: ifa->rxmtint = ip->rxmtint;
698: ifa->waitint = ip->waitint;
699: ifa->deadint = ip->deadint;
700: ifa->inftransdelay = ip->inftransdelay;
701: ifa->tx_length = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
702: ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
703: ifa->autype = ip->autype;
704: ifa->passwords = ip->passwords;
705: ifa->instance_id = ip->instance_id;
706:
707: ifa->type = OSPF_IT_VLINK;
708:
709: ifa->state = OSPF_IS_DOWN;
710: init_list(&ifa->neigh_list);
711: init_list(&ifa->nbma_list);
712:
713: add_tail(&p->iface_list, NODE ifa);
714:
715: ifa->hello_timer = tm_new_init(ifa->pool, hello_timer_hook, ifa, ifa->helloint S, 0);
716:
717: ifa->flood_queue_size = ifa_flood_queue_size(ifa);
718: ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
719: }
720:
721: static void
722: ospf_iface_change_timer(timer *tm, uint val)
723: {
724: if (!tm)
725: return;
726:
727: tm->recurrent = val S;
728:
729: if (tm_active(tm))
730: tm_start(tm, val S);
731: }
732:
733: static inline void
734: ospf_iface_update_flood_queue_size(struct ospf_iface *ifa)
735: {
736: uint old_size = ifa->flood_queue_size;
737: uint new_size = ifa_flood_queue_size(ifa);
738:
739: if (new_size <= old_size)
740: return;
741:
742: ifa->flood_queue_size = new_size;
743: ifa->flood_queue = mb_realloc(ifa->flood_queue, new_size * sizeof(void *));
744: bzero(ifa->flood_queue + old_size, (new_size - old_size) * sizeof(void *));
745: }
746:
747: int
748: ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
749: {
750: struct ospf_proto *p = ifa->oa->po;
751: struct ospf_iface_patt *old = ifa->cf;
752: char *ifname = ifa->ifname;
753:
754: /* Type could be changed in ospf_iface_new(),
755: but if config values are same then also results are same */
756: int old_type = ospf_iface_classify(old->type, ifa->addr);
757: int new_type = ospf_iface_classify(new->type, ifa->addr);
758: if (old_type != new_type)
759: return 0;
760:
761: int new_stub = ospf_iface_stubby(new, ifa->addr);
762: if (ifa->stub != new_stub)
763: return 0;
764:
765: /* Change of these options would require to reset the iface socket */
766: if ((new->real_bcast != old->real_bcast) ||
767: (new->tx_tos != old->tx_tos) ||
768: (new->tx_priority != old->tx_priority) ||
769: (new->ttl_security != old->ttl_security))
770: return 0;
771:
772: ifa->cf = new;
773: ifa->marked = 0;
774:
775: /* Cancel GR peers if GR is disabled */
776: if (!p->gr_mode && p->gr_count)
777: {
778: struct ospf_neighbor *n, *nx;
779: WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
780: if (n->gr_active)
781: ospf_neigh_cancel_graceful_restart(n);
782: }
783:
784: /* HELLO TIMER */
785: if (ifa->helloint != new->helloint)
786: {
787: OSPF_TRACE(D_EVENTS, "Changing hello interval of %s from %d to %d",
788: ifname, ifa->helloint, new->helloint);
789:
790: ifa->helloint = new->helloint;
791: ospf_iface_change_timer(ifa->hello_timer, ifa->helloint);
792: }
793:
794: /* RXMT TIMER */
795: if (ifa->rxmtint != new->rxmtint)
796: {
797: OSPF_TRACE(D_EVENTS, "Changing retransmit interval of %s from %d to %d",
798: ifname, ifa->rxmtint, new->rxmtint);
799:
800: ifa->rxmtint = new->rxmtint;
801: /* FIXME: Update neighbors' timers */
802: }
803:
804: /* POLL TIMER */
805: if (ifa->pollint != new->pollint)
806: {
807: OSPF_TRACE(D_EVENTS, "Changing poll interval of %s from %d to %d",
808: ifname, ifa->pollint, new->pollint);
809:
810: ifa->pollint = new->pollint;
811: ospf_iface_change_timer(ifa->poll_timer, ifa->pollint);
812: }
813:
814: /* WAIT TIMER */
815: if (ifa->waitint != new->waitint)
816: {
817: OSPF_TRACE(D_EVENTS, "Changing wait interval of %s from %d to %d",
818: ifname, ifa->waitint, new->waitint);
819:
820: ifa->waitint = new->waitint;
821: if (ifa->wait_timer && tm_active(ifa->wait_timer))
822: tm_start(ifa->wait_timer, ifa->waitint S);
823: }
824:
825: /* DEAD TIMER */
826: if (ifa->deadint != new->deadint)
827: {
828: OSPF_TRACE(D_EVENTS, "Changing dead interval of %s from %d to %d",
829: ifname, ifa->deadint, new->deadint);
830: ifa->deadint = new->deadint;
831: }
832:
833: /* INFTRANS */
834: if (ifa->inftransdelay != new->inftransdelay)
835: {
836: OSPF_TRACE(D_EVENTS, "Changing transmit delay of %s from %d to %d",
837: ifname, ifa->inftransdelay, new->inftransdelay);
838: ifa->inftransdelay = new->inftransdelay;
839: }
840:
841: /* AUTHENTICATION */
842: if (ifa->autype != new->autype)
843: {
844: OSPF_TRACE(D_EVENTS, "Changing authentication type of %s", ifname);
845: ifa->autype = new->autype;
846:
847: /* For OSPFv3, we need to update checksum calculation by OS */
848: if (ospf_is_v3(p) && ifa->sk)
849: if (sk_set_ipv6_checksum(ifa->sk, ifa->autype ? -1 : 12) < 0)
850: {
851: sk_log_error(ifa->sk, p->p.name);
852: return 0;
853: }
854: }
855:
856: /* Update passwords */
857: ifa->passwords = new->passwords;
858:
859: /* Update header length */
860: ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
861:
862: /* Remaining options are just for proper interfaces */
863: if (ifa->type == OSPF_IT_VLINK)
864: return 1;
865:
866:
867: /* COST */
868: if (ifa->cost != new->cost)
869: {
870: OSPF_TRACE(D_EVENTS, "Changing cost of %s from %d to %d",
871: ifname, ifa->cost, new->cost);
872:
873: ifa->cost = new->cost;
874: }
875:
876: /* PRIORITY */
877: if (ifa->priority != new->priority)
878: {
879: OSPF_TRACE(D_EVENTS, "Changing priority of %s from %d to %d",
880: ifname, ifa->priority, new->priority);
881:
882: ifa->priority = new->priority;
883: ospf_iface_sm(ifa, ISM_NEICH);
884: ospf_notify_link_lsa(ifa);
885: }
886:
887: /* STRICT NBMA */
888: if (ifa->strictnbma != new->strictnbma)
889: {
890: OSPF_TRACE(D_EVENTS, "Changing NBMA strictness of %s from %d to %d",
891: ifname, ifa->strictnbma, new->strictnbma);
892: ifa->strictnbma = new->strictnbma;
893: }
894:
895: struct nbma_node *nb, *nbx;
896:
897: /* NBMA LIST - remove or update old */
898: WALK_LIST_DELSAFE(nb, nbx, ifa->nbma_list)
899: {
900: struct nbma_node *nb2 = find_nbma_node_(&new->nbma_list, nb->ip);
901: if (nb2)
902: {
903: if (nb->eligible != nb2->eligible)
904: {
905: OSPF_TRACE(D_EVENTS, "Changing eligibility of NBMA neighbor %I on %s",
906: nb->ip, ifname);
907: nb->eligible = nb2->eligible;
908: }
909: }
910: else
911: {
912: OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on %s",
913: nb->ip, ifname);
914: rem_node(NODE nb);
915: mb_free(nb);
916: }
917: }
918:
919: /* NBMA LIST - add new */
920: WALK_LIST(nb, new->nbma_list)
921: {
922: /* See related note in ospf_iface_new() */
923: if (ospf_is_v2(p) && !ipa_in_netX(nb->ip, &ifa->addr->prefix))
924: continue;
925:
926: if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
927: log(L_WARN "%s: Configured neighbor address (%I) should be link-local",
928: p->p.name, nb->ip);
929:
930: if (! find_nbma_node(ifa, nb->ip))
931: {
932: OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on %s",
933: nb->ip, ifname);
934: add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip));
935: }
936: }
937:
938: int update_buffers = 0;
939:
940: /* TX LENGTH */
941: if (old->tx_length != new->tx_length)
942: {
943: OSPF_TRACE(D_EVENTS, "Changing TX length of %s from %d to %d",
944: ifname, old->tx_length, new->tx_length);
945:
946: /* ifa cannot be vlink */
947: ifa->tx_length = ifa_tx_length(ifa);
948: update_buffers = 1;
949:
950: if (!ifa->stub)
951: ospf_iface_update_flood_queue_size(ifa);
952: }
953:
954: /* RX BUFFER */
955: if (old->rx_buffer != new->rx_buffer)
956: {
957: OSPF_TRACE(D_EVENTS, "Changing buffer size of %s from %d to %d",
958: ifname, old->rx_buffer, new->rx_buffer);
959:
960: /* ifa cannot be vlink */
961: update_buffers = 1;
962: }
963:
964: /* Buffer size depends on both tx_length and rx_buffer options */
965: if (update_buffers && ifa->sk)
966: {
967: uint bsize = ifa_bufsize(ifa);
968: sk_set_rbsize(ifa->sk, bsize);
969: sk_set_tbsize(ifa->sk, bsize);
970: }
971:
972: /* LINK */
973: if (ifa->check_link != new->check_link)
974: {
975: OSPF_TRACE(D_EVENTS, "%s link check for %s",
976: new->check_link ? "Enabling" : "Disabling", ifname);
977: ifa->check_link = new->check_link;
978:
979: /* ifa cannot be vlink */
980: if (!(ifa->iface->flags & IF_LINK_UP))
981: ospf_iface_sm(ifa, ifa->check_link ? ISM_LOOP : ISM_UNLOOP);
982: }
983:
984: /* ECMP weight */
985: if (ifa->ecmp_weight != new->ecmp_weight)
986: {
987: OSPF_TRACE(D_EVENTS, "Changing ECMP weight of %s from %d to %d",
988: ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1);
989: ifa->ecmp_weight = new->ecmp_weight;
990: }
991:
992: /* Link LSA suppression */
993: if (((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) &&
994: (ifa->link_lsa_suppression != new->link_lsa_suppression))
995: {
996: OSPF_TRACE(D_EVENTS, "Changing link LSA suppression of %s from %d to %d",
997: ifname, ifa->link_lsa_suppression, new->link_lsa_suppression);
998:
999: ifa->link_lsa_suppression = new->link_lsa_suppression;
1000: ospf_notify_link_lsa(ifa);
1001: }
1002:
1003: /* BFD */
1004: if (ifa->bfd != new->bfd)
1005: {
1006: OSPF_TRACE(D_EVENTS, "%s BFD for %s",
1007: new->bfd ? "Enabling" : "Disabling", ifname);
1008: ifa->bfd = new->bfd;
1009:
1010: struct ospf_neighbor *n;
1011: WALK_LIST(n, ifa->neigh_list)
1012: ospf_neigh_update_bfd(n, ifa->bfd);
1013: }
1014:
1015:
1016: /* instance_id is not updated - it is part of key */
1017:
1018: return 1;
1019: }
1020:
1021:
1022: /*
1023: * State for matching iface pattterns walk
1024: *
1025: * This is significantly different in OSPFv2 and OSPFv3.
1026: * In OSPFv2, OSPF ifaces are created for each IP prefix (struct ifa)
1027: * In OSPFv3, OSPF ifaces are created based on real iface (struct iface)
1028: * We support instance_id for both OSPFv2 (RFC 6549) and OSPFv3.
1029: *
1030: * We process one ifa/iface and match it for all configured instance IDs. We
1031: * maintain bitfields to track whether given instance ID was already matched.
1032: * We have two bitfields, one global (active) and one per area (ignore), to
1033: * detect misconfigured cases where one iface with one instance ID matches in
1034: * multiple areas.
1035: */
1036:
1037: struct ospf_mip_walk {
1038: u32 active[8]; /* Bitfield of active instance IDs */
1039: u32 ignore[8]; /* Bitfield of instance IDs matched in current area */
1040: struct ospf_area *oa; /* Current area */
1041: struct ospf_iface_patt *ip; /* Current iface pattern */
1042: struct iface *iface; /* Specified iface (input) */
1043: struct ifa *a; /* Specified ifa (input) */
1044: int warn; /* Whether iface matched in multiple areas */
1045: };
1046:
1047: static int
1048: ospf_walk_matching_iface_patts(struct ospf_proto *p, struct ospf_mip_walk *s)
1049: {
1050: int id;
1051:
1052: if (s->ip)
1053: goto step;
1054:
1055: WALK_LIST(s->oa, p->area_list)
1056: {
1057: if (s->oa->marked)
1058: continue;
1059:
1060: WALK_LIST(s->ip, s->oa->ac->patt_list)
1061: {
1062: id = s->ip->instance_id;
1063: if (BIT32_TEST(s->ignore, id))
1064: continue;
1065:
1066: if (iface_patt_match(&s->ip->i, s->iface, s->a))
1067: {
1068: /* Now we matched ifa/iface/instance_id for the first time in current area */
1069: BIT32_SET(s->ignore, id);
1070:
1071: /* If we already found it in previous areas, ignore it and add warning */
1072: if (BIT32_TEST(s->active, id))
1073: { s->warn = 1; continue; }
1074:
1075: BIT32_SET(s->active, id);
1076: return 1;
1077: step:
1078: ;
1079: }
1080: }
1081: BIT32_ZERO(s->ignore, 256);
1082: }
1083:
1084: if (s->warn)
1085: log(L_WARN "%s: Interface %s matches for multiple areas", p->p.name, s->iface->name);
1086:
1087: return 0;
1088: }
1089:
1090:
1091: static struct ospf_iface *
1092: ospf_iface_find_by_key(struct ospf_proto *p, struct ifa *a, int instance_id)
1093: {
1094: struct ospf_iface *ifa;
1095:
1096: WALK_LIST(ifa, p->iface_list)
1097: if ((ifa->addr == a) && (ifa->instance_id == instance_id) &&
1098: (ifa->type != OSPF_IT_VLINK))
1099: return ifa;
1100:
1101: return NULL;
1102: }
1103:
1104:
1105: void
1106: ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a)
1107: {
1108: struct ospf_proto *p = (struct ospf_proto *) P;
1109:
1110: if (a->prefix.type != NET_IP4)
1111: return;
1112:
1113: if (a->flags & IA_SECONDARY)
1114: return;
1115:
1116: if (a->scope <= SCOPE_LINK)
1117: return;
1118:
1119: /* In OSPFv2, we create OSPF iface for each address. */
1120: if (flags & IF_CHANGE_UP)
1121: {
1122: struct ospf_mip_walk s = { .iface = a->iface, .a = a };
1123: while (ospf_walk_matching_iface_patts(p, &s))
1124: ospf_iface_new(s.oa, a, s.ip);
1125: }
1126:
1127: if (flags & IF_CHANGE_DOWN)
1128: {
1129: struct ospf_iface *ifa, *ifx;
1130: WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1131: if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
1132: ospf_iface_remove(ifa);
1133: /* See a note in ospf_iface_notify() */
1134: }
1135: }
1136:
1137: void
1138: ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a)
1139: {
1140: struct ospf_proto *p = (struct ospf_proto *) P;
1141:
1142: if (a->flags & IA_SECONDARY)
1143: return;
1144:
1145: if (a->scope < SCOPE_LINK)
1146: return;
1147:
1148: /* In OSPFv3, we create OSPF iface for link-local address,
1149: other addresses are used for link-LSA. */
1150: if (a->scope == SCOPE_LINK)
1151: {
1152: if (a->prefix.type != NET_IP6)
1153: return;
1154:
1155: if (flags & IF_CHANGE_UP)
1156: {
1157: struct ospf_mip_walk s = { .iface = a->iface };
1158: while (ospf_walk_matching_iface_patts(p, &s))
1159: ospf_iface_new(s.oa, a, s.ip);
1160: }
1161:
1162: if (flags & IF_CHANGE_DOWN)
1163: {
1164: struct ospf_iface *ifa, *ifx;
1165: WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1166: if ((ifa->addr == a) && (ifa->type != OSPF_IT_VLINK))
1167: ospf_iface_remove(ifa);
1168: }
1169: }
1170: else
1171: {
1172: if (a->prefix.type != ospf_get_af(p))
1173: return;
1174:
1175: struct ospf_iface *ifa;
1176: WALK_LIST(ifa, p->iface_list)
1177: if (ifa->iface == a->iface)
1178: {
1179: /* RFC 5340 4.4.3 Event 5 - prefix added/deleted */
1180: ospf_notify_link_lsa(ifa);
1181: ospf_notify_rt_lsa(ifa->oa);
1182: }
1183: }
1184: }
1185:
1186:
1187: static void
1188: ospf_reconfigure_ifaces2(struct ospf_proto *p)
1189: {
1190: struct iface *iface;
1191: struct ifa *a;
1192:
1193: WALK_LIST(iface, iface_list)
1194: {
1195: if (! (iface->flags & IF_UP))
1196: continue;
1197:
1198: WALK_LIST(a, iface->addrs)
1199: {
1200: if (a->prefix.type != NET_IP4)
1201: continue;
1202:
1203: if (a->flags & IA_SECONDARY)
1204: continue;
1205:
1206: if (a->scope <= SCOPE_LINK)
1207: continue;
1208:
1209: struct ospf_mip_walk s = { .iface = iface, .a = a };
1210: while (ospf_walk_matching_iface_patts(p, &s))
1211: {
1212: /* Main inner loop */
1213: struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id);
1214: if (ifa)
1215: {
1216: if ((ifa->oa == s.oa) && (ifa->marked < 2) &&
1217: ospf_iface_reconfigure(ifa, s.ip))
1218: continue;
1219:
1220: /* Hard restart */
1221: log(L_INFO "%s: Restarting interface %s (%N) in area %R",
1222: p->p.name, ifa->ifname, &a->prefix, s.oa->areaid);
1223: ospf_iface_shutdown(ifa);
1224: ospf_iface_remove(ifa);
1225: }
1226:
1227: ospf_iface_new(s.oa, a, s.ip);
1228: }
1229: }
1230: }
1231: }
1232:
1233: static void
1234: ospf_reconfigure_ifaces3(struct ospf_proto *p)
1235: {
1236: struct iface *iface;
1237: struct ifa *a;
1238:
1239: WALK_LIST(iface, iface_list)
1240: {
1241: if (! (iface->flags & IF_UP))
1242: continue;
1243:
1244: WALK_LIST(a, iface->addrs)
1245: {
1246: if (a->prefix.type != NET_IP6)
1247: continue;
1248:
1249: if (a->flags & IA_SECONDARY)
1250: continue;
1251:
1252: if (a->scope != SCOPE_LINK)
1253: continue;
1254:
1255: struct ospf_mip_walk s = { .iface = iface };
1256: while (ospf_walk_matching_iface_patts(p, &s))
1257: {
1258: /* Main inner loop */
1259: struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id);
1260: if (ifa)
1261: {
1262: if ((ifa->oa == s.oa) && (ifa->marked < 2) &&
1263: ospf_iface_reconfigure(ifa, s.ip))
1264: continue;
1265:
1266: /* Hard restart */
1267: log(L_INFO "%s: Restarting interface %s (IID %d) in area %R",
1268: p->p.name, ifa->ifname, ifa->instance_id, s.oa->areaid);
1269: ospf_iface_shutdown(ifa);
1270: ospf_iface_remove(ifa);
1271: }
1272:
1273: ospf_iface_new(s.oa, a, s.ip);
1274: }
1275: }
1276: }
1277: }
1278:
1279: void
1280: ospf_reconfigure_ifaces(struct ospf_proto *p)
1281: {
1282: if (ospf_is_v2(p))
1283: ospf_reconfigure_ifaces2(p);
1284: else
1285: ospf_reconfigure_ifaces3(p);
1286: }
1287:
1288:
1289: static void
1290: ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa)
1291: {
1292: /* ifa is not vlink */
1293:
1294: OSPF_TRACE(D_EVENTS, "Interface %s changed MTU to %d",
1295: ifa->ifname, ifa->iface->mtu);
1296:
1297: ifa->tx_length = ifa_tx_length(ifa);
1298:
1299: if (!ifa->sk)
1300: return;
1301:
1302: /* We do not shrink dynamic buffers */
1303: uint bsize = ifa_bufsize(ifa);
1304: if (bsize > ifa->sk->rbsize)
1305: sk_set_rbsize(ifa->sk, bsize);
1306: if (bsize > ifa->sk->tbsize)
1307: sk_set_tbsize(ifa->sk, bsize);
1308:
1309: if (!ifa->stub)
1310: ospf_iface_update_flood_queue_size(ifa);
1311: }
1312:
1313: static void
1314: ospf_iface_notify(struct ospf_proto *p, uint flags, struct ospf_iface *ifa)
1315: {
1316: /* ifa is not vlink */
1317:
1318: if (flags & IF_CHANGE_DOWN)
1319: {
1320: ospf_iface_remove(ifa);
1321: return;
1322: }
1323:
1324: if (flags & IF_CHANGE_LINK)
1325: ospf_iface_sm(ifa, (ifa->iface->flags & IF_LINK_UP) ? ISM_UNLOOP : ISM_LOOP);
1326:
1327: if (flags & IF_CHANGE_MTU)
1328: ospf_iface_change_mtu(p, ifa);
1329: }
1330:
1331: void
1332: ospf_if_notify(struct proto *P, uint flags, struct iface *iface)
1333: {
1334: struct ospf_proto *p = (struct ospf_proto *) P;
1335:
1336: /*
1337: if (iface->flags & IF_IGNORE)
1338: return;
1339: */
1340:
1341: /* Going up means that there are no such ifaces yet */
1342: if (flags & IF_CHANGE_UP)
1343: return;
1344:
1345: struct ospf_iface *ifa, *ifx;
1346: WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1347: if (ifa->iface == iface)
1348: ospf_iface_notify(p, flags, ifa);
1349:
1350: /* We use here that even shutting down iface also shuts down
1351: the vlinks, but vlinks are not freed and stays in the
1352: iface_list even when down */
1353: }
1354:
1355: void
1356: ospf_iface_info(struct ospf_iface *ifa)
1357: {
1358: char *more = "";
1359:
1360: if (ifa->strictnbma &&
1361: ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
1362: more = " (strict)";
1363:
1364: if (ifa->cf->real_bcast &&
1365: ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)))
1366: more = " (real)";
1367:
1368: if (ifa->type == OSPF_IT_VLINK)
1369: {
1370: cli_msg(-1015, "Virtual link %s to %R", ifa->ifname, ifa->vid);
1371: cli_msg(-1015, "\tPeer IP: %I", ifa->vip);
1372: cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid, ifa->voa->areaid);
1373: }
1374: else
1375: {
1376: if (ospf_is_v3(ifa->oa->po))
1377: cli_msg(-1015, "Interface %s (IID %d)", ifa->ifname, ifa->instance_id);
1378: else if (ifa->addr->flags & IA_PEER)
1379: cli_msg(-1015, "Interface %s (peer %I)", ifa->ifname, ifa->addr->opposite);
1380: else
1381: cli_msg(-1015, "Interface %s (%N)", ifa->ifname, &ifa->addr->prefix);
1382:
1383: cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
1384: cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
1385: }
1386: cli_msg(-1015, "\tState: %s%s", ospf_is_names[ifa->state], ifa->stub ? " (stub)" : "");
1387: cli_msg(-1015, "\tPriority: %u", ifa->priority);
1388: cli_msg(-1015, "\tCost: %u", ifa->cost);
1389: if (ifa->oa->po->ecmp)
1390: cli_msg(-1015, "\tECMP weight: %d", ((int) ifa->ecmp_weight) + 1);
1391: cli_msg(-1015, "\tHello timer: %u", ifa->helloint);
1392:
1393: if (ifa->type == OSPF_IT_NBMA)
1394: {
1395: cli_msg(-1015, "\tPoll timer: %u", ifa->pollint);
1396: }
1397: cli_msg(-1015, "\tWait timer: %u", ifa->waitint);
1398: cli_msg(-1015, "\tDead timer: %u", ifa->deadint);
1399: cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint);
1400: if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
1401: {
1402: cli_msg(-1015, "\tDesignated router (ID): %R", ifa->drid);
1403: cli_msg(-1015, "\tDesignated router (IP): %I", ifa->drip);
1404: cli_msg(-1015, "\tBackup designated router (ID): %R", ifa->bdrid);
1405: cli_msg(-1015, "\tBackup designated router (IP): %I", ifa->bdrip);
1406: }
1407: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>