Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / unix / krt-set.c @ 08c69a77

History | View | Annotate | Download (2.62 KB)

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

    
9
#include <string.h>
10
#include <sys/socket.h>
11
#include <netinet/in.h>
12
#include <sys/ioctl.h>
13
#include <net/route.h>
14

    
15
#define LOCAL_DEBUG
16

    
17
#include "nest/bird.h"
18
#include "nest/iface.h"
19
#include "nest/route.h"
20
#include "nest/protocol.h"
21
#include "lib/unix.h"
22
#include "lib/krt.h"
23

    
24
int
25
krt_capable(rte *e)
26
{
27
  rta *a = e->attrs;
28

    
29
  return
30
    a->cast == RTC_UNICAST &&
31
    (a->dest == RTD_ROUTER
32
     || a->dest == RTD_DEVICE
33
#ifdef RTF_REJECT
34
     || a->dest == RTD_UNREACHABLE
35
#endif
36
     ) &&
37
    !a->tos;
38
}
39

    
40
static inline int
41
krt_capable_op(rte *e)
42
{
43
  rta *a = e->attrs;
44

    
45
#ifdef CONFIG_AUTO_ROUTES
46
  if (a->dest == RTD_ROUTER && a->source == RTS_DEVICE)
47
    return 0;
48
#endif
49
  return krt_capable(e);
50
}
51

    
52
static void
53
krt_ioctl(int ioc, rte *e, char *name)
54
{
55
  net *net = e->net;
56
  struct rtentry re;
57
  rta *a = e->attrs;
58

    
59
  bzero(&re, sizeof(re));
60
  fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
61
  fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
62
  re.rt_flags = RTF_UP;
63
  if (net->n.pxlen == 32)
64
    re.rt_flags |= RTF_HOST;
65
  switch (a->dest)
66
    {
67
    case RTD_ROUTER:
68
      fill_in_sockaddr((struct sockaddr_in *) &re.rt_gateway, a->gw, 0);
69
      re.rt_flags |= RTF_GATEWAY;
70
      break;
71
    case RTD_DEVICE:
72
      re.rt_dev = a->iface->name;
73
      break;
74
#ifdef RTF_REJECT
75
    case RTD_UNREACHABLE:
76
      re.rt_flags |= RTF_REJECT;
77
      break;
78
#endif
79
    default:
80
      bug("krt set: unknown flags, but not filtered");
81
    }
82

    
83
  if (ioctl(if_scan_sock, ioc, &re) < 0)
84
    log(L_ERR "%s(%I/%d): %m", name, net->n.prefix, net->n.pxlen);
85
}
86

    
87
void
88
krt_remove_route(rte *old)
89
{
90
  net *net = old->net;
91

    
92
  if (!krt_capable_op(old))
93
    {
94
      DBG("krt_remove_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
95
      return;
96
    }
97
  DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
98
  krt_ioctl(SIOCDELRT, old, "SIOCDELRT");
99
}
100

    
101
void
102
krt_add_route(rte *new)
103
{
104
  net *net = new->net;
105

    
106
  if (!krt_capable_op(new))
107
    {
108
      DBG("krt_add_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
109
      return;
110
    }
111
  DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
112
  krt_ioctl(SIOCADDRT, new, "SIOCADDRT");
113
}
114

    
115
void
116
krt_set_notify(struct proto *x, net *net, rte *new, rte *old)
117
{
118
  if (x->state != PRS_UP)
119
    return;
120
  if (old)
121
    krt_remove_route(old);
122
  if (new)
123
    krt_add_route(new);
124
}
125

    
126
void
127
krt_set_preconfig(struct krt_proto *x)
128
{
129
  if (if_scan_sock < 0)
130
    bug("krt set: missing socket");
131
  x->p.rt_notify = krt_set_notify;
132
}