Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / iface.c @ a7a7372a

History | View | Annotate | Download (32.3 KB)

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

    
13

    
14
char *ospf_is[] = { "down", "loop", "waiting", "ptp", "drother",
15
  "backup", "dr"
16
};
17

    
18
char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen",
19
  "neighbor change", "loop indicated", "unloop indicated", "interface down"
20
};
21

    
22
char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" };
23

    
24

    
25
static void
26
poll_timer_hook(timer * timer)
27
{
28
  ospf_send_hello(timer->data, OHS_POLL, NULL);
29
}
30

    
31
static void
32
hello_timer_hook(timer * timer)
33
{
34
  ospf_send_hello(timer->data, OHS_HELLO, NULL);
35
}
36

    
37
static void
38
wait_timer_hook(timer * timer)
39
{
40
  struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
41
  struct ospf_proto *p = ifa->oa->po;
42

    
43
  OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s", ifa->ifname);
44
  ospf_iface_sm(ifa, ISM_WAITF);
45
}
46

    
47
static inline uint
48
ifa_tx_length(struct ospf_iface *ifa)
49
{
50
  return ifa->cf->tx_length ?: ifa->iface->mtu; 
51
}
52

    
53
static inline uint
54
ifa_bufsize(struct ospf_iface *ifa)
55
{
56
  uint bsize = ifa->cf->rx_buffer ?: ifa->iface->mtu;
57
  return MAX(bsize, ifa->tx_length);
58
}
59

    
60
int
61
ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
62
{
63
  plen += SIZE_OF_IP_HEADER;
64

    
65
  /* This is relevant just for OSPFv2 */
66
  if (ifa->autype == OSPF_AUTH_CRYPT)
67
    plen += OSPF_AUTH_CRYPT_SIZE;
68

    
69
  if (plen <= ifa->sk->tbsize)
70
    return 0;
71

    
72
  if (ifa->cf->rx_buffer || (plen > 0xffff))
73
    return -1;
74

    
75
  plen = BIRD_ALIGN(plen, 1024);
76
  plen = MIN(plen, 0xffff);
77
  sk_set_tbsize(ifa->sk, plen);
78
  return 1;
79
}
80

    
81

    
82
struct nbma_node *
83
find_nbma_node_(list *nnl, ip_addr ip)
84
{
85
  struct nbma_node *nn;
86

    
87
  WALK_LIST(nn, *nnl)
88
    if (ipa_equal(nn->ip, ip))
89
      return nn;
90

    
91
  return NULL;
92
}
93

    
94

    
95
static int
96
ospf_sk_open(struct ospf_iface *ifa)
97
{
98
  struct ospf_proto *p = ifa->oa->po;
99

    
100
  sock *sk = sk_new(ifa->pool);
101
  sk->type = SK_IP;
102
  sk->dport = OSPF_PROTO;
103
  sk->saddr = ifa->addr->ip;
104
  sk->iface = ifa->iface;
105

    
106
  sk->tos = ifa->cf->tx_tos;
107
  sk->priority = ifa->cf->tx_priority;
108
  sk->rx_hook = ospf_rx_hook;
109
  // sk->tx_hook = ospf_tx_hook;
110
  sk->err_hook = ospf_err_hook;
111
  sk->rbsize = sk->tbsize = ifa_bufsize(ifa);
112
  sk->data = (void *) ifa;
113
  sk->flags = SKF_LADDR_RX | (ifa->check_ttl ? SKF_TTL_RX : 0);
114
  sk->ttl = ifa->cf->ttl_security ? 255 : 1;
115

    
116
  if (sk_open(sk) < 0)
117
    goto err;
118

    
119
  /* 12 is an offset of the checksum in an OSPFv3 packet */
120
  if (ospf_is_v3(p))
121
    if (sk_set_ipv6_checksum(sk, 12) < 0)
122
      goto err;
123

    
124
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
125
  {
126
    if (ifa->cf->real_bcast)
127
    {
128
      ifa->all_routers = ifa->addr->brd;
129
      ifa->des_routers = IPA_NONE;
130

    
131
      if (sk_setup_broadcast(sk) < 0)
132
        goto err;
133
    }
134
    else
135
    {
136
      ifa->all_routers = ospf_is_v2(p) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS;
137
      ifa->des_routers = ospf_is_v2(p) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS;
138

    
139
      if (sk_setup_multicast(sk) < 0)
140
        goto err;
141

    
142
      if (sk_join_group(sk, ifa->all_routers) < 0)
143
        goto err;
144
    }
145
  }
146

    
147
  ifa->sk = sk;
148
  ifa->sk_dr = 0;
149
  return 1;
150

    
151
 err:
152
  sk_log_error(sk, p->p.name);
153
  rfree(sk);
154
  return 0;
155
}
156

    
157
static inline void
158
ospf_sk_join_dr(struct ospf_iface *ifa)
159
{
160
  if (ifa->sk_dr)
161
    return;
162

    
163
  if (sk_join_group(ifa->sk, ifa->des_routers) < 0)
164
    sk_log_error(ifa->sk, ifa->oa->po->p.name);
165

    
166
  ifa->sk_dr = 1;
167
}
168

    
169
static inline void
170
ospf_sk_leave_dr(struct ospf_iface *ifa)
171
{
172
  if (!ifa->sk_dr)
173
    return;
174

    
175
  if (sk_leave_group(ifa->sk, ifa->des_routers) < 0)
176
    sk_log_error(ifa->sk, ifa->oa->po->p.name);
177

    
178
  ifa->sk_dr = 0;
179
}
180

    
181
void
182
ospf_open_vlink_sk(struct ospf_proto *p)
183
{
184
  sock *sk = sk_new(p->p.pool);
185
  sk->type = SK_IP;
186
  sk->dport = OSPF_PROTO;
187

    
188
  /* FIXME: configurable tos/priority ? */
189
  sk->tos = IP_PREC_INTERNET_CONTROL;
190
  sk->priority = sk_priority_control;
191
  sk->err_hook = ospf_verr_hook;
192

    
193
  sk->rbsize = 0;
194
  sk->tbsize = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
195
  sk->data = (void *) p;
196
  sk->flags = 0;
197

    
198
  if (sk_open(sk) < 0)
199
    goto err;
200

    
201
  /* 12 is an offset of the checksum in an OSPFv3 packet */
202
  if (ospf_is_v3(p))
203
    if (sk_set_ipv6_checksum(sk, 12) < 0)
204
      goto err;
205

    
206
  p->vlink_sk = sk;
207
  return;
208

    
209
 err:
210
  sk_log_error(sk, p->p.name);
211
  log(L_ERR "%s: Cannot open virtual link socket", p->p.name);
212
  rfree(sk);
213
}
214

    
215
static void
216
ospf_iface_down(struct ospf_iface *ifa)
217
{
218
  struct ospf_proto *p = ifa->oa->po;
219
  struct ospf_neighbor *n, *nx;
220
  struct ospf_iface *iff;
221

    
222
  if (ifa->type != OSPF_IT_VLINK)
223
  {
224
    if (ospf_is_v3(ifa->oa->po))
225
      OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
226
                 ifa->ifname, ifa->instance_id, ifa->oa->areaid);
227
    else if (ifa->addr->flags & IA_PEER)
228
      OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R",
229
                 ifa->ifname, ifa->addr->opposite, ifa->oa->areaid);
