]>
Commit | Line | Data |
---|---|---|
4364b47e OF |
1 | /* |
2 | * BIRD -- OSPF | |
3 | * | |
f158bb71 | 4 | * (c) 1999--2004 Ondrej Filip <feela@network.cz> |
70945cb6 OZ |
5 | * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org> |
6 | * (c) 2009--2014 CZ.NIC z.s.p.o. | |
4364b47e OF |
7 | * |
8 | * Can be freely distributed and used under the terms of the GNU GPL. | |
9 | */ | |
10 | ||
11 | #include "ospf.h" | |
12 | ||
c3226991 | 13 | |
70945cb6 | 14 | struct ospf_dbdes2_packet |
c3226991 | 15 | { |
70945cb6 | 16 | struct ospf_packet hdr; |
4727d1db | 17 | union ospf_auth2 auth; |
70945cb6 | 18 | |
c3226991 OZ |
19 | u16 iface_mtu; |
20 | u8 options; | |
70945cb6 | 21 | u8 imms; /* I, M, MS bits */ |
c3226991 | 22 | u32 ddseq; |
c3226991 | 23 | |
70945cb6 OZ |
24 | struct ospf_lsa_header lsas[]; |
25 | }; | |
c3226991 | 26 | |
70945cb6 | 27 | struct ospf_dbdes3_packet |
c3226991 | 28 | { |
70945cb6 OZ |
29 | struct ospf_packet hdr; |
30 | ||
c3226991 OZ |
31 | u32 options; |
32 | u16 iface_mtu; | |
33 | u8 padding; | |
70945cb6 | 34 | u8 imms; /* I, M, MS bits */ |
c3226991 | 35 | u32 ddseq; |
70945cb6 OZ |
36 | |
37 | struct ospf_lsa_header lsas[]; | |
c3226991 OZ |
38 | }; |
39 | ||
c3226991 | 40 | |
4727d1db OZ |
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 | ||
70945cb6 OZ |
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 | ||
70945cb6 OZ |
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 | } | |
742029eb | 65 | |
70945cb6 OZ |
66 | static void |
67 | ospf_dump_dbdes(struct ospf_proto *p, struct ospf_packet *pkt) | |
8298d780 | 68 | { |
70945cb6 OZ |
69 | struct ospf_lsa_header *lsas; |
70 | uint i, lsa_count; | |
71 | u32 pkt_ddseq; | |
72 | u16 pkt_iface_mtu; | |
73 | u8 pkt_imms; | |
8298d780 | 74 | |
70945cb6 OZ |
75 | ASSERT(pkt->type == DBDES_P); |
76 | ospf_dump_common(p, pkt); | |
8298d780 | 77 | |
70945cb6 OZ |
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 | } | |
8298d780 | 92 | |
70945cb6 OZ |
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); | |
8298d780 | 99 | |
70945cb6 OZ |
100 | ospf_dbdes_body(p, pkt, &lsas, &lsa_count); |
101 | for (i = 0; i < lsa_count; i++) | |
102 | ospf_dump_lsahdr(p, lsas + i); | |
8298d780 OZ |
103 | } |
104 | ||
105 | ||
70945cb6 | 106 | static void |
f8fefde3 | 107 | ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) |
70945cb6 OZ |
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 | ||
f8fefde3 | 115 | /* Update DBDES buffer */ |
70945cb6 OZ |
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); | |
5a50a989 | 130 | ps->options = ifa->oa->options | OPT_O; |
70945cb6 OZ |
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; | |
4727d1db | 138 | ps->options = htonl(ifa->oa->options | (ifa->autype == OSPF_AUTH_CRYPT ? OPT_AT : 0)); |
70945cb6 OZ |
139 | ps->iface_mtu = htons(iface_mtu); |
140 | ps->padding = 0; | |
141 | ps->imms = 0; /* Will be set later */ | |
142 | ps->ddseq = htonl(n->dds); | |
143 | length = sizeof(struct ospf_dbdes3_packet); | |
144 | } | |
145 | ||
f8fefde3 OZ |
146 | /* Prepare DBDES body */ |
147 | if (!(n->myimms & DBDES_I) && (n->myimms & DBDES_M)) | |
70945cb6 OZ |
148 | { |
149 | struct ospf_lsa_header *lsas; | |
150 | struct top_hash_entry *en; | |
151 | uint i = 0, lsa_max; | |
152 | ||
153 | ospf_dbdes_body(p, pkt, &lsas, &lsa_max); | |
154 | en = (void *) s_get(&(n->dbsi)); | |
155 | ||
156 | while (i < lsa_max) | |
157 | { | |
158 | if (!SNODE_VALID(en)) | |
159 | { | |
160 | n->myimms &= ~DBDES_M; /* Unset More bit */ | |
161 | break; | |
162 | } | |
163 | ||
164 | if ((en->lsa.age < LSA_MAXAGE) && | |
5a50a989 OZ |
165 | lsa_flooding_allowed(en->lsa_type, en->domain, ifa) && |
166 | lsa_is_acceptable(en->lsa_type, n, p)) | |
70945cb6 OZ |
167 | { |
168 | lsa_hton_hdr(&(en->lsa), lsas + i); | |
169 | i++; | |
170 | } | |
171 | ||
172 | en = SNODE_NEXT(en); | |
173 | } | |
174 | ||
175 | s_put(&(n->dbsi), SNODE en); | |
176 | ||
177 | length += i * sizeof(struct ospf_lsa_header); | |
178 | } | |
179 | ||
180 | if (ospf_is_v2(p)) | |
181 | ((struct ospf_dbdes2_packet *) pkt)->imms = n->myimms; | |
182 | else | |
183 | ((struct ospf_dbdes3_packet *) pkt)->imms = n->myimms; | |
184 | ||
185 | pkt->length = htons(length); | |
186 | } | |
187 | ||
188 | static void | |
189 | ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) | |
190 | { | |
191 | struct ospf_iface *ifa = n->ifa; | |
192 | ||
193 | OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer, | |
f8fefde3 | 194 | "DBDES packet sent to nbr %R on %s", n->rid, ifa->ifname); |
70945cb6 OZ |
195 | sk_set_tbuf(ifa->sk, n->ldd_buffer); |
196 | ospf_send_to(ifa, n->ip); | |
197 | sk_set_tbuf(ifa->sk, NULL); | |
198 | } | |
199 | ||
eee9cefd | 200 | /** |
70945cb6 | 201 | * ospf_send_dbdes - transmit database description packet |
8e433d6a | 202 | * @p: OSPF protocol instance |
eee9cefd OF |
203 | * @n: neighbor |
204 | * | |
c3226991 | 205 | * Sending of a database description packet is described in 10.8 of RFC 2328. |
baa5dd6c OF |
206 | * Reception of each packet is acknowledged in the sequence number of another. |
207 | * When I send a packet to a neighbor I keep a copy in a buffer. If the neighbor | |
208 | * does not reply, I don't create a new packet but just send the content | |
209 | * of the buffer. | |
eee9cefd | 210 | */ |
4364b47e | 211 | void |
f8fefde3 | 212 | ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) |
4364b47e | 213 | { |
70945cb6 | 214 | /* RFC 2328 10.8 */ |
4364b47e | 215 | |
f8fefde3 OZ |
216 | ASSERT((n->state == NEIGHBOR_EXSTART) || (n->state == NEIGHBOR_EXCHANGE)); |
217 | ||
a7a7372a | 218 | if (n->ifa->oa->rt == NULL) |
70945cb6 | 219 | return; |
054a3524 | 220 | |
f8fefde3 OZ |
221 | ospf_prepare_dbdes(p, n); |
222 | ospf_do_send_dbdes(p, n); | |
f8fefde3 | 223 | } |
12bed559 | 224 | |
f8fefde3 OZ |
225 | void |
226 | ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) | |
227 | { | |
228 | ASSERT(n->state > NEIGHBOR_EXSTART); | |
e7ef86a5 | 229 | |
f8fefde3 OZ |
230 | if (!n->ldd_buffer) |
231 | { | |
232 | log(L_WARN "%s: No DBDES packet for retransmit", p->p.name); | |
233 | ospf_neigh_sm(n, INM_SEQMIS); | |
234 | return; | |
70945cb6 | 235 | } |
04c6319a | 236 | |
f8fefde3 OZ |
237 | /* Send last packet */ |
238 | ospf_do_send_dbdes(p, n); | |
239 | } | |
48e5f32d | 240 | |
70945cb6 OZ |
241 | static int |
242 | ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n) | |
243 | { | |
244 | struct ospf_iface *ifa = n->ifa; | |
f8fefde3 OZ |
245 | struct ospf_lsa_header *lsas, lsa; |
246 | struct top_hash_entry *en, *req; | |
247 | const char *err_dsc = NULL; | |
248 | u32 lsa_type, lsa_domain; | |
70945cb6 OZ |
249 | uint i, lsa_count; |
250 | ||
251 | ospf_dbdes_body(p, pkt, &lsas, &lsa_count); | |
252 | ||
253 | for (i = 0; i < lsa_count; i++) | |
254 | { | |
70945cb6 OZ |
255 | lsa_ntoh_hdr(lsas + i, &lsa); |
256 | lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain); | |
b1f7229a | 257 | |
70945cb6 | 258 | /* RFC 2328 10.6 and RFC 5340 4.2.2 */ |
b1f7229a | 259 | |
70945cb6 | 260 | if (!lsa_type) |
f8fefde3 | 261 | DROP1("LSA of unknown type"); |
4364b47e | 262 | |
70945cb6 | 263 | if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS)) |
f8fefde3 | 264 | DROP1("LSA with AS scope in stub area"); |
4364b47e | 265 | |
70945cb6 OZ |
266 | /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */ |
267 | if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT)) | |
f8fefde3 | 268 | DROP1("rt-summary-LSA in stub area"); |
910e557b | 269 | |
70945cb6 OZ |
270 | /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */ |
271 | if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES) | |
f8fefde3 | 272 | DROP1("LSA with invalid scope"); |
910e557b | 273 | |
70945cb6 OZ |
274 | en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type); |
275 | if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER)) | |
276 | { | |
6f8bbaa1 | 277 | /* This should be splitted to ospf_lsa_lsrq_up() */ |
70945cb6 | 278 | req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type); |
6d2b3211 | 279 | |
70945cb6 OZ |
280 | if (!SNODE_VALID(req)) |
281 | s_add_tail(&n->lsrql, SNODE req); | |
6d2b3211 | 282 | |
6f8bbaa1 OZ |
283 | if (!SNODE_VALID(n->lsrqi)) |
284 | n->lsrqi = req; | |
285 | ||
70945cb6 | 286 | req->lsa = lsa; |
a7a7372a | 287 | req->lsa_body = LSA_BODY_DUMMY; |
6f8bbaa1 | 288 | |
a6f79ca5 OZ |
289 | if (!tm_active(n->lsrq_timer)) |
290 | tm_start(n->lsrq_timer, 0); | |
95eb1dba | 291 | } |
6d2b3211 | 292 | } |
70945cb6 OZ |
293 | |
294 | return 0; | |
295 | ||
f8fefde3 OZ |
296 | drop: |
297 | LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in DBDES", lsa_type, lsa.id, lsa.rt); | |
298 | LOG_LSA2(" received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc); | |
299 | ||
70945cb6 OZ |
300 | ospf_neigh_sm(n, INM_SEQMIS); |
301 | return -1; | |
4364b47e OF |
302 | } |
303 | ||
304 | void | |
70945cb6 | 305 | ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, |
c3226991 | 306 | struct ospf_neighbor *n) |
4364b47e | 307 | { |
70945cb6 | 308 | struct ospf_proto *p = ifa->oa->po; |
f8fefde3 | 309 | const char *err_dsc = NULL; |
70945cb6 OZ |
310 | u32 rcv_ddseq, rcv_options; |
311 | u16 rcv_iface_mtu; | |
312 | u8 rcv_imms; | |
6f8bbaa1 | 313 | uint plen, err_val = 0; |
4364b47e | 314 | |
70945cb6 OZ |
315 | /* RFC 2328 10.6 */ |
316 | ||
317 | plen = ntohs(pkt->length); | |
318 | if (plen < ospf_dbdes_hdrlen(p)) | |
6f8bbaa1 OZ |
319 | { |
320 | LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen); | |
321 | return; | |
322 | } | |
a6bc04d5 | 323 | |
f8fefde3 | 324 | OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname); |
b1f7229a | 325 | |
4bb9ce56 | 326 | ospf_neigh_sm(n, INM_HELLOREC); |
353f3261 | 327 | |
70945cb6 OZ |
328 | if (ospf_is_v2(p)) |
329 | { | |
330 | struct ospf_dbdes2_packet *ps = (void *) pkt; | |
331 | rcv_iface_mtu = ntohs(ps->iface_mtu); | |
332 | rcv_options = ps->options; | |
333 | rcv_imms = ps->imms; | |
334 | rcv_ddseq = ntohl(ps->ddseq); | |
335 | } | |
336 | else /* OSPFv3 */ | |
337 | { | |
338 | struct ospf_dbdes3_packet *ps = (void *) pkt; | |
339 | rcv_options = ntohl(ps->options); | |
340 | rcv_iface_mtu = ntohs(ps->iface_mtu); | |
341 | rcv_imms = ps->imms; | |
342 | rcv_ddseq = ntohl(ps->ddseq); | |
343 | } | |
742029eb | 344 | |
267da813 OZ |
345 | /* Reject packets with non-matching MTU */ |
346 | if ((ifa->type != OSPF_IT_VLINK) && | |
347 | (rcv_iface_mtu != ifa->iface->mtu) && | |
348 | (rcv_iface_mtu != 0) && (ifa->iface->mtu != 0)) | |
349 | { | |
350 | LOG_PKT("MTU mismatch with nbr %R on %s (remote %d, local %d)", | |
351 | n->rid, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu); | |
352 | return; | |
353 | } | |
354 | ||
12bed559 | 355 | switch (n->state) |
4364b47e | 356 | { |
12bed559 OF |
357 | case NEIGHBOR_DOWN: |
358 | case NEIGHBOR_ATTEMPT: | |
359 | case NEIGHBOR_2WAY: | |
f8fefde3 | 360 | OSPF_TRACE(D_PACKETS, "DBDES packet ignored - lesser state than ExStart"); |
12bed559 | 361 | return; |
70945cb6 | 362 | |
12bed559 OF |
363 | case NEIGHBOR_INIT: |
364 | ospf_neigh_sm(n, INM_2WAYREC); | |
365 | if (n->state != NEIGHBOR_EXSTART) | |
366 | return; | |
d4cebc6b | 367 | /* fallthrough */ |
9f1500f5 | 368 | |
70945cb6 | 369 | case NEIGHBOR_EXSTART: |
d3f4f92b | 370 | if (((rcv_imms & DBDES_IMMS) == DBDES_IMMS) && |
70945cb6 OZ |
371 | (n->rid > p->router_id) && |
372 | (plen == ospf_dbdes_hdrlen(p))) | |
12bed559 OF |
373 | { |
374 | /* I'm slave! */ | |
70945cb6 OZ |
375 | n->dds = rcv_ddseq; |
376 | n->ddr = rcv_ddseq; | |
377 | n->options = rcv_options; | |
378 | n->myimms &= ~DBDES_MS; | |
379 | n->imms = rcv_imms; | |
a6f79ca5 | 380 | tm_stop(n->dbdes_timer); |
12bed559 | 381 | ospf_neigh_sm(n, INM_NEGDONE); |
f8fefde3 | 382 | ospf_send_dbdes(p, n); |
4364b47e | 383 | break; |
12bed559 | 384 | } |
b1f7229a | 385 | |
70945cb6 OZ |
386 | if (!(rcv_imms & DBDES_I) && |
387 | !(rcv_imms & DBDES_MS) && | |
742029eb | 388 | (n->rid < p->router_id) && |
70945cb6 | 389 | (n->dds == rcv_ddseq)) |
12bed559 | 390 | { |
b1f7229a | 391 | /* I'm master! */ |
70945cb6 OZ |
392 | n->options = rcv_options; |
393 | n->ddr = rcv_ddseq - 1; /* It will be set corectly a few lines down */ | |
394 | n->imms = rcv_imms; | |
b1f7229a | 395 | ospf_neigh_sm(n, INM_NEGDONE); |
6f8bbaa1 | 396 | /* Continue to the NEIGHBOR_EXCHANGE case */ |
12bed559 | 397 | } |
b1f7229a OF |
398 | else |
399 | { | |
70945cb6 | 400 | DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms); |
12bed559 | 401 | break; |
b1f7229a | 402 | } |
70945cb6 | 403 | |
12bed559 | 404 | case NEIGHBOR_EXCHANGE: |
70945cb6 OZ |
405 | if ((rcv_imms == n->imms) && |
406 | (rcv_options == n->options) && | |
407 | (rcv_ddseq == n->ddr)) | |
f8fefde3 | 408 | goto duplicate; |
910e557b | 409 | |
f8fefde3 OZ |
410 | if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS)) |
411 | DROP("MS-bit mismatch", rcv_imms); | |
12bed559 | 412 | |
f8fefde3 OZ |
413 | if (rcv_imms & DBDES_I) |
414 | DROP("I-bit mismatch", rcv_imms); | |
415 | ||
416 | if (rcv_options != n->options) | |
417 | DROP("options mismatch", rcv_options); | |
4364b47e | 418 | |
70945cb6 OZ |
419 | n->ddr = rcv_ddseq; |
420 | n->imms = rcv_imms; | |
421 | ||
422 | if (n->myimms & DBDES_MS) | |
12bed559 | 423 | { |
f8fefde3 OZ |
424 | /* MASTER */ |
425 | ||
426 | if (rcv_ddseq != n->dds) | |
427 | DROP("DD sequence number mismatch", rcv_ddseq); | |
70945cb6 | 428 | |
12bed559 | 429 | n->dds++; |
70945cb6 OZ |
430 | |
431 | if (ospf_process_dbdes(p, pkt, n) < 0) | |
432 | return; | |
433 | ||
434 | if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M)) | |
6f8bbaa1 | 435 | { |
a6f79ca5 | 436 | tm_stop(n->dbdes_timer); |
12bed559 | 437 | ospf_neigh_sm(n, INM_EXDONE); |
6f8bbaa1 OZ |
438 | break; |
439 | } | |
440 | ||
441 | ospf_send_dbdes(p, n); | |
a6f79ca5 | 442 | tm_start(n->dbdes_timer, n->ifa->rxmtint S); |
12bed559 OF |
443 | } |
444 | else | |
445 | { | |
f8fefde3 OZ |
446 | /* SLAVE */ |
447 | ||
448 | if (rcv_ddseq != (n->dds + 1)) | |
449 | DROP("DD sequence number mismatch", rcv_ddseq); | |
12bed559 | 450 | |
70945cb6 OZ |
451 | n->ddr = rcv_ddseq; |
452 | n->dds = rcv_ddseq; | |
453 | ||
454 | if (ospf_process_dbdes(p, pkt, n) < 0) | |
455 | return; | |
456 | ||
f8fefde3 | 457 | ospf_send_dbdes(p, n); |
6f8bbaa1 OZ |
458 | |
459 | if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M)) | |
460 | ospf_neigh_sm(n, INM_EXDONE); | |
70945cb6 | 461 | } |
12bed559 | 462 | break; |
70945cb6 | 463 | |
12bed559 OF |
464 | case NEIGHBOR_LOADING: |
465 | case NEIGHBOR_FULL: | |
70945cb6 OZ |
466 | if ((rcv_imms == n->imms) && |
467 | (rcv_options == n->options) && | |
468 | (rcv_ddseq == n->ddr)) | |
f8fefde3 OZ |
469 | goto duplicate; |
470 | ||
f8fefde3 | 471 | DROP("too late for DD exchange", n->state); |
70945cb6 | 472 | |
189dab54 | 473 | default: |
f8fefde3 | 474 | bug("Undefined interface state"); |
12bed559 | 475 | } |
f8fefde3 OZ |
476 | return; |
477 | ||
478 | duplicate: | |
479 | OSPF_TRACE(D_PACKETS, "DBDES packet is duplicate"); | |
480 | ||
481 | /* Slave should retransmit DBDES packet */ | |
482 | if (!(n->myimms & DBDES_MS)) | |
483 | ospf_rxmt_dbdes(p, n); | |
484 | return; | |
485 | ||
486 | drop: | |
487 | LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", | |
488 | n->rid, ifa->ifname, err_dsc, err_val); | |
489 | ||
6f8bbaa1 | 490 | ospf_neigh_sm(n, INM_SEQMIS); |
f8fefde3 | 491 | return; |
12bed559 | 492 | } |