Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / ospf.c @ 9a158361

History | View | Annotate | Download (6.51 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999 Ondrej Filip <feela@network.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 "conf/conf.h"
18
#include "lib/ip.h"
19
#include "lib/socket.h"
20
#include "lib/lists.h"
21
#include "lib/timer.h"
22

    
23
#include "ospf.h"
24

    
25
int
26
ospf_rx_hook(sock *sk, int size)
27
{
28
  DBG(" OSPF: RX_Hook called on interface ");
29
  DBG(sk->iface->name);
30
  DBG(".\n");
31
  return(1);
32
}
33

    
34
void
35
ospf_tx_hook(sock *sk)
36
{
37
  DBG(" OSPF: TX_Hook called on interface ");
38
  DBG(sk->iface->name);
39
  DBG(".\n");
40
}
41

    
42
void
43
ospf_err_hook(sock *sk, int err)
44
{
45
  DBG(" OSPF: Err_Hook called on interface ");
46
  DBG(sk->iface->name);
47
  DBG(".\n");
48
}
49

    
50
/* This will change ! */
51
sock *
52
ospf_open_socket(struct proto *p, struct ospf_iface *ifa)
53
{
54
  sock *mcsk;
55

    
56
  /* No NBMA networks now */
57

    
58
  if(ifa->iface->flags & IF_MULTICAST)
59
  {
60
    mcsk=sk_new(p->pool);
61
    mcsk->type=SK_IP_MC;
62
    mcsk->dport=OSPF_PROTO;
63
    mcsk->saddr=AllSPFRouters;
64
    mcsk->daddr=AllSPFRouters;
65
    mcsk->ttl=1;
66
    mcsk->rx_hook=ospf_rx_hook;
67
    mcsk->tx_hook=ospf_tx_hook;
68
    mcsk->err_hook=ospf_err_hook;
69
    mcsk->iface=ifa->iface;
70
    mcsk->rbsize=ifa->iface->mtu;
71
    mcsk->tbsize=ifa->iface->mtu;
72
    if(sk_open(mcsk)!=0)
73
    {
74
      DBG(" OSPF: SK_OPEN: failed\n");
75
      return(NULL);
76
    }
77
    DBG(" OSPF: SK_OPEN: open\n");
78
    return(mcsk);
79
  }
80
  else return(NULL);
81
}
82

    
83
/* 
84
 * This will later decide, wheter use iface for OSPF or not
85
 * depending on config
86
 */
87
int
88
is_good_iface(struct proto *p, struct iface *iface)
89
{
90
  if(iface->flags & IF_UP)
91
  {
92
    if(!(iface->flags & IF_IGNORE)) return 1;
93
  }
94
  return 0;
95
}
96

    
97
/* Of course, it's NOT true now */
98
int
99
ospf_iface_clasify(struct iface *ifa)
100
{
101
  /* FIXME: Latter I'll use config - this is incorrect */
102
  if((ifa->flags & (IF_MULTIACCESS|IF_MULTICAST))==
103
    (IF_MULTIACCESS|IF_MULTICAST))
104
  {
105
     DBG(" OSPF: Clasifying BROADCAST.\n");
106
     return OSPF_IT_BROADCAST;
107
  }
108
  if((ifa->flags & (IF_MULTIACCESS|IF_MULTICAST))==
109
    IF_MULTIACCESS)
110
  {
111
    DBG(" OSPF: Clasifying NBMA.\n");
112
    return OSPF_IT_NBMA;
113
  }
114
  DBG(" OSPF: Clasifying P-T-P.\n");
115
  return OSPF_IT_PTP;
116
}
117

    
118
void
119
hello_timer_hook(timer *timer)
120
{
121
  struct ospf_iface *ifa;
122

    
123
  ifa=(struct ospf_iface *)timer->data;
124
  debug(" OSPF: Hello timer fired on interface %s.\n",
125
    ifa->iface->name);
126
}
127

    
128
void
129
add_hello_timer(struct ospf_iface *ifa)
130
{
131
  if(ifa->helloint==0) ifa->helloint=HELLOINT_D;
132
  
133
  ifa->timer->hook=hello_timer_hook;
134
  ifa->timer->recurrent=ifa->helloint;
135
  ifa->timer->expires=0;
136
  tm_start(ifa->timer,0);
137
  DBG(" OSPF: Installing hello timer.\n");
138
}
139

    
140
void
141
wait_timer_hook(timer *timer)
142
{
143
  struct ospf_iface *ifa;
144

    
145
  ifa=(struct ospf_iface *)timer->data;
146
  debug(" OSPF: Wait timer fired on interface %s.\n",
147
    ifa->iface->name);
148
  if(ifa->state=OSPF_IS_WAITING)
149
  {
150
    /*
151
     * Wait time fired. Now we must change state
152
     * to DR or DROTHER depending on priority
153
     */
154
    if(ifa->priority!=0)
155
    {
156
      debug(" OSPF: Changing state into DR.\n");
157
      ifa->state=OSPF_IS_DR;
158
      ifa->drip=ifa->iface->addr->ip;
159
      /* FIXME: Set ifa->drid */
160
    }
161
    else
162
    {
163
      debug(" OSPF: Changing state into DROTHER.\n");
164
      ifa->state=OSPF_IS_DROTHER;
165
    }
166
    add_hello_timer(ifa);
167
  }
168
}
169

    
170
void
171
add_wait_timer(struct ospf_iface *ifa,pool *pool, int wait)
172
{
173
  ifa->timer=tm_new(pool);
174
  ifa->timer->data=ifa;
175
  ifa->timer->randomize=1;
176
  if((ifa->type!=OSPF_IT_PTP))
177
  {
178
    ifa->timer->hook=wait_timer_hook;
179
    ifa->timer->recurrent=0;
180
    ifa->timer->expires=0;
181
    tm_start(ifa->timer,(wait!=0 ? wait : WAIT_D));
182
    DBG(" OSPF: Installing wait timer.\n");
183
  }
184
  else
185
  {
186
    add_hello_timer(ifa);
187
  }
188
}
189

    
190
void
191
ospf_iface_default(struct ospf_iface *ifa)
192
{
193
  int i;
194

    
195
  ifa->area=0;
196
  ifa->cost=COST_D;
197
  ifa->rxmtint=RXMTINT_D;
198
  ifa->iftransdelay=IFTRANSDELAY_D;
199
  ifa->priority=PRIORITY_D;
200
  ifa->helloint=HELLOINT_D;
201
  ifa->deadint=DEADINT_D;
202
  ifa->autype=0;
203
  for(i=0;i<8;i++) ifa->aukey[i]=0;
204
  ifa->options=0;
205
  ifa->drip=ipa_from_u32(0x00000000);
206
  ifa->drid=0;
207
  ifa->bdrip=ipa_from_u32(0x00000000);
208
  ifa->bdrid=0;
209
  ifa->type=ospf_iface_clasify(ifa->iface);
210
}
211

    
212
struct ospf_iface*
213
find_iface(struct proto_ospf *p, struct iface *what)
214
{
215
  struct ospf_iface *i;
216

    
217
  WALK_LIST (i, p->iface_list)
218
    if ((i)->iface == what)
219
      return i;
220
  return NULL;
221
}
222

    
223
void
224
ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
225
{
226
  struct ospf_iface *ifa;
227
  sock *mcsk, *newsk;
228
  struct ospf_sock *osk;
229

    
230
  struct ospf_config *c;
231
  c=(struct ospf_config *)(p->cf);
232

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

    
237
  if((flags & IF_CHANGE_UP) && is_good_iface(p, iface))
238
  {
239
    debug(" OSPF: using interface %s.\n", iface->name);
240
    /* FIXME: Latter I'll use config - this is incorrect */
241
    ifa=mb_alloc(p->pool, sizeof(struct ospf_iface));
242
    ifa->iface=iface;
243
    add_tail(&((struct proto_ospf *)p)->iface_list, NODE ifa);
244
    ospf_iface_default(ifa);
245
    /* FIXME: This should read config */
246
    add_wait_timer(ifa,p->pool,0);
247
    init_list(&(ifa->sk_list));
248
    if((mcsk=ospf_open_socket(p, ifa))!=NULL)
249
    {
250
      osk=(struct ospf_sock *)mb_alloc(p->pool, sizeof(struct ospf_sock));
251
      osk->sk=mcsk;
252
      add_tail(&(ifa->sk_list),NODE osk);
253
    }
254
  }
255

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

    
264
  if(flags & IF_CHANGE_MTU)
265
  {
266
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
267
    {
268
      debug(" OSPF: changing MTU on interface %s.\n", iface->name);
269
    }
270
  }
271
}
272

    
273

    
274
static int
275
ospf_start(struct proto *p)
276
{
277
  DBG(" OSPF: Start\n");
278

    
279
  p->if_notify=ospf_if_notify;
280

    
281
  return PS_UP;
282
}
283

    
284
static void
285
ospf_dump(struct proto *p)
286
{
287
  char areastr[20];
288
  struct ospf_config *c = (void *) p->cf;
289

    
290
  DBG(" OSPF: Dump.\n");
291
  debug(" -AreaID: %d\n", c->area );
292
}
293

    
294
static struct proto *
295
ospf_init(struct proto_config *c)
296
{
297
  struct proto *p = proto_new(c, sizeof(struct proto_ospf));
298

    
299
  DBG(" OSPF: Init.\n");
300
  p->neigh_notify = NULL;
301
  p->if_notify = NULL;
302
  init_list(&((struct proto_ospf *)p)->iface_list);
303
  return p;
304
}
305

    
306
static void
307
ospf_preconfig(struct protocol *p, struct config *c)
308
{
309
  DBG( " OSPF: preconfig\n" );
310
}
311

    
312
static void
313
ospf_postconfig(struct proto_config *c)
314
{
315
  DBG( " OSPF: postconfig\n" );
316
}
317

    
318

    
319
struct protocol proto_ospf = {
320
  name:                "OSPF",
321
  init:                ospf_init,
322
  dump:                ospf_dump,
323
  start:        ospf_start,
324
  preconfig:        ospf_preconfig,
325
  postconfig:        ospf_postconfig,
326
};