Revision 9a158361

View differences:

TODO
27 27
- iface: we always need ifindex at least for PtP links (OSPF)
28 28
- iface: interface filters should support filtering by IP address as well
29 29

  
30
- socket: Use IP_RECVERR for BGP TCP sockets?
31

  
30 32
Cleanup
31 33
~~~~~~~
32 34
- right usage of DBG vs. debug
nest/iface.c
31 31
static int
32 32
if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
33 33
{
34
  struct ifa *b;
35

  
34 36
  if (!(i->flags & IF_UP))
35 37
    return 0;
36
  if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->opposite))
38
  if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->addr->opposite))
37 39
    return 1;
38
  if (!ipa_in_net(*a, i->prefix, i->pxlen))
39
    return 0;
40
  if (ipa_equal(*a, i->prefix) ||	/* Network address */
41
      ipa_equal(*a, i->brd) ||		/* Broadcast */
42
      ipa_equal(*a, i->ip))		/* Our own address */
43
    return -1;
44
  return 1;
40
  WALK_LIST(b, i->addrs)
41
    if (ipa_in_net(*a, b->prefix, b->pxlen))
42
      {
43
	if (ipa_equal(*a, b->prefix) ||	/* Network address */
44
	    ipa_equal(*a, b->brd) ||	/* Broadcast */
45
	    ipa_equal(*a, b->ip))	/* Our own address */
46
	  return -1;
47
	return 1;
48
      }
49
  return 0;
45 50
}
46 51

  
47 52
neighbor *
......
69 74
      case -1:
70 75
	return NULL;
71 76
      case 1:
72
	if (!j || j->pxlen > i->pxlen)
77
	if (!j)				/* FIXME: Search for _optimal_ iface route? */
73 78
	  j = i;
74 79
	/* Fall-thru */
75 80
      }
......
188 193
list iface_list;
189 194

  
190 195
void
196
ifa_dump(struct ifa *a)
197
{
198
  debug("\t%I, net %I/%-2d bc %I -> %I%s%s\n", a->ip, a->prefix, a->pxlen, a->brd, a->opposite,
199
	(a->flags & IF_UP) ? "" : " DOWN",
200
	(a->flags & IA_PRIMARY) ? "" : " SEC");
201
}
202

  
203
void
191 204
if_dump(struct iface *i)
192 205
{
206
  struct ifa *a;
207

  
193 208
  debug("IF%d: %s", i->index, i->name);
194 209
  if (i->flags & IF_ADMIN_DOWN)
195 210
    debug(" ADMIN-DOWN");
......
213 228
    debug(" LOOP");
214 229
  if (i->flags & IF_IGNORE)
215 230
    debug(" IGN");
231
  if (i->flags & IF_TMP_DOWN)
232
    debug(" TDOWN");
216 233
  debug(" MTU=%d\n", i->mtu);
217
  debug("\t%I, net %I/%-2d bc %I -> %I\n", i->ip, i->prefix, i->pxlen, i->brd, i->opposite);
234
  WALK_LIST(a, i->addrs)
235
    {
236
      ifa_dump(a);
237
      ASSERT((a != i->addr) == !(a->flags & IA_PRIMARY));
238
    }
218 239
}
219 240

  
220 241
void
......
228 249
  debug("Router ID: %08x\n", config->router_id);