230
    else
231
      OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R",
232
                 ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
233

    
234
    /* First of all kill all the related vlinks */
235
    WALK_LIST(iff, p->iface_list)
236
    {
237
      if ((iff->type == OSPF_IT_VLINK) && (iff->vifa == ifa))
238
        ospf_iface_sm(iff, ISM_DOWN);
239
    }
240
  }
241

    
242
  WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
243
  {
244
    OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
245
    ospf_neigh_remove(n);
246
  }
247

    
248
  if (ifa->hello_timer)
249
    tm_stop(ifa->hello_timer);
250

    
251
  if (ifa->poll_timer)
252
    tm_stop(ifa->poll_timer);
253

    
254
  if (ifa->wait_timer)
255
    tm_stop(ifa->wait_timer);
256

    
257
  ospf_flush2_lsa(p, &ifa->link_lsa);
258
  ospf_flush2_lsa(p, &ifa->net_lsa);
259
  ospf_flush2_lsa(p, &ifa->pxn_lsa);
260

    
261
  if (ifa->type == OSPF_IT_VLINK)
262
  {
263
    ifa->vifa = NULL;
264
    ifa->addr = NULL;
265
    ifa->cost = 0;
266
    ifa->vip = IPA_NONE;
267
  }
268

    
269
  ifa->rt_pos_beg = 0;
270
  ifa->rt_pos_end = 0;
271
  ifa->px_pos_beg = 0;
272
  ifa->px_pos_end = 0;
273
}
274

    
275

    
276
void
277
ospf_iface_remove(struct ospf_iface *ifa)
278
{
279
  struct ospf_proto *p = ifa->oa->po;
280

    
281
  if (ifa->type == OSPF_IT_VLINK)
282
    OSPF_TRACE(D_EVENTS, "Removing vlink to %R via area %R", ifa->vid, ifa->voa->areaid);
283

    
284
  ospf_iface_sm(ifa, ISM_DOWN);
285
  rem_node(NODE ifa);
286
  rfree(ifa->pool);
287
}
288

    
289
void
290
ospf_iface_shutdown(struct ospf_iface *ifa)
291
{
292
  if (ifa->state > OSPF_IS_DOWN)
293
    ospf_send_hello(ifa, OHS_SHUTDOWN, NULL);
294
}
295

    
296
/**
297
 * ospf_iface_chstate - handle changes of interface state
298
 * @ifa: OSPF interface
299
 * @state: new state
300
 *
301
 * Many actions must be taken according to interface state changes. New network
302
 * LSAs must be originated, flushed, new multicast sockets to listen for messages for
303
 * %ALLDROUTERS have to be opened, etc.
304
 */
305
void
306
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
307
{
308
  struct ospf_proto *p = ifa->oa->po;
309
  u8 oldstate = ifa->state;
310

    
311
  if (state == oldstate)
312
    return;
313

    
314
  OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
315
             ifa->ifname, ospf_is[oldstate], ospf_is[state]);
316

    
317
  ifa->state = state;
318

    
319
  if ((ifa->type == OSPF_IT_BCAST) && ipa_nonzero(ifa->des_routers) && ifa->sk)
320
  {
321
    if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
322
      ospf_sk_join_dr(ifa);
323
    else
324
      ospf_sk_leave_dr(ifa);
325
  }
326

    
327
  if ((oldstate > OSPF_IS_LOOP) && (state <= OSPF_IS_LOOP))
328
    ospf_iface_down(ifa);
329

    
330
  /* RFC 2328 12.4 Event 2 - iface state change */
331
  ospf_notify_rt_lsa(ifa->oa);
332

    
333
  /* RFC 5340 4.4.3 Event 1 - iface state change */
334
  ospf_notify_link_lsa(ifa);
335

    
336
  /* RFC 2328 12.4 Event 3 - iface enters/leaves DR state */
337
  ospf_notify_net_lsa(ifa);
338
}
339

    
340
/**
341
 * ospf_iface_sm - OSPF interface state machine
342
 * @ifa: OSPF interface
343
 * @event: event comming to state machine
344
 *
345
 * This fully respects 9.3 of RFC 2328 except we have slightly
346
 * different handling of %DOWN and %LOOP state. We remove intefaces
347
 * that are %DOWN. %DOWN state is used when an interface is waiting
348
 * for a lock. %LOOP state is used when an interface does not have a
349
 * link.
350
 */
351
void
352
ospf_iface_sm(struct ospf_iface *ifa, int event)
353
{
354
  DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism[event]);
355

    
356
  switch (event)
