]>
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); | |
1aec7112 | 130 | ps->options = ifa->oa->options & DBDES2_OPT_MASK; |
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; | |
1aec7112 OZ |
138 | u32 options = ifa->oa->options | (ifa->autype == OSPF_AUTH_CRYPT ? OPT_AT : 0); |
139 | ps->options = htonl(options & DBDES3_OPT_MASK); | |
70945cb6 OZ |
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 | ||
f8fefde3 OZ |
147 | /* Prepare DBDES body */ |
148 | if (!(n->myimms & DBDES_I) && (n->myimms & DBDES_M)) | |
70945cb6 OZ |
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) && | |
5a50a989 OZ |
166 | lsa_flooding_allowed(en->lsa_type, en->domain, ifa) && |
167 | lsa_is_acceptable(en->lsa_type, n, p)) | |
70945cb6 OZ |
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, | |
f8fefde3 | 195 | "DBDES packet sent to nbr %R on %s", n->rid, ifa->ifname); |
70945cb6 | 196 | sk_set_tbuf(ifa->sk, n->ldd_buffer); |
bc591061 | 197 | ospf_send_to_nbr(ifa, n); |
70945cb6 OZ |
198 | sk_set_tbuf(ifa->sk, NULL); |
199 | } | |
200 | ||
eee9cefd | 201 | /** |
70945cb6 | 202 | * ospf_send_dbdes - transmit database description packet |
8e433d6a | 203 | * @p: OSPF protocol instance |
eee9cefd OF |
204 | * @n: neighbor |
205 | * | |
c3226991 | 206 | * Sending of a database description packet is described in 10.8 of RFC 2328. |
baa5dd6c OF |
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. | |
eee9cefd | 211 | */ |
4364b47e | 212 | void |
f8fefde3 | 213 | ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) |
4364b47e | 214 | { |
70945cb6 | 215 | /* RFC 2328 10.8 */ |
4364b47e | 216 | |
f8fefde3 OZ |
217 | ASSERT((n->state == NEIGHBOR_EXSTART) || (n->state == NEIGHBOR_EXCHANGE)); |
218 | ||
1a2ad348 | 219 | if (!n->ifa->oa->rt && !p->gr_recovery) |
70945cb6 | 220 | return; |
054a3524 | 221 | |
f8fefde3 OZ |
222 | ospf_prepare_dbdes(p, n); |
223 | ospf_do_send_dbdes(p, n); | |
f8fefde3 | 224 | } |
12bed559 | 225 | |
f8fefde3 OZ |
226 | void |
227 | ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) | |
228 | { | |
229 | ASSERT(n->state > NEIGHBOR_EXSTART); | |
e7ef86a5 | 230 | |
f8fefde3 OZ |
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; | |
70945cb6 | 236 | } |
04c6319a | 237 | |
f8fefde3 OZ |
238 | /* Send last packet */ |
239 | ospf_do_send_dbdes(p, n); | |
240 | } | |
48e5f32d | 241 | |
16605f2f OZ |
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 | ||
70945cb6 OZ |
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; | |
f8fefde3 OZ |
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; | |
70945cb6 OZ |
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 | { | |
70945cb6 OZ |
264 | lsa_ntoh_hdr(lsas + i, &lsa); |
265 | lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain); | |
b1f7229a | 266 | |
70945cb6 | 267 | /* RFC 2328 10.6 and RFC 5340 4.2.2 */ |
b1f7229a | 268 | |
70945cb6 | 269 | if (!lsa_type) |
f8fefde3 | 270 | DROP1("LSA of unknown type"); |
4364b47e | 271 | |
70945cb6 | 272 | if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS)) |
f8fefde3 | 273 | DROP1("LSA with AS scope in stub area"); |
4364b47e | 274 | |
70945cb6 OZ |
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)) | |
f8fefde3 | 277 | DROP1("rt-summary-LSA in stub area"); |
910e557b | 278 | |
70945cb6 OZ |
279 | /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */ |
280 | if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES) | |
f8fefde3 | 281 | DROP1("LSA with invalid scope"); |
910e557b | 282 | |
1a2ad348 OZ |
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 | ||
70945cb6 OZ |
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 | { | |
6f8bbaa1 | 290 | /* This should be splitted to ospf_lsa_lsrq_up() */ |
70945cb6 | 291 | req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type); |
6d2b3211 | 292 | |
70945cb6 OZ |
293 | if (!SNODE_VALID(req)) |
294 | s_add_tail(&n->lsrql, SNODE req); | |
6d2b3211 | 295 | |
6f8bbaa1 OZ |
296 | if (!SNODE_VALID(n->lsrqi)) |
297 | n->lsrqi = req; | |
298 | ||
70945cb6 | 299 | req->lsa = lsa; |
a7a7372a | 300 | req->lsa_body = LSA_BODY_DUMMY; |
6f8bbaa1 | 301 | |
a6f79ca5 OZ |
302 | if (!tm_active(n->lsrq_timer)) |
303 | tm_start(n->lsrq_timer, 0); | |
95eb1dba | 304 | } |
6d2b3211 | 305 | } |
70945cb6 OZ |
306 | |
307 | return 0; | |
308 | ||
f8fefde3 OZ |
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 | ||
70945cb6 OZ |
313 | ospf_neigh_sm(n, INM_SEQMIS); |
314 | return -1; | |
4364b47e OF |
315 | } |
316 | ||
317 | void | |
70945cb6 | 318 | ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, |
c3226991 | 319 | struct ospf_neighbor *n) |
4364b47e | 320 | { |
70945cb6 | 321 | struct ospf_proto *p = ifa->oa->po; |
f8fefde3 | 322 | const char *err_dsc = NULL; |
70945cb6 OZ |
323 | u32 rcv_ddseq, rcv_options; |
324 | u16 rcv_iface_mtu; | |
325 | u8 rcv_imms; | |
6f8bbaa1 | 326 | uint plen, err_val = 0; |
4364b47e | 327 | |
70945cb6 OZ |
328 | /* RFC 2328 10.6 */ |
329 | ||
330 | plen = ntohs(pkt->length); | |
331 | if (plen < ospf_dbdes_hdrlen(p)) | |
6f8bbaa1 OZ |
332 | { |
333 | LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen); | |
334 | return; | |
335 | } | |
a6bc04d5 | 336 | |
f8fefde3 | 337 | OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname); |
b1f7229a | 338 | |
4bb9ce56 | 339 | ospf_neigh_sm(n, INM_HELLOREC); |
353f3261 | 340 | |
70945cb6 OZ |
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 | } | |
742029eb | 357 | |
267da813 OZ |
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 | ||
12bed559 | 368 | switch (n->state) |
4364b47e | 369 | { |
12bed559 OF |
370 | case NEIGHBOR_DOWN: |
371 | case NEIGHBOR_ATTEMPT: | |
372 | case NEIGHBOR_2WAY: | |
f8fefde3 | 373 | OSPF_TRACE(D_PACKETS, "DBDES packet ignored - lesser state than ExStart"); |
12bed559 | 374 | return; |
70945cb6 | 375 | |
12bed559 OF |
376 | case NEIGHBOR_INIT: |
377 | ospf_neigh_sm(n, INM_2WAYREC); | |
378 | if (n->state != NEIGHBOR_EXSTART) | |
379 | return; | |
d4cebc6b | 380 | /* fallthrough */ |
9f1500f5 | 381 | |
70945cb6 | 382 | case NEIGHBOR_EXSTART: |
d3f4f92b | 383 | if (((rcv_imms & DBDES_IMMS) == DBDES_IMMS) && |
70945cb6 OZ |
384 | (n->rid > p->router_id) && |
385 | (plen == ospf_dbdes_hdrlen(p))) | |
12bed559 OF |
386 | { |
387 | /* I'm slave! */ | |
70945cb6 OZ |
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; | |
a6f79ca5 | 393 | tm_stop(n->dbdes_timer); |
12bed559 | 394 | ospf_neigh_sm(n, INM_NEGDONE); |
f8fefde3 | 395 | ospf_send_dbdes(p, n); |
4364b47e | 396 | break; |
12bed559 | 397 | } |
b1f7229a | 398 | |
70945cb6 OZ |
399 | if (!(rcv_imms & DBDES_I) && |
400 | !(rcv_imms & DBDES_MS) && | |
742029eb | 401 | (n->rid < p->router_id) && |
70945cb6 | 402 | (n->dds == rcv_ddseq)) |
12bed559 | 403 | { |
b1f7229a | 404 | /* I'm master! */ |
70945cb6 OZ |
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; | |
b1f7229a | 408 | ospf_neigh_sm(n, INM_NEGDONE); |
6f8bbaa1 | 409 | /* Continue to the NEIGHBOR_EXCHANGE case */ |
12bed559 | 410 | } |
b1f7229a OF |
411 | else |
412 | { | |
70945cb6 | 413 | DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms); |
12bed559 | 414 | break; |
b1f7229a | 415 | } |
70945cb6 | 416 | |
12bed559 | 417 | case NEIGHBOR_EXCHANGE: |
70945cb6 OZ |
418 | if ((rcv_imms == n->imms) && |
419 | (rcv_options == n->options) && | |
420 | (rcv_ddseq == n->ddr)) | |
f8fefde3 | 421 | goto duplicate; |
910e557b | 422 | |
f8fefde3 OZ |
423 | if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS)) |
424 | DROP("MS-bit mismatch", rcv_imms); | |
12bed559 | 425 | |
f8fefde3 OZ |
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); | |
4364b47e | 431 | |
70945cb6 OZ |
432 | n->ddr = rcv_ddseq; |
433 | n->imms = rcv_imms; | |
434 | ||
435 | if (n->myimms & DBDES_MS) | |
12bed559 | 436 | { |
f8fefde3 OZ |
437 | /* MASTER */ |
438 | ||
439 | if (rcv_ddseq != n->dds) | |
440 | DROP("DD sequence number mismatch", rcv_ddseq); | |
70945cb6 | 441 | |
12bed559 | 442 | n->dds++; |
70945cb6 OZ |
443 | |
444 | if (ospf_process_dbdes(p, pkt, n) < 0) | |
445 | return; | |
446 | ||
447 | if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M)) | |
6f8bbaa1 | 448 | { |
a6f79ca5 | 449 | tm_stop(n->dbdes_timer); |
16605f2f | 450 | ospf_reset_ldd(p, n); |
12bed559 | 451 | ospf_neigh_sm(n, INM_EXDONE); |
6f8bbaa1 OZ |
452 | break; |
453 | } | |
454 | ||
455 | ospf_send_dbdes(p, n); | |
a6f79ca5 | 456 | tm_start(n->dbdes_timer, n->ifa->rxmtint S); |
12bed559 OF |
457 | } |
458 | else | |
459 | { | |
f8fefde3 OZ |
460 | /* SLAVE */ |
461 | ||
462 | if (rcv_ddseq != (n->dds + 1)) | |
463 | DROP("DD sequence number mismatch", rcv_ddseq); | |
12bed559 | 464 | |
70945cb6 OZ |
465 | n->ddr = rcv_ddseq; |
466 | n->dds = rcv_ddseq; | |
467 | ||
468 | if (ospf_process_dbdes(p, pkt, n) < 0) | |
469 | return; | |
470 | ||
f8fefde3 | 471 | ospf_send_dbdes(p, n); |
6f8bbaa1 OZ |
472 | |
473 | if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M)) | |
16605f2f OZ |
474 | { |
475 | /* Use dbdes timer to postpone freeing of Last DBDES packet buffer */ | |
476 | tm_start(n->dbdes_timer, n->ifa->deadint S); | |
6f8bbaa1 | 477 | ospf_neigh_sm(n, INM_EXDONE); |
16605f2f | 478 | } |
70945cb6 | 479 | } |
12bed559 | 480 | break; |
70945cb6 | 481 | |
12bed559 OF |
482 | case NEIGHBOR_LOADING: |
483 | case NEIGHBOR_FULL: | |
70945cb6 OZ |
484 | if ((rcv_imms == n->imms) && |
485 | (rcv_options == n->options) && | |
486 | (rcv_ddseq == n->ddr)) | |
f8fefde3 OZ |
487 | goto duplicate; |
488 | ||
f8fefde3 | 489 | DROP("too late for DD exchange", n->state); |
70945cb6 | 490 | |
189dab54 | 491 | default: |
f8fefde3 | 492 | bug("Undefined interface state"); |
12bed559 | 493 | } |
f8fefde3 OZ |
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 | ||
6f8bbaa1 | 508 | ospf_neigh_sm(n, INM_SEQMIS); |
f8fefde3 | 509 | return; |
12bed559 | 510 | } |