Statistics
| Branch: | Revision:

iof-bird-daemon / nest / iface.c @ f92e6ab3

History | View | Annotate | Download (17.5 KB)

1
/*
2
 *        BIRD -- Management of Interfaces and Neighbor Cache
3
 *
4
 *        (c) 1998--2000 Martin Mares <mj@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
/**
10
 * DOC: Interfaces
11
 *
12
 * The interface module keeps track of all network interfaces in the
13
 * system and their addresses.
14
 *
15
 * Each interface is represented by an &iface structure which carries
16
 * interface capability flags (%IF_MULTIACCESS, %IF_BROADCAST etc.),
17
 * MTU, interface name and index and finally a linked list of network
18
 * prefixes assigned to the interface, each one represented by
19
 * struct &ifa.
20
 *
21
 * The interface module keeps a `soft-up' state for each &iface which
22
 * is a conjunction of link being up, the interface being of a `sane'
23
 * type and at least one IP address assigned to it.
24
 */
25

    
26
#undef LOCAL_DEBUG
27

    
28
#include "nest/bird.h"
29
#include "nest/iface.h"
30
#include "nest/protocol.h"
31
#include "nest/cli.h"
32
#include "lib/resource.h"
33
#include "lib/string.h"
34
#include "conf/conf.h"
35

    
36
static pool *if_pool;
37

    
38
list iface_list;
39

    
40
/**
41
 * ifa_dump - dump interface address
42
 * @a: interface address descriptor
43
 *
44
 * This function dumps contents of an &ifa to the debug output.
45
 */
46
void
47
ifa_dump(struct ifa *a)
48
{
49
  debug("\t%I, net %I/%-2d bc %I -> %I%s%s%s\n", a->ip, a->prefix, a->pxlen, a->brd, a->opposite,
50
        (a->flags & IF_UP) ? "" : " DOWN",
51
        (a->flags & IA_PRIMARY) ? "" : " SEC",
52
        (a->flags & IA_PEER) ? "PEER" : "");
53
}
54

    
55
/**
56
 * if_dump - dump interface
57
 * @i: interface to dump
58
 *
59
 * This function dumps all information associated with a given
60
 * network interface to the debug output.
61
 */
62
void
63
if_dump(struct iface *i)
64
{
65
  struct ifa *a;
66

    
67
  debug("IF%d: %s", i->index, i->name);
68
  if (i->flags & IF_SHUTDOWN)
69
    debug(" SHUTDOWN");
70
  if (i->flags & IF_UP)
71
    debug(" UP");
72
  else
73
    debug(" DOWN");
74
  if (i->flags & IF_ADMIN_UP)
75
    debug(" LINK-UP");
76
  if (i->flags & IF_MULTIACCESS)
77
    debug(" MA");
78
  if (i->flags & IF_BROADCAST)
79
    debug(" BC");
80
  if (i->flags & IF_MULTICAST)
81
    debug(" MC");
82
  if (i->flags & IF_LOOPBACK)
83
    debug(" LOOP");
84
  if (i->flags & IF_IGNORE)
85
    debug(" IGN");
86
  if (i->flags & IF_TMP_DOWN)
87
    debug(" TDOWN");
88
  debug(" MTU=%d\n", i->mtu);
89
  WALK_LIST(a, i->addrs)
90
    {
91
      ifa_dump(a);
92
      ASSERT((a != i->addr) == !(a->flags & IA_PRIMARY));
93
    }
94
}
95

    
96
/**
97
 * if_dump_all - dump all interfaces
98
 *
99
 * This function dumps information about all known network
100
 * interfaces to the debug output.
101
 */