357
  {
358
  case ISM_UP:
359
    if (ifa->state <= OSPF_IS_LOOP)
360
    {
361
      /* Now, nothing should be adjacent */
362
      if ((ifa->type == OSPF_IT_PTP) ||
363
          (ifa->type == OSPF_IT_PTMP) ||
364
          (ifa->type == OSPF_IT_VLINK))
365
      {
366
        ospf_iface_chstate(ifa, OSPF_IS_PTP);
367
      }
368
      else
369
      {
370
        if (ifa->priority == 0)
371
          ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
372
        else
373
        {
374
          ospf_iface_chstate(ifa, OSPF_IS_WAITING);
375
          if (ifa->wait_timer)
376
            tm_start(ifa->wait_timer, ifa->waitint);
377
        }
378
      }
379

    
380
      if (ifa->hello_timer)
381
        tm_start(ifa->hello_timer, ifa->helloint);
382

    
383
      if (ifa->poll_timer)
384
        tm_start(ifa->poll_timer, ifa->pollint);
385

    
386
      ospf_send_hello(ifa, OHS_HELLO, NULL);
387
    }
388
    break;
389

    
390
  case ISM_BACKS:
391
  case ISM_WAITF:
392
    if (ifa->state == OSPF_IS_WAITING)
393
      ospf_dr_election(ifa);
394
    break;
395

    
396
  case ISM_NEICH:
397
    if (ifa->state >= OSPF_IS_DROTHER)
398
      ospf_dr_election(ifa);
399
    break;
400

    
401
  case ISM_LOOP:
402
    if ((ifa->state > OSPF_IS_LOOP) && ifa->check_link)
403
      ospf_iface_chstate(ifa, OSPF_IS_LOOP);
404
    break;
405

    
406
  case ISM_UNLOOP:
407
    /* Immediate go UP */
408
    if (ifa->state == OSPF_IS_LOOP)
409
      ospf_iface_sm(ifa, ISM_UP);
410
    break;
411

    
412
  case ISM_DOWN:
413
    ospf_iface_chstate(ifa, OSPF_IS_DOWN);
414
    break;
415

    
416
  default:
417
    bug("OSPF_I_SM - Unknown event?");
418
    break;
419
  }
420

    
421
}
422

    
423
static u8
424
ospf_iface_classify_(struct iface *ifa, struct ifa *addr)
425
{
426
  if (ipa_nonzero(addr->opposite))
427
    return (ifa->flags & IF_MULTICAST) ? OSPF_IT_PTP :  OSPF_IT_PTMP;
428

    
429
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
430
      (IF_MULTIACCESS | IF_MULTICAST))
431
    return OSPF_IT_BCAST;
432

    
433
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS)
434
    return OSPF_IT_NBMA;
435

    
436
  return OSPF_IT_PTP;
437
}
438

    
439
static inline u8
440
ospf_iface_classify(u8 type, struct ifa *addr)
441
{
442
  return (type != OSPF_IT_UNDEF) ? type : ospf_iface_classify_(addr->iface, addr);
443
}
444

    
445

    
446
struct ospf_iface *
447
ospf_iface_find(struct ospf_proto *p, struct iface *what)
448
{
449
  struct ospf_iface *ifa;
450

    
451
  WALK_LIST(ifa, p->iface_list)
452
    if ((ifa->iface == what) && (ifa->type != OSPF_IT_VLINK))
453
      return ifa;
454

    
455
  return NULL;
456
}
457

    
458
static void
459
ospf_iface_add(struct object_lock *lock)
460
{
461
  struct ospf_iface *ifa = lock->data;
462
  struct ospf_proto *p = ifa->oa->po;
463

    
464
  /* Open socket if interface is not stub */
465
  if (! ifa->stub && ! ospf_sk_open(ifa))
466
  {
467
    log(L_ERR "%s: Cannot open socket for %s, declaring as stub", p->p.name, ifa->ifname);
468
    ifa->ioprob = OSPF_I_SK;
469
    ifa->stub = 1;
470
  }
471

    
472
  if (! ifa->stub)
473
  {
474
    ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
475

    
476
    if (ifa->type == OSPF_IT_NBMA)
477
      ifa->poll_timer = tm_new_set(ifa->pool, poll_timer_hook, ifa, 0, ifa->pollint);
478

    
479
    if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
480
      ifa->wait_timer = tm_new_set(ifa->pool, wait_timer_hook, ifa, 0, 0);
481
  }
482

    
483
  /* Do iface UP, unless there is no link and we use link detection */
484
  ospf_iface_sm(ifa, (ifa->check_link && !(ifa->iface->flags & IF_LINK_UP)) ? ISM_LOOP : ISM_UP);
485
}
486

    
487
static inline void
488
add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
489
{
490
  struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node));
491
  add_tail(&ifa->nbma_list, NODE n);
492
  n->ip = src->ip;
493
  n->eligible = src->eligible;
494
  n->found = found;
495
}
496

    
497
static int
498
ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
499
{
500
  /* a host address */
501
  if (addr->flags & IA_HOST)
502
    return 1;
503

    
504
  /* a loopback iface */
505
  if (addr->iface->flags & IF_LOOPBACK)
506
    return 1;
507

    
508
  /*
509
   * For compatibility reasons on BSD systems, we force OSPF
510
   * interfaces with non-primary IP prefixes to be stub.
511
   */
512
#if defined(OSPFv2) && !defined(CONFIG_MC_PROPER_SRC)
513
  if (!ip->bsd_secondary && !(addr->flags & IA_PRIMARY))
514
    return 1;
515
#endif
516

    
517
  return ip->stub;
518
}
519

    
520
void
521
ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip)
522
{
523
  struct ospf_proto *p = oa->po;
524
  struct iface *iface = addr->iface;
525
  struct ospf_iface *ifa;
526
  struct pool *pool;
527

    
528
  if (ospf_is_v3(p))
529
    OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
530
               iface->name, ip->instance_id, oa->areaid);
531
  else if (addr->flags & IA_PEER)
