]> git.ipfire.org Git - thirdparty/bird.git/blame - proto/ospf/hello.c
Fix configure to enable warnings and fix most of them.
[thirdparty/bird.git] / proto / ospf / hello.c
CommitLineData
4364b47e
OF
1/*
2 * BIRD -- OSPF
3 *
bc4ea680 4 * (c) 1999--2004 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
c3226991
OZ
11
12#ifdef OSPFv2
13struct ospf_hello_packet
14{
15 struct ospf_packet ospf_packet;
16 ip_addr netmask;
17 u16 helloint;
18 u8 options;
19 u8 priority;
20 u32 deadint;
21 u32 dr;
22 u32 bdr;
23};
24#endif
25
26
27#ifdef OSPFv3
28struct ospf_hello_packet
29{
30 struct ospf_packet ospf_packet;
31 u32 iface_id;
32 u8 priority;
33 u8 options3;
34 u8 options2;
35 u8 options;
36 u16 helloint;
37 u16 deadint;
38 u32 dr;
39 u32 bdr;
40};
41#endif
42
43
4364b47e 44void
c3226991
OZ
45ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
46 struct ospf_neighbor *n, ip_addr faddr)
4364b47e 47{
8a70a13e
OZ
48 struct proto_ospf *po = ifa->oa->po;
49 struct proto *p = &po->proto;
a6bc04d5 50 char *beg = "Bad OSPF HELLO packet from ", *rec = " received: ";
e81b440f
OZ
51 unsigned int size, i, twoway, eligible, peers;
52 u32 tmp;
a6bc04d5
OZ
53 u32 *pnrid;
54
55 size = ntohs(ps_i->length);
56 if (size < sizeof(struct ospf_hello_packet))
57 {
58 log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
59 return;
60 }
61
62 struct ospf_hello_packet *ps = (void *) ps_i;
4364b47e 63
8298d780 64 OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr,
3b16080c 65 (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
c3226991
OZ
66
67#ifdef OSPFv2
f9c799a0 68 ip_addr mask = ps->netmask;
099c017f 69 ipa_ntoh(mask);
8cc598a5
OZ
70 if (ifa->type != OSPF_IT_VLINK)
71 {
72 char *msg = L_WARN "Received HELLO packet %s (%I) is inconsistent "
73 "with the primary address of interface %s.";
74
75 if ((ifa->type != OSPF_IT_PTP) &&
76 !ipa_equal(mask, ipa_mkmask(ifa->iface->addr->pxlen)))
77 {
78 if (!n) log(msg, "netmask", mask, ifa->iface->name);
79 return;
80 }
81
82 /* This check is not specified in RFC 2328, but it is needed
83 * to handle the case when there is more IP networks on one
84 * physical network (which is not handled in RFC 2328).
85 * We allow OSPF on primary IP address only and ignore HELLO packets
86 * with secondary addresses (which are sent for example by Quagga.
87 */
88 if ((ifa->iface->addr->flags & IA_UNNUMBERED) ?
89 !ipa_equal(faddr, ifa->iface->addr->opposite) :
90 !ipa_equal(ipa_and(faddr,mask), ifa->iface->addr->prefix))
91 {
92 if (!n) log(msg, "address", faddr, ifa->iface->name);
93 return;
94 }
95 }
c3226991 96#endif
77539c44 97
c3226991
OZ
98 tmp = ntohs(ps->helloint);
99 if (tmp != ifa->helloint)
4364b47e 100 {
c3226991 101 log(L_ERR "%s%I%shello interval mismatch (%d).", beg, faddr, rec, tmp);
4364b47e
OF
102 return;
103 }
104
c3226991
OZ
105#ifdef OSPFv2
106 tmp = ntohl(ps->deadint);
107#else /* OSPFv3 */
108 tmp = ntohs(ps->deadint);
109#endif
110 if (tmp != ifa->dead)
4364b47e 111 {
c3226991 112 log(L_ERR "%s%I%sdead interval mismatch (%d).", beg, faddr, rec, tmp);
4364b47e
OF
113 return;
114 }
115
c3226991
OZ
116 tmp = !(ps->options & OPT_E);
117 if (tmp != ifa->oa->stub)
4364b47e 118 {
c3226991 119 log(L_ERR "%s%I%sstub area flag mismatch (%d).", beg, faddr, rec, tmp);
4364b47e
OF
120 return;
121 }
122
5e3436d2 123 if (!n)
4364b47e 124 {
77539c44 125 if ((ifa->type == OSPF_IT_NBMA))
a190e720
OF
126 {
127 struct nbma_node *nn;
77539c44 128 int found = 0;
a190e720 129
77539c44 130 WALK_LIST(nn, ifa->nbma_list)
a190e720 131 {
a417ad13 132 if (ipa_equal(faddr, nn->ip))
a190e720 133 {
77539c44 134 found = 1;
a190e720
OF
135 break;
136 }
137 }
77539c44 138 if ((found == 0) && (ifa->strictnbma))
a190e720 139 {
77539c44
OF
140 log(L_WARN "Ignoring new neighbor: %I on %s.", faddr,
141 ifa->iface->name);
a190e720
OF
142 return;
143 }
77539c44 144 if (found)
a190e720 145 {
77539c44
OF
146 eligible = nn->eligible;
147 if (((ps->priority == 0) && eligible)
148 || ((ps->priority > 0) && (eligible == 0)))
149 {
150 log(L_ERR "Eligibility mismatch for neighbor: %I on %s",
151 faddr, ifa->iface->name);
a190e720 152 return;
77539c44 153 }
a190e720
OF
154 }
155 }
abcbfd04 156 OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s.", faddr,
77539c44 157 ifa->iface->name);
39e517d4
OF
158
159 n = ospf_neighbor_new(ifa);
160
5e3436d2 161 n->rid = ntohl(((struct ospf_packet *) ps)->routerid);
77539c44 162 n->ip = faddr;
c3226991
OZ
163 n->dr = ntohl(ps->dr);
164 n->bdr = ntohl(ps->bdr);
77539c44 165 n->priority = ps->priority;
c3226991
OZ
166#ifdef OSPFv3
167 n->iface_id = ntohl(ps->iface_id);
168#endif
4364b47e
OF
169 }
170 ospf_neigh_sm(n, INM_HELLOREC);
171
77539c44 172 pnrid = (u32 *) ((struct ospf_hello_packet *) (ps + 1));
4364b47e 173
bc4ea680
OF
174 peers = (size - sizeof(struct ospf_hello_packet))/ sizeof(u32);
175
77539c44 176 twoway = 0;
bc4ea680 177 for (i = 0; i < peers; i++)
4364b47e 178 {
8a70a13e 179 if (ntohl(pnrid[i]) == po->router_id)
4364b47e 180 {
31dca435 181 DBG("%s: Twoway received from %I\n", p->name, faddr);
4364b47e 182 ospf_neigh_sm(n, INM_2WAYREC);
77539c44 183 twoway = 1;
4364b47e
OF
184 break;
185 }
186 }
187
77539c44
OF
188 if (!twoway)
189 ospf_neigh_sm(n, INM_1WAYREC);
4364b47e 190
e81b440f
OZ
191 u32 olddr = n->dr;
192 u32 oldbdr = n->bdr;
193 u32 oldpriority = n->priority;
c3226991 194#ifdef OSPFv3
e81b440f 195 u32 oldiface_id = n->iface_id;
c3226991
OZ
196#endif
197
198 n->dr = ntohl(ps->dr);
199 n->bdr = ntohl(ps->bdr);
b29c620f 200 n->priority = ps->priority;
c3226991
OZ
201#ifdef OSPFv3
202 n->iface_id = ntohl(ps->iface_id);
203#endif
204
b29c620f 205
4364b47e 206 /* Check priority change */
77539c44 207 if (n->state >= NEIGHBOR_2WAY)
4364b47e 208 {
c3226991 209#ifdef OSPFv2
8a70a13e 210 u32 neigh = ipa_to_u32(n->ip);
c3226991 211#else /* OSPFv3 */
8a70a13e 212 u32 neigh = n->rid;
c3226991
OZ
213#endif
214
77539c44 215 if (n->priority != oldpriority)
a5918961 216 ospf_iface_sm(ifa, ISM_NEICH);
4364b47e 217
c3226991
OZ
218#ifdef OSPFv3
219 if (n->iface_id != oldiface_id)
220 ospf_iface_sm(ifa, ISM_NEICH);
221#endif
222
8a70a13e
OZ
223 /* Neighbor is declaring itself ad DR and there is no BDR */
224 if ((n->dr == neigh) && (n->bdr == 0)
77539c44 225 && (n->state != NEIGHBOR_FULL))
a5918961 226 ospf_iface_sm(ifa, ISM_BACKS);
4364b47e 227
b29c620f 228 /* Neighbor is declaring itself as BDR */
8a70a13e 229 if ((n->bdr == neigh) && (n->state != NEIGHBOR_FULL))
a5918961 230 ospf_iface_sm(ifa, ISM_BACKS);
b29c620f
OF
231
232 /* Neighbor is newly declaring itself as DR or BDR */
8a70a13e
OZ
233 if (((n->dr == neigh) && (n->dr != olddr))
234 || ((n->bdr == neigh) && (n->bdr != oldbdr)))
a5918961 235 ospf_iface_sm(ifa, ISM_NEICH);
b29c620f
OF
236
237 /* Neighbor is no more declaring itself as DR or BDR */
8a70a13e
OZ
238 if (((olddr == neigh) && (n->dr != olddr))
239 || ((oldbdr == neigh) && (n->bdr != oldbdr)))
a5918961 240 ospf_iface_sm(ifa, ISM_NEICH);
4364b47e 241 }
4364b47e 242
3b16080c 243 if (ifa->type == OSPF_IT_NBMA)
a190e720 244 {
77539c44
OF
245 if ((ifa->priority == 0) && (n->priority > 0))
246 ospf_hello_send(NULL, 0, n);
a190e720 247 }
4364b47e
OF
248 ospf_neigh_sm(n, INM_HELLOREC);
249}
250
a190e720 251void
c3226991 252ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
4364b47e
OF
253{
254 struct ospf_iface *ifa;
255 struct ospf_hello_packet *pkt;
256 struct ospf_packet *op;
257 struct proto *p;
98ac6176 258 struct ospf_neighbor *neigh, *n1;
4364b47e
OF
259 u16 length;
260 u32 *pp;
98ac6176
OF
261 int i, send;
262 struct nbma_node *nb;
86c84d76 263
77539c44
OF
264 if (timer == NULL)
265 ifa = dirn->ifa;
266 else
267 ifa = (struct ospf_iface *) timer->data;
a190e720 268
98ac6176
OF
269 if (ifa->state == OSPF_IS_DOWN)
270 return;
271
77539c44
OF
272 if (ifa->stub)
273 return; /* Don't send any packet on stub iface */
e3bc10fd 274
86c84d76 275 p = (struct proto *) (ifa->oa->po);
a190e720 276 DBG("%s: Hello/Poll timer fired on interface %s.\n",
77539c44 277 p->name, ifa->iface->name);
4364b47e 278
f9c799a0
OZ
279 /* Now we should send a hello packet */
280 pkt = (struct ospf_hello_packet *) (ifa->sk->tbuf);
77539c44 281 op = (struct ospf_packet *) pkt;
4364b47e 282
f9c799a0 283 /* Now fill ospf_hello header */
3e2bd0f1 284 ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
e5b5d18c 285
c3226991 286#ifdef OSPFv2
77539c44 287 pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
e5b5d18c 288 ipa_hton(pkt->netmask);
f571473e
OZ
289 if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
290 pkt->netmask = IPA_NONE;
c3226991
OZ
291#endif
292
77539c44 293 pkt->helloint = ntohs(ifa->helloint);
77539c44 294 pkt->priority = ifa->priority;
c3226991
OZ
295
296#ifdef OSPFv3
297 pkt->iface_id = htonl(ifa->iface->index);
298
299 pkt->options3 = ifa->oa->options >> 16;
300 pkt->options2 = ifa->oa->options >> 8;
301#endif
302 pkt->options = ifa->oa->options;
303
304#ifdef OSPFv2
d8c7d9e8 305 pkt->deadint = htonl(ifa->dead);
c3226991
OZ
306 pkt->dr = htonl(ipa_to_u32(ifa->drip));
307 pkt->bdr = htonl(ipa_to_u32(ifa->bdrip));
308#else /* OSPFv3 */
309 pkt->deadint = htons(ifa->dead);
310 pkt->dr = htonl(ifa->drid);
311 pkt->bdr = htonl(ifa->bdrid);
312#endif
e5b5d18c
OF
313
314 /* Fill all neighbors */
77539c44
OF
315 i = 0;
316 pp = (u32 *) (((u8 *) pkt) + sizeof(struct ospf_hello_packet));
317 WALK_LIST(neigh, ifa->neigh_list)
e5b5d18c 318 {
3e2bd0f1
OF
319 if ((i+1) * sizeof(u32) + sizeof(struct ospf_hello_packet) > ospf_pkt_maxsize(ifa))
320 {
321 OSPF_TRACE(D_PACKETS, "Too many neighbors on the interface!");
322 break;
323 }
77539c44 324 *(pp + i) = htonl(neigh->rid);
e5b5d18c
OF
325 i++;
326 }
327
77539c44
OF
328 length = sizeof(struct ospf_hello_packet) + i * sizeof(u32);
329 op->length = htons(length);
e5b5d18c 330
98ac6176 331 switch(ifa->type)
e5b5d18c 332 {
98ac6176
OF
333 case OSPF_IT_NBMA:
334 if (timer == NULL) /* Response to received hello */
e5b5d18c 335 {
f9c799a0 336 ospf_send_to(ifa, dirn->ip);
e5b5d18c 337 }
98ac6176 338 else
a190e720 339 {
98ac6176
OF
340 int toall = 0;
341 int meeli = 0;
342 if (ifa->state > OSPF_IS_DROTHER)
343 toall = 1;
344 if (ifa->priority > 0)
345 meeli = 1;
346
347 WALK_LIST(nb, ifa->nbma_list)
348 {
349 send = 1;
350 WALK_LIST(n1, ifa->neigh_list)
351 {
a417ad13 352 if (ipa_equal(nb->ip, n1->ip))
98ac6176
OF
353 {
354 send = 0;
355 break;
356 }
357 }
358 if ((poll == 1) && (send))
359 {
360 if (toall || (meeli && nb->eligible))
f9c799a0 361 ospf_send_to(ifa, nb->ip);
98ac6176
OF
362 }
363 }
364 if (poll == 0)
365 {
366 WALK_LIST(n1, ifa->neigh_list)
367 {
368 if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
369 (meeli && (n1->priority > 0)))
f9c799a0 370 ospf_send_to(ifa, n1->ip);
98ac6176
OF
371 }
372 }
a190e720 373 }
98ac6176
OF
374 break;
375 case OSPF_IT_VLINK:
f9c799a0 376 ospf_send_to(ifa, ifa->vip);
98ac6176
OF
377 break;
378 default:
f9c799a0 379 ospf_send_to(ifa, AllSPFRouters);
e5b5d18c 380 }
8298d780
OZ
381
382 OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s%s",
383 (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
4364b47e 384}