Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / unix / krt-set.c @ 013a9b91

History | View | Annotate | Download (3.1 KB)

1
/*
2
 *        BIRD -- Unix Routing Table Syncing
3
 *
4
 *        (c) 1998--1999 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 (old)
119
    krt_remove_route(old);
120
  if (new)
121
    krt_add_route(new);
122
}
123

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

    
132
void
133
krt_set_preconfig(struct krt_config *c)
134
{
135
}
136

    
137
void
138
krt_set_shutdown(struct krt_proto *x)
139
{
140
  struct rtable *t = &master_table;
141

    
142
  if (((struct krt_config *) x->p.cf)->setopt.persist)
143
    return;
144
  DBG("Flushing kernel routes...\n");
145
  while (t && t->tos)
146
    t = t->sibling;
147
  if (!t)
148
    return;
149
  FIB_WALK(&t->fib, f)
150
    {
151
      net *n = (net *) f;
152
      rte *e = n->routes;
153
      if (e)
154
        {
155
          rta *a = e->attrs;
156
          if (a->source != RTS_DEVICE && a->source != RTS_INHERIT)
157
            krt_remove_route(e);
158
        }
159
    }
160
  FIB_WALK_END;
161
}