102
void
103
if_dump_all(void)
104
{
105
  struct iface *i;
106

    
107
  debug("Known network interfaces:\n");
108
  WALK_LIST(i, iface_list)
109
    if_dump(i);
110
  debug("Router ID: %08x\n", config->router_id);
111
}
112

    
113
static inline unsigned
114
if_what_changed(struct iface *i, struct iface *j)
115
{
116
  unsigned c;
117

    
118
  if (((i->flags ^ j->flags) & ~(IF_UP | IF_SHUTDOWN | IF_UPDATED | IF_ADMIN_UP | IF_LINK_UP | IF_TMP_DOWN | IF_JUST_CREATED))
119
      || i->index != j->index)
120
    return IF_CHANGE_TOO_MUCH;
121
  c = 0;
122
  if ((i->flags ^ j->flags) & IF_UP)
123
    c |= (i->flags & IF_UP) ? IF_CHANGE_DOWN : IF_CHANGE_UP;
124
  if ((i->flags ^ j->flags) & IF_LINK_UP)
125
    c |= IF_CHANGE_LINK;
126
  if (i->mtu != j->mtu)
127
    c |= IF_CHANGE_MTU;
128
  return c;
129
}
130

    
131
static inline void
132
if_copy(struct iface *to, struct iface *from)
133
{
134
  to->flags = from->flags | (to->flags & IF_TMP_DOWN);
135
  to->mtu = from->mtu;
136
}
137

    
138
static inline void
139
ifa_send_notify(struct proto *p, unsigned c, struct ifa *a)
140
{
141
  if (p->ifa_notify)
142
    {
143
      if (p->debug & D_IFACES)
144
        log(L_TRACE "%s < %s address %I/%d on interface %s %s",
145
            p->name, (a->flags & IA_PRIMARY) ? "primary" : "secondary",
146
            a->prefix, a->pxlen, a->iface->name,
147
            (c & IF_CHANGE_UP) ? "added" : "removed");
148
      p->ifa_notify(p, c, a);
149
    }
150
}
151

    
152
static void
153
ifa_notify_change_(unsigned c, struct ifa *a)
154
{
155
  struct proto *p;
156

    
157
  DBG("IFA change notification (%x) for %s:%I\n", c, a->iface->name, a->ip);
158

    
159
  WALK_LIST(p, active_proto_list)
160
    ifa_send_notify(p, c, a);
161
}
162

    
163
static inline void
164
ifa_notify_change(unsigned c, struct ifa *a)
165
{
166
  if (c & IF_CHANGE_DOWN)
167
    neigh_ifa_update(a);
168

    
169
  ifa_notify_change_(c, a);
170

    
171
  if (c & IF_CHANGE_UP)
172
    neigh_ifa_update(a);
173
}
174

    
175
static inline void
176
if_send_notify(struct proto *p, unsigned c, struct iface *i)
177
{
178
  if (p->if_notify)
179
    {
180
      if (p->debug & D_IFACES)
181
        log(L_TRACE "%s < interface %s %s", p->name, i->name,
182
            (c & IF_CHANGE_UP) ? "goes up" :
183
            (c & IF_CHANGE_DOWN) ? "goes down" :
184
            (c & IF_CHANGE_MTU) ? "changes MTU" :
185
            (c & IF_CHANGE_LINK) ? "changes link" :
186
            (c & IF_CHANGE_CREATE) ? "created" :
187
            "sends unknown event");
188
      p->if_notify(p, c, i);
189
    }
190
}
191

    
192
static void
193
if_notify_change(unsigned c, struct iface *i)
194
{
195
  struct proto *p;
196
  struct ifa *a;
197

    
198
  if (i->flags & IF_JUST_CREATED)
199
    {
200
      i->flags &= ~IF_JUST_CREATED;
201
      c |= IF_CHANGE_CREATE | IF_CHANGE_MTU;
202
    }
203

    
204
  DBG("Interface change notification (%x) for %s\n", c, i->name);
205
#ifdef LOCAL_DEBUG
206
  if_dump(i);
207
#endif
208

    
209
  if (c & IF_CHANGE_DOWN)
210
    neigh_if_down(i);
211

    
212
  if (c & IF_CHANGE_DOWN)
213
    WALK_LIST(a, i->addrs)
214
      {
215
        a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
216
        ifa_notify_change_(IF_CHANGE_DOWN, a);
217
      }
218

    
219
  WALK_LIST(p, active_proto_list)
220
    if_send_notify(p, c, i);
221

    
222
  if (c & IF_CHANGE_UP)
223
    WALK_LIST(a, i->addrs)
224
      {
225
        a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
226
        ifa_notify_change_(IF_CHANGE_UP, a);
227
      }
228

    
229
  if (c & IF_CHANGE_UP)
230
    neigh_if_up(i);
231

    
232
  if ((c & (IF_CHANGE_UP | IF_CHANGE_DOWN | IF_CHANGE_LINK)) == IF_CHANGE_LINK)
233
    neigh_if_link(i);
234
}
235

    
236
static unsigned
237
if_recalc_flags(struct iface *i, unsigned flags)
238
{
239
  if ((flags & (IF_SHUTDOWN | IF_TMP_DOWN)) ||
240
      !(flags & IF_ADMIN_UP) ||
241
      !i->addr)
242
    flags &= ~IF_UP;
243
  else
244
    flags |= IF_UP;
245
  return flags;
246
}
247

    
248
static void
249
if_change_flags(struct iface *i, unsigned flags)
250
{
251
  unsigned of = i->flags;
252

    
253
  i->flags = if_recalc_flags(i, flags);
254
  if ((i->flags ^ of) & IF_UP)
255
    if_notify_change((i->flags & IF_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN, i);
256
}
257

    
258
/**
259
 * if_delete - remove interface
260
 * @old: interface
261
 *
262
 * This function is called by the low-level platform dependent code
263
 * whenever it notices an interface disappears. It is just a shorthand
264
 * for if_update().
265
 */
266

    
267
void
268
if_delete(struct iface *old)
269
{
270
  struct iface f = {};
271
  strncpy(f.name, old->name, sizeof(f.name)-1);
272
  f.flags = IF_SHUTDOWN;
273
  if_update(&f);
274
}
275

    
276
/**
277
 * if_update - update interface status
278
 * @new: new interface status
279
 *
280
 * if_update() is called by the low-level platform dependent code
281
 * whenever it notices an interface change.
282
 *
283
 * There exist two types of interface updates -- synchronous and asynchronous
284
 * ones. In the synchronous case, the low-level code calls if_start_update(),
285
 * scans all interfaces reported by the OS, uses if_update() and ifa_update()
286
 * to pass them to the core and then it finishes the update sequence by
287
 * calling if_end_update(). When working asynchronously, the sysdep code
288
 * calls if_update() and ifa_update() whenever it notices a change.
289
 *
290
 * if_update() will automatically notify all other modules about the change.
291
 */
292
struct iface *
293
if_update(struct iface *new)
294
{
295
  struct iface *i;
296
  unsigned c;
297

    
298
  WALK_LIST(i, iface_list)
299
    if (!strcmp(new->name, i->name))
300
      {
301
        new->addr = i->addr;
302
        new->flags = if_recalc_flags(new, new->flags);
303
        c = if_what_changed(i, new);
304
        if (c & IF_CHANGE_TOO_MUCH)        /* Changed a lot, convert it to down/up */
305
          {
306
            DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
307
            if_change_flags(i, i->flags | IF_TMP_DOWN);
308
            rem_node(&i->n);
309
            new->addr = i->addr;
310
            memcpy(&new->addrs, &i->addrs, sizeof(i->addrs));
311
            memcpy(i, new, sizeof(*i));
312
            i->flags &= ~IF_UP; /* IF_TMP_DOWN will be added later */
313
            goto newif;
314
          }
315

    
316
        if_copy(i, new);
317
        if (c)
318
          if_notify_change(c, i);
319

    
320
        i->flags |= IF_UPDATED;
321
        return i;
322
      }
323
  i = mb_alloc(if_pool, sizeof(struct iface));
324
  memcpy(i, new, sizeof(*i));
325
  init_list(&i->addrs);
326
newif:
327
  init_list(&i->neighbors);
328
  i->flags |= IF_UPDATED | IF_TMP_DOWN;                /* Tmp down as we don't have addresses yet */
329
  add_tail(&iface_list, &i->n);
330
  return i;
331
}
332

    
333
void
334
if_start_update(void)
335
{
336
  struct iface *i;
337
  struct ifa *a;
338

    
339
  WALK_LIST(i, iface_list)
340
    {
341
      i->flags &= ~IF_UPDATED;
342
      WALK_LIST(a, i->addrs)
343
        a->flags &= ~IF_UPDATED;
344
    }
345
}
346

    
347
void
348
if_end_partial_update(struct iface *i)
349
{
350
  if (i->flags & IF_TMP_DOWN)
351
    if_change_flags(i, i->flags & ~IF_TMP_DOWN);
352
}
353

    
354
void
355
if_end_update(void)
356
{
357
  struct iface *i;
358
  struct ifa *a, *b;
359

    
360
  WALK_LIST(i, iface_list)
361
    {
362
      if (!(i->flags & IF_UPDATED))
363
        if_change_flags(i, (i->flags & ~IF_ADMIN_UP) | IF_SHUTDOWN);
364
      else
365
        {
366
          WALK_LIST_DELSAFE(a, b, i->addrs)
367
            if (!(a->flags & IF_UPDATED))
368
              ifa_delete(a);
369
          if_end_partial_update(i);
370
        }
371
    }
372
}
373

    
374
void
375
if_flush_ifaces(struct proto *p)
376
{
377
  if (p->debug & D_EVENTS)
378
    log(L_TRACE "%s: Flushing interfaces", p->name);
379
  if_start_update();
380
  if_end_update();
381
}
382

    
383
/**
384
 * if_feed_baby - advertise interfaces to a new protocol
385
 * @p: protocol to feed
386
 *
387
 * When a new protocol starts, this function sends it a series
388
 * of notifications about all existing interfaces.
389
 */
390
void
391
if_feed_baby(struct proto *p)
392
{
393
  struct iface *i;
394
  struct ifa *a;
395

    
396
  if (!p->if_notify && !p->ifa_notify)        /* shortcut */
397
    return;
398
  DBG("Announcing interfaces to new protocol %s\n", p->name);
399
  WALK_LIST(i, iface_list)
400
    {
401
      if_send_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i);
402
      if (i->flags & IF_UP)
403
        WALK_LIST(a, i->addrs)
404
          ifa_send_notify(p, IF_CHANGE_CREATE | IF_CHANGE_UP, a);
405
    }
406
}
407

    
408
/**
409
 * if_find_by_index - find interface by ifindex
410
 * @idx: ifindex
411
 *
412
 * This function finds an &iface structure corresponding to an interface
413
 * of the given index @idx. Returns a pointer to the structure or %NULL
414
 * if no such structure exists.
415
 */
