Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / iface.c @ 18a0c0bb

History | View | Annotate | Download (9.46 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
#include "ospf.h"
10

    
11
char *ospf_is[]={ "down", "loop", "waiting", "point-to-point", "drother",
12
  "backup", "dr" };
13

    
14
char *ospf_ism[]={ "interface up", "wait timer fired", "backup seen",
15
  "neighbor change", "loop indicated", "unloop indicated", "interface down"};   
16

    
17
void
18
iface_chstate(struct ospf_iface *ifa, u8 state)
19
{
20
  struct proto *p;
21

    
22
  if(ifa->state!=state)
23
  {
24
    p=(struct proto *)(ifa->proto);
25
    debug("%s: Changing state of iface: %s from \"%s\" into \"%s\".\n",
26
      p->name, ifa->iface->name, ospf_is[ifa->state], ospf_is[state]);
27
    ifa->state=state;
28
    if(ifa->iface->flags & IF_MULTICAST)
29
    {
30
      if((state==OSPF_IS_BACKUP)||(state==OSPF_IS_DR))
31
      {
32
        if(ifa->dr_sk==NULL)
33
        {
34
          DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
35
          ifa->dr_sk=sk_new(p->pool);
36
          ifa->dr_sk->type=SK_IP_MC;
37
          ifa->dr_sk->dport=OSPF_PROTO;
38
          ifa->dr_sk->saddr=AllDRouters;
39
          ifa->dr_sk->daddr=AllDRouters;
40
          ifa->dr_sk->tos=IP_PREC_INTERNET_CONTROL;
41
          ifa->dr_sk->ttl=1;
42
          ifa->dr_sk->rx_hook=ospf_rx_hook;
43
          ifa->dr_sk->tx_hook=ospf_tx_hook;
44
          ifa->dr_sk->err_hook=ospf_err_hook;
45
          ifa->dr_sk->iface=ifa->iface;
46
          ifa->dr_sk->rbsize=ifa->iface->mtu;
47
          ifa->dr_sk->tbsize=ifa->iface->mtu;
48
          ifa->dr_sk->data=(void *)ifa;
49
          if(sk_open(ifa->dr_sk)!=0)
50
          {
51
            DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
52
          }
53
        }
54
      }
55
      else
56
      {
57
        if(ifa->dr_sk!=NULL)
58
        {
59
          sk_close(ifa->dr_sk);
60
          rfree(ifa->dr_sk);
61
        }
62
      }
63
    }
64
  }
65
}
66

    
67
void
68
downint(struct ospf_iface *ifa)
69
{
70
  struct ospf_neighbor *n;
71
  struct proto *p=&ifa->proto->proto;
72
  struct proto_ospf *po=ifa->proto;
73

    
74
  WALK_LIST(n,ifa->neigh_list)
75
  {
76
    debug("%s: Removing neighbor %I", p->name, n->ip);
77
    ospf_neigh_remove(n);
78
  }
79
  rem_node(NODE ifa);
80
  if(ifa->hello_sk!=NULL)
81
  {
82
    sk_close(ifa->hello_sk);
83
    rfree(ifa->hello_sk);
84
  }
85
  if(ifa->dr_sk!=NULL)
86
  {
87
    sk_close(ifa->dr_sk);
88
    rfree(ifa->dr_sk);
89
  }
90
  if(ifa->ip_sk!=NULL)
91
  {
92
    sk_close(ifa->ip_sk);
93
    rfree(ifa->ip_sk);
94
  }
95
  if(ifa->wait_timer!=NULL)
96
  {
97
    tm_stop(ifa->wait_timer);
98
    rfree(ifa->wait_timer);
99
  }
100
  mb_free(ifa);
101
}
102

    
103
void
104
ospf_int_sm(struct ospf_iface *ifa, int event)
105
{
106
  struct proto *p=(struct proto *)(ifa->proto);
107
  struct proto_ospf *po=ifa->proto;
108

    
109
  debug("%s: SM on iface %s. Event is \"%s\".\n",
110
    p->name, ifa->iface->name, ospf_ism[event]);
111

    
112
  switch(event)
113
  {
114
    case ISM_UP:
115
      if(ifa->state==OSPF_IS_DOWN)
116
      {
117
        /* Now, nothing should be adjacent */
118
        restart_hellotim(ifa);
119
        if((ifa->type==OSPF_IT_PTP) || (ifa->type==OSPF_IT_VLINK))
120
        {
121
          iface_chstate(ifa, OSPF_IS_PTP);
122
        }
123
        else
124
        {
125
          if(ifa->priority==0)
126
          {
127
            iface_chstate(ifa, OSPF_IS_DROTHER);
128
          } 
129
          else
130
          {
131
             iface_chstate(ifa, OSPF_IS_WAITING);
132
             restart_waittim(ifa);
133
          }
134
        }
135
        addifa_rtlsa(ifa);
136
      }
137
      originate_rt_lsa(ifa->oa,po);
138
      break;
139
    case ISM_BACKS:
140
    case ISM_WAITF:
141
      if(ifa->state==OSPF_IS_WAITING)
142
      {
143
        bdr_election(ifa ,p);
144
      }
145
      break;
146
    case ISM_NEICH:
147
      if((ifa->state==OSPF_IS_DROTHER) || (ifa->state==OSPF_IS_DR) ||
148
        (ifa->state==OSPF_IS_BACKUP))
149
      {
150
        bdr_election(ifa ,p);
151
        originate_rt_lsa(ifa->oa,po);
152
      }
153
      break;
154
    case ISM_DOWN:
155
      iface_chstate(ifa, OSPF_IS_DOWN);
156
      downint(ifa);
157
      originate_rt_lsa(ifa->oa,po);
158
      break;
159
    case ISM_LOOP:        /* Useless? */
160
      iface_chstate(ifa, OSPF_IS_LOOP);
161
      downint(ifa);
162
      originate_rt_lsa(ifa->oa,po);
163
      break;
164
    case ISM_UNLOOP:
165
      iface_chstate(ifa, OSPF_IS_DOWN);
166
      originate_rt_lsa(ifa->oa,po);
167
      break;
168
    default:
169
      die("%s: ISM - Unknown event?",p->name);
170
      break;
171
  }
172
        
173
}
174

    
175
sock *
176
ospf_open_mc_socket(struct ospf_iface *ifa)
177
{
178
  sock *mcsk;
179
  struct proto *p;
180

    
181
  p=(struct proto *)(ifa->proto);
182

    
183
  mcsk=sk_new(p->pool);
184
  mcsk->type=SK_IP_MC;
185
  mcsk->dport=OSPF_PROTO;
186
  mcsk->saddr=AllSPFRouters;
187
  mcsk->daddr=AllSPFRouters;
188
  mcsk->tos=IP_PREC_INTERNET_CONTROL;
189
  mcsk->ttl=1;
190
  mcsk->rx_hook=ospf_rx_hook;
191
  mcsk->tx_hook=ospf_tx_hook;
192
  mcsk->err_hook=ospf_err_hook;
193
  mcsk->iface=ifa->iface;
194
  mcsk->rbsize=ifa->iface->mtu;
195
  mcsk->tbsize=ifa->iface->mtu;
196
  mcsk->data=(void *)ifa;
197
  if(sk_open(mcsk)!=0)
198
  {
199
    DBG("%s: SK_OPEN: mc open failed.\n",p->name);
200
    return(NULL);
201
  }
202
  DBG("%s: SK_OPEN: mc opened.\n",p->name);
203
  return(mcsk);
204
}
205

    
206
sock *
207
ospf_open_ip_socket(struct ospf_iface *ifa)
208
{
209
  sock *ipsk;
210
  struct proto *p;
211

    
212
  p=(struct proto *)(ifa->proto);
213

    
214
  ipsk=sk_new(p->pool);
215
  ipsk->type=SK_IP;
216
  ipsk->dport=OSPF_PROTO;
217
  ipsk->saddr=ifa->iface->addr->ip;
218
  ipsk->tos=IP_PREC_INTERNET_CONTROL;
219
  ipsk->ttl=1;
220
  ipsk->rx_hook=ospf_rx_hook;
221
  ipsk->tx_hook=ospf_tx_hook;
222
  ipsk->err_hook=ospf_err_hook;
223
  ipsk->iface=ifa->iface;
224
  ipsk->rbsize=ifa->iface->mtu;
225
  ipsk->tbsize=ifa->iface->mtu;
226
  ipsk->data=(void *)ifa;
227
  if(sk_open(ipsk)!=0)
228
  {
229
    DBG("%s: SK_OPEN: ip open failed.\n",p->name);
230
    return(NULL);
231
  }
232
  DBG("%s: SK_OPEN: ip opened.\n",p->name);
233
  return(ipsk);
234
}
235

    
236
/* 
237
 * This will later decide, wheter use iface for OSPF or not
238
 * depending on config
239
 */
240
u8
241
is_good_iface(struct proto *p, struct iface *iface)
242
{
243
  if(iface->flags & IF_UP)
244
  {
245
    if(!(iface->flags & IF_IGNORE)) return 1;
246
  }
247
  return 0;
248
}
249

    
250
/* Of course, it's NOT true now */
251
u8
252
ospf_iface_clasify(struct iface *ifa, struct proto *p)
253
{
254
  /* FIXME: Latter I'll use config - this is incorrect */
255
  DBG("%s: Iface flags=%x.\n", p->name, ifa->flags);
256
  if((ifa->flags & (IF_MULTIACCESS|IF_MULTICAST))==
257
    (IF_MULTIACCESS|IF_MULTICAST))
258
  {
259
     DBG("%s: Clasifying BCAST.\n", p->name);
260
     return OSPF_IT_BCAST;
261
  }
262
  if((ifa->flags & (IF_MULTIACCESS|IF_MULTICAST))==
263
    IF_MULTIACCESS)
264
  {
265
    DBG("%s: Clasifying NBMA.\n", p->name);
266
    return OSPF_IT_NBMA;
267
  }
268
  DBG("%s: Clasifying P-T-P.\n", p->name);
269
  return OSPF_IT_PTP;
270
}
271

    
272
void
273
ospf_add_timers(struct ospf_iface *ifa, pool *pool)
274
{
275
  struct proto *p;
276

    
277
  p=(struct proto *)(ifa->proto);
278
  /* Add hello timer */
279
  ifa->hello_timer=tm_new(pool);
280
  ifa->hello_timer->data=ifa;
281
  ifa->hello_timer->randomize=0;
282
  if(ifa->helloint==0) ifa->helloint=HELLOINT_D;
283
  ifa->hello_timer->hook=hello_timer_hook;
284
  ifa->hello_timer->recurrent=ifa->helloint;
285
  DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
286

    
287
  ifa->wait_timer=tm_new(pool);
288
  ifa->wait_timer->data=ifa;
289
  ifa->wait_timer->randomize=0;
290
  ifa->wait_timer->hook=wait_timer_hook;
291
  ifa->wait_timer->recurrent=0;
292
  if(ifa->waitint==0) ifa->waitint= WAIT_DMH*ifa->helloint;
293
  DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
294

    
295
  if(ifa->rxmtint==0) ifa->rxmtint=RXMTINT_D;
296
}
297

    
298
void
299
ospf_iface_default(struct ospf_iface *ifa)
300
{
301
  u8 i;
302

    
303
  ifa->oa=NULL;
304
  ifa->an=0;                /* FIXME This should respect config */
305
  ifa->cost=COST_D;
306
  ifa->rxmtint=RXMTINT_D;
307
  ifa->inftransdelay=INFTRANSDELAY_D;
308
  ifa->priority=PRIORITY_D;
309
  ifa->helloint=HELLOINT_D;
310
  ifa->deadc=DEADC_D;
311
  ifa->autype=0;
312
  for(i=0;i<8;i++) ifa->aukey[i]=0;
313
  ifa->options=2;
314
  ifa->drip=ipa_from_u32(0x00000000);
315
  ifa->drid=0;
316
  ifa->bdrip=ipa_from_u32(0x00000000);
317
  ifa->bdrid=0;
318
  ifa->type=ospf_iface_clasify(ifa->iface, (struct proto *)ifa->proto);
319
}
320

    
321
struct ospf_iface*
322
find_iface(struct proto_ospf *p, struct iface *what)
323
{
324
  struct ospf_iface *i;
325

    
326
  WALK_LIST (i, p->iface_list)
327
    if ((i)->iface == what)
328
      return i;
329
  return NULL;
330
}
331

    
332
void
333
ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
334
{
335
  struct ospf_iface *ifa;
336
  sock *mcsk;
337

    
338
  struct ospf_config *c;
339
  c=(struct ospf_config *)(p->cf);
340

    
341
  DBG("%s: If notify called\n", p->name);
342
  if (iface->flags & IF_IGNORE)
343
    return;
344

    
345
  if((flags & IF_CHANGE_UP) && is_good_iface(p, iface))
346
  {
347
    debug("%s: using interface %s.\n", p->name, iface->name);
348
    /* FIXME: Latter I'll use config - this is incorrect */
349
    ifa=mb_allocz(p->pool, sizeof(struct ospf_iface));
350
    ifa->proto=(struct proto_ospf *)p;
351
    ifa->iface=iface;
352
    ospf_iface_default(ifa);
353
    if(ifa->type!=OSPF_IT_NBMA)
354
    {
355
      if((ifa->hello_sk=ospf_open_mc_socket(ifa))==NULL)
356
      {
357
        log("%s: Huh? could not open mc socket on interface %s?", p->name,
358
          iface->name);
359
        mb_free(ifa);
360
        log("%s: Ignoring this interface\n", p->name);
361
        return;
362
      }
363
      ifa->dr_sk=NULL;
364

    
365
      if((ifa->ip_sk=ospf_open_ip_socket(ifa))==NULL)
366
      {
367
        log("%s: Huh? could not open ip socket on interface %s?", p->name,
368
          iface->name);
369
        mb_free(ifa);
370
        log("%s: Ignoring this interface\n", p->name);
371
        return;
372
      }
373

    
374
      init_list(&(ifa->neigh_list));
375
    }
376
    /* FIXME: This should read config */
377
    ifa->helloint=0;
378
    ifa->waitint=0;
379
    ospf_add_timers(ifa,p->pool);
380
    add_tail(&((struct proto_ospf *)p)->iface_list, NODE ifa);
381
    ifa->state=OSPF_IS_DOWN;
382
    ifa->nlsa=NULL;
383
    ifa->fadj=0;
384
    ospf_int_sm(ifa, ISM_UP);
385
  }
386

    
387
  if(flags & IF_CHANGE_DOWN)
388
  {
389
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
390
    {
391
      debug(" OSPF: killing interface %s.\n", iface->name);
392
      ospf_int_sm(ifa, ISM_DOWN);
393
    }
394
  }
395

    
396
  if(flags & IF_CHANGE_MTU)
397
  {
398
    if((ifa=find_iface((struct proto_ospf *)p, iface))!=NULL)
399
    {
400
      debug(" OSPF: changing MTU on interface %s.\n", iface->name);
401
      /* FIXME: change MTU */
402
    }
403
  }
404
}
405