229 250
}
230 251

  
231
static inline int
232
if_change_too_big_p(struct iface *i, struct iface *j)
252
static inline unsigned
253
if_what_changed(struct iface *i, struct iface *j)
233 254
{
234
  if (!ipa_equal(i->ip, j->ip) ||	/* Address change isn't */
235
      !ipa_equal(i->prefix, j->prefix) ||
236
      i->pxlen != j->pxlen ||
237
      !ipa_equal(i->brd, j->brd) ||
238
      !ipa_equal(i->opposite, j->opposite))
239
    return 1;
240
  if ((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED | IF_LINK_UP))
241
    return 1;				/* Interface type change isn't as well */
242
  return 0;
255
  unsigned c;
256

  
257
  if (((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED | IF_LINK_UP | IF_TMP_DOWN | IF_JUST_CREATED))
258
      || i->index != j->index)
259
    return IF_CHANGE_TOO_MUCH;
260
  c = 0;
261
  if ((i->flags ^ j->flags) & IF_UP)
262
    c |= (i->flags & IF_UP) ? IF_CHANGE_DOWN : IF_CHANGE_UP;
263
  if (i->mtu != j->mtu)
264
    c |= IF_CHANGE_MTU;
265
  return c;
243 266
}
244 267

  
245 268
static inline void
246 269
if_copy(struct iface *to, struct iface *from)
247 270
{
248
  to->flags = from->flags;
271
  to->flags = from->flags | (to->flags & IF_TMP_DOWN);
249 272
  to->mtu = from->mtu;
250
  to->index = from->index;
251
  to->neigh = from->neigh;
252 273
}
253 274

  
254
static unsigned
255
if_changed(struct iface *i, struct iface *j)
275
static void
276
ifa_notify_change(unsigned c, struct ifa *a)
256 277
{
257
  unsigned f = 0;
278
  struct proto *p;
258 279

  
259
  if (i->mtu != j->mtu)
260
    f |= IF_CHANGE_MTU;
261
  if ((i->flags ^ j->flags) & ~IF_UPDATED)
262
    {
263
      f |= IF_CHANGE_FLAGS;
264
      if ((i->flags ^ j->flags) & IF_UP)
265
	if (i->flags & IF_UP)
266
	  f |= IF_CHANGE_DOWN;
267
	else
268
	  f |= IF_CHANGE_UP;
269
    }
270
  return f;
280
  debug("IFA change notification (%x) for %s:%I\n", c, a->iface->name, a->ip);
281
  WALK_LIST(p, proto_list)
282
    if (p->ifa_notify)
283
      p->ifa_notify(p, c, a);
271 284
}
272 285

  
273 286
static void
274
if_notify_change(unsigned c, struct iface *old, struct iface *new, struct iface *real)
287
if_notify_change(unsigned c, struct iface *i)
275 288
{
276 289
  struct proto *p;
290
  struct ifa *a;
277 291

  
278
  debug("Interface change notification (%x) for %s\n", c, new->name);
279
  if (old)
280
    if_dump(old);
281
  if (new)
282
    if_dump(new);
292
  if (i->flags & IF_JUST_CREATED)
293
    {
294
      i->flags &= ~IF_JUST_CREATED;
295
      c |= IF_CHANGE_CREATE | IF_CHANGE_MTU;
296
    }
297

  
298
  debug("Interface change notification (%x) for %s\n", c, i->name);
299
  if_dump(i);
283 300

  
284 301
  if (c & IF_CHANGE_UP)
285
    neigh_if_up(real);
302
    neigh_if_up(i);
303
  if (c & IF_CHANGE_DOWN)
304
    WALK_LIST(a, i->addrs)
305
      {
306
	a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
307
	ifa_notify_change(IF_CHANGE_DOWN, a);
308
      }
286 309

  
287 310
  WALK_LIST(p, proto_list)
288 311
    if (p->if_notify)
289
      p->if_notify(p, c, new, old);
312
      p->if_notify(p, c, i);
290 313

  
314
  if (c & IF_CHANGE_UP)
315
    WALK_LIST(a, i->addrs)
316
      {
317
	a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
318
	ifa_notify_change(IF_CHANGE_UP, a);
319
      }
291 320
  if (c & IF_CHANGE_DOWN)
292
    neigh_if_down(real);
321
    neigh_if_down(i);
293 322
}
294 323

  
295
void
324
static unsigned
325
if_recalc_flags(struct iface *i, unsigned flags)
326
{
327
  if ((flags & (IF_ADMIN_DOWN | IF_TMP_DOWN)) ||
328
      !(flags & IF_LINK_UP) ||
329
      !i->addr)
330
    flags &= ~IF_UP;
331
  else
332
    flags |= IF_UP;
333
  return flags;
334
}
335

  
336
static void
337
if_change_flags(struct iface *i, unsigned flags)
338
{
339
  unsigned of = i->flags;
340

  
341
  i->flags = if_recalc_flags(i, flags);
342
  if ((i->flags ^ of) & IF_UP)
343
    if_notify_change((i->flags & IF_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN, i);
344
}
345

  
346
struct iface *
296 347
if_update(struct iface *new)
297 348
{
298 349
  struct iface *i;
350
  struct ifa *a, *b;
299 351
  unsigned c;
300 352

  
301
  if ((new->flags & IF_LINK_UP) && !(new->flags & IF_ADMIN_DOWN) && ipa_nonzero(new->ip))
302
    new->flags |= IF_UP;
303
  else
304
    new->flags &= ~IF_UP;
305

  
306 353
  WALK_LIST(i, iface_list)
307 354
    if (!strcmp(new->name, i->name))
308 355
      {
309
	if (if_change_too_big_p(i, new)) /* Changed a lot, convert it to down/up */
356
	new->addr = i->addr;
357
	new->flags = if_recalc_flags(new, new->flags);
358
	c = if_what_changed(i, new);
359
	if (c & IF_CHANGE_TOO_MUCH)	/* Changed a lot, convert it to down/up */
310 360
	  {
311 361
	    DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
312
	    if (i->flags & IF_UP)
313
	      {
314
		struct iface j;
315
		memcpy(&j, i, sizeof(struct iface));
316
		i->flags &= ~IF_UP;
317
		if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i, i);
318
	      }
362
	    if_change_flags(i, i->flags | IF_TMP_DOWN);
319 363
	    rem_node(&i->n);
364
	    WALK_LIST_DELSAFE(a, b, i->addrs)
365
	      ifa_delete(a);
320 366
	    goto newif;
321 367
	  }
322
	c = if_changed(i, new);
323
	if (c)
324
	  if_notify_change(c, i, new, i);
325
	if_copy(i, new);		/* Even if c==0 as we might need to update i->index et al. */
368
	else if (c)
369
	  {
370
	    if_copy(i, new);
371
	    if_notify_change(c, i);
372
	  }
326 373
	i->flags |= IF_UPDATED;
327
	return;
374
	return i;
328 375
      }
329

  
330 376
  i = mb_alloc(if_pool, sizeof(struct iface));
331 377
newif:
332 378
  memcpy(i, new, sizeof(*i));
333
  i->flags |= IF_UPDATED;
379
  init_list(&i->addrs);
380
  i->flags |= IF_UPDATED | IF_TMP_DOWN;		/* Tmp down as we don't have addresses yet */
334 381
  add_tail(&iface_list, &i->n);
335
  if_notify_change(IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0)
336
		   | IF_CHANGE_FLAGS | IF_CHANGE_MTU, NULL, i, i);