416
struct iface *
417
if_find_by_index(unsigned idx)
418
{
419
  struct iface *i;
420

    
421
  WALK_LIST(i, iface_list)
422
    if (i->index == idx && !(i->flags & IF_SHUTDOWN))
423
      return i;
424
  return NULL;
425
}
426

    
427
/**
428
 * if_find_by_name - find interface by name
429
 * @name: interface name
430
 *
431
 * This function finds an &iface structure corresponding to an interface
432
 * of the given name @name. Returns a pointer to the structure or %NULL
433
 * if no such structure exists.
434
 */
435
struct iface *
436
if_find_by_name(char *name)
437
{
438
  struct iface *i;
439

    
440
  WALK_LIST(i, iface_list)
441
    if (!strcmp(i->name, name))
442
      return i;
443
  return NULL;
444
}
445

    
446
struct iface *
447
if_get_by_name(char *name)
448
{
449
  struct iface *i;
450

    
451
  if (i = if_find_by_name(name))
452
    return i;
453

    
454
  /* No active iface, create a dummy */
455
  i = mb_allocz(if_pool, sizeof(struct iface));
456
  strncpy(i->name, name, sizeof(i->name)-1);
457
  i->flags = IF_SHUTDOWN;
458
  init_list(&i->addrs);
459
  init_list(&i->neighbors);
460
  add_tail(&iface_list, &i->n);
461
  return i;
462
}
463

    
464
struct ifa *kif_choose_primary(struct iface *i);
465

    
466
static int
467
ifa_recalc_primary(struct iface *i)
468
{
469
  struct ifa *a = kif_choose_primary(i);
470

    
471
  if (a == i->addr)
472
    return 0;
473

    
474
  if (i->addr)
475
    i->addr->flags &= ~IA_PRIMARY;
476

    
477
  if (a)
478
    {
479
      a->flags |= IA_PRIMARY;
480
      rem_node(&a->n);
481
      add_head(&i->addrs, &a->n);
482
    }
483

    
484
  i->addr = a;
485
  return 1;
486
}
487

    
488
void
489
ifa_recalc_all_primary_addresses(void)
490
{
491
  struct iface *i;
492

    
493
  WALK_LIST(i, iface_list)
494
    {
495
      if (ifa_recalc_primary(i))
496
        if_change_flags(i, i->flags | IF_TMP_DOWN);
497
    }
498
}
499

    
500
static inline int
501
ifa_same(struct ifa *a, struct ifa *b)
502
{
503
  return ipa_equal(a->ip, b->ip) && ipa_equal(a->prefix, b->prefix) &&
504
    a->pxlen == b->pxlen;
505
}
506

    
507

    
508
/**
509
 * ifa_update - update interface address
510
 * @a: new interface address
511
 *
512
 * This function adds address information to a network
513
 * interface. It's called by the platform dependent code during
514
 * the interface update process described under if_update().
515
 */