532
    OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R",
533
               iface->name, addr->opposite, oa->areaid);
534
  else
535
    OSPF_TRACE(D_EVENTS, "Adding interface %s (%I/%d) to area %R",
536
               iface->name, addr->prefix, addr->pxlen, oa->areaid);
537

    
538
  pool = rp_new(p->p.pool, "OSPF Interface");
539
  ifa = mb_allocz(pool, sizeof(struct ospf_iface));
540
  ifa->iface = iface;
541
  ifa->addr = addr;
542
  ifa->oa = oa;
543
  ifa->cf = ip;
544
  ifa->pool = pool;
545

    
546
  ifa->iface_id = iface->index;
547
  ifa->ifname = iface->name;
548

    
549
  ifa->cost = ip->cost;
550
  ifa->rxmtint = ip->rxmtint;
551
  ifa->inftransdelay = ip->inftransdelay;
552
  ifa->priority = ip->priority;
553
  ifa->helloint = ip->helloint;
554
  ifa->pollint = ip->pollint;
555
  ifa->strictnbma = ip->strictnbma;
556
  ifa->waitint = ip->waitint;
557
  ifa->deadint = ip->deadint;
558
  ifa->stub = ospf_iface_stubby(ip, addr);
559
  ifa->ioprob = OSPF_I_OK;
560
  ifa->tx_length = ifa_tx_length(ifa);
561
  ifa->check_link = ip->check_link;
562
  ifa->ecmp_weight = ip->ecmp_weight;
563
  ifa->check_ttl = (ip->ttl_security == 1);
564
  ifa->bfd = ip->bfd;
565
  ifa->autype = ip->autype;
566
  ifa->passwords = ip->passwords;
567
  ifa->instance_id = ip->instance_id;
568

    
569
  ifa->ptp_netmask = !(addr->flags & IA_PEER);
570
  if (ip->ptp_netmask < 2)
571
    ifa->ptp_netmask = ip->ptp_netmask;
572

    
573

    
574
  ifa->type = ospf_iface_classify(ip->type, addr);
575

    
576
  /* Check validity of interface type */
577
  int old_type = ifa->type;
578
  u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
579

    
580
  if (ospf_is_v2(p) && (ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
581
    ifa->type = OSPF_IT_PTP;
582

    
583
  if (ospf_is_v2(p) && (ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
584
    ifa->type = OSPF_IT_PTMP;
585

    
586
  if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag))
587
    ifa->type = OSPF_IT_NBMA;
588

    
589
  if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag))
590
    ifa->type = OSPF_IT_PTMP;
591

    
592
  if (ifa->type != old_type)
593
    log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
594
        p->p.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
595

    
596

    
597
  if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP))
598
    ifa->link_lsa_suppression = ip->link_lsa_suppression;
599

    
600
  ifa->state = OSPF_IS_DOWN;
601
  init_list(&ifa->neigh_list);
602
  init_list(&ifa->nbma_list);
603

    
604
  struct nbma_node *nb;
605
  WALK_LIST(nb, ip->nbma_list)
606
  {
607
    /* In OSPFv3, addr is link-local while configured neighbors could
608
       have global IP (although RFC 5340 C.5 says link-local addresses
609
       should be used). Because OSPFv3 iface is not subnet-specific,
610
       there is no need for ipa_in_net() check */
611

    
612
    if (ospf_is_v2(p) && !ipa_in_net(nb->ip, addr->prefix, addr->pxlen))
613
      continue;
614

    
615
    if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
616
      log(L_WARN "In OSPFv3, configured neighbor address (%I) should be link-local", nb->ip);
617

    
618
    add_nbma_node(ifa, nb, 0);
619
  }
620

    
621
  add_tail(&oa->po->iface_list, NODE ifa);
622

    
623
  struct object_lock *lock = olock_new(pool);
624
  lock->addr = ospf_is_v2(p) ? ifa->addr->prefix : IPA_NONE;
625
  lock->type = OBJLOCK_IP;
626
  lock->port = OSPF_PROTO;
627
  lock->inst = ifa->instance_id;
628
  lock->iface = iface;
629
  lock->data = ifa;
630
  lock->hook = ospf_iface_add;
631

    
632
  olock_acquire(lock);