382
  return i;
337 383
}
338 384

  
339 385
void
340 386
if_start_update(void)
341 387
{
342 388
  struct iface *i;
389
  struct ifa *a;
343 390

  
344 391
  WALK_LIST(i, iface_list)
345
    i->flags &= ~IF_UPDATED;
392
    {
393
      i->flags &= ~IF_UPDATED;
394
      WALK_LIST(a, i->addrs)
395
	a->flags &= ~IF_UPDATED;
396
    }
397
}
398

  
399
void
400
if_end_partial_update(struct iface *i)
401
{
402
  if (i->flags & IF_TMP_DOWN)
403
    if_change_flags(i, i->flags & ~IF_TMP_DOWN);
346 404
}
347 405

  
348 406
void
349 407
if_end_update(void)
350 408
{
351 409
  struct iface *i, j;
410
  struct ifa *a, *b;
352 411

  
353 412
  if (!config->router_id)
354 413
    auto_router_id();
355 414

  
356 415
  WALK_LIST(i, iface_list)
357
    if (!(i->flags & IF_UPDATED))
358
      {
359
	memcpy(&j, i, sizeof(struct iface));
360
	i->flags = (i->flags & ~(IF_LINK_UP | IF_UP)) | IF_ADMIN_DOWN;
361
	if (i->flags != j.flags)
362
	  if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i, i);
363
      }
416
    {
417
      if (!(i->flags & IF_UPDATED))
418
	if_change_flags(i, (i->flags & ~IF_LINK_UP) | IF_ADMIN_DOWN);
419
      else
420
	{
421
	  WALK_LIST_DELSAFE(a, b, i->addrs)
422
	    if (!(a->flags & IF_UPDATED))
423
	      ifa_delete(a);
424
	  if_end_partial_update(i);
425
	}
426
    }
364 427
}
365 428

  
366 429
void
367 430
if_feed_baby(struct proto *p)
368 431
{
369 432
  struct iface *i;
433
  struct ifa *a;
370 434

  
371
  if (!p->if_notify)
435
  if (!p->if_notify && !p->ifa_notify)
372 436
    return;
373 437
  debug("Announcing interfaces to new protocol %s\n", p->name);
374 438
  WALK_LIST(i, iface_list)
375
    p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i, NULL);
439
    {
440
      if (p->if_notify)
441
	p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i);
442
      if (p->ifa_notify && (i->flags & IF_UP))
443
	WALK_LIST(a, i->addrs)
444
	  p->ifa_notify(p, IF_CHANGE_CREATE | IF_CHANGE_UP, a);
445
    }
376 446
}
377 447

  
378 448
struct iface *
......
386 456
  return NULL;
