Annotation of embedaddon/bird/proto/ospf/hello.c, revision 1.1.1.2
1.1 misho 1: /*
2: * BIRD -- OSPF
3: *
4: * (c) 1999--2004 Ondrej Filip <feela@network.cz>
5: * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
6: * (c) 2009--2014 CZ.NIC z.s.p.o.
7: *
8: * Can be freely distributed and used under the terms of the GNU GPL.
9: */
10:
11: #include "ospf.h"
12:
13:
14: struct ospf_hello2_packet
15: {
16: struct ospf_packet hdr;
17: union ospf_auth auth;
18:
19: u32 netmask;
20: u16 helloint;
21: u8 options;
22: u8 priority;
23: u32 deadint;
24: u32 dr;
25: u32 bdr;
26:
27: u32 neighbors[];
28: };
29:
30: struct ospf_hello3_packet
31: {
32: struct ospf_packet hdr;
33:
34: u32 iface_id;
35: u8 priority;
36: u8 options3;
37: u8 options2;
38: u8 options;
39: u16 helloint;
40: u16 deadint;
41: u32 dr;
42: u32 bdr;
43:
44: u32 neighbors[];
45: };
46:
47:
48: void
49: ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
50: {
51: struct ospf_proto *p = ifa->oa->po;
52: struct ospf_packet *pkt;
53: struct ospf_neighbor *neigh, *n1;
54: struct nbma_node *nb;
55: u32 *neighbors;
56: uint length;
57: int i, max;
58:
59: if (ifa->state <= OSPF_IS_LOOP)
60: return;
61:
62: if (ifa->stub)
63: return;
64:
65:
66: pkt = ospf_tx_buffer(ifa);
67: ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
68:
69: if (ospf_is_v2(p))
70: {
71: struct ospf_hello2_packet *ps = (void *) pkt;
72:
73: if ((ifa->type == OSPF_IT_VLINK) ||
74: ((ifa->type == OSPF_IT_PTP) && !ifa->ptp_netmask))
75: ps->netmask = 0;
76: else
77: ps->netmask = htonl(u32_mkmask(ifa->addr->pxlen));
78:
79: ps->helloint = ntohs(ifa->helloint);
80: ps->options = ifa->oa->options;
81: ps->priority = ifa->priority;
82: ps->deadint = htonl(ifa->deadint);
83: ps->dr = htonl(ipa_to_u32(ifa->drip));
84: ps->bdr = htonl(ipa_to_u32(ifa->bdrip));
85:
86: length = sizeof(struct ospf_hello2_packet);
87: neighbors = ps->neighbors;
88: }
89: else
90: {
91: struct ospf_hello3_packet *ps = (void *) pkt;
92:
93: ps->iface_id = htonl(ifa->iface_id);
94: ps->priority = ifa->priority;
95: ps->options3 = ifa->oa->options >> 16;
96: ps->options2 = ifa->oa->options >> 8;
97: ps->options = ifa->oa->options;
98: ps->helloint = ntohs(ifa->helloint);
99: ps->deadint = htons(ifa->deadint);
100: ps->dr = htonl(ifa->drid);
101: ps->bdr = htonl(ifa->bdrid);
102:
103: length = sizeof(struct ospf_hello3_packet);
104: neighbors = ps->neighbors;
105: }
106:
107: i = 0;
108: max = (ospf_pkt_maxsize(ifa) - length) / sizeof(u32);
109:
110: /* Fill all neighbors */
111: if (kind != OHS_SHUTDOWN)
112: {
113: WALK_LIST(neigh, ifa->neigh_list)
114: {
115: if (i == max)
116: {
117: log(L_WARN "%s: Too many neighbors on %s", p->p.name, ifa->ifname);
118: break;
119: }
120: neighbors[i] = htonl(neigh->rid);
121: i++;
122: }
123: }
124:
125: length += i * sizeof(u32);
126: pkt->length = htons(length);
127:
128: OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s", ifa->ifname);
129:
130: switch(ifa->type)
131: {
132: case OSPF_IT_BCAST:
133: case OSPF_IT_PTP:
134: ospf_send_to_all(ifa);
135: break;
136:
137: case OSPF_IT_NBMA:
138: if (dirn) /* Response to received hello */
139: {
140: ospf_send_to(ifa, dirn->ip);
141: break;
142: }
143:
144: int to_all = ifa->state > OSPF_IS_DROTHER;
145: int me_elig = ifa->priority > 0;
146:
147: if (kind == OHS_POLL) /* Poll timer */
148: {
149: WALK_LIST(nb, ifa->nbma_list)
150: if (!nb->found && (to_all || (me_elig && nb->eligible)))
151: ospf_send_to(ifa, nb->ip);
152: }
153: else /* Hello timer */
154: {
155: WALK_LIST(n1, ifa->neigh_list)
156: if (to_all || (me_elig && (n1->priority > 0)) ||
157: (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid))
158: ospf_send_to(ifa, n1->ip);
159: }
160: break;
161:
162: case OSPF_IT_PTMP:
163: WALK_LIST(n1, ifa->neigh_list)
164: ospf_send_to(ifa, n1->ip);
165:
166: WALK_LIST(nb, ifa->nbma_list)
167: if (!nb->found)
168: ospf_send_to(ifa, nb->ip);
169:
170: /* If there is no other target, we also send HELLO packet to the other end */
171: if (ipa_nonzero(ifa->addr->opposite) && !ifa->strictnbma &&
172: EMPTY_LIST(ifa->neigh_list) && EMPTY_LIST(ifa->nbma_list))
173: ospf_send_to(ifa, ifa->addr->opposite);
174: break;
175:
176: case OSPF_IT_VLINK:
177: ospf_send_to(ifa, ifa->vip);
178: break;
179:
180: default:
181: bug("Bug in ospf_send_hello()");
182: }
183: }
184:
185:
186: void
187: ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
188: struct ospf_neighbor *n, ip_addr faddr)
189: {
190: struct ospf_proto *p = ifa->oa->po;
191: const char *err_dsc = NULL;
192: u32 rcv_iface_id, rcv_helloint, rcv_deadint, rcv_dr, rcv_bdr;
193: u8 rcv_options, rcv_priority;
194: u32 *neighbors;
195: u32 neigh_count;
196: uint plen, i, err_val = 0;
197:
198: /* RFC 2328 10.5 */
199:
200: /*
201: * We may not yet havethe associate neighbor, so we use Router ID from the
202: * packet instead of one from the neighbor structure for log messages.
203: */
204: u32 rcv_rid = ntohl(pkt->routerid);
205: OSPF_TRACE(D_PACKETS, "HELLO packet received from nbr %R on %s", rcv_rid, ifa->ifname);
206:
207: plen = ntohs(pkt->length);
208:
209: if (ospf_is_v2(p))
210: {
211: struct ospf_hello2_packet *ps = (void *) pkt;
212:
213: if (plen < sizeof(struct ospf_hello2_packet))
214: DROP("too short", plen);
215:
216: rcv_iface_id = 0;
217: rcv_helloint = ntohs(ps->helloint);
218: rcv_deadint = ntohl(ps->deadint);
219: rcv_dr = ntohl(ps->dr);
220: rcv_bdr = ntohl(ps->bdr);
221: rcv_options = ps->options;
222: rcv_priority = ps->priority;
223:
224: int pxlen = u32_masklen(ntohl(ps->netmask));
225: if (pxlen < 0)
226: DROP("prefix garbled", ntohl(ps->netmask));
227:
228: if ((ifa->type != OSPF_IT_VLINK) &&
229: (ifa->type != OSPF_IT_PTP) &&
230: ((uint) pxlen != ifa->addr->pxlen))
231: DROP("prefix length mismatch", pxlen);
232:
233: neighbors = ps->neighbors;
234: neigh_count = (plen - sizeof(struct ospf_hello2_packet)) / sizeof(u32);
235: }
236: else /* OSPFv3 */
237: {
238: struct ospf_hello3_packet *ps = (void *) pkt;
239:
240: if (plen < sizeof(struct ospf_hello3_packet))
241: DROP("too short", plen);
242:
243: rcv_iface_id = ntohl(ps->iface_id);
244: rcv_helloint = ntohs(ps->helloint);
245: rcv_deadint = ntohs(ps->deadint);
246: rcv_dr = ntohl(ps->dr);
247: rcv_bdr = ntohl(ps->bdr);
248: rcv_options = ps->options;
249: rcv_priority = ps->priority;
250:
251: neighbors = ps->neighbors;
252: neigh_count = (plen - sizeof(struct ospf_hello3_packet)) / sizeof(u32);
253: }
254:
255: if (rcv_helloint != ifa->helloint)
256: DROP("hello interval mismatch", rcv_helloint);
257:
258: if (rcv_deadint != ifa->deadint)
259: DROP("dead interval mismatch", rcv_deadint);
260:
261: /* Check whether bits E, N match */
262: if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N))
263: DROP("area type mismatch", rcv_options);
264:
265: /* Check consistency of existing neighbor entry */
266: if (n)
267: {
268: uint t = ifa->type;
269: if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
270: {
271: /* Neighbor identified by IP address; Router ID may change */
272: if (n->rid != rcv_rid)
273: {
274: OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed Router ID to %R",
275: n->rid, ifa->ifname, rcv_rid);
276: ospf_neigh_sm(n, INM_KILLNBR);
277: n = NULL;
278: }
279: }
280: else /* OSPFv3 or OSPFv2/PtP */
281: {
282: /* Neighbor identified by Router ID; IP address may change */
283: if (!ipa_equal(faddr, n->ip))
284: {
285: OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed IP address to %I",
1.1.1.2 ! misho 286: n->rid, ifa->ifname, faddr);
1.1 misho 287: n->ip = faddr;
288: }
289: }
290: }
291:
292: if (!n)
293: {
294: if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
295: {
296: struct nbma_node *nn = find_nbma_node(ifa, faddr);
297:
298: if (!nn && ifa->strictnbma)
299: DROP1("new neighbor denied");
300:
301: if (nn && (ifa->type == OSPF_IT_NBMA) &&
302: (((rcv_priority == 0) && nn->eligible) ||
303: ((rcv_priority > 0) && !nn->eligible)))
304: DROP("eligibility mismatch", rcv_priority);
305:
306: if (nn)
307: nn->found = 1;
308: }
309:
310: OSPF_TRACE(D_EVENTS, "New neighbor %R on %s, IP address %I",
311: rcv_rid, ifa->ifname, faddr);
312:
313: n = ospf_neighbor_new(ifa);
314:
315: n->rid = rcv_rid;
316: n->ip = faddr;
317: n->dr = rcv_dr;
318: n->bdr = rcv_bdr;
319: n->priority = rcv_priority;
320: n->iface_id = rcv_iface_id;
321:
322: if (n->ifa->cf->bfd)
323: ospf_neigh_update_bfd(n, n->ifa->bfd);
324: }
325:
326: u32 n_id = ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid;
327:
328: u32 old_dr = n->dr;
329: u32 old_bdr = n->bdr;
330: u32 old_priority = n->priority;
331: u32 old_iface_id = n->iface_id;
332:
333: n->dr = rcv_dr;
334: n->bdr = rcv_bdr;
335: n->priority = rcv_priority;
336: n->iface_id = rcv_iface_id;
337:
338:
339: /* Update inactivity timer */
340: ospf_neigh_sm(n, INM_HELLOREC);
341:
342: /* RFC 2328 9.5.1 - non-eligible routers reply to hello on NBMA nets */
343: if (ifa->type == OSPF_IT_NBMA)
344: if ((ifa->priority == 0) && (n->priority > 0))
345: ospf_send_hello(n->ifa, OHS_HELLO, n);
346:
347:
348: /* Examine list of neighbors */
349: for (i = 0; i < neigh_count; i++)
350: if (neighbors[i] == htonl(p->router_id))
351: goto found_self;
352:
353: ospf_neigh_sm(n, INM_1WAYREC);
354: return;
355:
356: found_self:
357: ospf_neigh_sm(n, INM_2WAYREC);
358:
359:
360: if (n->iface_id != old_iface_id)
361: {
362: /* If neighbor is DR, also update cached DR interface ID */
363: if (ifa->drid == n->rid)
364: ifa->dr_iface_id = n->iface_id;
365:
366: /* RFC 5340 4.4.3 Event 4 - change of neighbor's interface ID */
367: ospf_notify_rt_lsa(ifa->oa);
368:
369: /* Missed in RFC 5340 4.4.3 Event 4 - (Px-)Net-LSA uses iface_id to ref Link-LSAs */
370: ospf_notify_net_lsa(ifa);
371: }
372:
373: if (ifa->state == OSPF_IS_WAITING)
374: {
375: /* Neighbor is declaring itself DR (and there is no BDR) or as BDR */
376: if (((n->dr == n_id) && (n->bdr == 0)) || (n->bdr == n_id))
377: ospf_iface_sm(ifa, ISM_BACKS);
378: }
379: else if (ifa->state >= OSPF_IS_DROTHER)
380: {
381: /* Neighbor changed priority or started/stopped declaring itself as DR/BDR */
382: if ((n->priority != old_priority) ||
383: ((n->dr == n_id) && (old_dr != n_id)) ||
384: ((n->dr != n_id) && (old_dr == n_id)) ||
385: ((n->bdr == n_id) && (old_bdr != n_id)) ||
386: ((n->bdr != n_id) && (old_bdr == n_id)))
387: ospf_iface_sm(ifa, ISM_NEICH);
388: }
389:
390: return;
391:
392: drop:
393: LOG_PKT("Bad HELLO packet from nbr %R on %s - %s (%u)",
394: rcv_rid, ifa->ifname, err_dsc, err_val);
395: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>