]>
Commit | Line | Data |
---|---|---|
4364b47e OF |
1 | /* |
2 | * BIRD -- OSPF | |
3 | * | |
e300066d | 4 | * (c) 1999--2005 Ondrej Filip <feela@network.cz> |
4364b47e OF |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #include "ospf.h" | |
10 | ||
b9ed99f7 OF |
11 | char *ospf_is[] = { "down", "loop", "waiting", "point-to-point", "drother", |
12 | "backup", "dr" | |
13 | }; | |
8914e37d | 14 | |
b9ed99f7 OF |
15 | char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen", |
16 | "neighbor change", "loop indicated", "unloop indicated", "interface down" | |
17 | }; | |
79f036ef | 18 | |
b9ed99f7 | 19 | char *ospf_it[] = { "broadcast", "nbma", "point-to-point", "virtual link" }; |
c4f0f014 | 20 | |
9831e591 | 21 | static void |
b9ed99f7 | 22 | poll_timer_hook(timer * timer) |
39e517d4 | 23 | { |
3b16080c | 24 | log("POLL!"); |
39e517d4 OF |
25 | ospf_hello_send(timer, 1, NULL); |
26 | } | |
27 | ||
9831e591 | 28 | static void |
b9ed99f7 | 29 | hello_timer_hook(timer * timer) |
39e517d4 OF |
30 | { |
31 | ospf_hello_send(timer, 0, NULL); | |
32 | } | |
33 | ||
9831e591 | 34 | static void |
b9ed99f7 | 35 | wait_timer_hook(timer * timer) |
39e517d4 | 36 | { |
b9ed99f7 | 37 | struct ospf_iface *ifa = (struct ospf_iface *) timer->data; |
86c84d76 | 38 | struct proto *p = &ifa->oa->po->proto; |
39e517d4 | 39 | |
b9ed99f7 OF |
40 | OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name); |
41 | ospf_iface_sm(ifa, ISM_WAITF); | |
39e517d4 OF |
42 | } |
43 | ||
94c42054 OF |
44 | u32 |
45 | rxbufsize(struct ospf_iface *ifa) | |
46 | { | |
47 | switch(ifa->rxbuf) | |
48 | { | |
49 | case OSPF_RXBUF_NORMAL: | |
50 | return (ifa->iface->mtu * 2); | |
51 | break; | |
52 | case OSPF_RXBUF_LARGE: | |
53 | return OSPF_MAX_PKT_SIZE; | |
54 | break; | |
55 | default: | |
56 | return ifa->rxbuf; | |
57 | break; | |
58 | } | |
59 | } | |
60 | ||
3b16080c | 61 | static sock * |
f9c799a0 | 62 | ospf_open_socket(struct ospf_iface *ifa, int mc) |
3b16080c OF |
63 | { |
64 | sock *ipsk; | |
86c84d76 | 65 | struct proto *p = &ifa->oa->po->proto; |
3b16080c OF |
66 | |
67 | ipsk = sk_new(p->pool); | |
68 | ipsk->type = SK_IP; | |
69 | ipsk->dport = OSPF_PROTO; | |
061ab802 OZ |
70 | |
71 | #ifdef OSPFv2 | |
f9c799a0 OZ |
72 | // ipsk->saddr = ifa->iface->addr->ip; |
73 | ipsk->saddr = IPA_NONE; | |
061ab802 OZ |
74 | #else /* OSPFv3 */ |
75 | ipsk->saddr = ifa->lladdr; | |
76 | #endif | |
77 | ||
3b16080c OF |
78 | ipsk->tos = IP_PREC_INTERNET_CONTROL; |
79 | ipsk->ttl = 1; | |
80 | if (ifa->type == OSPF_IT_VLINK) | |
81 | ipsk->ttl = 255; | |
82 | ipsk->rx_hook = ospf_rx_hook; | |
83 | ipsk->tx_hook = ospf_tx_hook; | |
84 | ipsk->err_hook = ospf_err_hook; | |
85 | ipsk->iface = ifa->iface; | |
94c42054 | 86 | ipsk->rbsize = rxbufsize(ifa); |
3b16080c OF |
87 | ipsk->tbsize = ifa->iface->mtu; |
88 | ipsk->data = (void *) ifa; | |
89 | if (sk_open(ipsk) != 0) | |
f9c799a0 OZ |
90 | goto err; |
91 | ||
92 | if (mc) | |
3b16080c | 93 | { |
f9c799a0 OZ |
94 | if (sk_setup_multicast(ipsk) < 0) |
95 | goto err; | |
96 | ||
97 | if (sk_join_group(ipsk, AllSPFRouters) < 0) | |
98 | goto err; | |
3b16080c | 99 | } |
f9c799a0 OZ |
100 | |
101 | return ipsk; | |
102 | ||
103 | err: | |
104 | rfree(ipsk); | |
105 | return NULL; | |
3b16080c OF |
106 | } |
107 | ||
39e517d4 | 108 | |
d5e4b518 | 109 | /** |
b9ed99f7 | 110 | * ospf_iface_chstate - handle changes of interface state |
d5e4b518 OF |
111 | * @ifa: OSPF interface |
112 | * @state: new state | |
113 | * | |
baa5dd6c OF |
114 | * Many actions must be taken according to interface state changes. New network |
115 | * LSAs must be originated, flushed, new multicast sockets to listen for messages for | |
116 | * %ALLDROUTERS have to be opened, etc. | |
d5e4b518 | 117 | */ |
4364b47e | 118 | void |
b9ed99f7 | 119 | ospf_iface_chstate(struct ospf_iface *ifa, u8 state) |
4364b47e | 120 | { |
86c84d76 | 121 | struct proto_ospf *po = ifa->oa->po; |
b9ed99f7 | 122 | struct proto *p = &po->proto; |
3b16080c | 123 | u8 oldstate = ifa->state; |
4364b47e | 124 | |
3b16080c | 125 | if (oldstate != state) |
2a092594 | 126 | { |
b9ed99f7 | 127 | ifa->state = state; |
3b16080c OF |
128 | |
129 | if (ifa->type == OSPF_IT_VLINK) | |
2a092594 | 130 | { |
3b16080c | 131 | OSPF_TRACE(D_EVENTS, |
3aab39f5 OZ |
132 | "Changing state of virtual link %R from \"%s\" into \"%s\".", |
133 | ifa->vid, ospf_is[oldstate], ospf_is[state]); | |
3b16080c | 134 | if (state == OSPF_IS_PTP) |
2a092594 | 135 | { |
f9c799a0 | 136 | ifa->sk = ospf_open_socket(ifa, 0); |
3b16080c OF |
137 | } |
138 | } | |
139 | else | |
140 | { | |
141 | OSPF_TRACE(D_EVENTS, | |
142 | "Changing state of iface: %s from \"%s\" into \"%s\".", | |
143 | ifa->iface->name, ospf_is[oldstate], ospf_is[state]); | |
144 | if (ifa->iface->flags & IF_MULTICAST) | |
145 | { | |
f9c799a0 OZ |
146 | if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) && |
147 | ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))) | |
b9ed99f7 | 148 | { |
f9c799a0 OZ |
149 | /* FIXME some error handing ? */ |
150 | sk_join_group(ifa->sk, AllDRouters); | |
151 | ifa->dr_up = 1; | |
b9ed99f7 | 152 | } |
f9c799a0 | 153 | else if (ifa->dr_up) |
eb2c99a1 | 154 | { |
f9c799a0 OZ |
155 | sk_leave_group(ifa->sk, AllDRouters); |
156 | ifa->dr_up = 0; | |
3b16080c | 157 | } |
c3226991 | 158 | if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL)) |
3b16080c | 159 | { |
c3226991 | 160 | ifa->net_lsa->lsa.age = LSA_MAXAGE; |
3b16080c OF |
161 | if (state >= OSPF_IS_WAITING) |
162 | { | |
c3226991 | 163 | ospf_lsupd_flush_nlsa(po, ifa->net_lsa); |
3b16080c | 164 | } |
86c84d76 | 165 | if (can_flush_lsa(po)) |
c3226991 OZ |
166 | flush_lsa(ifa->net_lsa, po); |
167 | ifa->net_lsa = NULL; | |
eb2c99a1 | 168 | } |
dc2548d2 | 169 | } |
2a092594 OF |
170 | } |
171 | } | |
4364b47e OF |
172 | } |
173 | ||
b9ed99f7 OF |
174 | static void |
175 | ospf_iface_down(struct ospf_iface *ifa) | |
4364b47e | 176 | { |
b9ed99f7 | 177 | struct ospf_neighbor *n, *nx; |
86c84d76 OF |
178 | struct proto_ospf *po = ifa->oa->po; |
179 | struct proto *p = &po->proto; | |
98ac6176 | 180 | struct ospf_iface *iff; |
18a0c0bb | 181 | |
3b16080c OF |
182 | /* First of all kill all the related vlinks */ |
183 | if (ifa->type != OSPF_IT_VLINK) | |
184 | { | |
185 | WALK_LIST(iff, po->iface_list) | |
186 | { | |
187 | if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface)) | |
188 | ospf_iface_down(iff); | |
189 | } | |
190 | } | |
191 | ||
b9ed99f7 | 192 | WALK_LIST_DELSAFE(n, nx, ifa->neigh_list) |
18a0c0bb | 193 | { |
1ae494a7 | 194 | OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip); |
18a0c0bb OF |
195 | ospf_neigh_remove(n); |
196 | } | |
f9c799a0 OZ |
197 | |
198 | rfree(ifa->sk); | |
199 | ifa->sk = NULL; | |
c9f6cf8a | 200 | |
3b16080c | 201 | if (ifa->type == OSPF_IT_VLINK) |
98ac6176 | 202 | { |
98ac6176 OF |
203 | ifa->iface = NULL; |
204 | return; | |
205 | } | |
206 | else | |
207 | { | |
208 | rfree(ifa->wait_timer); | |
209 | rfree(ifa->hello_timer); | |
210 | rfree(ifa->poll_timer); | |
211 | rfree(ifa->lock); | |
212 | rem_node(NODE ifa); | |
213 | mb_free(ifa); | |
214 | } | |
4364b47e OF |
215 | } |
216 | ||
d5e4b518 | 217 | /** |
b9ed99f7 | 218 | * ospf_iface_sm - OSPF interface state machine |
d5e4b518 OF |
219 | * @ifa: OSPF interface |
220 | * @event: event comming to state machine | |
221 | * | |
98ac6176 | 222 | * This fully respects 9.3 of RFC 2328 except we don't use %LOOP state of |
d5e4b518 OF |
223 | * interface. |
224 | */ | |
4364b47e | 225 | void |
b9ed99f7 | 226 | ospf_iface_sm(struct ospf_iface *ifa, int event) |
4364b47e | 227 | { |
b9ed99f7 | 228 | struct ospf_area *oa = ifa->oa; |
4364b47e | 229 | |
23d67029 | 230 | DBG("SM on iface %s. Event is '%s'\n", ifa->iface->name, ospf_ism[event]); |
4364b47e | 231 | |
b9ed99f7 | 232 | switch (event) |
4364b47e | 233 | { |
b9ed99f7 OF |
234 | case ISM_UP: |
235 | if (ifa->state == OSPF_IS_DOWN) | |
236 | { | |
237 | /* Now, nothing should be adjacent */ | |
b9ed99f7 | 238 | if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK)) |
3b16080c | 239 | { |
b9ed99f7 | 240 | ospf_iface_chstate(ifa, OSPF_IS_PTP); |
3b16080c | 241 | } |
b9ed99f7 | 242 | else |
4364b47e | 243 | { |
b9ed99f7 OF |
244 | if (ifa->priority == 0) |
245 | ospf_iface_chstate(ifa, OSPF_IS_DROTHER); | |
246 | else | |
247 | { | |
248 | ospf_iface_chstate(ifa, OSPF_IS_WAITING); | |
249 | tm_start(ifa->wait_timer, ifa->waitint); | |
250 | } | |
4364b47e | 251 | } |
3b16080c OF |
252 | |
253 | tm_start(ifa->hello_timer, ifa->helloint); | |
254 | ||
255 | if (ifa->poll_timer) | |
256 | tm_start(ifa->poll_timer, ifa->pollint); | |
257 | ||
897999c2 | 258 | hello_timer_hook(ifa->hello_timer); |
b9ed99f7 OF |
259 | } |
260 | schedule_rt_lsa(ifa->oa); | |
261 | break; | |
262 | case ISM_BACKS: | |
263 | case ISM_WAITF: | |
264 | if (ifa->state == OSPF_IS_WAITING) | |
265 | { | |
266 | bdr_election(ifa); | |
267 | } | |
268 | break; | |
269 | case ISM_NEICH: | |
270 | if ((ifa->state == OSPF_IS_DROTHER) || (ifa->state == OSPF_IS_DR) || | |
271 | (ifa->state == OSPF_IS_BACKUP)) | |
272 | { | |
273 | bdr_election(ifa); | |
70a38319 | 274 | schedule_rt_lsa(ifa->oa); |
b9ed99f7 OF |
275 | } |
276 | break; | |
277 | case ISM_DOWN: | |
278 | ospf_iface_chstate(ifa, OSPF_IS_DOWN); | |
279 | ospf_iface_down(ifa); | |
280 | schedule_rt_lsa(oa); | |
281 | break; | |
282 | case ISM_LOOP: /* Useless? */ | |
283 | ospf_iface_chstate(ifa, OSPF_IS_LOOP); | |
284 | ospf_iface_down(ifa); | |
285 | schedule_rt_lsa(ifa->oa); | |
286 | break; | |
287 | case ISM_UNLOOP: | |
288 | ospf_iface_chstate(ifa, OSPF_IS_DOWN); | |
289 | schedule_rt_lsa(ifa->oa); | |
290 | break; | |
291 | default: | |
292 | bug("OSPF_I_SM - Unknown event?"); | |
293 | break; | |
4364b47e | 294 | } |
b9ed99f7 | 295 | |
4364b47e OF |
296 | } |
297 | ||
f9c799a0 | 298 | #if 0 |
b9ed99f7 | 299 | static sock * |
4364b47e OF |
300 | ospf_open_mc_socket(struct ospf_iface *ifa) |
301 | { | |
302 | sock *mcsk; | |
86c84d76 | 303 | struct proto *p = &ifa->oa->po->proto; |
b9ed99f7 OF |
304 | |
305 | mcsk = sk_new(p->pool); | |
306 | mcsk->type = SK_IP_MC; | |
307 | mcsk->sport = 0; | |
308 | mcsk->dport = OSPF_PROTO; | |
061ab802 OZ |
309 | |
310 | #ifdef OSPFv2 | |
d2ceaf4e | 311 | mcsk->saddr = AllSPFRouters; |
061ab802 | 312 | #else /* OSPFv3 */ |
d2ceaf4e | 313 | // mcsk->saddr = AllSPFRouters; |
061ab802 OZ |
314 | mcsk->saddr = ifa->lladdr; |
315 | #endif | |
316 | ||
b9ed99f7 OF |
317 | mcsk->daddr = AllSPFRouters; |
318 | mcsk->tos = IP_PREC_INTERNET_CONTROL; | |
319 | mcsk->ttl = 1; | |
320 | mcsk->rx_hook = ospf_rx_hook; | |
321 | mcsk->tx_hook = ospf_tx_hook; | |
322 | mcsk->err_hook = ospf_err_hook; | |
323 | mcsk->iface = ifa->iface; | |
94c42054 | 324 | mcsk->rbsize = rxbufsize(ifa); |
b9ed99f7 OF |
325 | mcsk->tbsize = ifa->iface->mtu; |
326 | mcsk->data = (void *) ifa; | |
327 | if (sk_open(mcsk) != 0) | |
4364b47e | 328 | { |
b9ed99f7 OF |
329 | DBG("%s: SK_OPEN: mc open failed.\n", p->name); |
330 | return (NULL); | |
4364b47e | 331 | } |
b9ed99f7 OF |
332 | DBG("%s: SK_OPEN: mc opened.\n", p->name); |
333 | return (mcsk); | |
4364b47e | 334 | } |
f9c799a0 | 335 | #endif |
4364b47e | 336 | |
4364b47e | 337 | u8 |
2e10a170 | 338 | ospf_iface_clasify(struct iface * ifa) |
4364b47e | 339 | { |
b9ed99f7 OF |
340 | if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == |
341 | (IF_MULTIACCESS | IF_MULTICAST)) | |
342 | return OSPF_IT_BCAST; | |
343 | ||
344 | if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS) | |
4364b47e | 345 | return OSPF_IT_NBMA; |
b9ed99f7 | 346 | |
4364b47e OF |
347 | return OSPF_IT_PTP; |
348 | } | |
349 | ||
b9ed99f7 OF |
350 | struct ospf_iface * |
351 | ospf_iface_find(struct proto_ospf *p, struct iface *what) | |
4364b47e OF |
352 | { |
353 | struct ospf_iface *i; | |
354 | ||
3b16080c | 355 | WALK_LIST(i, p->iface_list) if ((i->iface == what) && (i->type != OSPF_IT_VLINK)) |
b9ed99f7 | 356 | return i; |
4364b47e OF |
357 | return NULL; |
358 | } | |
359 | ||
b9ed99f7 OF |
360 | static void |
361 | ospf_iface_add(struct object_lock *lock) | |
362 | { | |
363 | struct ospf_iface *ifa = lock->data; | |
86c84d76 | 364 | struct proto_ospf *po = ifa->oa->po; |
b9ed99f7 | 365 | struct proto *p = &po->proto; |
86c84d76 | 366 | struct iface *iface = lock->iface; |
b9ed99f7 | 367 | |
98ac6176 OF |
368 | ifa->lock = lock; |
369 | ||
b9ed99f7 OF |
370 | ifa->ioprob = OSPF_I_OK; |
371 | ||
f9c799a0 OZ |
372 | ifa->sk = ospf_open_socket(ifa, ifa->type != OSPF_IT_NBMA); |
373 | if (ifa->sk == NULL) | |
b9ed99f7 OF |
374 | { |
375 | log("%s: Huh? could not open ip socket on interface %s?", p->name, | |
376 | iface->name); | |
377 | log("%s: Declaring as stub.", p->name); | |
378 | ifa->stub = 1; | |
379 | ifa->ioprob += OSPF_I_IP; | |
380 | } | |
b9ed99f7 OF |
381 | |
382 | ifa->state = OSPF_IS_DOWN; | |
383 | ospf_iface_sm(ifa, ISM_UP); | |
384 | } | |
385 | ||
98ac6176 | 386 | void |
3b16080c OF |
387 | ospf_iface_new(struct proto_ospf *po, struct iface *iface, |
388 | struct ospf_area_config *ac, struct ospf_iface_patt *ip) | |
98ac6176 OF |
389 | { |
390 | struct proto *p = &po->proto; | |
391 | struct ospf_iface *ifa; | |
392 | struct nbma_node *nbma, *nb; | |
393 | struct object_lock *lock; | |
394 | struct ospf_area *oa; | |
395 | ||
396 | ifa = mb_allocz(p->pool, sizeof(struct ospf_iface)); | |
98ac6176 OF |
397 | ifa->iface = iface; |
398 | ||
98ac6176 OF |
399 | ifa->cost = ip->cost; |
400 | ifa->rxmtint = ip->rxmtint; | |
401 | ifa->inftransdelay = ip->inftransdelay; | |
402 | ifa->priority = ip->priority; | |
403 | ifa->helloint = ip->helloint; | |
404 | ifa->pollint = ip->pollint; | |
405 | ifa->strictnbma = ip->strictnbma; | |
406 | ifa->waitint = ip->waitint; | |
d8c7d9e8 | 407 | ifa->dead = (ip->dead == 0) ? ip->deadc * ifa->helloint : ip->dead; |
98ac6176 | 408 | ifa->stub = ip->stub; |
c3226991 OZ |
409 | |
410 | #ifdef OSPFv2 | |
98ac6176 | 411 | ifa->autype = ip->autype; |
3e2bd0f1 | 412 | ifa->passwords = ip->passwords; |
c3226991 OZ |
413 | #endif |
414 | ||
415 | #ifdef OSPFv3 | |
416 | ifa->instance_id = ip->instance_id; | |
b49e6f5a OZ |
417 | |
418 | ifa->lladdr = IPA_NONE; | |
419 | ||
420 | /* Find link-local address */ | |
421 | if (ifa->type != OSPF_IT_VLINK) | |
422 | { | |
423 | struct ifa *a; | |
424 | WALK_LIST(a, iface->addrs) | |
425 | if (a->scope == SCOPE_LINK) | |
426 | { | |
427 | ifa->lladdr = a->ip; | |
428 | break; | |
429 | } | |
430 | ||
431 | if (! ipa_nonzero(ifa->lladdr)) | |
432 | log(L_WARN "%s: Missing link local address on interface %s", p->name, iface->name); | |
433 | } | |
c3226991 OZ |
434 | #endif |
435 | ||
94c42054 | 436 | ifa->rxbuf = ip->rxbuf; |
98ac6176 OF |
437 | |
438 | if (ip->type == OSPF_IT_UNDEF) | |
439 | ifa->type = ospf_iface_clasify(ifa->iface); | |
440 | else | |
441 | ifa->type = ip->type; | |
442 | ||
443 | init_list(&ifa->neigh_list); | |
444 | init_list(&ifa->nbma_list); | |
3b16080c | 445 | |
98ac6176 OF |
446 | WALK_LIST(nb, ip->nbma_list) |
447 | { | |
448 | nbma = mb_alloc(p->pool, sizeof(struct nbma_node)); | |
449 | nbma->ip = nb->ip; | |
450 | nbma->eligible = nb->eligible; | |
451 | add_tail(&ifa->nbma_list, NODE nbma); | |
452 | } | |
453 | ||
454 | /* Add hello timer */ | |
455 | ifa->hello_timer = tm_new(p->pool); | |
456 | ifa->hello_timer->data = ifa; | |
457 | ifa->hello_timer->randomize = 0; | |
458 | ifa->hello_timer->hook = hello_timer_hook; | |
459 | ifa->hello_timer->recurrent = ifa->helloint; | |
460 | DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint); | |
461 | ||
462 | if (ifa->type == OSPF_IT_NBMA) | |
463 | { | |
464 | ifa->poll_timer = tm_new(p->pool); | |
465 | ifa->poll_timer->data = ifa; | |
466 | ifa->poll_timer->randomize = 0; | |
467 | ifa->poll_timer->hook = poll_timer_hook; | |
468 | ifa->poll_timer->recurrent = ifa->pollint; | |
469 | DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint); | |
470 | } | |
471 | else | |
472 | ifa->poll_timer = NULL; | |
473 | ||
474 | ifa->wait_timer = tm_new(p->pool); | |
475 | ifa->wait_timer->data = ifa; | |
476 | ifa->wait_timer->randomize = 0; | |
477 | ifa->wait_timer->hook = wait_timer_hook; | |
478 | ifa->wait_timer->recurrent = 0; | |
479 | DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint); | |
480 | add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa); | |
481 | ifa->state = OSPF_IS_DOWN; | |
482 | ||
3b16080c | 483 | ifa->oa = NULL; |
98ac6176 OF |
484 | WALK_LIST(oa, po->area_list) |
485 | { | |
3b16080c OF |
486 | if (oa->areaid == ac->areaid) |
487 | { | |
488 | ifa->oa = oa; | |
98ac6176 | 489 | break; |
3b16080c | 490 | } |
98ac6176 OF |
491 | } |
492 | ||
3b16080c | 493 | if (!ifa->oa) |
98ac6176 OF |
494 | bug("Cannot add any area to accepted Interface"); |
495 | else | |
98ac6176 OF |
496 | |
497 | if (ifa->type == OSPF_IT_VLINK) | |
498 | { | |
499 | ifa->oa = po->backbone; | |
500 | ifa->voa = oa; | |
501 | ifa->vid = ip->vid; | |
3b16080c | 502 | return; /* Don't lock, don't add sockets */ |
98ac6176 OF |
503 | } |
504 | ||
505 | lock = olock_new(p->pool); | |
506 | lock->addr = AllSPFRouters; | |
507 | lock->type = OBJLOCK_IP; | |
508 | lock->port = OSPF_PROTO; | |
509 | lock->iface = iface; | |
510 | lock->data = ifa; | |
511 | lock->hook = ospf_iface_add; | |
512 | ||
513 | olock_acquire(lock); | |
514 | } | |
515 | ||
94c42054 OF |
516 | void |
517 | ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa) | |
518 | { | |
519 | struct proto *p = &po->proto; | |
520 | struct ospf_packet *op; | |
521 | struct ospf_neighbor *n; | |
522 | OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s.", ifa->iface->name); | |
f9c799a0 OZ |
523 | |
524 | if (ifa->sk) | |
94c42054 | 525 | { |
f9c799a0 OZ |
526 | ifa->sk->rbsize = rxbufsize(ifa); |
527 | ifa->sk->tbsize = ifa->iface->mtu; | |
528 | sk_reallocate(ifa->sk); | |
94c42054 OF |
529 | } |
530 | ||
531 | WALK_LIST(n, ifa->neigh_list) | |
532 | { | |
533 | op = (struct ospf_packet *) n->ldbdes; | |
534 | n->ldbdes = mb_allocz(n->pool, ifa->iface->mtu); | |
535 | ||
536 | if (ntohs(op->length) <= ifa->iface->mtu) /* If the packet in old buffer is bigger, let it filled by zeros */ | |
537 | memcpy(n->ldbdes, op, ifa->iface->mtu); /* If the packet is old is same or smaller, copy it */ | |
538 | ||
539 | rfree(op); | |
540 | } | |
541 | } | |
542 | ||
4364b47e | 543 | void |
b9ed99f7 | 544 | ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface) |
4364b47e | 545 | { |
b9ed99f7 OF |
546 | struct proto_ospf *po = (struct proto_ospf *) p; |
547 | struct ospf_config *c = (struct ospf_config *) (p->cf); | |
3b580a23 | 548 | struct ospf_area_config *ac; |
b9ed99f7 | 549 | struct ospf_iface_patt *ip = NULL; |
f8f1e1f1 | 550 | struct ospf_iface *ifa; |
4364b47e | 551 | |
e6fcf113 | 552 | DBG("%s: If notify called\n", p->name); |
4364b47e OF |
553 | if (iface->flags & IF_IGNORE) |
554 | return; | |
555 | ||
b9ed99f7 | 556 | if (flags & IF_CHANGE_UP) |
4364b47e | 557 | { |
3b580a23 | 558 | WALK_LIST(ac, c->area_list) |
4364b47e | 559 | { |
b9ed99f7 | 560 | if (ip = (struct ospf_iface_patt *) |
20e94fb8 | 561 | iface_patt_find(&ac->patt_list, iface)) |
b9ed99f7 | 562 | break; |
3b580a23 | 563 | } |
4364b47e | 564 | |
b9ed99f7 | 565 | if (ip) |
3b580a23 | 566 | { |
abcbfd04 | 567 | OSPF_TRACE(D_EVENTS, "Using interface %s.", iface->name); |
98ac6176 | 568 | ospf_iface_new(po, iface, ac, ip); |
4364b47e | 569 | } |
4364b47e OF |
570 | } |
571 | ||
b9ed99f7 | 572 | if (flags & IF_CHANGE_DOWN) |
4364b47e | 573 | { |
b9ed99f7 | 574 | if ((ifa = ospf_iface_find((struct proto_ospf *) p, iface)) != NULL) |
4364b47e | 575 | { |
abcbfd04 | 576 | OSPF_TRACE(D_EVENTS, "Killing interface %s.", iface->name); |
b9ed99f7 | 577 | ospf_iface_sm(ifa, ISM_DOWN); |
4364b47e OF |
578 | } |
579 | } | |
580 | ||
b9ed99f7 | 581 | if (flags & IF_CHANGE_MTU) |
4364b47e | 582 | { |
b9ed99f7 | 583 | if ((ifa = ospf_iface_find((struct proto_ospf *) p, iface)) != NULL) |
94c42054 | 584 | ospf_iface_change_mtu(po, ifa); |
4364b47e OF |
585 | } |
586 | } | |
587 | ||
c4f0f014 OF |
588 | void |
589 | ospf_iface_info(struct ospf_iface *ifa) | |
590 | { | |
b9ed99f7 OF |
591 | char *strict = "(strict)"; |
592 | ||
593 | if ((ifa->type != OSPF_IT_NBMA) || (ifa->strictnbma == 0)) | |
594 | strict = ""; | |
3b16080c OF |
595 | if (ifa->type == OSPF_IT_VLINK) |
596 | { | |
3aab39f5 OZ |
597 | cli_msg(-1015, "Virtual link to %R:", ifa->vid); |
598 | cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid, | |
3b16080c OF |
599 | ifa->voa->areaid); |
600 | } | |
601 | else | |
602 | { | |
603 | cli_msg(-1015, "Interface \"%s\":", | |
604 | (ifa->iface ? ifa->iface->name : "(none)")); | |
605 | cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict); | |
3aab39f5 | 606 | cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid); |
3b16080c | 607 | } |
b9ed99f7 OF |
608 | cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state], |
609 | ifa->stub ? "(stub)" : ""); | |
610 | cli_msg(-1015, "\tPriority: %u", ifa->priority); | |
611 | cli_msg(-1015, "\tCost: %u", ifa->cost); | |
612 | cli_msg(-1015, "\tHello timer: %u", ifa->helloint); | |
f9bdcad4 | 613 | |
b9ed99f7 | 614 | if (ifa->type == OSPF_IT_NBMA) |
f8f1e1f1 | 615 | { |
b9ed99f7 | 616 | cli_msg(-1015, "\tPoll timer: %u", ifa->pollint); |
f8f1e1f1 | 617 | } |
b9ed99f7 | 618 | cli_msg(-1015, "\tWait timer: %u", ifa->waitint); |
d8c7d9e8 | 619 | cli_msg(-1015, "\tDead timer: %u", ifa->dead); |
b9ed99f7 OF |
620 | cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint); |
621 | if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA)) | |
f8f1e1f1 | 622 | { |
3aab39f5 | 623 | cli_msg(-1015, "\tDesigned router (ID): %R", ifa->drid); |
b9ed99f7 | 624 | cli_msg(-1015, "\tDesigned router (IP): %I", ifa->drip); |
3aab39f5 | 625 | cli_msg(-1015, "\tBackup designed router (ID): %R", ifa->bdrid); |
b9ed99f7 | 626 | cli_msg(-1015, "\tBackup designed router (IP): %I", ifa->bdrip); |
f8f1e1f1 | 627 | } |
78e2c6cc | 628 | } |
39e517d4 OF |
629 | |
630 | void | |
631 | ospf_iface_shutdown(struct ospf_iface *ifa) | |
632 | { | |
633 | init_list(&ifa->neigh_list); | |
634 | hello_timer_hook(ifa->hello_timer); | |
635 | } |