516
struct ifa *
517
ifa_update(struct ifa *a)
518
{
519
  struct iface *i = a->iface;
520
  struct ifa *b;
521

    
522
  WALK_LIST(b, i->addrs)
523
    if (ifa_same(b, a))
524
      {
525
        if (ipa_equal(b->brd, a->brd) &&
526
            ipa_equal(b->opposite, a->opposite) &&
527
            b->scope == a->scope &&
528
            !((b->flags ^ a->flags) & IA_PEER))
529
          {
530
            b->flags |= IF_UPDATED;
531
            return b;
532
          }
533
        ifa_delete(b);
534
        break;
535
      }
536

    
537
#ifndef IPV6
538
  if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd))
539
    log(L_ERR "Missing broadcast address for interface %s", i->name);
540
#endif
541

    
542
  b = mb_alloc(if_pool, sizeof(struct ifa));
543
  memcpy(b, a, sizeof(struct ifa));
544
  add_tail(&i->addrs, &b->n);
545
  b->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
546
  if (ifa_recalc_primary(i))
547
    if_change_flags(i, i->flags | IF_TMP_DOWN);
548
  if (b->flags & IF_UP)
549
    ifa_notify_change(IF_CHANGE_CREATE | IF_CHANGE_UP, b);
550
  return b;