387 457
}
388 458

  
459
struct iface *
460
if_find_by_name(char *name)
461
{
462
  struct iface *i;
463

  
464
  WALK_LIST(i, iface_list)
465
    if (!strcmp(i->name, name))
466
      return i;
467
  return NULL;
468
}
469

  
470
static int
471
ifa_recalc_primary(struct iface *i)
472
{
473
  struct ifa *a, *b = NULL;
474
  int res;
475

  
476
  WALK_LIST(a, i->addrs)
477
    {
478
      if (!(a->flags & IA_SECONDARY) && (!b || a->scope > b->scope))
479
	b = a;
480
      a->flags &= ~IA_PRIMARY;
481
    }
482
  res = (b != i->addr);
483
  i->addr = b;
484
  if (b)
485
    {
486
      b->flags |= IA_PRIMARY;
487
      rem_node(&b->n);
488
      add_head(&i->addrs, &b->n);
489
    }
490
  return res;
491
}
492

  
493
struct ifa *
494
ifa_update(struct ifa *a)
495
{
496
  struct iface *i = a->iface;
497
  struct ifa *b;
498

  
499
  WALK_LIST(b, i->addrs)
500
    if (ipa_equal(b->ip, a->ip))
501
      {
502
	if (ipa_equal(b->prefix, a->prefix) &&
503
	    b->pxlen == a->pxlen &&
504
	    ipa_equal(b->brd, a->brd) &&
505
	    ipa_equal(b->opposite, a->opposite) &&
506
	    b->scope == a->scope)
507
	  {
508
	    b->flags |= IF_UPDATED;
509
	    return b;
510
	  }
511
	ifa_delete(b);
512
	break;
513
      }
514
  b = mb_alloc(if_pool, sizeof(struct ifa));
515
  memcpy(b, a, sizeof(struct ifa));
516
  add_tail(&i->addrs, &b->n);
517
  b->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
518
  if ((!i->addr || i->addr->scope < b->scope) && ifa_recalc_primary(i))
519
    if_change_flags(i, i->flags | IF_TMP_DOWN);
520
  if (b->flags & IF_UP)
521
    ifa_notify_change(IF_CHANGE_CREATE | IF_CHANGE_UP, b);
522
  return b;
523
}
524

  
525
void
526
ifa_delete(struct ifa *a)
527
{
528
  struct iface *i = a->iface;
529
  struct ifa *b;
530

  
531
  WALK_LIST(b, i->addrs)
532
    if (ipa_equal(b->ip, a->ip))
533
      {
534
	rem_node(&b->n);
535
	if (b->flags & IF_UP)
536
	  {
537
	    b->flags &= ~IF_UP;
538
	    ifa_notify_change(IF_CHANGE_DOWN, b);
539
	  }
540
	if (b->flags & IA_PRIMARY)
541
	  {
542
	    if_change_flags(i, i->flags | IF_TMP_DOWN);
543
	    ifa_recalc_primary(i);
544
	  }
545
	mb_free(b);
546
      }
547
}
548

  
389 549
static void
390 550
auto_router_id(void)			/* FIXME: What if we run IPv6??? */
391 551
{
......
393 553

  
394 554
  j = NULL;
395 555
  WALK_LIST(i, iface_list)
396
    if ((i->flags & IF_UP) &&
397
	!(i->flags & (IF_UNNUMBERED | IF_IGNORE)) &&
398
	(!j || ipa_to_u32(i->ip) < ipa_to_u32(j->ip)))
556
    if ((i->flags & IF_LINK_UP) &&
557
	!(i->flags & (IF_UNNUMBERED | IF_IGNORE | IF_ADMIN_DOWN)) &&
558
	i->addr &&
559
	(!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip)))
399 560
      j = i;
400 561
  if (!j)
401 562
    die("Cannot determine router ID (no suitable network interface found), please configure it manually");
402
  debug("Guessed router ID %I (%s)\n", j->ip, j->name);
403
  config->router_id = ipa_to_u32(j->ip);
563
  debug("Guessed router ID %I (%s)\n", j->addr->ip, j->name);
564
  config->router_id = ipa_to_u32(j->addr->ip);