633
}
634

    
635
void
636
ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
637
{
638
  struct ospf_iface *ifa;
639
  struct pool *pool;
640

    
641
  if (!p->vlink_sk)
642
    return;
643

    
644
  OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
645

    
646
  /* Vlink ifname is stored just after the ospf_iface structure */
647

    
648
  pool = rp_new(p->p.pool, "OSPF Vlink");
649
  ifa = mb_allocz(pool, sizeof(struct ospf_iface) + 16);
650
  ifa->oa = p->backbone;
651
  ifa->cf = ip;
652
  ifa->pool = pool;
653

    
654
  /* Assign iface ID, for vlinks, this is ugly hack */
655
  u32 vlink_id = p->last_vlink_id++;
656
  ifa->iface_id = vlink_id + OSPF_VLINK_ID_OFFSET;
657
  ifa->ifname = (void *) (ifa + 1);
658
  bsprintf(ifa->ifname, "vlink%d", vlink_id);
659

    
660
  ifa->voa = ospf_find_area(p, ip->voa);
661
  ifa->vid = ip->vid;
662
  ifa->sk = p->vlink_sk;
663

    
664
  ifa->helloint = ip->helloint;
665
  ifa->rxmtint = ip->rxmtint;
666
  ifa->waitint = ip->waitint;
667
  ifa->deadint = ip->deadint;
668
  ifa->inftransdelay = ip->inftransdelay;
669
  ifa->tx_length = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
670
  ifa->autype = ip->autype;
671
  ifa->passwords = ip->passwords;
672
  ifa->instance_id = ip->instance_id;
673

    
674
  ifa->type = OSPF_IT_VLINK;
675

    
676
  ifa->state = OSPF_IS_DOWN;
677
  init_list(&ifa->neigh_list);
678
  init_list(&ifa->nbma_list);
679

    
680
  add_tail(&p->iface_list, NODE ifa);
681

    
682
  ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
683
}
684

    
685
static void
686
ospf_iface_change_timer(timer *tm, uint val)
687
{
688
  if (!tm)
689
    return;
690

    
691
  tm->recurrent = val;
692

    
693
  if (tm->expires)
694
    tm_start(tm, val);
695
}
696

    
697
int
698
ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
699
{
700
  struct ospf_proto *p = ifa->oa->po;
701
  struct ospf_iface_patt *old = ifa->cf;
702
  char *ifname = ifa->ifname;
703

    
704
  /* Type could be changed in ospf_iface_new(),
705
     but if config values are same then also results are same */
706
  int old_type = ospf_iface_classify(old->type, ifa->addr);  
707
  int new_type = ospf_iface_classify(new->type, ifa->addr);
708
  if (old_type != new_type)
709
    return 0;
710

    
711
  int new_stub = ospf_iface_stubby(new, ifa->addr);
712
  if (ifa->stub != new_stub)
713
    return 0;
714

    
715
  /* Change of these options would require to reset the iface socket */
716
  if ((new->real_bcast != old->real_bcast) ||
717
      (new->tx_tos != old->tx_tos) ||
718
      (new->tx_priority != old->tx_priority) ||
719
      (new->ttl_security != old->ttl_security))
720
    return 0;
721

    
722
  ifa->cf = new;
723
  ifa->marked = 0;
724

    
725

    
726
  /* HELLO TIMER */
727
  if (ifa->helloint != new->helloint)
728
  {
729
    OSPF_TRACE(D_EVENTS, "Changing hello interval on interface %s from %d to %d",
730
               ifname, ifa->helloint, new->helloint);
731

    
732
    ifa->helloint = new->helloint;
733
    ospf_iface_change_timer(ifa->hello_timer, ifa->helloint);
734
  }
735

    
736
  /* RXMT TIMER */
737
  if (ifa->rxmtint != new->rxmtint)
738
  {
739
    OSPF_TRACE(D_EVENTS, "Changing retransmit interval on interface %s from %d to %d",
740
               ifname, ifa->rxmtint, new->rxmtint);
741

    
742
    ifa->rxmtint = new->rxmtint;
743
  }
744

    
745
  /* POLL TIMER */
746
  if (ifa->pollint != new->pollint)
747
  {
748
    OSPF_TRACE(D_EVENTS, "Changing poll interval on interface %s from %d to %d",
749
               ifname, ifa->pollint, new->pollint);
750

    
751
    ifa->pollint = new->pollint;
752
    ospf_iface_change_timer(ifa->poll_timer, ifa->pollint);
753
  }
754

    
755
  /* WAIT TIMER */
756
  if (ifa->waitint != new->waitint)
757
  {
758
    OSPF_TRACE(D_EVENTS, "Changing wait interval on interface %s from %d to %d",
759
               ifname, ifa->waitint, new->waitint);
760

    
761
    ifa->waitint = new->waitint;
762
    if (ifa->wait_timer && ifa->wait_timer->expires)
763
      tm_start(ifa->wait_timer, ifa->waitint);
764
  }
765

    
766
  /* DEAD TIMER */
767
  if (ifa->deadint != new->deadint)
768
  {
769
    OSPF_TRACE(D_EVENTS, "Changing dead interval on interface %s from %d to %d",
770
               ifname, ifa->deadint, new->deadint);
771
    ifa->deadint = new->deadint;
772
  }
773

    
774
  /* INFTRANS */
775
  if (ifa->inftransdelay != new->inftransdelay)
776
  {
777
    OSPF_TRACE(D_EVENTS, "Changing transmit delay on interface %s from %d to %d",
778
                     ifname, ifa->inftransdelay, new->inftransdelay);
779
    ifa->inftransdelay = new->inftransdelay;
780
  }
781

    
782
  /* AUTHENTICATION */
783
  if (ifa->autype != new->autype)
784
  {
785
    OSPF_TRACE(D_EVENTS, "Changing authentication type on interface %s", ifname);
786
    ifa->autype = new->autype;
787
  }
788

    
789
  /* Update passwords */
790
  ifa->passwords = new->passwords;
791

    
792
  /* Remaining options are just for proper interfaces */
793
  if (ifa->type == OSPF_IT_VLINK)
794
    return 1;
795

    
796

    
797
  /* COST */
798
  if (ifa->cost != new->cost)
799
  {
800
    OSPF_TRACE(D_EVENTS, "Changing cost on interface %s from %d to %d",
801
               ifname, ifa->cost, new->cost);
802

    
803
    ifa->cost = new->cost;
804
  }
805

    
806
  /* PRIORITY */
807
  if (ifa->priority != new->priority)
808
  {
809
    OSPF_TRACE(D_EVENTS, "Changing priority on interface %s from %d to %d",
810
               ifname, ifa->priority, new->priority);
811

    
812
    ifa->priority = new->priority;
813
    ospf_notify_link_lsa(ifa);
814
  }
815

    
816
  /* STRICT NBMA */
817
  if (ifa->strictnbma != new->strictnbma)
818
  {
819
    OSPF_TRACE(D_EVENTS, "Changing NBMA strictness on interface %s", ifname);
820
    ifa->strictnbma = new->strictnbma;
821
  }
822

    
823
  struct nbma_node *nb, *nbx;
824

    
825
  /* NBMA LIST - remove or update old */
826
  WALK_LIST_DELSAFE(nb, nbx, ifa->nbma_list)
827
  {
828
    struct nbma_node *nb2 = find_nbma_node_(&new->nbma_list, nb->ip);
829
    if (nb2)
830
    {
831
      if (nb->eligible != nb2->eligible)
832
      {
833
        OSPF_TRACE(D_EVENTS, "Changing eligibility of neighbor %I on interface %s",
834
                   nb->ip, ifname);
835
        nb->eligible = nb2->eligible;
836
      }
837
    }
838
    else
839
    {
840
      OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on interface %s",
841
                       nb->ip, ifname);
842
      rem_node(NODE nb);
843
      mb_free(nb);
844
    }
845
  }