551
}
552

    
553
/**
554
 * ifa_delete - remove interface address
555
 * @a: interface address
556
 *
557
 * This function removes address information from a network
558
 * interface. It's called by the platform dependent code during
559
 * the interface update process described under if_update().
560
 */
561
void
562
ifa_delete(struct ifa *a)
563
{
564
  struct iface *i = a->iface;
565
  struct ifa *b;
566

    
567
  WALK_LIST(b, i->addrs)
568
    if (ifa_same(b, a))
569
      {
570
        rem_node(&b->n);
571
        if (b->flags & IF_UP)
572
          {
573
            b->flags &= ~IF_UP;
574
            ifa_notify_change(IF_CHANGE_DOWN, b);
575
          }
576
        if (b->flags & IA_PRIMARY)
577
          {
578
            if_change_flags(i, i->flags | IF_TMP_DOWN);
579
            ifa_recalc_primary(i);
580
          }
581
        mb_free(b);
582
        return;
583
      }
584
}
585

    
586
u32
587
if_choose_router_id(struct iface_patt *mask, u32 old_id)
588
{
589
#ifndef IPV6
590
  struct iface *i;
591
  struct ifa *a, *b;
592

    
593
  b = NULL;
594
  WALK_LIST(i, iface_list)
595
    {
596
      if (!(i->flags & IF_ADMIN_UP) ||
597
          (i->flags & IF_SHUTDOWN))
598
        continue;
599

    
600
      WALK_LIST(a, i->addrs)
601
        {
602
          if (a->flags & IA_SECONDARY)
603
            continue;
604

    
605
          if (a->scope <= SCOPE_LINK)
606
            continue;
607

    
608
          /* Check pattern if specified */
609
          if (mask && !iface_patt_match(mask, i, a))
610
            continue;
611

    
612
          /* No pattern or pattern matched */
613
          if (!b || ipa_to_u32(a->ip) < ipa_to_u32(b->ip))
614
            b = a;
615
        }
616
    }
617

    
618
  if (!b)
619
    return 0;
620

    
621
  u32 id = ipa_to_u32(b->ip);
622
  if (id != old_id)
623
    log(L_INFO "Chosen router ID %R according to interface %s", id, b->iface->name);
624

    
625
  return id;
626

    
627
#else
628
  return 0;
629
#endif
630
}
631

    
632
/**
633
 * if_init - initialize interface module
634
 *
635
 * This function is called during BIRD startup to initialize
636
 * all data structures of the interface module.
637
 */
