]> git.ipfire.org Git - thirdparty/bird.git/blame - proto/ospf/hello.c
Documentation update
[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
11void
77539c44 12ospf_hello_receive(struct ospf_hello_packet *ps,
5e3436d2 13 struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr)
4364b47e 14{
5e3436d2 15 u32 *pnrid;
77539c44 16 ip_addr olddr, oldbdr;
099c017f 17 ip_addr mask;
77539c44 18 char *beg = "Bad OSPF hello packet from ", *rec = " received: ";
86c84d76 19 struct proto *p = (struct proto *) ifa->oa->po;
bc4ea680 20 unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers;
4364b47e 21
3b16080c
OF
22 OSPF_TRACE(D_PACKETS, "Received hello from %I via %s%s", faddr,
23 (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
77539c44 24 mask = ps->netmask;
099c017f 25 ipa_ntoh(mask);
31dca435 26
5d3f5552 27 if (((ifa->type != OSPF_IT_VLINK) && (ifa->type != OSPF_IT_PTP)) &&
3b16080c 28 ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen))
4364b47e 29 {
5e3436d2 30 log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask);
4364b47e
OF
31 return;
32 }
77539c44
OF
33
34 if (ntohs(ps->helloint) != ifa->helloint)
4364b47e 35 {
2e10a170
OF
36 log(L_WARN "%s%I%shello interval mismatch (%d).", beg, faddr, rec,
37 ntohs(ps->helloint));
4364b47e
OF
38 return;
39 }
40
d8c7d9e8 41 if (ntohl(ps->deadint) != ifa->dead)
4364b47e 42 {
2e10a170
OF
43 log(L_ERR "%s%I%sdead interval mismatch (%d).", beg, faddr, rec,
44 ntohl(ps->deadint));
4364b47e
OF
45 return;
46 }
47
621ccdfe 48 if (ps->options != ifa->oa->opt.byte)
4364b47e 49 {
a5918961 50 log(L_ERR "%s%I%soptions mismatch (0x%x).", beg, faddr, rec, ps->options);
4364b47e
OF
51 return;
52 }
53
5e3436d2 54 if (!n)
4364b47e 55 {
77539c44 56 if ((ifa->type == OSPF_IT_NBMA))
a190e720
OF
57 {
58 struct nbma_node *nn;
77539c44 59 int found = 0;
a190e720 60
77539c44 61 WALK_LIST(nn, ifa->nbma_list)
a190e720 62 {
a417ad13 63 if (ipa_equal(faddr, nn->ip))
a190e720 64 {
77539c44 65 found = 1;
a190e720
OF
66 break;
67 }
68 }
77539c44 69 if ((found == 0) && (ifa->strictnbma))
a190e720 70 {
77539c44
OF
71 log(L_WARN "Ignoring new neighbor: %I on %s.", faddr,
72 ifa->iface->name);
a190e720
OF
73 return;
74 }
77539c44 75 if (found)
a190e720 76 {
77539c44
OF
77 eligible = nn->eligible;
78 if (((ps->priority == 0) && eligible)
79 || ((ps->priority > 0) && (eligible == 0)))
80 {
81 log(L_ERR "Eligibility mismatch for neighbor: %I on %s",
82 faddr, ifa->iface->name);
a190e720 83 return;
77539c44 84 }
a190e720
OF
85 }
86 }
abcbfd04 87 OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s.", faddr,
77539c44 88 ifa->iface->name);
39e517d4
OF
89
90 n = ospf_neighbor_new(ifa);
91
5e3436d2 92 n->rid = ntohl(((struct ospf_packet *) ps)->routerid);
77539c44
OF
93 n->ip = faddr;
94 n->dr = ps->dr;
099c017f 95 ipa_ntoh(n->dr);
77539c44 96 n->bdr = ps->bdr;
099c017f 97 ipa_ntoh(n->bdr);
77539c44
OF
98 n->priority = ps->priority;
99 n->options = ps->options;
4364b47e
OF
100 }
101 ospf_neigh_sm(n, INM_HELLOREC);
102
77539c44 103 pnrid = (u32 *) ((struct ospf_hello_packet *) (ps + 1));
4364b47e 104
bc4ea680
OF
105 peers = (size - sizeof(struct ospf_hello_packet))/ sizeof(u32);
106
77539c44 107 twoway = 0;
bc4ea680 108 for (i = 0; i < peers; i++)
4364b47e 109 {
77539c44 110 if (ntohl(*(pnrid + i)) == p->cf->global->router_id)
4364b47e 111 {
31dca435 112 DBG("%s: Twoway received from %I\n", p->name, faddr);
4364b47e 113 ospf_neigh_sm(n, INM_2WAYREC);
77539c44 114 twoway = 1;
4364b47e
OF
115 break;
116 }
117 }
118
77539c44
OF
119 if (!twoway)
120 ospf_neigh_sm(n, INM_1WAYREC);
4364b47e 121
b29c620f 122 olddr = n->dr;
59ba3342 123 n->dr = ipa_ntoh(ps->dr);
b29c620f 124 oldbdr = n->bdr;
59ba3342 125 n->bdr = ipa_ntoh(ps->bdr);
b29c620f
OF
126 oldpriority = n->priority;
127 n->priority = ps->priority;
128
4364b47e 129 /* Check priority change */
77539c44 130 if (n->state >= NEIGHBOR_2WAY)
4364b47e 131 {
77539c44 132 if (n->priority != oldpriority)
a5918961 133 ospf_iface_sm(ifa, ISM_NEICH);
4364b47e 134
b29c620f 135 /* Router is declaring itself ad DR and there is no BDR */
a417ad13 136 if (ipa_equal(n->ip, n->dr) && (ipa_to_u32(n->bdr) == 0)
77539c44 137 && (n->state != NEIGHBOR_FULL))
a5918961 138 ospf_iface_sm(ifa, ISM_BACKS);
4364b47e 139
b29c620f 140 /* Neighbor is declaring itself as BDR */
a417ad13 141 if (ipa_equal(n->ip, n->bdr) && (n->state != NEIGHBOR_FULL))
a5918961 142 ospf_iface_sm(ifa, ISM_BACKS);
b29c620f
OF
143
144 /* Neighbor is newly declaring itself as DR or BDR */
a417ad13
OF
145 if ((ipa_equal(n->ip, n->dr) && (!ipa_equal(n->dr, olddr)))
146 || (ipa_equal(n->ip, n->bdr) && (!ipa_equal(n->bdr, oldbdr))))
a5918961 147 ospf_iface_sm(ifa, ISM_NEICH);
b29c620f
OF
148
149 /* Neighbor is no more declaring itself as DR or BDR */
a417ad13
OF
150 if ((ipa_equal(n->ip, olddr) && (!ipa_equal(n->dr, olddr)))
151 || (ipa_equal(n->ip, oldbdr) && (!ipa_equal(n->bdr, oldbdr))))
a5918961 152 ospf_iface_sm(ifa, ISM_NEICH);
4364b47e 153 }
4364b47e 154
3b16080c 155 if (ifa->type == OSPF_IT_NBMA)
a190e720 156 {
77539c44
OF
157 if ((ifa->priority == 0) && (n->priority > 0))
158 ospf_hello_send(NULL, 0, n);
a190e720 159 }
4364b47e
OF
160 ospf_neigh_sm(n, INM_HELLOREC);
161}
162
a190e720 163void
77539c44 164ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
4364b47e
OF
165{
166 struct ospf_iface *ifa;
167 struct ospf_hello_packet *pkt;
168 struct ospf_packet *op;
169 struct proto *p;
98ac6176 170 struct ospf_neighbor *neigh, *n1;
4364b47e
OF
171 u16 length;
172 u32 *pp;
98ac6176
OF
173 int i, send;
174 struct nbma_node *nb;
86c84d76 175
77539c44
OF
176 if (timer == NULL)
177 ifa = dirn->ifa;
178 else
179 ifa = (struct ospf_iface *) timer->data;
a190e720 180
98ac6176
OF
181 if (ifa->state == OSPF_IS_DOWN)
182 return;
183
77539c44
OF
184 if (ifa->stub)
185 return; /* Don't send any packet on stub iface */
e3bc10fd 186
86c84d76 187 p = (struct proto *) (ifa->oa->po);
a190e720 188 DBG("%s: Hello/Poll timer fired on interface %s.\n",
77539c44 189 p->name, ifa->iface->name);
4364b47e
OF
190 /* Now we should send a hello packet */
191 /* First a common packet header */
98ac6176 192 if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
4364b47e 193 {
98ac6176 194 pkt = (struct ospf_hello_packet *) (ifa->ip_sk->tbuf);
e5b5d18c 195 }
77539c44 196 else
e5b5d18c 197 {
98ac6176 198 pkt = (struct ospf_hello_packet *) (ifa->hello_sk->tbuf);
e5b5d18c 199 }
4364b47e 200
e5b5d18c 201 /* Now fill ospf_hello header */
77539c44 202 op = (struct ospf_packet *) pkt;
4364b47e 203
3e2bd0f1 204 ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
e5b5d18c 205
77539c44 206 pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
e5b5d18c 207 ipa_hton(pkt->netmask);
3b16080c 208 if (ifa->type == OSPF_IT_VLINK) pkt->netmask = IPA_NONE;
77539c44 209 pkt->helloint = ntohs(ifa->helloint);
621ccdfe 210 pkt->options = ifa->oa->opt.byte;
77539c44 211 pkt->priority = ifa->priority;
d8c7d9e8 212 pkt->deadint = htonl(ifa->dead);
77539c44 213 pkt->dr = ifa->drip;
099c017f 214 ipa_hton(pkt->dr);
77539c44 215 pkt->bdr = ifa->bdrip;
099c017f 216 ipa_hton(pkt->bdr);
e5b5d18c
OF
217
218 /* Fill all neighbors */
77539c44
OF
219 i = 0;
220 pp = (u32 *) (((u8 *) pkt) + sizeof(struct ospf_hello_packet));
221 WALK_LIST(neigh, ifa->neigh_list)
e5b5d18c 222 {
3e2bd0f1
OF
223 if ((i+1) * sizeof(u32) + sizeof(struct ospf_hello_packet) > ospf_pkt_maxsize(ifa))
224 {
225 OSPF_TRACE(D_PACKETS, "Too many neighbors on the interface!");
226 break;
227 }
77539c44 228 *(pp + i) = htonl(neigh->rid);
e5b5d18c
OF
229 i++;
230 }
231
77539c44
OF
232 length = sizeof(struct ospf_hello_packet) + i * sizeof(u32);
233 op->length = htons(length);
e5b5d18c 234
98ac6176 235 switch(ifa->type)
e5b5d18c 236 {
98ac6176
OF
237 case OSPF_IT_NBMA:
238 if (timer == NULL) /* Response to received hello */
e5b5d18c 239 {
3e2bd0f1 240 ospf_send_to(ifa->ip_sk, dirn->ip, ifa);
e5b5d18c 241 }
98ac6176 242 else
a190e720 243 {
98ac6176
OF
244 int toall = 0;
245 int meeli = 0;
246 if (ifa->state > OSPF_IS_DROTHER)
247 toall = 1;
248 if (ifa->priority > 0)
249 meeli = 1;
250
251 WALK_LIST(nb, ifa->nbma_list)
252 {
253 send = 1;
254 WALK_LIST(n1, ifa->neigh_list)
255 {
a417ad13 256 if (ipa_equal(nb->ip, n1->ip))
98ac6176
OF
257 {
258 send = 0;
259 break;
260 }
261 }
262 if ((poll == 1) && (send))
263 {
264 if (toall || (meeli && nb->eligible))
3e2bd0f1 265 ospf_send_to(ifa->ip_sk, nb->ip, ifa);
98ac6176
OF
266 }
267 }
268 if (poll == 0)
269 {
270 WALK_LIST(n1, ifa->neigh_list)
271 {
272 if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
273 (meeli && (n1->priority > 0)))
3e2bd0f1 274 ospf_send_to(ifa->ip_sk, n1->ip, ifa);
98ac6176
OF
275 }
276 }
a190e720 277 }
98ac6176
OF
278 break;
279 case OSPF_IT_VLINK:
3e2bd0f1 280 ospf_send_to(ifa->ip_sk, ifa->vip, ifa);
98ac6176
OF
281 break;
282 default:
3e2bd0f1 283 ospf_send_to(ifa->hello_sk, IPA_NONE, ifa);
e5b5d18c 284 }
3b16080c
OF
285 OSPF_TRACE(D_PACKETS, "Hello sent via %s%s",
286 (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
4364b47e 287}