846

    
847
  /* NBMA LIST - add new */
848
  WALK_LIST(nb, new->nbma_list)
849
  {
850
    /* See related note in ospf_iface_new() */
851
    if (ospf_is_v2(p) && !ipa_in_net(nb->ip, ifa->addr->prefix, ifa->addr->pxlen))
852
      continue;
853

    
854
    if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
855
      log(L_WARN "In OSPFv3, configured neighbor address (%I) should be link-local", nb->ip);
856

    
857
    if (! find_nbma_node(ifa, nb->ip))
858
    {
859
      OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on interface %s",
860
                 nb->ip, ifname);
861
      add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip));
862
    }
863
  }
864

    
865
  int update_buffers = 0;
866

    
867
  /* TX LENGTH */
868
  if (old->tx_length != new->tx_length)
869
  {
870
    OSPF_TRACE(D_EVENTS, "Changing TX length on interface %s from %d to %d",
871
               ifname, old->tx_length, new->tx_length);
872

    
873
    /* ifa cannot be vlink */
874
    ifa->tx_length = ifa_tx_length(ifa);
875
    update_buffers = 1;
876
  }
877

    
878
  /* RX BUFFER */
879
  if (old->rx_buffer != new->rx_buffer)
880
  {
881
    OSPF_TRACE(D_EVENTS, "Changing buffer size on interface %s from %d to %d",
882
               ifname, old->rx_buffer, new->rx_buffer);
883

    
884
    /* ifa cannot be vlink */
885
    update_buffers = 1;
886
  }
887

    
888
  /* Buffer size depends on both tx_length and rx_buffer options */
889
  if (update_buffers && ifa->sk)
890
  {
891
    uint bsize = ifa_bufsize(ifa);
892
    sk_set_rbsize(ifa->sk, bsize);
893
    sk_set_tbsize(ifa->sk, bsize);
894
  }
895

    
896
  /* LINK */
897
  if (ifa->check_link != new->check_link)
898
  {
899
    OSPF_TRACE(D_EVENTS, "%s link check on interface %s",
900
               new->check_link ? "Enabling" : "Disabling", ifname);
901
    ifa->check_link = new->check_link;
902

    
903
    /* ifa cannot be vlink */
904
    if (!(ifa->iface->flags & IF_LINK_UP))
905
      ospf_iface_sm(ifa, ifa->check_link ? ISM_LOOP : ISM_UNLOOP);
906
  }
907

    
908
  /* ECMP weight */
909
  if (ifa->ecmp_weight != new->ecmp_weight)
910
  {
911
    OSPF_TRACE(D_EVENTS, "Changing ECMP weight of interface %s from %d to %d",
912
               ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1);
913
    ifa->ecmp_weight = new->ecmp_weight;
914
  }
915

    
916
  /* Link LSA suppression */
917
  if (((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) &&
918
      (ifa->link_lsa_suppression != new->link_lsa_suppression))
919
  {
920
    OSPF_TRACE(D_EVENTS, "Changing link LSA suppression of %s from %d to %d",
921
               ifname, ifa->link_lsa_suppression, new->link_lsa_suppression);
922

    
923
    ifa->link_lsa_suppression = new->link_lsa_suppression;
924
    ospf_notify_link_lsa(ifa);
925
  }
926

    
927
  /* BFD */
928
  if (ifa->bfd != new->bfd)
929
  {
930
    OSPF_TRACE(D_EVENTS, "%s BFD on interface %s",
931
               new->bfd ? "Enabling" : "Disabling", ifname);
932
    ifa->bfd = new->bfd;
933

    
934
    struct ospf_neighbor *n;
935
    WALK_LIST(n, ifa->neigh_list)
936
      ospf_neigh_update_bfd(n, ifa->bfd);
937
  }
938

    
939

    
940
  /* instance_id is not updated - it is part of key */
941

    
942
  return 1;
943
}
944

    
945

    
946
/*
947
 * State for matching iface pattterns walk
948
 *
949
 * This is significantly different in OSPFv2 and OSPFv3.
950
 * In OSPFv2, OSPF ifaces are created for each IP prefix (struct ifa)
951
 * In OSPFv3, OSPF ifaces are created based on real iface (struct iface)
952
 * We support instance_id for both OSPFv2 (RFC 6549) and OSPFv3.
953
 *
954
 * We process one ifa/iface and match it for all configured instance IDs. We
955
 * maintain bitfields to track whether given instance ID was already matched.
956
 * We have two bitfields, one global (active) and one per area (ignore), to
957
 * detect misconfigured cases where one iface with one instance ID matches in
958
 * multiple areas.
959
 */