638
void
639
if_init(void)
640
{
641
  if_pool = rp_new(&root_pool, "Interfaces");
642
  init_list(&iface_list);
643
  neigh_init(if_pool);
644
}
645

    
646
/*
647
 *        Interface Pattern Lists
648
 */
649

    
650
int
651
iface_patt_match(struct iface_patt *ifp, struct iface *i, struct ifa *a)
652
{
653
  struct iface_patt_node *p;
654

    
655
  WALK_LIST(p, ifp->ipn_list)
656
    {
657
      char *t = p->pattern;
658
      int pos = p->positive;
659

    
660
      if (t)
661
        {
662
          if (*t == '-')
663
            {
664
              t++;
665
              pos = !pos;
666
            }
667

    
668
          if (!patmatch(t, i->name))
669
            continue;
670
        }
671

    
672
      if (p->pxlen == 0)
673
        return pos;
674

    
675
      if (!a)
676
        continue;
677

    
678
      if (ipa_in_net(a->ip, p->prefix, p->pxlen))
679
        return pos;
680

    
681
      if ((a->flags & IA_PEER) &&
682
          ipa_in_net(a->opposite, p->prefix, p->pxlen))
683
        return pos;
684

    
685
      continue;
686
    }
687

    
688
  return 0;
689
}
690

    
691
struct iface_patt *
692
iface_patt_find(list *l, struct iface *i, struct ifa *a)
693
{
694
  struct iface_patt *p;
695

    
696
  WALK_LIST(p, *l)
697
    if (iface_patt_match(p, i, a))
698
      return p;
699

    
700
  return NULL;
701
}
702

    
703
static int
704
iface_plists_equal(struct iface_patt *pa, struct iface_patt *pb)
705
{
706
  struct iface_patt_node *x, *y;
707

    
708
  x = HEAD(pa->ipn_list);
709
  y = HEAD(pb->ipn_list);
710
  while (x->n.next && y->n.next)
711
    {
712
      if ((x->positive != y->positive) ||
713
          (!x->pattern && y->pattern) ||        /* This nasty lines where written by me... :-( Feela */
714
          (!y->pattern && x->pattern) ||
715
          ((x->pattern != y->pattern) && strcmp(x->pattern, y->pattern)) ||
716
          !ipa_equal(x->prefix, y->prefix) ||
717
          (x->pxlen != y->pxlen))
718
        return 0;
719
      x = (void *) x->n.next;
720
      y = (void *) y->n.next;
721
    }
722
  return (!x->n.next && !y->n.next);
723
}
724

    
725
int
726
iface_patts_equal(list *a, list *b, int (*comp)(struct iface_patt *, struct iface_patt *))
727
{
728
  struct iface_patt *x, *y;
729

    
730
  x = HEAD(*a);
731
  y = HEAD(*b);
732
  while (x->n.next && y->n.next)
733
    {
734
      if (!iface_plists_equal(x, y) ||
735
          (comp && !comp(x, y)))
736
        return 0;
737
      x = (void *) x->n.next;
738
      y = (void *) y->n.next;
739
    }
740
  return (!x->n.next && !y->n.next);
741
}
742

    
743
/*
744
 *  CLI commands.
745
 */
