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_dbdes2_packet
15: {
16: struct ospf_packet hdr;
17: union ospf_auth2 auth;
18:
19: u16 iface_mtu;
20: u8 options;
21: u8 imms; /* I, M, MS bits */
22: u32 ddseq;
23:
24: struct ospf_lsa_header lsas[];
25: };
26:
27: struct ospf_dbdes3_packet
28: {
29: struct ospf_packet hdr;
30:
31: u32 options;
32: u16 iface_mtu;
33: u8 padding;
34: u8 imms; /* I, M, MS bits */
35: u32 ddseq;
36:
37: struct ospf_lsa_header lsas[];
38: };
39:
40:
41: uint
42: ospf_dbdes3_options(struct ospf_packet *pkt)
43: {
44: struct ospf_dbdes3_packet *ps = (void *) pkt;
45: return ntohl(ps->options);
46: }
47:
48: static inline uint
49: ospf_dbdes_hdrlen(struct ospf_proto *p)
50: {
51: return ospf_is_v2(p) ?
52: sizeof(struct ospf_dbdes2_packet) : sizeof(struct ospf_dbdes3_packet);
53: }
54:
55: static void
56: ospf_dbdes_body(struct ospf_proto *p, struct ospf_packet *pkt,
57: struct ospf_lsa_header **body, uint *count)
58: {
59: uint plen = ntohs(pkt->length);
60: uint hlen = ospf_dbdes_hdrlen(p);
61:
62: *body = ((void *) pkt) + hlen;
63: *count = (plen - hlen) / sizeof(struct ospf_lsa_header);
64: }
65:
66: static void
67: ospf_dump_dbdes(struct ospf_proto *p, struct ospf_packet *pkt)
68: {
69: struct ospf_lsa_header *lsas;
70: uint i, lsa_count;
71: u32 pkt_ddseq;
72: u16 pkt_iface_mtu;
73: u8 pkt_imms;
74:
75: ASSERT(pkt->type == DBDES_P);
76: ospf_dump_common(p, pkt);
77:
78: if (ospf_is_v2(p))
79: {
80: struct ospf_dbdes2_packet *ps = (void *) pkt;
81: pkt_iface_mtu = ntohs(ps->iface_mtu);
82: pkt_imms = ps->imms;
83: pkt_ddseq = ntohl(ps->ddseq);
84: }
85: else /* OSPFv3 */
86: {
87: struct ospf_dbdes3_packet *ps = (void *) pkt;
88: pkt_iface_mtu = ntohs(ps->iface_mtu);
89: pkt_imms = ps->imms;
90: pkt_ddseq = ntohl(ps->ddseq);
91: }
92:
93: log(L_TRACE "%s: mtu %u", p->p.name, pkt_iface_mtu);
94: log(L_TRACE "%s: imms %s%s%s", p->p.name,
95: (pkt_imms & DBDES_I) ? "I " : "",
96: (pkt_imms & DBDES_M) ? "M " : "",
97: (pkt_imms & DBDES_MS) ? "MS" : "");
98: log(L_TRACE "%s: ddseq %u", p->p.name, pkt_ddseq);
99:
100: ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
101: for (i = 0; i < lsa_count; i++)
102: ospf_dump_lsahdr(p, lsas + i);
103: }
104:
105:
106: static void
107: ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
108: {
109: struct ospf_iface *ifa = n->ifa;
110: struct ospf_packet *pkt;
111: uint length;
112:
113: u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu;
114:
115: /* Update DBDES buffer */
116: if (n->ldd_bsize != ifa->tx_length)
117: {
118: mb_free(n->ldd_buffer);
119: n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length);
120: n->ldd_bsize = ifa->tx_length;
121: }
122:
123: pkt = n->ldd_buffer;
124: ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
125:
126: if (ospf_is_v2(p))
127: {
128: struct ospf_dbdes2_packet *ps = (void *) pkt;
129: ps->iface_mtu = htons(iface_mtu);
130: ps->options = ifa->oa->options & DBDES2_OPT_MASK;
131: ps->imms = 0; /* Will be set later */
132: ps->ddseq = htonl(n->dds);
133: length = sizeof(struct ospf_dbdes2_packet);
134: }
135: else /* OSPFv3 */
136: {
137: struct ospf_dbdes3_packet *ps = (void *) pkt;
138: u32 options = ifa->oa->options | (ifa->autype == OSPF_AUTH_CRYPT ? OPT_AT : 0);
139: ps->options = htonl(options & DBDES3_OPT_MASK);
140: ps->iface_mtu = htons(iface_mtu);
141: ps->padding = 0;
142: ps->imms = 0; /* Will be set later */
143: ps->ddseq = htonl(n->dds);
144: length = sizeof(struct ospf_dbdes3_packet);
145: }
146:
147: /* Prepare DBDES body */
148: if (!(n->myimms & DBDES_I) && (n->myimms & DBDES_M))
149: {
150: struct ospf_lsa_header *lsas;
151: struct top_hash_entry *en;
152: uint i = 0, lsa_max;
153:
154: ospf_dbdes_body(p, pkt, &lsas, &lsa_max);
155: en = (void *) s_get(&(n->dbsi));
156:
157: while (i < lsa_max)
158: {
159: if (!SNODE_VALID(en))
160: {
161: n->myimms &= ~DBDES_M; /* Unset More bit */
162: break;
163: }
164:
165: if ((en->lsa.age < LSA_MAXAGE) &&
166: lsa_flooding_allowed(en->lsa_type, en->domain, ifa) &&
167: lsa_is_acceptable(en->lsa_type, n, p))
168: {
169: lsa_hton_hdr(&(en->lsa), lsas + i);
170: i++;
171: }
172:
173: en = SNODE_NEXT(en);
174: }
175:
176: s_put(&(n->dbsi), SNODE en);
177:
178: length += i * sizeof(struct ospf_lsa_header);
179: }
180:
181: if (ospf_is_v2(p))
182: ((struct ospf_dbdes2_packet *) pkt)->imms = n->myimms;
183: else
184: ((struct ospf_dbdes3_packet *) pkt)->imms = n->myimms;
185:
186: pkt->length = htons(length);
187: }
188:
189: static void
190: ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
191: {
192: struct ospf_iface *ifa = n->ifa;
193:
194: OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer,
195: "DBDES packet sent to nbr %R on %s", n->rid, ifa->ifname);
196: sk_set_tbuf(ifa->sk, n->ldd_buffer);
197: ospf_send_to(ifa, n->ip);
198: sk_set_tbuf(ifa->sk, NULL);
199: }
200:
201: /**
202: * ospf_send_dbdes - transmit database description packet
203: * @p: OSPF protocol instance
204: * @n: neighbor
205: *
206: * Sending of a database description packet is described in 10.8 of RFC 2328.
207: * Reception of each packet is acknowledged in the sequence number of another.
208: * When I send a packet to a neighbor I keep a copy in a buffer. If the neighbor
209: * does not reply, I don't create a new packet but just send the content
210: * of the buffer.
211: */
212: void
213: ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
214: {
215: /* RFC 2328 10.8 */
216:
217: ASSERT((n->state == NEIGHBOR_EXSTART) || (n->state == NEIGHBOR_EXCHANGE));
218:
219: if (!n->ifa->oa->rt && !p->gr_recovery)
220: return;
221:
222: ospf_prepare_dbdes(p, n);
223: ospf_do_send_dbdes(p, n);
224: }
225:
226: void
227: ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
228: {
229: ASSERT(n->state > NEIGHBOR_EXSTART);
230:
231: if (!n->ldd_buffer)
232: {
233: log(L_WARN "%s: No DBDES packet for retransmit", p->p.name);
234: ospf_neigh_sm(n, INM_SEQMIS);
235: return;
236: }
237:
238: /* Send last packet */
239: ospf_do_send_dbdes(p, n);
240: }
241:
242: void
243: ospf_reset_ldd(struct ospf_proto *p UNUSED, struct ospf_neighbor *n)
244: {
245: mb_free(n->ldd_buffer);
246: n->ldd_buffer = NULL;
247: n->ldd_bsize = 0;
248: }
249:
250: static int
251: ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n)
252: {
253: struct ospf_iface *ifa = n->ifa;
254: struct ospf_lsa_header *lsas, lsa;
255: struct top_hash_entry *en, *req;
256: const char *err_dsc = NULL;
257: u32 lsa_type, lsa_domain;
258: uint i, lsa_count;
259:
260: ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
261:
262: for (i = 0; i < lsa_count; i++)
263: {
264: lsa_ntoh_hdr(lsas + i, &lsa);
265: lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain);
266:
267: /* RFC 2328 10.6 and RFC 5340 4.2.2 */
268:
269: if (!lsa_type)
270: DROP1("LSA of unknown type");
271:
272: if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
273: DROP1("LSA with AS scope in stub area");
274:
275: /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
276: if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
277: DROP1("rt-summary-LSA in stub area");
278:
279: /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */
280: if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
281: DROP1("LSA with invalid scope");
282:
283: /* RFC 3623 2.2 (2) special case - check for my router-LSA (GR recovery) */
284: if ((lsa_type == LSA_T_RT) && (lsa.rt == p->router_id))
285: n->got_my_rt_lsa = 1;
286:
287: en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
288: if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
289: {
290: /* This should be splitted to ospf_lsa_lsrq_up() */
291: req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
292:
293: if (!SNODE_VALID(req))
294: s_add_tail(&n->lsrql, SNODE req);
295:
296: if (!SNODE_VALID(n->lsrqi))
297: n->lsrqi = req;
298:
299: req->lsa = lsa;
300: req->lsa_body = LSA_BODY_DUMMY;
301:
302: if (!tm_active(n->lsrq_timer))
303: tm_start(n->lsrq_timer, 0);
304: }
305: }
306:
307: return 0;
308:
309: drop:
310: LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in DBDES", lsa_type, lsa.id, lsa.rt);
311: LOG_LSA2(" received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc);
312:
313: ospf_neigh_sm(n, INM_SEQMIS);
314: return -1;
315: }
316:
317: void
318: ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
319: struct ospf_neighbor *n)
320: {
321: struct ospf_proto *p = ifa->oa->po;
322: const char *err_dsc = NULL;
323: u32 rcv_ddseq, rcv_options;
324: u16 rcv_iface_mtu;
325: u8 rcv_imms;
326: uint plen, err_val = 0;
327:
328: /* RFC 2328 10.6 */
329:
330: plen = ntohs(pkt->length);
331: if (plen < ospf_dbdes_hdrlen(p))
332: {
333: LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
334: return;
335: }
336:
337: OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname);
338:
339: ospf_neigh_sm(n, INM_HELLOREC);
340:
341: if (ospf_is_v2(p))
342: {
343: struct ospf_dbdes2_packet *ps = (void *) pkt;
344: rcv_iface_mtu = ntohs(ps->iface_mtu);
345: rcv_options = ps->options;
346: rcv_imms = ps->imms;
347: rcv_ddseq = ntohl(ps->ddseq);
348: }
349: else /* OSPFv3 */
350: {
351: struct ospf_dbdes3_packet *ps = (void *) pkt;
352: rcv_options = ntohl(ps->options);
353: rcv_iface_mtu = ntohs(ps->iface_mtu);
354: rcv_imms = ps->imms;
355: rcv_ddseq = ntohl(ps->ddseq);
356: }
357:
358: /* Reject packets with non-matching MTU */
359: if ((ifa->type != OSPF_IT_VLINK) &&
360: (rcv_iface_mtu != ifa->iface->mtu) &&
361: (rcv_iface_mtu != 0) && (ifa->iface->mtu != 0))
362: {
363: LOG_PKT("MTU mismatch with nbr %R on %s (remote %d, local %d)",
364: n->rid, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu);
365: return;
366: }
367:
368: switch (n->state)
369: {
370: case NEIGHBOR_DOWN:
371: case NEIGHBOR_ATTEMPT:
372: case NEIGHBOR_2WAY:
373: OSPF_TRACE(D_PACKETS, "DBDES packet ignored - lesser state than ExStart");
374: return;
375:
376: case NEIGHBOR_INIT:
377: ospf_neigh_sm(n, INM_2WAYREC);
378: if (n->state != NEIGHBOR_EXSTART)
379: return;
380: /* fallthrough */
381:
382: case NEIGHBOR_EXSTART:
383: if (((rcv_imms & DBDES_IMMS) == DBDES_IMMS) &&
384: (n->rid > p->router_id) &&
385: (plen == ospf_dbdes_hdrlen(p)))
386: {
387: /* I'm slave! */
388: n->dds = rcv_ddseq;
389: n->ddr = rcv_ddseq;
390: n->options = rcv_options;
391: n->myimms &= ~DBDES_MS;
392: n->imms = rcv_imms;
393: tm_stop(n->dbdes_timer);
394: ospf_neigh_sm(n, INM_NEGDONE);
395: ospf_send_dbdes(p, n);
396: break;
397: }
398:
399: if (!(rcv_imms & DBDES_I) &&
400: !(rcv_imms & DBDES_MS) &&
401: (n->rid < p->router_id) &&
402: (n->dds == rcv_ddseq))
403: {
404: /* I'm master! */
405: n->options = rcv_options;
406: n->ddr = rcv_ddseq - 1; /* It will be set corectly a few lines down */
407: n->imms = rcv_imms;
408: ospf_neigh_sm(n, INM_NEGDONE);
409: /* Continue to the NEIGHBOR_EXCHANGE case */
410: }
411: else
412: {
413: DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms);
414: break;
415: }
416:
417: case NEIGHBOR_EXCHANGE:
418: if ((rcv_imms == n->imms) &&
419: (rcv_options == n->options) &&
420: (rcv_ddseq == n->ddr))
421: goto duplicate;
422:
423: if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
424: DROP("MS-bit mismatch", rcv_imms);
425:
426: if (rcv_imms & DBDES_I)
427: DROP("I-bit mismatch", rcv_imms);
428:
429: if (rcv_options != n->options)
430: DROP("options mismatch", rcv_options);
431:
432: n->ddr = rcv_ddseq;
433: n->imms = rcv_imms;
434:
435: if (n->myimms & DBDES_MS)
436: {
437: /* MASTER */
438:
439: if (rcv_ddseq != n->dds)
440: DROP("DD sequence number mismatch", rcv_ddseq);
441:
442: n->dds++;
443:
444: if (ospf_process_dbdes(p, pkt, n) < 0)
445: return;
446:
447: if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
448: {
449: tm_stop(n->dbdes_timer);
450: ospf_reset_ldd(p, n);
451: ospf_neigh_sm(n, INM_EXDONE);
452: break;
453: }
454:
455: ospf_send_dbdes(p, n);
456: tm_start(n->dbdes_timer, n->ifa->rxmtint S);
457: }
458: else
459: {
460: /* SLAVE */
461:
462: if (rcv_ddseq != (n->dds + 1))
463: DROP("DD sequence number mismatch", rcv_ddseq);
464:
465: n->ddr = rcv_ddseq;
466: n->dds = rcv_ddseq;
467:
468: if (ospf_process_dbdes(p, pkt, n) < 0)
469: return;
470:
471: ospf_send_dbdes(p, n);
472:
473: if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
474: {
475: /* Use dbdes timer to postpone freeing of Last DBDES packet buffer */
476: tm_start(n->dbdes_timer, n->ifa->deadint S);
477: ospf_neigh_sm(n, INM_EXDONE);
478: }
479: }
480: break;
481:
482: case NEIGHBOR_LOADING:
483: case NEIGHBOR_FULL:
484: if ((rcv_imms == n->imms) &&
485: (rcv_options == n->options) &&
486: (rcv_ddseq == n->ddr))
487: goto duplicate;
488:
489: DROP("too late for DD exchange", n->state);
490:
491: default:
492: bug("Undefined interface state");
493: }
494: return;
495:
496: duplicate:
497: OSPF_TRACE(D_PACKETS, "DBDES packet is duplicate");
498:
499: /* Slave should retransmit DBDES packet */
500: if (!(n->myimms & DBDES_MS))
501: ospf_rxmt_dbdes(p, n);
502: return;
503:
504: drop:
505: LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)",
506: n->rid, ifa->ifname, err_dsc, err_val);
507:
508: ospf_neigh_sm(n, INM_SEQMIS);
509: return;
510: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>