960

    
961
struct ospf_mip_walk {
962
  u32 active[8];                /* Bitfield of active instance IDs */
963
  u32 ignore[8];                /* Bitfield of instance IDs matched in current area */
964
  struct ospf_area *oa;                /* Current area */
965
  struct ospf_iface_patt *ip;        /* Current iface pattern */
966
  struct iface *iface;                /* Specified iface (input) */
967
  struct ifa *a;                /* Specified ifa (input) */
968
  int warn;                        /* Whether iface matched in multiple areas */
969
};
970

    
971
static int
972
ospf_walk_matching_iface_patts(struct ospf_proto *p, struct ospf_mip_walk *s)
973
{
974
  int id;
975

    
976
  if (s->ip)
977
    goto step;
978

    
979
  WALK_LIST(s->oa, p->area_list)
980
  {
981
    WALK_LIST(s->ip, s->oa->ac->patt_list)
982
    {
983
      id = s->ip->instance_id;
984
      if (BIT32_TEST(s->ignore, id))
985
        continue;
986

    
987
      if (iface_patt_match(&s->ip->i, s->iface, s->a))
988
      {
989
        /* Now we matched ifa/iface/instance_id for the first time in current area */
990
        BIT32_SET(s->ignore, id);
991

    
992
        /* If we already found it in previous areas, ignore it and add warning */
993
        if (BIT32_TEST(s->active, id))
994
          { s->warn = 1; continue; }
995

    
996
        BIT32_SET(s->active, id);
997
        return 1;
998
      step:
999
        ;
1000
      }
1001
    }
1002
    BIT32_ZERO(s->ignore, 256);
1003
  }
1004

    
1005
  if (s->warn)
1006
    log(L_WARN "%s: Interface %s matches for multiple areas", p->p.name, s->iface->name);
1007

    
1008
  return 0;
1009
}
1010

    
1011

    
1012
static struct ospf_iface *
1013
ospf_iface_find_by_key(struct ospf_proto *p, struct ifa *a, int instance_id)
1014
{
1015
  struct ospf_iface *ifa;
1016

    
1017
  WALK_LIST(ifa, p->iface_list)
1018
    if ((ifa->addr == a) && (ifa->instance_id == instance_id) &&
1019
        (ifa->type != OSPF_IT_VLINK))
1020
      return ifa;
1021

    
1022
  return NULL;
1023
}
1024

    
1025

    
1026
void
1027
ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a)
1028
{
1029
  struct ospf_proto *p = (struct ospf_proto *) P;
1030

    
1031
  if (a->flags & IA_SECONDARY)
1032
    return;
1033

    
1034
  if (a->scope <= SCOPE_LINK)
1035
    return;
1036

    
1037
  /* In OSPFv2, we create OSPF iface for each address. */
1038
  if (flags & IF_CHANGE_UP)
1039
  {
1040
    struct ospf_mip_walk s = { .iface = a->iface, .a = a };
1041
    while (ospf_walk_matching_iface_patts(p, &s))
1042
      ospf_iface_new(s.oa, a, s.ip);
1043
  }
1044

    
1045
  if (flags & IF_CHANGE_DOWN)
1046
  {
1047
    struct ospf_iface *ifa, *ifx;
1048
    WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1049
      if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
1050
        ospf_iface_remove(ifa);
1051
    /* See a note in ospf_iface_notify() */
1052
  }
1053
}
1054

    
1055
void
1056
ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a)
1057
{
1058
  struct ospf_proto *p = (struct ospf_proto *) P;
1059

    
1060
  if (a->flags & IA_SECONDARY)
1061
    return;
1062

    
1063
  if (a->scope < SCOPE_LINK)
1064
    return;
1065

    
1066
  /* In OSPFv3, we create OSPF iface for link-local address,
1067
     other addresses are used for link-LSA. */
1068
  if (a->scope == SCOPE_LINK)
1069
  {
1070
    if (flags & IF_CHANGE_UP)
1071
    {
1072
      struct ospf_mip_walk s = { .iface = a->iface };
1073
      while (ospf_walk_matching_iface_patts(p, &s))
1074
        ospf_iface_new(s.oa, a, s.ip);
1075
    }
1076

    
1077
    if (flags & IF_CHANGE_DOWN)
1078
    {
1079
      struct ospf_iface *ifa, *ifx;
1080
      WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1081
        if ((ifa->addr == a) && (ifa->type != OSPF_IT_VLINK))
1082
          ospf_iface_remove(ifa);
1083
    }
1084
  }
1085
  else
1086
  {
1087
    struct ospf_iface *ifa;
1088
    WALK_LIST(ifa, p->iface_list)
1089
      if (ifa->iface == a->iface)
1090
      {
1091
        /* RFC 5340 4.4.3 Event 5 - prefix added/deleted */
1092
        ospf_notify_link_lsa(ifa);
1093
        ospf_notify_rt_lsa(ifa->oa);
1094
      }
1095
  }
1096
}
1097

    
1098

    
1099
static void
1100
ospf_reconfigure_ifaces2(struct ospf_proto *p)
1101
{
1102
  struct iface *iface;
1103
  struct ifa *a;
1104

    
1105
  WALK_LIST(iface, iface_list)
1106
  {
1107
    if (! (iface->flags & IF_UP))
1108
      continue;
1109

    
1110
    WALK_LIST(a, iface->addrs)
1111
    {
1112
      if (a->flags & IA_SECONDARY)
1113
        continue;
1114

    
1115
      if (a->scope <= SCOPE_LINK)
1116
        continue;
1117

    
1118
      struct ospf_mip_walk s = { .iface = iface, .a = a };
1119
      while (ospf_walk_matching_iface_patts(p, &s))
1120
      {
1121
        /* Main inner loop */
1122
        struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id);
1123
        if (ifa)
1124
        {
1125
          if ((ifa->oa == s.oa) && (ifa->marked < 2) &&
1126
              ospf_iface_reconfigure(ifa, s.ip))
1127
            continue;
1128

    
1129
          /* Hard restart */
1130
          log(L_INFO "%s: Restarting interface %s (%I/%d) in area %R",
1131
              p->p.name, ifa->ifname, a->prefix, a->pxlen, s.oa->areaid);
1132
          ospf_iface_shutdown(ifa);
1133
          ospf_iface_remove(ifa);
1134
        }
1135
        
1136
        ospf_iface_new(s.oa, a, s.ip);
1137
      }
1138
    }
1139
  }