746

    
747
static void
748
if_show_addr(struct ifa *a)
749
{
750
  byte opp[STD_ADDRESS_P_LENGTH + 16];
751

    
752
  if (ipa_nonzero(a->opposite))
753
    bsprintf(opp, ", opposite %I", a->opposite);
754
  else
755
    opp[0] = 0;
756
  cli_msg(-1003, "\t%I/%d (%s%s, scope %s)",
757
          a->ip, a->pxlen,
758
          (a->flags & IA_PRIMARY) ? "Primary" : (a->flags & IA_SECONDARY) ? "Secondary" : "Unselected",
759
          opp, ip_scope_text(a->scope));
760
}
761

    
762
void
763
if_show(void)
764
{
765
  struct iface *i;
766
  struct ifa *a;
767
  char *type;
768

    
769
  WALK_LIST(i, iface_list)
770
    {
771
      if (i->flags & IF_SHUTDOWN)
772
        continue;
773

    
774
      cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "up" : "DOWN", i->index);
775
      if (!(i->flags & IF_MULTIACCESS))
776
        type = "PtP";
777
      else
778
        type = "MultiAccess";
779
      cli_msg(-1004, "\t%s%s%s Admin%s Link%s%s%s MTU=%d",
780
              type,
781
              (i->flags & IF_BROADCAST) ? " Broadcast" : "",
782
              (i->flags & IF_MULTICAST) ? " Multicast" : "",
783
              (i->flags & IF_ADMIN_UP) ? "Up" : "Down",
784
              (i->flags & IF_LINK_UP) ? "Up" : "Down",
785
              (i->flags & IF_LOOPBACK) ? " Loopback" : "",
786
              (i->flags & IF_IGNORE) ? " Ignored" : "",
787
              i->mtu);
788
      if (i->addr)
789
        if_show_addr(i->addr);
790
      WALK_LIST(a, i->addrs)
791
        if (a != i->addr)
792
          if_show_addr(a);
793
    }
794
  cli_msg(0, "");
795
}
796

    
797
void
798
if_show_summary(void)
799
{
800
  struct iface *i;
801
  byte addr[STD_ADDRESS_P_LENGTH + 16];
802

    
803
  cli_msg(-2005, "interface state address");
804
  WALK_LIST(i, iface_list)
805
    {
806
      if (i->addr)
807
        bsprintf(addr, "%I/%d", i->addr->ip, i->addr->pxlen);
808
      else
809
        addr[0] = 0;
810
      cli_msg(-1005, "%-9s %-5s %s", i->name, (i->flags & IF_UP) ? "up" : "DOWN", addr);
811
    }
812
  cli_msg(0, "");
813
}