Statistics
| Branch: | Revision:

iof-bird-daemon / proto / static / static.c @ feed8226

History | View | Annotate | Download (4.44 KB)

1
/*
2
 *        BIRD -- Static Route Generator
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
#define LOCAL_DEBUG
10

    
11
#include <string.h>
12

    
13
#include "nest/bird.h"
14
#include "nest/iface.h"
15
#include "nest/protocol.h"
16
#include "nest/route.h"
17
#include "nest/cli.h"
18
#include "conf/conf.h"
19
#include "lib/string.h"
20

    
21
#include "static.h"
22

    
23
static void
24
static_install(struct proto *p, struct static_route *r, struct iface *ifa)
25
{
26
  net *n;
27
  rta a, *aa;
28
  rte *e;
29

    
30
  DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest);
31
  bzero(&a, sizeof(a));
32
  a.proto = p;
33
  a.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC;
34
  a.scope = SCOPE_UNIVERSE;
35
  a.cast = RTC_UNICAST;
36
  a.dest = r->dest;
37
  a.gw = r->via;
38
  a.iface = ifa;
39
  aa = rta_lookup(&a);
40

    
41
  n = net_get(p->table, r->net, r->masklen);
42
  e = rte_get_temp(aa);
43
  e->net = n;
44
  e->pflags = 0;
45
  rte_update(p->table, n, p, e);
46
  r->installed = 1;
47
}
48

    
49
static void
50
static_remove(struct proto *p, struct static_route *r)
51
{
52
  net *n;
53

    
54
  DBG("Removing static route %I/%d\n", r->net, r->masklen);
55
  n = net_find(p->table, r->net, r->masklen);
56
  if (n)
57
    rte_update(p->table, n, p, NULL);
58
  r->installed = 0;
59
}
60

    
61
static int
62
static_start(struct proto *p)
63
{
64
  struct static_config *c = (void *) p->cf;
65
  struct static_route *r;
66

    
67
  DBG("Static: take off!\n");
68
  WALK_LIST(r, c->other_routes)
69
    switch (r->dest)
70
      {
71
      case RTD_ROUTER:
72
        {
73
          struct neighbor *n = neigh_find(p, &r->via, NEF_STICKY);
74
          if (n)
75
            {
76
              r->chain = n->data;
77
              n->data = r;
78
              r->neigh = n;
79
              if (n->iface)
80
                static_install(p, r, n->iface);
81
            }
82
          else
83
            log(L_ERR "Static route destination %I is invalid. Ignoring.\n", r->via);
84
          break;
85
        }
86
      case RTD_DEVICE:
87
        break;
88
      default:
89
        static_install(p, r, NULL);
90
      }
91
  return PS_UP;
92
}
93

    
94
static void
95
static_neigh_notify(struct neighbor *n)
96
{
97
  struct proto *p = n->proto;
98
  struct static_route *r;
99

    
100
  DBG("Static: neighbor notify for %I: iface %p\n", n->addr, n->iface);
101
  for(r=n->data; r; r=r->chain)
102
    if (n->iface)
103
      static_install(p, r, n->iface);
104
    else
105
      static_remove(p, r);
106
}
107

    
108
static void
109
static_dump_rt(struct static_route *r)
110
{
111
  debug("%16I/%2d: ", r->net, r->masklen);
112
  switch (r->dest)
113
    {
114
    case RTD_ROUTER:
115
      debug("via %I\n", r->via);
116
      break;
117
    case RTD_DEVICE:
118
      debug("dev %s\n", r->if_name);
119
      break;
120
    default:
121
      debug("rtd %d\n", r->dest);
122
      break;
123
    }
124
}
125

    
126
static void
127
static_dump(struct proto *p)
128
{
129
  struct static_config *c = (void *) p->cf;
130
  struct static_route *r;
131

    
132
  debug("Independent static routes:\n");
133
  WALK_LIST(r, c->other_routes)
134
    static_dump_rt(r);
135
  debug("Device static routes:\n");
136
  WALK_LIST(r, c->iface_routes)
137
    static_dump_rt(r);
138
}
139

    
140
static void
141
static_if_notify(struct proto *p, unsigned flags, struct iface *i)
142
{
143
  struct static_route *r;
144
  struct static_config *c = (void *) p->cf;
145

    
146
  if (flags & IF_CHANGE_UP)
147
    {
148
      WALK_LIST(r, c->iface_routes)
149
        if (!strcmp(r->if_name, i->name))
150
          static_install(p, r, i);
151
    }
152
  else if (flags & IF_CHANGE_DOWN)
153
    {
154
      WALK_LIST(r, c->iface_routes)
155
        if (!strcmp(r->if_name, i->name))
156
          static_remove(p, r);
157
    }
158
}
159

    
160
void
161
static_init_config(struct static_config *c)
162
{
163
  c->c.preference = DEF_PREF_STATIC;
164
  init_list(&c->iface_routes);
165
  init_list(&c->other_routes);
166
}
167

    
168
static struct proto *
169
static_init(struct proto_config *c)
170
{
171
  struct proto *p = proto_new(c, sizeof(struct proto));
172

    
173
  p->neigh_notify = static_neigh_notify;
174
  p->if_notify = static_if_notify;
175
  return p;
176
}
177

    
178
struct protocol proto_static = {
179
  name:                "Static",
180
  init:                static_init,
181
  dump:                static_dump,
182
  start:        static_start,
183
};
184

    
185
static void
186
static_show_rt(struct static_route *r)
187
{
188
  byte via[STD_ADDRESS_P_LENGTH + 16];
189

    
190
  switch (r->dest)
191
    {
192
    case RTD_ROUTER:        bsprintf(via, "via %I", r->via); break;
193
    case RTD_DEVICE:        bsprintf(via, "to %s", r->if_name); break;
194
    case RTD_BLACKHOLE:        bsprintf(via, "blackhole"); break;
195
    case RTD_UNREACHABLE:        bsprintf(via, "unreachable"); break;
196
    case RTD_PROHIBIT:        bsprintf(via, "prohibited"); break;
197
    default:                bsprintf(via, "???");
198
    }
199
  cli_msg(-1009, "%I/%d %s%s", r->net, r->masklen, via, r->installed ? "" : " (dormant)");
200
}
201

    
202
void
203
static_show(struct proto *P)
204
{
205
  struct static_config *c = (void *) P->cf;
206
  struct static_route *r;
207

    
208
  WALK_LIST(r, c->other_routes)
209
    static_show_rt(r);
210
  WALK_LIST(r, c->iface_routes)
211
    static_show_rt(r);
212
  cli_msg(0, "");
213
}