1140
}
1141

    
1142
static void
1143
ospf_reconfigure_ifaces3(struct ospf_proto *p)
1144
{
1145
  struct iface *iface;
1146
  struct ifa *a;
1147

    
1148
  WALK_LIST(iface, iface_list)
1149
  {
1150
    if (! (iface->flags & IF_UP))
1151
      continue;
1152

    
1153
    WALK_LIST(a, iface->addrs)
1154
    {
1155
      if (a->flags & IA_SECONDARY)
1156
        continue;
1157

    
1158
      if (a->scope != SCOPE_LINK)
1159
        continue;
1160

    
1161
      struct ospf_mip_walk s = { .iface = iface };
1162
      while (ospf_walk_matching_iface_patts(p, &s))
1163
      {
1164
        /* Main inner loop */
1165
        struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id);
1166
        if (ifa)
1167
        {
1168
          if ((ifa->oa == s.oa) && (ifa->marked < 2) &&
1169
              ospf_iface_reconfigure(ifa, s.ip))
1170
            continue;
1171

    
1172
          /* Hard restart */
1173
          log(L_INFO "%s: Restarting interface %s (IID %d) in area %R",
1174
              p->p.name, ifa->ifname, ifa->instance_id, s.oa->areaid);
1175
          ospf_iface_shutdown(ifa);
1176
          ospf_iface_remove(ifa);
1177
        }
1178

    
1179
        ospf_iface_new(s.oa, a, s.ip);
1180
      }
1181
    }
1182
  }
1183
}
1184

    
1185
void
1186
ospf_reconfigure_ifaces(struct ospf_proto *p)
1187
{
1188
  if (ospf_is_v2(p))
1189
    ospf_reconfigure_ifaces2(p);
1190
  else
1191
    ospf_reconfigure_ifaces3(p);
1192
}
1193

    
1194

    
1195
static void
1196
ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa)
1197
{
1198
  /* ifa is not vlink */
1199

    
1200
  OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s", ifa->ifname);
1201

    
1202
  ifa->tx_length = ifa_tx_length(ifa);
1203

    
1204
  if (!ifa->sk)
1205
    return;
1206

    
1207
  /* We do not shrink dynamic buffers */
1208
  uint bsize = ifa_bufsize(ifa);
1209
  if (bsize > ifa->sk->rbsize)
1210
    sk_set_rbsize(ifa->sk, bsize);
1211
  if (bsize > ifa->sk->tbsize)
1212
    sk_set_tbsize(ifa->sk, bsize);
1213
}
1214

    
1215
static void
1216
ospf_iface_notify(struct ospf_proto *p, uint flags, struct ospf_iface *ifa)
1217
{
1218
  /* ifa is not vlink */
1219

    
1220
  if (flags & IF_CHANGE_DOWN)
1221
  {
1222
    ospf_iface_remove(ifa);
1223
    return;
1224
  }
1225

    
1226
  if (flags & IF_CHANGE_LINK)
1227
    ospf_iface_sm(ifa, (ifa->iface->flags & IF_LINK_UP) ? ISM_UNLOOP : ISM_LOOP);
1228

    
1229
  if (flags & IF_CHANGE_MTU)
1230
    ospf_iface_change_mtu(p, ifa);
1231
}
1232

    
1233
void
1234
ospf_if_notify(struct proto *P, uint flags, struct iface *iface)
1235
{
1236
  struct ospf_proto *p = (struct ospf_proto *) P;
1237

    
1238
  /*
1239
  if (iface->flags & IF_IGNORE)
1240
    return;
1241
  */
1242

    
1243
  /* Going up means that there are no such ifaces yet */
1244
  if (flags & IF_CHANGE_UP)
1245
    return;
1246

    
1247
  struct ospf_iface *ifa, *ifx;
1248
  WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
1249
    if (ifa->iface == iface)
1250
      ospf_iface_notify(p, flags, ifa);
1251

    
1252
  /* We use here that even shutting down iface also shuts down
1253
     the vlinks, but vlinks are not freed and stays in the
1254
     iface_list even when down */
1255
}
1256

    
1257
void
1258
ospf_iface_info(struct ospf_iface *ifa)
1259
{
1260
  char *more = "";
1261

    
1262
  if (ifa->strictnbma &&
1263
      ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
1264
    more = " (strict)";
1265

    
1266
  if (ifa->cf->real_bcast &&
1267
      ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)))
1268
    more = " (real)";
1269

    
1270
  if (ifa->type == OSPF_IT_VLINK)
1271
  {
1272
    cli_msg(-1015, "Virtual link %s to %R", ifa->ifname, ifa->vid);
1273
    cli_msg(-1015, "\tPeer IP: %I", ifa->vip);
1274
    cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid, ifa->voa->areaid);
1275
  }
1276
  else
1277
  {
1278
    if (ospf_is_v3(ifa->oa->po))
1279
      cli_msg(-1015, "Interface %s (IID %d)", ifa->ifname, ifa->instance_id);
1280
    else if (ifa->addr->flags & IA_PEER)
1281
      cli_msg(-1015, "Interface %s (peer %I)", ifa->ifname, ifa->addr->opposite);
1282
    else
1283
      cli_msg(-1015, "Interface %s (%I/%d)", ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen);
1284

    
1285
    cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
1286
    cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
1287
  }
1288
  cli_msg(-1015, "\tState: %s%s", ospf_is[ifa->state], ifa->stub ? " (stub)" : "");
1289
  cli_msg(-1015, "\tPriority: %u", ifa->priority);
1290
  cli_msg(-1015, "\tCost: %u", ifa->cost);
1291
  if (ifa->oa->po->ecmp)
1292
    cli_msg(-1015, "\tECMP weight: %d", ((int) ifa->ecmp_weight) + 1);
1293
  cli_msg(-1015, "\tHello timer: %u", ifa->helloint);
1294

    
1295
  if (ifa->type == OSPF_IT_NBMA)
1296
  {
1297
    cli_msg(-1015, "\tPoll timer: %u", ifa->pollint);
1298
  }
1299
  cli_msg(-1015, "\tWait timer: %u", ifa->waitint);
1300
  cli_msg(-1015, "\tDead timer: %u", ifa->deadint);
1301
  cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint);
1302
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
1303
  {
1304
    cli_msg(-1015, "\tDesigned router (ID): %R", ifa->drid);
1305
    cli_msg(-1015, "\tDesigned router (IP): %I", ifa->drip);
1306
    cli_msg(-1015, "\tBackup designed router (ID): %R", ifa->bdrid);
1307
    cli_msg(-1015, "\tBackup designed router (IP): %I", ifa->bdrip);
1308
  }
1309
}
1310