404 565
}
405 566

  
406 567
void
nest/iface.h
15 15

  
16 16
struct proto;
17 17

  
18
struct ifa {				/* Interface address */
19
  node n;
20
  struct iface *iface;			/* Interface this address belongs to */
21
  ip_addr ip;				/* IP address of this host */
22
  ip_addr prefix;			/* Network prefix */
23
  unsigned pxlen;			/* Prefix length */
24
  ip_addr brd;				/* Broadcast address */
25
  ip_addr opposite;			/* Opposite end of a point-to-point link */
26
  unsigned scope;			/* Interface address scope */
27
  unsigned flags;			/* Analogous to iface->flags */
28
};
29

  
18 30
struct iface {
19 31
  node n;
20 32
  char name[16];
21 33
  unsigned flags;
22 34
  unsigned mtu;
23 35
  unsigned index;			/* OS-dependent interface index */
24
  ip_addr ip;				/* IP address of this host (0=unset) */
25
  ip_addr prefix;			/* Network prefix */
26
  unsigned pxlen;			/* Prefix length */
27
  ip_addr brd;				/* Broadcast address */
28
  ip_addr opposite;			/* Opposite end of a point-to-point link */
36
  list addrs;				/* Addresses assigned to this interface */
37
  struct ifa *addr;			/* Primary address */
29 38
  struct neighbor *neigh;		/* List of neighbors on this interface */
30 39
};
31 40

  
32
#define IF_UP 1				/* IF_LINK_UP, not IF_IGNORE and IP address known */
41
#define IF_UP 1				/* IF_LINK_UP and IP address known */
33 42
#define IF_MULTIACCESS 2
34 43
#define IF_UNNUMBERED 4
35 44
#define IF_BROADCAST 8
36
#define IF_MULTICAST 16
37
#define IF_TUNNEL 32
38
#define IF_ADMIN_DOWN 64
39
#define IF_LOOPBACK 128
40
#define IF_IGNORE 256
41
#define IF_LINK_UP 512
45
#define IF_MULTICAST 0x10
46
#define IF_TUNNEL 0x20
47
#define IF_ADMIN_DOWN 0x40
48
#define IF_LOOPBACK 0x80
49
#define IF_IGNORE 0x100			/* Not to be used by routing protocols (loopbacks etc.) */
50
#define IF_LINK_UP 0x200
51

  
52
#define IA_PRIMARY 0x10000		/* This address is primary */
53
#define IA_SECONDARY 0x20000		/* This address has been reported as secondary by the kernel */
54
#define IA_FLAGS 0xff0000
55

  
56
#define IF_JUST_CREATED 0x10000000	/* Send creation event as soon as possible */
57
#define IF_TMP_DOWN 0x20000000		/* Temporary shutdown due to interface reconfiguration */
42 58
#define IF_UPDATED 0x40000000		/* Touched in last scan */
43 59

  
44 60
/* Interface change events */
45 61

  
46 62
#define IF_CHANGE_UP 1
47 63
#define IF_CHANGE_DOWN 2
48
#define IF_CHANGE_FLAGS 4		/* Can be converted to down/up internally */
49
#define IF_CHANGE_MTU 8
50
#define IF_CHANGE_CREATE 16		/* Seen this interface for the first time */
64
#define IF_CHANGE_MTU 4
65
#define IF_CHANGE_CREATE 8		/* Seen this interface for the first time */
66
#define IF_CHANGE_TOO_MUCH 0x40000000	/* Used internally */
51 67

  
52 68
void if_init(void);
53 69
void if_dump(struct iface *);
54 70
void if_dump_all(void);
55
void if_update(struct iface *);
71
void ifa_dump(struct ifa *);
72
struct iface *if_update(struct iface *);
73
struct ifa *ifa_update(struct ifa *);
74
void ifa_delete(struct ifa *);
56 75
void if_start_update(void);
57 76
void if_end_update(void);
77
void if_end_partial_update(struct iface *);
58 78
void if_feed_baby(struct proto *);
59 79
struct iface *if_find_by_index(unsigned);
80
struct iface *if_find_by_name(char *);
60 81

  
61 82
/*
62 83
 *	Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
nest/protocol.h
13 13
#include "lib/resource.h"
14 14

  
15 15
struct iface;
16
struct ifa;
16 17
struct rte;
17 18
struct neighbor;
18 19
struct rta;
......
96 97
   *	General protocol hooks:
97 98
   *
98 99
   *	   if_notify	Notify protocol about interface state changes.
100
   *	   ifa_notify	Notify protocol about interface address changes.
99 101
   *	   rt_notify	Notify protocol about routing table updates.
100 102
   *	   neigh_notify	Notify protocol about neighbor cache events.
101 103
   *	   make_tmp_attrs  Construct ea_list from private attrs stored in rte.
......
106 108
   *			0=process it through the import filter set by the user.
107 109
   */
108 110

  
109
  void (*if_notify)(struct proto *, unsigned flags, struct iface *new, struct iface *old);
111
  void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
112
  void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a);
110 113
  void (*rt_notify)(struct proto *, struct network *net, struct rte *new, struct rte *old);
111 114
  void (*neigh_notify)(struct neighbor *neigh);
112 115
  struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
nest/rt-dev.c
19 19
#include "lib/resource.h"
20 20

  
21 21
static void
22
dev_if_notify(struct proto *p, unsigned c, struct iface *new, struct iface *old)
22
dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
23 23
{
24 24
  struct rt_dev_config *P = (void *) p->cf;
25 25

  
26
  if (old && !iface_patt_match(&P->iface_list, old) ||
27
      new && !iface_patt_match(&P->iface_list, new))
26
  if (!iface_patt_match(&P->iface_list, ad->iface))
28 27
    return;
29 28
  if (c & IF_CHANGE_DOWN)
30 29
    {
31 30
      net *n;
32 31

  
33
      debug("dev_if_notify: %s going down\n", old->name);
34
      n = net_find(p->table, old->prefix, old->pxlen);
32
      DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip);
33
      n = net_find(p->table, ad->prefix, ad->pxlen);
35 34
      if (!n)
36 35
	{
37 36
	  debug("dev_if_notify: device shutdown: prefix not found\n");
......
45 44
      net *n;
46 45
      rte *e;
47 46

  
48
      debug("dev_if_notify: %s going up\n", new->name);
47
      debug("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
49 48
      bzero(&A, sizeof(A));
50 49
      A.proto = p;
51 50
      A.source = RTS_DEVICE;
52
      A.scope = (new->flags & IF_LOOPBACK) ? SCOPE_HOST : SCOPE_UNIVERSE;
51
      A.scope = ad->scope;
53 52
      A.cast = RTC_UNICAST;
54 53
      A.dest = RTD_DEVICE;
55
      A.iface = new;
54
      A.iface = ad->iface;
56 55
      A.attrs = NULL;
57 56
      a = rta_lookup(&A);
58
      if (new->flags & IF_UNNUMBERED)
59
	n = net_get(p->table, new->opposite, new->pxlen);
57
      if (ad->flags & IF_UNNUMBERED)
58
	n = net_get(p->table, ad->opposite, ad->pxlen);
60 59
      else
61
	n = net_get(p->table, new->prefix, new->pxlen);
60
	n = net_get(p->table, ad->prefix, ad->pxlen);
62 61
      e = rte_get_temp(a);
63 62
      e->net = n;
64 63
      e->pflags = 0;
......
71 70
{
72 71
  struct proto *p = proto_new(c, sizeof(struct proto));
73 72

  
74
  p->if_notify = dev_if_notify;
73
  p->ifa_notify = dev_ifa_notify;
75 74
  return p;
76 75
}
77 76

  
proto/ospf/ospf.c
155 155
    {
156 156
      debug(" OSPF: Changing state into DR.\n");
157 157
      ifa->state=OSPF_IS_DR;
158
      ifa->drip=ifa->iface->ip;
158
      ifa->drip=ifa->iface->addr->ip;
159 159
      /* FIXME: Set ifa->drid */
160 160
    }
161 161
    else
......
221 221
}
222 222

  
223 223
void
224
ospf_if_notify(struct proto *p, unsigned flags, struct iface *new, struct iface *old)
224
ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
225 225
{
226 226
  struct ospf_iface *ifa;
227 227
  sock *mcsk, *newsk;
......
231 231
  c=(struct ospf_config *)(p->cf);
232 232

  
233 233
  DBG(" OSPF: If notify called\n");
234
  if (iface->flags & IF_IGNORE)
235
    return;
234 236

  
235
  if((flags & IF_CHANGE_UP) && is_good_iface(p, new))
237
  if((flags & IF_CHANGE_UP) && is_good_iface(p, iface))
236 238
  {
237
    debug(" OSPF: using interface %s.\n", new->name);
239
    debug(" OSPF: using interface %s.\n", iface->name);
238 240
    /* FIXME: Latter I'll use config - this is incorrect */
239 241
    ifa=mb_alloc(p->pool, sizeof(struct ospf_iface));
240
    ifa->iface=new;
242
    ifa->iface=iface;
241 243
    add_tail(&((struct proto_ospf *)p)->iface_list, NODE ifa);
242 244
    ospf_iface_default(ifa);
243 245
    /* FIXME: This should read config */
......
253 255

  
254 256
  if(flags & IF_CHANGE_DOWN)
255 257
  {
256
    if((ifa=find_iface((struct proto_ospf *)p, old))!=NULL)
258
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
257 259
    {
258
      debug(" OSPF: killing interface %s.\n", old->name);
260
      debug(" OSPF: killing interface %s.\n", iface->name);
259 261
    }
260 262
  }
261 263

  
262 264
  if(flags & IF_CHANGE_MTU)
263 265
  {
264
    if((ifa=find_iface((struct proto_ospf *)p, old))!=NULL)
266
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
265 267
    {
266
      debug(" OSPF: changing MTU on interface %s.\n", old->name);
268
      debug(" OSPF: changing MTU on interface %s.\n", iface->name);
267 269
    }
268 270
  }
269 271
}
......
321 323
  start:	ospf_start,
322 324
  preconfig:	ospf_preconfig,
323 325
  postconfig:	ospf_postconfig,
324

  
325 326
};
326

  
proto/rip/rip.c
491 491
  if (want_multicast)
492 492
    rif->sock->daddr = ipa_from_u32(0x7f000001); /* FIXME: must lookup address in rfc's */
493 493
  if (flags & IF_BROADCAST)
494
    rif->sock->daddr = new->brd;
494
    rif->sock->daddr = new->addr->brd;
495 495
  if (flags & IF_UNNUMBERED)
496
    rif->sock->daddr = new->opposite;
496
    rif->sock->daddr = new->addr->opposite;
497 497

  
498 498
  if (!ipa_nonzero(rif->sock->daddr))
499 499
    log( L_WARN "RIP: interface %s is too strange for me", rif->iface ? rif->iface->name : "(dummy)" );
......
507 507
}
508 508

  
509 509
static void
510
rip_if_notify(struct proto *p, unsigned c, struct iface *new, struct iface *old)
510
rip_if_notify(struct proto *p, unsigned c, struct iface *iface)
511 511
{
512 512
  DBG( "RIP: if notify\n" );
513
  if (old) {
513
  if (iface->flags & IF_IGNORE)
514
    return;
515
  if (c & IF_CHANGE_DOWN) {
514 516
    struct rip_interface *i;
515
    i = find_interface(p, old);
517
    i = find_interface(p, iface);
516 518
    if (i) {
517 519
      rem_node(NODE i);
518 520
      kill_iface(p, i);
519 521
    }
520 522
  }
521
  if (new) {
523
  if (c & IF_CHANGE_UP) {
522 524
    struct rip_interface *rif;
523
    struct iface_patt *k = iface_patt_match(&P_CF->iface_list, new);
525
    struct iface_patt *k = iface_patt_match(&P_CF->iface_list, iface);
524 526

  
525 527
    if (!k) return; /* We are not interested in this interface */
526
    DBG("adding interface %s\n", new->name );
527
    rif = new_iface(p, new, new->flags);
528
    DBG("adding interface %s\n", iface->name );
529
    rif = new_iface(p, iface, iface->flags);
528 530
    rif->patt = (void *) k;
529 531
    add_head( &P->interfaces, NODE rif );
530 532
  }
proto/static/static.c
134 134
}
135 135

  
136 136
static void
137
static_if_notify(struct proto *p, unsigned flags, struct iface *new, struct iface *old)
137
static_if_notify(struct proto *p, unsigned flags, struct iface *i)
138 138
{
139 139
  struct static_route *r;
140 140
  struct static_config *c = (void *) p->cf;
......
142 142
  if (flags & IF_CHANGE_UP)
143 143
    {
144 144
      WALK_LIST(r, c->iface_routes)
145
	if (!strcmp(r->if_name, new->name))
146
	  static_install(p, r, new);
145
	if (!strcmp(r->if_name, i->name))
146
	  static_install(p, r, i);
147 147
    }
148 148
  else if (flags & IF_CHANGE_DOWN)
149 149
    {
150 150
      WALK_LIST(r, c->iface_routes)
151
	if (!strcmp(r->if_name, old->name))
151
	if (!strcmp(r->if_name, i->name))
152 152
	  static_remove(p, r);
153 153
    }
154 154
}
sysdep/linux/netlink/netlink.c
407 407
 *	Routes
408 408
 */
409 409

  
410
int					/* FIXME: Check use of this function in krt.c */
410
int
411 411
krt_capable(rte *e)
412 412
{
413 413
  rta *a = e->attrs;
414 414

  
415
  if (a->cast != RTC_UNICAST)	/* FIXME: For IPv6, we might support anycasts as well */
415
  if (a->cast != RTC_UNICAST
416
#ifdef IPV6
417
      && a->cast != RTC_ANYCAST
418
#endif
419
      )
416 420
    return 0;
417 421
  if (a->source == RTS_DEVICE)	/* Kernel takes care of device routes itself */
418 422
    return 0;
......
597 601
  net = net_get(&master_table, dst, i->rtm_dst_len);
598 602
  ra.proto = &p->p;
599 603
  ra.source = RTS_INHERIT;
600
  ra.scope = SCOPE_UNIVERSE;	/* FIXME: Use kernel scope? */
604
  ra.scope = SCOPE_UNIVERSE;
601 605
  ra.cast = RTC_UNICAST;
602 606
  ra.flags = ra.aflags = 0;
603 607
  ra.from = IPA_NONE;
sysdep/unix/io.c
414 414
#ifdef HAVE_STRUCT_IP_MREQN
415 415
	struct ip_mreqn mreq;
416 416
#define mreq_add mreq
417
	ASSERT(s->iface);
417
	ASSERT(s->iface && s->iface->addr);
418 418
	mreq.imr_ifindex = s->iface->index;
419
	set_inaddr(&mreq.imr_address, s->iface->ip);
419
	set_inaddr(&mreq.imr_address, s->iface->addr->ip);
420 420
#else
421 421
	struct in_addr mreq;
422 422
	struct ip_mreq mreq_add;
423
	ASSERT(s->iface);
424
	set_inaddr(&mreq, s->iface->ip);
423
	ASSERT(s->iface && s->iface->addr);
424
	set_inaddr(&mreq, s->iface->addr->ip);
425 425
#ifdef SO_BINDTODEVICE
426 426
	{
427 427
	  struct ifreq ifr;
sysdep/unix/krt-iface.c
30 30
static void
31 31
scan_ifs(struct ifreq *r, int cnt)
32 32
{
33
  struct iface i;
33
  struct iface i, *pi;
34
  struct ifa a;
34 35
  char *err;
35 36
  unsigned fl;
36 37
  ip_addr netmask;
......
40 41
  for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
41 42
    {
42 43
      bzero(&i, sizeof(i));
44
      bzero(&a, sizeof(a));
43 45
      DBG("%s\n", r->ifr_name);
44 46
      if (strchr(r->ifr_name, ':'))
45 47
	{
......
48 50
	  continue;
49 51
	}
50 52
      strncpy(i.name, r->ifr_name, sizeof(i.name) - 1);
51
      get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.ip, NULL);
52
      if (ipa_nonzero(i.ip))
53
      get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL);
54
      if (ipa_nonzero(a.ip))
53 55
	{
54
	  l = ipa_classify(i.ip);
56
	  l = ipa_classify(a.ip);
55 57
	  if (l < 0 || !(l & IADDR_HOST))
56 58
	    {
57 59
	      log(L_ERR "%s: Invalid interface address", i.name);
58
	      i.ip = IPA_NONE;
60
	      a.ip = IPA_NONE;
61
	    }
62
	  else
63
	    {
64
	      a.scope = l & IADDR_SCOPE_MASK;
65
	      if (a.scope == SCOPE_HOST)
66
		i.flags |= IF_LOOPBACK | IF_IGNORE;
59 67
	    }
60
	  else if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST)
61
	    i.flags |= IF_LOOPBACK | IF_IGNORE;
62 68
	}
63 69

  
64 70
      if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
......
83 89
	  log(L_ERR "%s: Invalid netmask", i.name);
84 90
	  goto bad;
85 91
	}
86
      i.pxlen = l;
92
      a.pxlen = l;
87 93

  
88 94
      if (fl & IFF_POINTOPOINT)
89 95
	{
90 96
	  i.flags |= IF_UNNUMBERED;
91
	  i.pxlen = BITS_PER_IP_ADDRESS;
97
	  a.pxlen = BITS_PER_IP_ADDRESS;
92 98
	  if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
93 99
	    { err = "SIOCGIFDSTADDR"; goto faulty; }
94
	  get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.opposite, NULL);
100
	  get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL);
95 101
	}
96 102
      if (fl & IFF_LOOPBACK)
97 103
	i.flags |= IF_LOOPBACK | IF_IGNORE;
......
100 106
#endif
101 107
	i.flags |= IF_MULTICAST;
102 108

  
103
      i.prefix = ipa_and(i.ip, ipa_mkmask(i.pxlen));
104
      if (i.pxlen < 32)
109
      a.prefix = ipa_and(a.ip, ipa_mkmask(a.pxlen));
110
      if (a.pxlen < 32)
105 111
	{
106
	  i.brd = ipa_or(i.prefix, ipa_not(ipa_mkmask(i.pxlen)));
107
	  if (ipa_equal(i.ip, i.prefix) || ipa_equal(i.ip, i.brd))
112
	  a.brd = ipa_or(a.prefix, ipa_not(ipa_mkmask(a.pxlen)));
113
	  if (ipa_equal(a.ip, a.prefix) || ipa_equal(a.ip, a.brd))
108 114
	    {
109 115
	      log(L_ERR "%s: Using network or broadcast address for interface", i.name);
110 116
	      goto bad;
111 117
	    }
112 118
	  if (fl & IFF_BROADCAST)
113 119
	    i.flags |= IF_BROADCAST;
114
	  if (i.pxlen < 30)
120
	  if (a.pxlen < 30)
115 121
	    i.flags |= IF_MULTIACCESS;
116 122
	  else
117
	    i.opposite = ipa_opposite(i.ip);
123
	    a.opposite = ipa_opposite(a.ip);
118 124
	}
119 125
      else
120
	i.brd = i.opposite;
126
	a.brd = a.opposite;
121 127

  
122 128
      if (ioctl(if_scan_sock, SIOCGIFMTU, r) < 0)
123 129
	{ err = "SIOCGIFMTU"; goto faulty; }
......
132 138
      /* FIXME: What else? Guess ifindex (we need it at least for OSPF on unnumbered links)? */
133 139
#endif
134 140

  
135
      if_update(&i);
141
      pi = if_update(&i);
142
      a.iface = pi;
143
      ifa_update(&a);
136 144
    }
137 145
  if_end_update();
138 146
}

Also available in: Unified diff