blob: d41fff57bd7baf03ab9ad1ccc1fe1700e69b0a32 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * OSPF Sending and Receiving OSPF Packets.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "thread.h"
26#include "memory.h"
27#include "linklist.h"
28#include "prefix.h"
29#include "if.h"
30#include "table.h"
31#include "sockunion.h"
32#include "stream.h"
33#include "log.h"
paul2dd8bb42004-07-23 15:13:48 +000034#include "sockopt.h"
paul484315f2005-11-03 09:08:29 +000035#include "checksum.h"
vincentc1a03d42005-09-28 15:47:44 +000036#include "md5.h"
paul718e3742002-12-13 20:15:29 +000037
38#include "ospfd/ospfd.h"
39#include "ospfd/ospf_network.h"
40#include "ospfd/ospf_interface.h"
41#include "ospfd/ospf_ism.h"
42#include "ospfd/ospf_asbr.h"
43#include "ospfd/ospf_lsa.h"
44#include "ospfd/ospf_lsdb.h"
45#include "ospfd/ospf_neighbor.h"
46#include "ospfd/ospf_nsm.h"
47#include "ospfd/ospf_packet.h"
48#include "ospfd/ospf_spf.h"
49#include "ospfd/ospf_flood.h"
50#include "ospfd/ospf_dump.h"
51
paul718e3742002-12-13 20:15:29 +000052/* Packet Type String. */
hassoeb1ce602004-10-08 08:17:22 +000053const char *ospf_packet_type_str[] =
paul718e3742002-12-13 20:15:29 +000054{
55 "unknown",
56 "Hello",
57 "Database Description",
58 "Link State Request",
59 "Link State Update",
60 "Link State Acknowledgment",
61};
62
paul718e3742002-12-13 20:15:29 +000063/* OSPF authentication checking function */
paul4dadc292005-05-06 21:37:42 +000064static int
paul718e3742002-12-13 20:15:29 +000065ospf_auth_type (struct ospf_interface *oi)
66{
67 int auth_type;
68
69 if (OSPF_IF_PARAM (oi, auth_type) == OSPF_AUTH_NOTSET)
70 auth_type = oi->area->auth_type;
71 else
72 auth_type = OSPF_IF_PARAM (oi, auth_type);
73
74 /* Handle case where MD5 key list is not configured aka Cisco */
75 if (auth_type == OSPF_AUTH_CRYPTOGRAPHIC &&
76 list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
77 return OSPF_AUTH_NULL;
78
79 return auth_type;
80
81}
82
paul718e3742002-12-13 20:15:29 +000083struct ospf_packet *
84ospf_packet_new (size_t size)
85{
86 struct ospf_packet *new;
87
88 new = XCALLOC (MTYPE_OSPF_PACKET, sizeof (struct ospf_packet));
89 new->s = stream_new (size);
90
91 return new;
92}
93
94void
95ospf_packet_free (struct ospf_packet *op)
96{
97 if (op->s)
98 stream_free (op->s);
99
100 XFREE (MTYPE_OSPF_PACKET, op);
101
102 op = NULL;
103}
104
105struct ospf_fifo *
106ospf_fifo_new ()
107{
108 struct ospf_fifo *new;
109
110 new = XCALLOC (MTYPE_OSPF_FIFO, sizeof (struct ospf_fifo));
111 return new;
112}
113
114/* Add new packet to fifo. */
115void
116ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
117{
118 if (fifo->tail)
119 fifo->tail->next = op;
120 else
121 fifo->head = op;
122
123 fifo->tail = op;
124
125 fifo->count++;
126}
127
128/* Delete first packet from fifo. */
129struct ospf_packet *
130ospf_fifo_pop (struct ospf_fifo *fifo)
131{
132 struct ospf_packet *op;
133
134 op = fifo->head;
135
136 if (op)
137 {
138 fifo->head = op->next;
139
140 if (fifo->head == NULL)
141 fifo->tail = NULL;
142
143 fifo->count--;
144 }
145
146 return op;
147}
148
149/* Return first fifo entry. */
150struct ospf_packet *
151ospf_fifo_head (struct ospf_fifo *fifo)
152{
153 return fifo->head;
154}
155
156/* Flush ospf packet fifo. */
157void
158ospf_fifo_flush (struct ospf_fifo *fifo)
159{
160 struct ospf_packet *op;
161 struct ospf_packet *next;
162
163 for (op = fifo->head; op; op = next)
164 {
165 next = op->next;
166 ospf_packet_free (op);
167 }
168 fifo->head = fifo->tail = NULL;
169 fifo->count = 0;
170}
171
172/* Free ospf packet fifo. */
173void
174ospf_fifo_free (struct ospf_fifo *fifo)
175{
176 ospf_fifo_flush (fifo);
177
178 XFREE (MTYPE_OSPF_FIFO, fifo);
179}
180
181void
182ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
183{
ajsc3eab872005-01-29 15:52:07 +0000184 if (!oi->obuf)
185 {
186 zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
187 "destination %s) called with NULL obuf, ignoring "
188 "(please report this bug)!\n",
189 IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
190 ospf_packet_type_str[stream_getc_from(op->s, 1)],
191 inet_ntoa (op->dst));
192 return;
193 }
194
paul718e3742002-12-13 20:15:29 +0000195 /* Add packet to end of queue. */
196 ospf_fifo_push (oi->obuf, op);
197
198 /* Debug of packet fifo*/
199 /* ospf_fifo_debug (oi->obuf); */
200}
201
202void
203ospf_packet_delete (struct ospf_interface *oi)
204{
205 struct ospf_packet *op;
206
207 op = ospf_fifo_pop (oi->obuf);
208
209 if (op)
210 ospf_packet_free (op);
211}
212
paul718e3742002-12-13 20:15:29 +0000213struct ospf_packet *
214ospf_packet_dup (struct ospf_packet *op)
215{
216 struct ospf_packet *new;
217
paul37163d62003-02-03 18:40:56 +0000218 if (stream_get_endp(op->s) != op->length)
219 zlog_warn ("ospf_packet_dup stream %ld ospf_packet %d size mismatch",
paul30961a12002-12-13 20:56:48 +0000220 STREAM_SIZE(op->s), op->length);
paul30961a12002-12-13 20:56:48 +0000221
222 /* Reserve space for MD5 authentication that may be added later. */
223 new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
paulfa81b712005-02-19 01:19:20 +0000224 stream_copy (new->s, op->s);
paul718e3742002-12-13 20:15:29 +0000225
226 new->dst = op->dst;
227 new->length = op->length;
228
229 return new;
230}
231
gdt86f1fd92005-01-10 14:20:43 +0000232/* XXX inline */
paul4dadc292005-05-06 21:37:42 +0000233static inline unsigned int
gdt86f1fd92005-01-10 14:20:43 +0000234ospf_packet_authspace (struct ospf_interface *oi)
235{
236 int auth = 0;
237
238 if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
239 auth = OSPF_AUTH_MD5_SIZE;
240
241 return auth;
242}
243
paul4dadc292005-05-06 21:37:42 +0000244static unsigned int
paul718e3742002-12-13 20:15:29 +0000245ospf_packet_max (struct ospf_interface *oi)
246{
247 int max;
248
gdt86f1fd92005-01-10 14:20:43 +0000249 max = oi->ifp->mtu - ospf_packet_authspace(oi);
250
paul68b73392004-09-12 14:21:37 +0000251 max -= (OSPF_HEADER_SIZE + sizeof (struct ip));
paul718e3742002-12-13 20:15:29 +0000252
253 return max;
254}
255
256
paul4dadc292005-05-06 21:37:42 +0000257static int
paul718e3742002-12-13 20:15:29 +0000258ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
259 u_int16_t length)
260{
paul6c835672004-10-11 11:00:30 +0000261 unsigned char *ibuf;
vincentc1a03d42005-09-28 15:47:44 +0000262 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000263 unsigned char digest[OSPF_AUTH_MD5_SIZE];
264 unsigned char *pdigest;
265 struct crypt_key *ck;
266 struct ospf_header *ospfh;
267 struct ospf_neighbor *nbr;
268
269
270 ibuf = STREAM_PNT (s);
271 ospfh = (struct ospf_header *) ibuf;
272
273 /* Get pointer to the end of the packet. */
274 pdigest = ibuf + length;
275
276 /* Get secret key. */
277 ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
278 ospfh->u.crypt.key_id);
279 if (ck == NULL)
280 {
281 zlog_warn ("interface %s: ospf_check_md5 no key %d",
282 IF_NAME (oi), ospfh->u.crypt.key_id);
283 return 0;
284 }
285
286 /* check crypto seqnum. */
287 nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id);
288
289 if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum))
290 {
291 zlog_warn ("interface %s: ospf_check_md5 bad sequence %d (expect %d)",
292 IF_NAME (oi),
293 ntohl(ospfh->u.crypt.crypt_seqnum),
294 ntohl(nbr->crypt_seqnum));
295 return 0;
296 }
297
298 /* Generate a digest for the ospf packet - their digest + our digest. */
vincentc1a03d42005-09-28 15:47:44 +0000299 memset(&ctx, 0, sizeof(ctx));
300 MD5Init(&ctx);
301 MD5Update(&ctx, ibuf, length);
302 MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
303 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +0000304
305 /* compare the two */
306 if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
307 {
308 zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
309 IF_NAME (oi));
310 return 0;
311 }
312
313 /* save neighbor's crypt_seqnum */
314 if (nbr)
315 nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
316 return 1;
317}
318
319/* This function is called from ospf_write(), it will detect the
320 authentication scheme and if it is MD5, it will change the sequence
321 and update the MD5 digest. */
paul4dadc292005-05-06 21:37:42 +0000322static int
paul718e3742002-12-13 20:15:29 +0000323ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
324{
325 struct ospf_header *ospfh;
326 unsigned char digest[OSPF_AUTH_MD5_SIZE];
vincentc1a03d42005-09-28 15:47:44 +0000327 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000328 void *ibuf;
paul9483e152002-12-13 20:55:25 +0000329 u_int32_t t;
paul718e3742002-12-13 20:15:29 +0000330 struct crypt_key *ck;
paul36238142005-10-11 04:12:54 +0000331 const u_int8_t *auth_key;
paul718e3742002-12-13 20:15:29 +0000332
333 ibuf = STREAM_DATA (op->s);
334 ospfh = (struct ospf_header *) ibuf;
335
336 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
337 return 0;
338
339 /* We do this here so when we dup a packet, we don't have to
340 waste CPU rewriting other headers. */
paul9483e152002-12-13 20:55:25 +0000341 t = (time(NULL) & 0xFFFFFFFF);
342 oi->crypt_seqnum = ( t > oi->crypt_seqnum ? t : oi->crypt_seqnum++);
343 ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum);
paul718e3742002-12-13 20:15:29 +0000344
345 /* Get MD5 Authentication key from auth_key list. */
346 if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
paul36238142005-10-11 04:12:54 +0000347 auth_key = (const u_int8_t *) "";
paul718e3742002-12-13 20:15:29 +0000348 else
349 {
paul1eb8ef22005-04-07 07:30:20 +0000350 ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
paul4dadc292005-05-06 21:37:42 +0000351 auth_key = ck->auth_key;
paul718e3742002-12-13 20:15:29 +0000352 }
353
354 /* Generate a digest for the entire packet + our secret key. */
vincentc1a03d42005-09-28 15:47:44 +0000355 memset(&ctx, 0, sizeof(ctx));
356 MD5Init(&ctx);
357 MD5Update(&ctx, ibuf, ntohs (ospfh->length));
358 MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE);
359 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +0000360
361 /* Append md5 digest to the end of the stream. */
paul718e3742002-12-13 20:15:29 +0000362 stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000363
364 /* We do *NOT* increment the OSPF header length. */
paul30961a12002-12-13 20:56:48 +0000365 op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
366
paul37163d62003-02-03 18:40:56 +0000367 if (stream_get_endp(op->s) != op->length)
368 zlog_warn("ospf_make_md5_digest: length mismatch stream %ld ospf_packet %d", stream_get_endp(op->s), op->length);
paul718e3742002-12-13 20:15:29 +0000369
370 return OSPF_AUTH_MD5_SIZE;
371}
372
373
paul4dadc292005-05-06 21:37:42 +0000374static int
paul718e3742002-12-13 20:15:29 +0000375ospf_ls_req_timer (struct thread *thread)
376{
377 struct ospf_neighbor *nbr;
378
379 nbr = THREAD_ARG (thread);
380 nbr->t_ls_req = NULL;
381
382 /* Send Link State Request. */
383 if (ospf_ls_request_count (nbr))
384 ospf_ls_req_send (nbr);
385
386 /* Set Link State Request retransmission timer. */
387 OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
388
389 return 0;
390}
391
392void
393ospf_ls_req_event (struct ospf_neighbor *nbr)
394{
395 if (nbr->t_ls_req)
396 {
397 thread_cancel (nbr->t_ls_req);
398 nbr->t_ls_req = NULL;
399 }
400 nbr->t_ls_req = thread_add_event (master, ospf_ls_req_timer, nbr, 0);
401}
402
403/* Cyclic timer function. Fist registered in ospf_nbr_new () in
404 ospf_neighbor.c */
405int
406ospf_ls_upd_timer (struct thread *thread)
407{
408 struct ospf_neighbor *nbr;
409
410 nbr = THREAD_ARG (thread);
411 nbr->t_ls_upd = NULL;
412
413 /* Send Link State Update. */
414 if (ospf_ls_retransmit_count (nbr) > 0)
415 {
hasso52dc7ee2004-09-23 19:18:23 +0000416 struct list *update;
paul718e3742002-12-13 20:15:29 +0000417 struct ospf_lsdb *lsdb;
418 int i;
paul718e3742002-12-13 20:15:29 +0000419 int retransmit_interval;
420
paul718e3742002-12-13 20:15:29 +0000421 retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval);
422
423 lsdb = &nbr->ls_rxmt;
424 update = list_new ();
425
426 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
427 {
428 struct route_table *table = lsdb->type[i].db;
429 struct route_node *rn;
430
431 for (rn = route_top (table); rn; rn = route_next (rn))
432 {
433 struct ospf_lsa *lsa;
434
435 if ((lsa = rn->info) != NULL)
436 /* Don't retransmit an LSA if we received it within
437 the last RxmtInterval seconds - this is to allow the
438 neighbour a chance to acknowledge the LSA as it may
439 have ben just received before the retransmit timer
440 fired. This is a small tweak to what is in the RFC,
441 but it will cut out out a lot of retransmit traffic
442 - MAG */
pauld24f6e22005-10-21 09:23:12 +0000443 if (tv_cmp (tv_sub (recent_time, lsa->tv_recv),
paul718e3742002-12-13 20:15:29 +0000444 int2tv (retransmit_interval)) >= 0)
445 listnode_add (update, rn->info);
446 }
447 }
448
449 if (listcount (update) > 0)
450 ospf_ls_upd_send (nbr, update, OSPF_SEND_PACKET_DIRECT);
451 list_delete (update);
452 }
453
454 /* Set LS Update retransmission timer. */
455 OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
456
457 return 0;
458}
459
460int
461ospf_ls_ack_timer (struct thread *thread)
462{
463 struct ospf_interface *oi;
464
465 oi = THREAD_ARG (thread);
466 oi->t_ls_ack = NULL;
467
468 /* Send Link State Acknowledgment. */
469 if (listcount (oi->ls_ack) > 0)
470 ospf_ls_ack_send_delayed (oi);
471
472 /* Set LS Ack timer. */
473 OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
474
475 return 0;
476}
477
paul0bfeca32004-09-24 08:07:54 +0000478#ifdef WANT_OSPF_WRITE_FRAGMENT
ajs5dcbdf82005-03-29 16:13:49 +0000479static void
paul6a99f832004-09-27 12:56:30 +0000480ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph,
paul62d8e962004-11-02 20:26:45 +0000481 struct msghdr *msg, unsigned int maxdatasize,
paul37ccfa32004-10-31 11:24:51 +0000482 unsigned int mtu, int flags, u_char type)
paul0bfeca32004-09-24 08:07:54 +0000483{
484#define OSPF_WRITE_FRAG_SHIFT 3
paul6a99f832004-09-27 12:56:30 +0000485 u_int16_t offset;
paul62d8e962004-11-02 20:26:45 +0000486 struct iovec *iovp;
paul6a99f832004-09-27 12:56:30 +0000487 int ret;
paul0bfeca32004-09-24 08:07:54 +0000488
489 assert ( op->length == stream_get_endp(op->s) );
paul62d8e962004-11-02 20:26:45 +0000490 assert (msg->msg_iovlen == 2);
paul0bfeca32004-09-24 08:07:54 +0000491
492 /* we can but try.
493 *
494 * SunOS, BSD and BSD derived kernels likely will clear ip_id, as
495 * well as the IP_MF flag, making this all quite pointless.
496 *
497 * However, for a system on which IP_MF is left alone, and ip_id left
498 * alone or else which sets same ip_id for each fragment this might
499 * work, eg linux.
500 *
501 * XXX-TODO: It would be much nicer to have the kernel's use their
502 * existing fragmentation support to do this for us. Bugs/RFEs need to
503 * be raised against the various kernels.
504 */
505
506 /* set More Frag */
507 iph->ip_off |= IP_MF;
508
509 /* ip frag offset is expressed in units of 8byte words */
510 offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT;
511
paul62d8e962004-11-02 20:26:45 +0000512 iovp = &msg->msg_iov[1];
513
paul0bfeca32004-09-24 08:07:54 +0000514 while ( (stream_get_endp(op->s) - stream_get_getp (op->s))
515 > maxdatasize )
516 {
517 /* data length of this frag is to next offset value */
paul62d8e962004-11-02 20:26:45 +0000518 iovp->iov_len = offset << OSPF_WRITE_FRAG_SHIFT;
519 iph->ip_len = iovp->iov_len + sizeof (struct ip);
paul6a99f832004-09-27 12:56:30 +0000520 assert (iph->ip_len <= mtu);
paul0bfeca32004-09-24 08:07:54 +0000521
paul18b12c32004-10-05 14:38:29 +0000522 sockopt_iphdrincl_swab_htosys (iph);
paul0bfeca32004-09-24 08:07:54 +0000523
paul6a99f832004-09-27 12:56:30 +0000524 ret = sendmsg (fd, msg, flags);
paul0bfeca32004-09-24 08:07:54 +0000525
paul18b12c32004-10-05 14:38:29 +0000526 sockopt_iphdrincl_swab_systoh (iph);
paul0bfeca32004-09-24 08:07:54 +0000527
528 if (ret < 0)
paul37ccfa32004-10-31 11:24:51 +0000529 zlog_warn ("*** ospf_write_frags: sendmsg failed to %s,"
ajs5dcbdf82005-03-29 16:13:49 +0000530 " id %d, off %d, len %d, mtu %u failed with %s",
531 inet_ntoa (iph->ip_dst),
532 iph->ip_id,
533 iph->ip_off,
534 iph->ip_len,
535 mtu,
536 safe_strerror (errno));
paul0bfeca32004-09-24 08:07:54 +0000537
paul37ccfa32004-10-31 11:24:51 +0000538 if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
539 {
ajs2a42e282004-12-08 18:43:03 +0000540 zlog_debug ("ospf_write_frags: sent id %d, off %d, len %d to %s\n",
paul37ccfa32004-10-31 11:24:51 +0000541 iph->ip_id, iph->ip_off, iph->ip_len,
542 inet_ntoa (iph->ip_dst));
543 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
544 {
ajs2a42e282004-12-08 18:43:03 +0000545 zlog_debug ("-----------------IP Header Dump----------------------");
paul37ccfa32004-10-31 11:24:51 +0000546 ospf_ip_header_dump (iph);
ajs2a42e282004-12-08 18:43:03 +0000547 zlog_debug ("-----------------------------------------------------");
paul37ccfa32004-10-31 11:24:51 +0000548 }
549 }
550
paul0bfeca32004-09-24 08:07:54 +0000551 iph->ip_off += offset;
paul9985f832005-02-09 15:51:56 +0000552 stream_forward_getp (op->s, iovp->iov_len);
paul62d8e962004-11-02 20:26:45 +0000553 iovp->iov_base = STREAM_PNT (op->s);
paul0bfeca32004-09-24 08:07:54 +0000554 }
555
556 /* setup for final fragment */
paul62d8e962004-11-02 20:26:45 +0000557 iovp->iov_len = stream_get_endp(op->s) - stream_get_getp (op->s);
558 iph->ip_len = iovp->iov_len + sizeof (struct ip);
paul0bfeca32004-09-24 08:07:54 +0000559 iph->ip_off &= (~IP_MF);
560}
561#endif /* WANT_OSPF_WRITE_FRAGMENT */
562
ajs5dcbdf82005-03-29 16:13:49 +0000563static int
paul718e3742002-12-13 20:15:29 +0000564ospf_write (struct thread *thread)
565{
paul68980082003-03-25 05:07:42 +0000566 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000567 struct ospf_interface *oi;
568 struct ospf_packet *op;
569 struct sockaddr_in sa_dst;
paul718e3742002-12-13 20:15:29 +0000570 struct ip iph;
571 struct msghdr msg;
paul62d8e962004-11-02 20:26:45 +0000572 struct iovec iov[2];
paul68980082003-03-25 05:07:42 +0000573 u_char type;
574 int ret;
575 int flags = 0;
hasso52dc7ee2004-09-23 19:18:23 +0000576 struct listnode *node;
paul0bfeca32004-09-24 08:07:54 +0000577#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000578 static u_int16_t ipid = 0;
paul0bfeca32004-09-24 08:07:54 +0000579#endif /* WANT_OSPF_WRITE_FRAGMENT */
paul6a99f832004-09-27 12:56:30 +0000580 u_int16_t maxdatasize;
paul68b73392004-09-12 14:21:37 +0000581#define OSPF_WRITE_IPHL_SHIFT 2
paul718e3742002-12-13 20:15:29 +0000582
paul68980082003-03-25 05:07:42 +0000583 ospf->t_write = NULL;
paul718e3742002-12-13 20:15:29 +0000584
paul68980082003-03-25 05:07:42 +0000585 node = listhead (ospf->oi_write_q);
paul718e3742002-12-13 20:15:29 +0000586 assert (node);
paul1eb8ef22005-04-07 07:30:20 +0000587 oi = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000588 assert (oi);
paul0bfeca32004-09-24 08:07:54 +0000589
590#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000591 /* seed ipid static with low order bits of time */
592 if (ipid == 0)
593 ipid = (time(NULL) & 0xffff);
paul0bfeca32004-09-24 08:07:54 +0000594#endif /* WANT_OSPF_WRITE_FRAGMENT */
595
paul68b73392004-09-12 14:21:37 +0000596 /* convenience - max OSPF data per packet */
597 maxdatasize = oi->ifp->mtu - sizeof (struct ip);
598
paul718e3742002-12-13 20:15:29 +0000599 /* Get one packet from queue. */
600 op = ospf_fifo_head (oi->obuf);
601 assert (op);
602 assert (op->length >= OSPF_HEADER_SIZE);
603
paul68980082003-03-25 05:07:42 +0000604 if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
605 || op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
paul68b73392004-09-12 14:21:37 +0000606 ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
607
paul718e3742002-12-13 20:15:29 +0000608 /* Rewrite the md5 signature & update the seq */
609 ospf_make_md5_digest (oi, op);
610
paul37ccfa32004-10-31 11:24:51 +0000611 /* Retrieve OSPF packet type. */
612 stream_set_getp (op->s, 1);
613 type = stream_getc (op->s);
614
paul68b73392004-09-12 14:21:37 +0000615 /* reset get pointer */
616 stream_set_getp (op->s, 0);
617
618 memset (&iph, 0, sizeof (struct ip));
paul718e3742002-12-13 20:15:29 +0000619 memset (&sa_dst, 0, sizeof (sa_dst));
paul68b73392004-09-12 14:21:37 +0000620
paul718e3742002-12-13 20:15:29 +0000621 sa_dst.sin_family = AF_INET;
622#ifdef HAVE_SIN_LEN
623 sa_dst.sin_len = sizeof(sa_dst);
624#endif /* HAVE_SIN_LEN */
625 sa_dst.sin_addr = op->dst;
626 sa_dst.sin_port = htons (0);
627
628 /* Set DONTROUTE flag if dst is unicast. */
629 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
630 if (!IN_MULTICAST (htonl (op->dst.s_addr)))
631 flags = MSG_DONTROUTE;
632
paul68b73392004-09-12 14:21:37 +0000633 iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
634 /* it'd be very strange for header to not be 4byte-word aligned but.. */
paul6c835672004-10-11 11:00:30 +0000635 if ( sizeof (struct ip)
636 > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
paul68b73392004-09-12 14:21:37 +0000637 iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
638
paul718e3742002-12-13 20:15:29 +0000639 iph.ip_v = IPVERSION;
paul68980082003-03-25 05:07:42 +0000640 iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
paul68b73392004-09-12 14:21:37 +0000641 iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
paul68b73392004-09-12 14:21:37 +0000642
paul0bfeca32004-09-24 08:07:54 +0000643#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000644 /* XXX-MT: not thread-safe at all..
645 * XXX: this presumes this is only programme sending OSPF packets
646 * otherwise, no guarantee ipid will be unique
647 */
648 iph.ip_id = ++ipid;
paul0bfeca32004-09-24 08:07:54 +0000649#endif /* WANT_OSPF_WRITE_FRAGMENT */
650
paul718e3742002-12-13 20:15:29 +0000651 iph.ip_off = 0;
652 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
653 iph.ip_ttl = OSPF_VL_IP_TTL;
654 else
655 iph.ip_ttl = OSPF_IP_TTL;
656 iph.ip_p = IPPROTO_OSPFIGP;
657 iph.ip_sum = 0;
658 iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
659 iph.ip_dst.s_addr = op->dst.s_addr;
660
661 memset (&msg, 0, sizeof (msg));
paul68defd62004-09-27 07:27:13 +0000662 msg.msg_name = (caddr_t) &sa_dst;
paul718e3742002-12-13 20:15:29 +0000663 msg.msg_namelen = sizeof (sa_dst);
664 msg.msg_iov = iov;
665 msg.msg_iovlen = 2;
666 iov[0].iov_base = (char*)&iph;
paul68b73392004-09-12 14:21:37 +0000667 iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
668 iov[1].iov_base = STREAM_PNT (op->s);
paul718e3742002-12-13 20:15:29 +0000669 iov[1].iov_len = op->length;
paul68b73392004-09-12 14:21:37 +0000670
671 /* Sadly we can not rely on kernels to fragment packets because of either
672 * IP_HDRINCL and/or multicast destination being set.
673 */
paul0bfeca32004-09-24 08:07:54 +0000674#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000675 if ( op->length > maxdatasize )
paul62d8e962004-11-02 20:26:45 +0000676 ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize,
677 oi->ifp->mtu, flags, type);
paul0bfeca32004-09-24 08:07:54 +0000678#endif /* WANT_OSPF_WRITE_FRAGMENT */
paul68b73392004-09-12 14:21:37 +0000679
680 /* send final fragment (could be first) */
paul18b12c32004-10-05 14:38:29 +0000681 sockopt_iphdrincl_swab_htosys (&iph);
paul68980082003-03-25 05:07:42 +0000682 ret = sendmsg (ospf->fd, &msg, flags);
paul6b333612004-10-11 10:11:25 +0000683 sockopt_iphdrincl_swab_systoh (&iph);
paul718e3742002-12-13 20:15:29 +0000684
685 if (ret < 0)
ajs083ee9d2005-02-09 15:35:50 +0000686 zlog_warn ("*** sendmsg in ospf_write failed to %s, "
ajs5dcbdf82005-03-29 16:13:49 +0000687 "id %d, off %d, len %d, interface %s, mtu %u: %s",
ajs083ee9d2005-02-09 15:35:50 +0000688 inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
ajs5dcbdf82005-03-29 16:13:49 +0000689 oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000690
paul718e3742002-12-13 20:15:29 +0000691 /* Show debug sending packet. */
692 if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
693 {
694 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
695 {
ajs2a42e282004-12-08 18:43:03 +0000696 zlog_debug ("-----------------------------------------------------");
paul37ccfa32004-10-31 11:24:51 +0000697 ospf_ip_header_dump (&iph);
paul718e3742002-12-13 20:15:29 +0000698 stream_set_getp (op->s, 0);
699 ospf_packet_dump (op->s);
700 }
701
ajs2a42e282004-12-08 18:43:03 +0000702 zlog_debug ("%s sent to [%s] via [%s].",
paul718e3742002-12-13 20:15:29 +0000703 ospf_packet_type_str[type], inet_ntoa (op->dst),
704 IF_NAME (oi));
705
706 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
ajs2a42e282004-12-08 18:43:03 +0000707 zlog_debug ("-----------------------------------------------------");
paul718e3742002-12-13 20:15:29 +0000708 }
709
710 /* Now delete packet from queue. */
711 ospf_packet_delete (oi);
712
713 if (ospf_fifo_head (oi->obuf) == NULL)
714 {
715 oi->on_write_q = 0;
paul68980082003-03-25 05:07:42 +0000716 list_delete_node (ospf->oi_write_q, node);
paul718e3742002-12-13 20:15:29 +0000717 }
718
719 /* If packets still remain in queue, call write thread. */
paul68980082003-03-25 05:07:42 +0000720 if (!list_isempty (ospf->oi_write_q))
721 ospf->t_write =
722 thread_add_write (master, ospf_write, ospf, ospf->fd);
paul718e3742002-12-13 20:15:29 +0000723
724 return 0;
725}
726
727/* OSPF Hello message read -- RFC2328 Section 10.5. */
paul4dadc292005-05-06 21:37:42 +0000728static void
paul718e3742002-12-13 20:15:29 +0000729ospf_hello (struct ip *iph, struct ospf_header *ospfh,
730 struct stream * s, struct ospf_interface *oi, int size)
731{
732 struct ospf_hello *hello;
733 struct ospf_neighbor *nbr;
paul718e3742002-12-13 20:15:29 +0000734 int old_state;
pauld3f0d622004-05-05 15:27:15 +0000735 struct prefix p;
paul718e3742002-12-13 20:15:29 +0000736
737 /* increment statistics. */
738 oi->hello_in++;
739
740 hello = (struct ospf_hello *) STREAM_PNT (s);
741
742 /* If Hello is myself, silently discard. */
paul68980082003-03-25 05:07:42 +0000743 if (IPV4_ADDR_SAME (&ospfh->router_id, &oi->ospf->router_id))
pauld3241812003-09-29 12:42:39 +0000744 {
745 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
746 {
ajs2a42e282004-12-08 18:43:03 +0000747 zlog_debug ("ospf_header[%s/%s]: selforiginated, "
pauld3241812003-09-29 12:42:39 +0000748 "dropping.",
749 ospf_packet_type_str[ospfh->type],
750 inet_ntoa (iph->ip_src));
751 }
752 return;
753 }
paul718e3742002-12-13 20:15:29 +0000754
755 /* If incoming interface is passive one, ignore Hello. */
paulf2c80652002-12-13 21:44:27 +0000756 if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
ajsba6454e2005-02-08 15:37:30 +0000757 char buf[3][INET_ADDRSTRLEN];
758 zlog_warn("Warning: ignoring HELLO from router %s sent to %s; we "
759 "should not receive hellos on passive interface %s!",
760 inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])),
761 inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
762 inet_ntop(AF_INET, &oi->address->u.prefix4,
763 buf[2], sizeof(buf[2])));
764 if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
765 {
766 /* Try to fix multicast membership. */
767 SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
768 ospf_if_set_multicast(oi);
769 }
paul718e3742002-12-13 20:15:29 +0000770 return;
paulf2c80652002-12-13 21:44:27 +0000771 }
paul718e3742002-12-13 20:15:29 +0000772
773 /* get neighbor prefix. */
774 p.family = AF_INET;
775 p.prefixlen = ip_masklen (hello->network_mask);
776 p.u.prefix4 = iph->ip_src;
777
778 /* Compare network mask. */
779 /* Checking is ignored for Point-to-Point and Virtual link. */
780 if (oi->type != OSPF_IFTYPE_POINTOPOINT
781 && oi->type != OSPF_IFTYPE_VIRTUALLINK)
782 if (oi->address->prefixlen != p.prefixlen)
783 {
784 zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.",
785 inet_ntoa (ospfh->router_id));
786 return;
787 }
788
paul718e3742002-12-13 20:15:29 +0000789 /* Compare Router Dead Interval. */
790 if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
791 {
792 zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch.",
793 inet_ntoa (ospfh->router_id));
794 return;
795 }
796
paulf9ad9372005-10-21 00:45:17 +0000797 /* Compare Hello Interval - ignored if fast-hellos are set. */
798 if (OSPF_IF_PARAM (oi, fast_hello) == 0)
799 {
800 if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
801 {
802 zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.",
803 inet_ntoa (ospfh->router_id));
804 return;
805 }
806 }
807
paul718e3742002-12-13 20:15:29 +0000808 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000809 zlog_debug ("Packet %s [Hello:RECV]: Options %s",
paul718e3742002-12-13 20:15:29 +0000810 inet_ntoa (ospfh->router_id),
811 ospf_options_dump (hello->options));
812
813 /* Compare options. */
814#define REJECT_IF_TBIT_ON 1 /* XXX */
815#ifdef REJECT_IF_TBIT_ON
816 if (CHECK_FLAG (hello->options, OSPF_OPTION_T))
817 {
818 /*
819 * This router does not support non-zero TOS.
820 * Drop this Hello packet not to establish neighbor relationship.
821 */
822 zlog_warn ("Packet %s [Hello:RECV]: T-bit on, drop it.",
823 inet_ntoa (ospfh->router_id));
824 return;
825 }
826#endif /* REJECT_IF_TBIT_ON */
827
828#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000829 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)
paul718e3742002-12-13 20:15:29 +0000830 && CHECK_FLAG (hello->options, OSPF_OPTION_O))
831 {
832 /*
833 * This router does know the correct usage of O-bit
834 * the bit should be set in DD packet only.
835 */
836 zlog_warn ("Packet %s [Hello:RECV]: O-bit abuse?",
837 inet_ntoa (ospfh->router_id));
838#ifdef STRICT_OBIT_USAGE_CHECK
839 return; /* Reject this packet. */
840#else /* STRICT_OBIT_USAGE_CHECK */
841 UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */
842#endif /* STRICT_OBIT_USAGE_CHECK */
843 }
844#endif /* HAVE_OPAQUE_LSA */
845
846 /* new for NSSA is to ensure that NP is on and E is off */
847
paul718e3742002-12-13 20:15:29 +0000848 if (oi->area->external_routing == OSPF_AREA_NSSA)
849 {
850 if (! (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_NP)
851 && CHECK_FLAG (hello->options, OSPF_OPTION_NP)
852 && ! CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E)
853 && ! CHECK_FLAG (hello->options, OSPF_OPTION_E)))
854 {
855 zlog_warn ("NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", inet_ntoa (ospfh->router_id), OPTIONS (oi), hello->options);
856 return;
857 }
858 if (IS_DEBUG_OSPF_NSSA)
ajs2a42e282004-12-08 18:43:03 +0000859 zlog_debug ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
paul718e3742002-12-13 20:15:29 +0000860 }
861 else
paul718e3742002-12-13 20:15:29 +0000862 /* The setting of the E-bit found in the Hello Packet's Options
863 field must match this area's ExternalRoutingCapability A
864 mismatch causes processing to stop and the packet to be
865 dropped. The setting of the rest of the bits in the Hello
866 Packet's Options field should be ignored. */
867 if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) !=
868 CHECK_FLAG (hello->options, OSPF_OPTION_E))
869 {
ajs3aa8d5f2004-12-11 18:00:06 +0000870 zlog_warn ("Packet %s [Hello:RECV]: my options: %x, his options %x",
871 inet_ntoa(ospfh->router_id), OPTIONS (oi), hello->options);
paul718e3742002-12-13 20:15:29 +0000872 return;
873 }
paul718e3742002-12-13 20:15:29 +0000874
pauld3f0d622004-05-05 15:27:15 +0000875 /* get neighbour struct */
876 nbr = ospf_nbr_get (oi, ospfh, iph, &p);
877
878 /* neighbour must be valid, ospf_nbr_get creates if none existed */
879 assert (nbr);
paul718e3742002-12-13 20:15:29 +0000880
881 old_state = nbr->state;
882
883 /* Add event to thread. */
884 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
885
886 /* RFC2328 Section 9.5.1
887 If the router is not eligible to become Designated Router,
888 (snip) It must also send an Hello Packet in reply to an
889 Hello Packet received from any eligible neighbor (other than
890 the current Designated Router and Backup Designated Router). */
891 if (oi->type == OSPF_IFTYPE_NBMA)
892 if (PRIORITY(oi) == 0 && hello->priority > 0
893 && IPV4_ADDR_CMP(&DR(oi), &iph->ip_src)
894 && IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src))
895 OSPF_NSM_TIMER_ON (nbr->t_hello_reply, ospf_hello_reply_timer,
896 OSPF_HELLO_REPLY_DELAY);
897
898 /* on NBMA network type, it happens to receive bidirectional Hello packet
899 without advance 1-Way Received event.
900 To avoid incorrect DR-seletion, raise 1-Way Received event.*/
901 if (oi->type == OSPF_IFTYPE_NBMA &&
902 (old_state == NSM_Down || old_state == NSM_Attempt))
903 {
904 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
905 nbr->priority = hello->priority;
906 nbr->d_router = hello->d_router;
907 nbr->bd_router = hello->bd_router;
908 return;
909 }
910
paul68980082003-03-25 05:07:42 +0000911 if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
paul718e3742002-12-13 20:15:29 +0000912 size - OSPF_HELLO_MIN_SIZE))
913 {
914 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
915 nbr->options |= hello->options;
916 }
917 else
918 {
919 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
920 /* Set neighbor information. */
921 nbr->priority = hello->priority;
922 nbr->d_router = hello->d_router;
923 nbr->bd_router = hello->bd_router;
924 return;
925 }
926
927 /* If neighbor itself declares DR and no BDR exists,
928 cause event BackupSeen */
929 if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router))
930 if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting)
931 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
932
933 /* neighbor itself declares BDR. */
934 if (oi->state == ISM_Waiting &&
935 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router))
936 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
937
938 /* had not previously. */
939 if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) &&
940 IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) ||
941 (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) &&
942 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router)))
943 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
944
945 /* had not previously. */
946 if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) &&
947 IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) ||
948 (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) &&
949 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router)))
950 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
951
952 /* Neighbor priority check. */
953 if (nbr->priority >= 0 && nbr->priority != hello->priority)
954 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
955
956 /* Set neighbor information. */
957 nbr->priority = hello->priority;
958 nbr->d_router = hello->d_router;
959 nbr->bd_router = hello->bd_router;
960}
961
962/* Save DD flags/options/Seqnum received. */
paul4dadc292005-05-06 21:37:42 +0000963static void
paul718e3742002-12-13 20:15:29 +0000964ospf_db_desc_save_current (struct ospf_neighbor *nbr,
965 struct ospf_db_desc *dd)
966{
967 nbr->last_recv.flags = dd->flags;
968 nbr->last_recv.options = dd->options;
969 nbr->last_recv.dd_seqnum = ntohl (dd->dd_seqnum);
970}
971
972/* Process rest of DD packet. */
973static void
974ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
975 struct ospf_neighbor *nbr, struct ospf_db_desc *dd,
976 u_int16_t size)
977{
978 struct ospf_lsa *new, *find;
979 struct lsa_header *lsah;
980
paul9985f832005-02-09 15:51:56 +0000981 stream_forward_getp (s, OSPF_DB_DESC_MIN_SIZE);
paul718e3742002-12-13 20:15:29 +0000982 for (size -= OSPF_DB_DESC_MIN_SIZE;
983 size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE)
984 {
985 lsah = (struct lsa_header *) STREAM_PNT (s);
paul9985f832005-02-09 15:51:56 +0000986 stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +0000987
988 /* Unknown LS type. */
989 if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
990 {
ajsbec595a2004-11-30 22:38:43 +0000991 zlog_warn ("Packet [DD:RECV]: Unknown LS type %d.", lsah->type);
paul718e3742002-12-13 20:15:29 +0000992 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
993 return;
994 }
995
996#ifdef HAVE_OPAQUE_LSA
997 if (IS_OPAQUE_LSA (lsah->type)
998 && ! CHECK_FLAG (nbr->options, OSPF_OPTION_O))
999 {
1000 zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
1001 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1002 return;
1003 }
1004#endif /* HAVE_OPAQUE_LSA */
1005
1006 switch (lsah->type)
1007 {
1008 case OSPF_AS_EXTERNAL_LSA:
1009#ifdef HAVE_OPAQUE_LSA
1010 case OSPF_OPAQUE_AS_LSA:
1011#endif /* HAVE_OPAQUE_LSA */
paul718e3742002-12-13 20:15:29 +00001012 /* Check for stub area. Reject if AS-External from stub but
1013 allow if from NSSA. */
1014 if (oi->area->external_routing == OSPF_AREA_STUB)
paul718e3742002-12-13 20:15:29 +00001015 {
1016 zlog_warn ("Packet [DD:RECV]: LSA[Type%d:%s] from %s area.",
1017 lsah->type, inet_ntoa (lsah->id),
1018 (oi->area->external_routing == OSPF_AREA_STUB) ?\
1019 "STUB" : "NSSA");
1020 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1021 return;
1022 }
1023 break;
1024 default:
1025 break;
1026 }
1027
1028 /* Create LS-request object. */
1029 new = ospf_ls_request_new (lsah);
1030
1031 /* Lookup received LSA, then add LS request list. */
1032 find = ospf_lsa_lookup_by_header (oi->area, lsah);
1033 if (!find || ospf_lsa_more_recent (find, new) < 0)
1034 {
1035 ospf_ls_request_add (nbr, new);
1036 ospf_lsa_discard (new);
1037 }
1038 else
1039 {
1040 /* Received LSA is not recent. */
1041 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001042 zlog_debug ("Packet [DD:RECV]: LSA received Type %d, "
paul718e3742002-12-13 20:15:29 +00001043 "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
1044 ospf_lsa_discard (new);
1045 continue;
1046 }
1047 }
1048
1049 /* Master */
1050 if (IS_SET_DD_MS (nbr->dd_flags))
1051 {
1052 nbr->dd_seqnum++;
1053 /* Entire DD packet sent. */
1054 if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
1055 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
1056 else
1057 /* Send new DD packet. */
1058 ospf_db_desc_send (nbr);
1059 }
1060 /* Slave */
1061 else
1062 {
1063 nbr->dd_seqnum = ntohl (dd->dd_seqnum);
1064
1065 /* When master's more flags is not set. */
1066 if (!IS_SET_DD_M (dd->flags) && ospf_db_summary_isempty (nbr))
1067 {
1068 nbr->dd_flags &= ~(OSPF_DD_FLAG_M);
1069 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
1070 }
1071
ajsbec595a2004-11-30 22:38:43 +00001072 /* Send DD packet in reply. */
paul718e3742002-12-13 20:15:29 +00001073 ospf_db_desc_send (nbr);
1074 }
1075
1076 /* Save received neighbor values from DD. */
1077 ospf_db_desc_save_current (nbr, dd);
1078}
1079
paul4dadc292005-05-06 21:37:42 +00001080static int
paul718e3742002-12-13 20:15:29 +00001081ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
1082{
1083 /* Is DD duplicated? */
1084 if (dd->options == nbr->last_recv.options &&
1085 dd->flags == nbr->last_recv.flags &&
1086 dd->dd_seqnum == htonl (nbr->last_recv.dd_seqnum))
1087 return 1;
1088
1089 return 0;
1090}
1091
1092/* OSPF Database Description message read -- RFC2328 Section 10.6. */
ajs3aa8d5f2004-12-11 18:00:06 +00001093static void
paul718e3742002-12-13 20:15:29 +00001094ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
1095 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1096{
1097 struct ospf_db_desc *dd;
1098 struct ospf_neighbor *nbr;
1099
1100 /* Increment statistics. */
1101 oi->db_desc_in++;
1102
1103 dd = (struct ospf_db_desc *) STREAM_PNT (s);
pauld363df22003-06-19 00:26:34 +00001104
pauld3f0d622004-05-05 15:27:15 +00001105 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001106 if (nbr == NULL)
1107 {
1108 zlog_warn ("Packet[DD]: Unknown Neighbor %s",
1109 inet_ntoa (ospfh->router_id));
1110 return;
1111 }
1112
1113 /* Check MTU. */
vincentba682532005-09-29 13:52:57 +00001114 if ((OSPF_IF_PARAM (oi, mtu_ignore) == 0) &&
1115 (ntohs (dd->mtu) > oi->ifp->mtu))
paul718e3742002-12-13 20:15:29 +00001116 {
ajs3aa8d5f2004-12-11 18:00:06 +00001117 zlog_warn ("Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u",
1118 inet_ntoa (nbr->router_id), ntohs (dd->mtu),
1119 IF_NAME (oi), oi->ifp->mtu);
paul718e3742002-12-13 20:15:29 +00001120 return;
1121 }
1122
pauld363df22003-06-19 00:26:34 +00001123 /*
1124 * XXX HACK by Hasso Tepper. Setting N/P bit in NSSA area DD packets is not
1125 * required. In fact at least JunOS sends DD packets with P bit clear.
1126 * Until proper solution is developped, this hack should help.
1127 *
1128 * Update: According to the RFCs, N bit is specified /only/ for Hello
1129 * options, unfortunately its use in DD options is not specified. Hence some
1130 * implementations follow E-bit semantics and set it in DD options, and some
1131 * treat it as unspecified and hence follow the directive "default for
1132 * options is clear", ie unset.
1133 *
1134 * Reset the flag, as ospfd follows E-bit semantics.
1135 */
1136 if ( (oi->area->external_routing == OSPF_AREA_NSSA)
1137 && (CHECK_FLAG (nbr->options, OSPF_OPTION_NP))
1138 && (!CHECK_FLAG (dd->options, OSPF_OPTION_NP)) )
1139 {
1140 if (IS_DEBUG_OSPF_EVENT)
ajs1210fa62004-12-03 16:43:24 +00001141 zlog_debug ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
pauld363df22003-06-19 00:26:34 +00001142 inet_ntoa (nbr->router_id) );
1143 SET_FLAG (dd->options, OSPF_OPTION_NP);
1144 }
pauld363df22003-06-19 00:26:34 +00001145
paul718e3742002-12-13 20:15:29 +00001146#ifdef REJECT_IF_TBIT_ON
1147 if (CHECK_FLAG (dd->options, OSPF_OPTION_T))
1148 {
1149 /*
1150 * In Hello protocol, optional capability must have checked
1151 * to prevent this T-bit enabled router be my neighbor.
1152 */
1153 zlog_warn ("Packet[DD]: Neighbor %s: T-bit on?", inet_ntoa (nbr->router_id));
1154 return;
1155 }
1156#endif /* REJECT_IF_TBIT_ON */
1157
1158#ifdef HAVE_OPAQUE_LSA
1159 if (CHECK_FLAG (dd->options, OSPF_OPTION_O)
paul68980082003-03-25 05:07:42 +00001160 && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00001161 {
1162 /*
1163 * This node is not configured to handle O-bit, for now.
1164 * Clear it to ignore unsupported capability proposed by neighbor.
1165 */
1166 UNSET_FLAG (dd->options, OSPF_OPTION_O);
1167 }
1168#endif /* HAVE_OPAQUE_LSA */
1169
1170 /* Process DD packet by neighbor status. */
1171 switch (nbr->state)
1172 {
1173 case NSM_Down:
1174 case NSM_Attempt:
1175 case NSM_TwoWay:
ajsbec595a2004-11-30 22:38:43 +00001176 zlog_warn ("Packet[DD]: Neighbor %s state is %s, packet discarded.",
ajs3aa8d5f2004-12-11 18:00:06 +00001177 inet_ntoa(nbr->router_id),
paul718e3742002-12-13 20:15:29 +00001178 LOOKUP (ospf_nsm_state_msg, nbr->state));
1179 break;
1180 case NSM_Init:
1181 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
1182 /* If the new state is ExStart, the processing of the current
1183 packet should then continue in this new state by falling
1184 through to case ExStart below. */
1185 if (nbr->state != NSM_ExStart)
1186 break;
1187 case NSM_ExStart:
1188 /* Initial DBD */
1189 if ((IS_SET_DD_ALL (dd->flags) == OSPF_DD_FLAG_ALL) &&
1190 (size == OSPF_DB_DESC_MIN_SIZE))
1191 {
paul68980082003-03-25 05:07:42 +00001192 if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0)
paul718e3742002-12-13 20:15:29 +00001193 {
1194 /* We're Slave---obey */
ajs17eaa722004-12-29 21:04:48 +00001195 zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Slave).",
ajs3aa8d5f2004-12-11 18:00:06 +00001196 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001197 nbr->dd_seqnum = ntohl (dd->dd_seqnum);
1198 nbr->dd_flags &= ~(OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I); /* Reset I/MS */
1199 }
1200 else
1201 {
1202 /* We're Master, ignore the initial DBD from Slave */
ajs3aa8d5f2004-12-11 18:00:06 +00001203 zlog_warn ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
1204 "ignoring.", inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001205 break;
1206 }
1207 }
1208 /* Ack from the Slave */
1209 else if (!IS_SET_DD_MS (dd->flags) && !IS_SET_DD_I (dd->flags) &&
1210 ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&
paul68980082003-03-25 05:07:42 +00001211 IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0)
paul718e3742002-12-13 20:15:29 +00001212 {
ajs17eaa722004-12-29 21:04:48 +00001213 zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Master).",
ajs3aa8d5f2004-12-11 18:00:06 +00001214 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001215 nbr->dd_flags &= ~OSPF_DD_FLAG_I;
1216 }
1217 else
1218 {
ajs3aa8d5f2004-12-11 18:00:06 +00001219 zlog_warn ("Packet[DD]: Neighbor %s Negotiation fails.",
1220 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001221 break;
1222 }
1223
1224 /* This is where the real Options are saved */
1225 nbr->options = dd->options;
1226
1227#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00001228 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00001229 {
1230 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001231 zlog_debug ("Neighbor[%s] is %sOpaque-capable.",
paul718e3742002-12-13 20:15:29 +00001232 inet_ntoa (nbr->router_id),
1233 CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");
1234
1235 if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
1236 && IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
1237 {
1238 zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; Opaque-LSAs cannot be reliably advertised in this network.", inet_ntoa (nbr->router_id));
1239 /* This situation is undesirable, but not a real error. */
1240 }
1241 }
1242#endif /* HAVE_OPAQUE_LSA */
1243
1244 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);
1245
1246 /* continue processing rest of packet. */
1247 ospf_db_desc_proc (s, oi, nbr, dd, size);
1248 break;
1249 case NSM_Exchange:
1250 if (ospf_db_desc_is_dup (dd, nbr))
1251 {
1252 if (IS_SET_DD_MS (nbr->dd_flags))
1253 /* Master: discard duplicated DD packet. */
ajs3aa8d5f2004-12-11 18:00:06 +00001254 zlog_warn ("Packet[DD] (Master): Neighbor %s packet duplicated.",
1255 inet_ntoa (nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001256 else
1257 /* Slave: cause to retransmit the last Database Description. */
1258 {
ajs3aa8d5f2004-12-11 18:00:06 +00001259 zlog_warn ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
1260 inet_ntoa (nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001261 ospf_db_desc_resend (nbr);
1262 }
1263 break;
1264 }
1265
1266 /* Otherwise DD packet should be checked. */
1267 /* Check Master/Slave bit mismatch */
1268 if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))
1269 {
ajs3aa8d5f2004-12-11 18:00:06 +00001270 zlog_warn ("Packet[DD]: Neighbor %s MS-bit mismatch.",
1271 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001272 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1273 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001274 zlog_debug ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
ajs3aa8d5f2004-12-11 18:00:06 +00001275 dd->flags, nbr->dd_flags);
paul718e3742002-12-13 20:15:29 +00001276 break;
1277 }
1278
1279 /* Check initialize bit is set. */
1280 if (IS_SET_DD_I (dd->flags))
1281 {
ajs3aa8d5f2004-12-11 18:00:06 +00001282 zlog_warn ("Packet[DD]: Neighbor %s I-bit set.",
1283 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001284 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1285 break;
1286 }
1287
1288 /* Check DD Options. */
1289 if (dd->options != nbr->options)
1290 {
1291#ifdef ORIGINAL_CODING
1292 /* Save the new options for debugging */
1293 nbr->options = dd->options;
1294#endif /* ORIGINAL_CODING */
ajs3aa8d5f2004-12-11 18:00:06 +00001295 zlog_warn ("Packet[DD]: Neighbor %s options mismatch.",
1296 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001297 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1298 break;
1299 }
1300
1301 /* Check DD sequence number. */
1302 if ((IS_SET_DD_MS (nbr->dd_flags) &&
1303 ntohl (dd->dd_seqnum) != nbr->dd_seqnum) ||
1304 (!IS_SET_DD_MS (nbr->dd_flags) &&
1305 ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))
1306 {
ajs3aa8d5f2004-12-11 18:00:06 +00001307 zlog_warn ("Packet[DD]: Neighbor %s sequence number mismatch.",
1308 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001309 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1310 break;
1311 }
1312
1313 /* Continue processing rest of packet. */
1314 ospf_db_desc_proc (s, oi, nbr, dd, size);
1315 break;
1316 case NSM_Loading:
1317 case NSM_Full:
1318 if (ospf_db_desc_is_dup (dd, nbr))
1319 {
1320 if (IS_SET_DD_MS (nbr->dd_flags))
1321 {
1322 /* Master should discard duplicate DD packet. */
ajs3aa8d5f2004-12-11 18:00:06 +00001323 zlog_warn("Packet[DD]: Neighbor %s duplicated, packet discarded.",
1324 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001325 break;
1326 }
1327 else
1328 {
1329 struct timeval t, now;
1330 gettimeofday (&now, NULL);
1331 t = tv_sub (now, nbr->last_send_ts);
1332 if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
1333 {
1334 /* In states Loading and Full the slave must resend
1335 its last Database Description packet in response to
1336 duplicate Database Description packets received
1337 from the master. For this reason the slave must
1338 wait RouterDeadInterval seconds before freeing the
1339 last Database Description packet. Reception of a
1340 Database Description packet from the master after
1341 this interval will generate a SeqNumberMismatch
1342 neighbor event. RFC2328 Section 10.8 */
1343 ospf_db_desc_resend (nbr);
1344 break;
1345 }
1346 }
1347 }
1348
1349 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1350 break;
1351 default:
ajs3aa8d5f2004-12-11 18:00:06 +00001352 zlog_warn ("Packet[DD]: Neighbor %s NSM illegal status %u.",
1353 inet_ntoa(nbr->router_id), nbr->state);
paul718e3742002-12-13 20:15:29 +00001354 break;
1355 }
1356}
1357
1358#define OSPF_LSA_KEY_SIZE 12 /* type(4) + id(4) + ar(4) */
1359
1360/* OSPF Link State Request Read -- RFC2328 Section 10.7. */
paul4dadc292005-05-06 21:37:42 +00001361static void
paul718e3742002-12-13 20:15:29 +00001362ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
1363 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1364{
1365 struct ospf_neighbor *nbr;
1366 u_int32_t ls_type;
1367 struct in_addr ls_id;
1368 struct in_addr adv_router;
1369 struct ospf_lsa *find;
hasso52dc7ee2004-09-23 19:18:23 +00001370 struct list *ls_upd;
paul6c835672004-10-11 11:00:30 +00001371 unsigned int length;
paul718e3742002-12-13 20:15:29 +00001372
1373 /* Increment statistics. */
1374 oi->ls_req_in++;
1375
pauld3f0d622004-05-05 15:27:15 +00001376 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001377 if (nbr == NULL)
1378 {
1379 zlog_warn ("Link State Request: Unknown Neighbor %s.",
1380 inet_ntoa (ospfh->router_id));
1381 return;
1382 }
1383
1384 /* Neighbor State should be Exchange or later. */
1385 if (nbr->state != NSM_Exchange &&
1386 nbr->state != NSM_Loading &&
1387 nbr->state != NSM_Full)
1388 {
ajsbec595a2004-11-30 22:38:43 +00001389 zlog_warn ("Link State Request received from %s: "
1390 "Neighbor state is %s, packet discarded.",
1391 inet_ntoa (ospfh->router_id),
paul718e3742002-12-13 20:15:29 +00001392 LOOKUP (ospf_nsm_state_msg, nbr->state));
1393 return;
1394 }
1395
1396 /* Send Link State Update for ALL requested LSAs. */
1397 ls_upd = list_new ();
1398 length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
1399
1400 while (size >= OSPF_LSA_KEY_SIZE)
1401 {
1402 /* Get one slice of Link State Request. */
1403 ls_type = stream_getl (s);
1404 ls_id.s_addr = stream_get_ipv4 (s);
1405 adv_router.s_addr = stream_get_ipv4 (s);
1406
1407 /* Verify LSA type. */
1408 if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA)
1409 {
1410 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
1411 list_delete (ls_upd);
1412 return;
1413 }
1414
1415 /* Search proper LSA in LSDB. */
1416 find = ospf_lsa_lookup (oi->area, ls_type, ls_id, adv_router);
1417 if (find == NULL)
1418 {
1419 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
1420 list_delete (ls_upd);
1421 return;
1422 }
1423
gdt86f1fd92005-01-10 14:20:43 +00001424 /* Packet overflows MTU size, send immediately. */
1425 if (length + ntohs (find->data->length) > ospf_packet_max (oi))
paul718e3742002-12-13 20:15:29 +00001426 {
1427 if (oi->type == OSPF_IFTYPE_NBMA)
1428 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
1429 else
1430 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
1431
1432 /* Only remove list contents. Keep ls_upd. */
1433 list_delete_all_node (ls_upd);
1434
1435 length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
1436 }
1437
1438 /* Append LSA to update list. */
1439 listnode_add (ls_upd, find);
1440 length += ntohs (find->data->length);
1441
1442 size -= OSPF_LSA_KEY_SIZE;
1443 }
1444
1445 /* Send rest of Link State Update. */
1446 if (listcount (ls_upd) > 0)
1447 {
1448 if (oi->type == OSPF_IFTYPE_NBMA)
1449 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
1450 else
1451 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
1452
1453 list_delete (ls_upd);
1454 }
1455 else
1456 list_free (ls_upd);
1457}
1458
1459/* Get the list of LSAs from Link State Update packet.
1460 And process some validation -- RFC2328 Section 13. (1)-(2). */
hasso52dc7ee2004-09-23 19:18:23 +00001461static struct list *
paul718e3742002-12-13 20:15:29 +00001462ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
1463 struct ospf_interface *oi, size_t size)
1464{
1465 u_int16_t count, sum;
1466 u_int32_t length;
1467 struct lsa_header *lsah;
1468 struct ospf_lsa *lsa;
hasso52dc7ee2004-09-23 19:18:23 +00001469 struct list *lsas;
paul718e3742002-12-13 20:15:29 +00001470
1471 lsas = list_new ();
1472
1473 count = stream_getl (s);
1474 size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */
1475
1476 for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;
paul9985f832005-02-09 15:51:56 +00001477 size -= length, stream_forward_getp (s, length), count--)
paul718e3742002-12-13 20:15:29 +00001478 {
1479 lsah = (struct lsa_header *) STREAM_PNT (s);
1480 length = ntohs (lsah->length);
1481
1482 if (length > size)
1483 {
1484 zlog_warn ("Link State Update: LSA length exceeds packet size.");
1485 break;
1486 }
1487
1488 /* Validate the LSA's LS checksum. */
1489 sum = lsah->checksum;
1490 if (sum != ospf_lsa_checksum (lsah))
1491 {
1492 zlog_warn ("Link State Update: LSA checksum error %x, %x.",
1493 sum, lsah->checksum);
1494 continue;
1495 }
1496
1497 /* Examine the LSA's LS type. */
1498 if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
1499 {
1500 zlog_warn ("Link State Update: Unknown LS type %d", lsah->type);
1501 continue;
1502 }
1503
1504 /*
1505 * What if the received LSA's age is greater than MaxAge?
1506 * Treat it as a MaxAge case -- endo.
1507 */
1508 if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)
1509 lsah->ls_age = htons (OSPF_LSA_MAXAGE);
1510
1511#ifdef HAVE_OPAQUE_LSA
1512 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1513 {
1514#ifdef STRICT_OBIT_USAGE_CHECK
1515 if ((IS_OPAQUE_LSA(lsah->type) &&
1516 ! CHECK_FLAG (lsah->options, OSPF_OPTION_O))
1517 || (! IS_OPAQUE_LSA(lsah->type) &&
1518 CHECK_FLAG (lsah->options, OSPF_OPTION_O)))
1519 {
1520 /*
1521 * This neighbor must know the exact usage of O-bit;
1522 * the bit will be set in Type-9,10,11 LSAs only.
1523 */
1524 zlog_warn ("LSA[Type%d:%s]: O-bit abuse?", lsah->type, inet_ntoa (lsah->id));
1525 continue;
1526 }
1527#endif /* STRICT_OBIT_USAGE_CHECK */
1528
1529 /* Do not take in AS External Opaque-LSAs if we are a stub. */
1530 if (lsah->type == OSPF_OPAQUE_AS_LSA
1531 && nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
1532 {
1533 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001534 zlog_debug ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
paul718e3742002-12-13 20:15:29 +00001535 continue;
1536 }
1537 }
1538 else if (IS_OPAQUE_LSA(lsah->type))
1539 {
1540 zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
1541 continue;
1542 }
1543#endif /* HAVE_OPAQUE_LSA */
1544
1545 /* Create OSPF LSA instance. */
1546 lsa = ospf_lsa_new ();
1547
1548 /* We may wish to put some error checking if type NSSA comes in
1549 and area not in NSSA mode */
1550 switch (lsah->type)
1551 {
1552 case OSPF_AS_EXTERNAL_LSA:
1553#ifdef HAVE_OPAQUE_LSA
1554 case OSPF_OPAQUE_AS_LSA:
1555 lsa->area = NULL;
1556 break;
1557 case OSPF_OPAQUE_LINK_LSA:
1558 lsa->oi = oi; /* Remember incoming interface for flooding control. */
1559 /* Fallthrough */
1560#endif /* HAVE_OPAQUE_LSA */
1561 default:
1562 lsa->area = oi->area;
1563 break;
1564 }
1565
1566 lsa->data = ospf_lsa_data_new (length);
1567 memcpy (lsa->data, lsah, length);
1568
1569 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001570 zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update",
paul718e3742002-12-13 20:15:29 +00001571 lsa->data->type, inet_ntoa (lsa->data->id), lsa);
1572 listnode_add (lsas, lsa);
1573 }
1574
1575 return lsas;
1576}
1577
1578/* Cleanup Update list. */
paul4dadc292005-05-06 21:37:42 +00001579static void
hasso52dc7ee2004-09-23 19:18:23 +00001580ospf_upd_list_clean (struct list *lsas)
paul718e3742002-12-13 20:15:29 +00001581{
paul1eb8ef22005-04-07 07:30:20 +00001582 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001583 struct ospf_lsa *lsa;
1584
paul1eb8ef22005-04-07 07:30:20 +00001585 for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
1586 ospf_lsa_discard (lsa);
paul718e3742002-12-13 20:15:29 +00001587
1588 list_delete (lsas);
1589}
1590
1591/* OSPF Link State Update message read -- RFC2328 Section 13. */
paul4dadc292005-05-06 21:37:42 +00001592static void
paul718e3742002-12-13 20:15:29 +00001593ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
1594 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1595{
1596 struct ospf_neighbor *nbr;
hasso52dc7ee2004-09-23 19:18:23 +00001597 struct list *lsas;
paul1eb8ef22005-04-07 07:30:20 +00001598 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001599 struct ospf_lsa *lsa = NULL;
1600 /* unsigned long ls_req_found = 0; */
1601
1602 /* Dis-assemble the stream, update each entry, re-encapsulate for flooding */
1603
1604 /* Increment statistics. */
1605 oi->ls_upd_in++;
1606
1607 /* Check neighbor. */
pauld3f0d622004-05-05 15:27:15 +00001608 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001609 if (nbr == NULL)
1610 {
1611 zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s",
1612 inet_ntoa (ospfh->router_id), IF_NAME (oi));
1613 return;
1614 }
1615
1616 /* Check neighbor state. */
1617 if (nbr->state < NSM_Exchange)
1618 {
ajs3aa8d5f2004-12-11 18:00:06 +00001619 zlog_warn ("Link State Update: "
1620 "Neighbor[%s] state %s is less than Exchange",
1621 inet_ntoa (ospfh->router_id),
1622 LOOKUP(ospf_nsm_state_msg, nbr->state));
paul718e3742002-12-13 20:15:29 +00001623 return;
1624 }
1625
1626 /* Get list of LSAs from Link State Update packet. - Also perorms Stages
1627 * 1 (validate LSA checksum) and 2 (check for LSA consistent type)
1628 * of section 13.
1629 */
1630 lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
1631
1632#ifdef HAVE_OPAQUE_LSA
1633 /*
paul718e3742002-12-13 20:15:29 +00001634 * If self-originated Opaque-LSAs that have flooded before restart
1635 * are contained in the received LSUpd message, corresponding LSReq
1636 * messages to be sent may have to be modified.
1637 * To eliminate possible race conditions such that flushing and normal
1638 * updating for the same LSA would take place alternately, this trick
1639 * must be done before entering to the loop below.
1640 */
paul69310a62005-05-11 18:09:59 +00001641 /* XXX: Why is this Opaque specific? Either our core code is deficient
1642 * and this should be fixed generally, or Opaque is inventing strawman
1643 * problems */
paul718e3742002-12-13 20:15:29 +00001644 ospf_opaque_adjust_lsreq (nbr, lsas);
1645#endif /* HAVE_OPAQUE_LSA */
1646
1647#define DISCARD_LSA(L,N) {\
1648 if (IS_DEBUG_OSPF_EVENT) \
ajs2a42e282004-12-08 18:43:03 +00001649 zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
paul718e3742002-12-13 20:15:29 +00001650 ospf_lsa_discard (L); \
1651 continue; }
1652
1653 /* Process each LSA received in the one packet. */
paul1eb8ef22005-04-07 07:30:20 +00001654 for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
paul718e3742002-12-13 20:15:29 +00001655 {
1656 struct ospf_lsa *ls_ret, *current;
1657 int ret = 1;
1658
paul718e3742002-12-13 20:15:29 +00001659 if (IS_DEBUG_OSPF_NSSA)
1660 {
1661 char buf1[INET_ADDRSTRLEN];
1662 char buf2[INET_ADDRSTRLEN];
1663 char buf3[INET_ADDRSTRLEN];
1664
ajs2a42e282004-12-08 18:43:03 +00001665 zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s",
paul718e3742002-12-13 20:15:29 +00001666 lsa->data->type,
1667 inet_ntop (AF_INET, &ospfh->router_id,
1668 buf1, INET_ADDRSTRLEN),
1669 inet_ntop (AF_INET, &lsa->data->id,
1670 buf2, INET_ADDRSTRLEN),
1671 inet_ntop (AF_INET, &lsa->data->adv_router,
1672 buf3, INET_ADDRSTRLEN));
1673 }
paul718e3742002-12-13 20:15:29 +00001674
1675 listnode_delete (lsas, lsa); /* We don't need it in list anymore */
1676
1677 /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */
1678
1679 /* LSA Type - Done above by ospf_ls_upd_list_lsa() */
1680
1681 /* Do not take in AS External LSAs if we are a stub or NSSA. */
1682
1683 /* Do not take in AS NSSA if this neighbor and we are not NSSA */
1684
1685 /* Do take in Type-7's if we are an NSSA */
1686
1687 /* If we are also an ABR, later translate them to a Type-5 packet */
1688
1689 /* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will
1690 translate them to a separate Type-5 packet. */
1691
1692 if (lsa->data->type == OSPF_AS_EXTERNAL_LSA)
1693 /* Reject from STUB or NSSA */
1694 if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
1695 {
1696 DISCARD_LSA (lsa, 1);
paul718e3742002-12-13 20:15:29 +00001697 if (IS_DEBUG_OSPF_NSSA)
ajs2a42e282004-12-08 18:43:03 +00001698 zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area");
paul718e3742002-12-13 20:15:29 +00001699 }
1700
paul718e3742002-12-13 20:15:29 +00001701 if (lsa->data->type == OSPF_AS_NSSA_LSA)
1702 if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)
1703 {
1704 DISCARD_LSA (lsa,2);
1705 if (IS_DEBUG_OSPF_NSSA)
ajs2a42e282004-12-08 18:43:03 +00001706 zlog_debug("Incoming NSSA LSA Discarded: Not NSSA Area");
paul718e3742002-12-13 20:15:29 +00001707 }
paul718e3742002-12-13 20:15:29 +00001708
1709 /* Find the LSA in the current database. */
1710
1711 current = ospf_lsa_lookup_by_header (oi->area, lsa->data);
1712
1713 /* If the LSA's LS age is equal to MaxAge, and there is currently
1714 no instance of the LSA in the router's link state database,
1715 and none of router's neighbors are in states Exchange or Loading,
1716 then take the following actions. */
1717
1718 if (IS_LSA_MAXAGE (lsa) && !current &&
paul68980082003-03-25 05:07:42 +00001719 (ospf_nbr_count (oi, NSM_Exchange) +
1720 ospf_nbr_count (oi, NSM_Loading)) == 0)
paul718e3742002-12-13 20:15:29 +00001721 {
1722 /* Response Link State Acknowledgment. */
1723 ospf_ls_ack_send (nbr, lsa);
1724
1725 /* Discard LSA. */
ajs3aa8d5f2004-12-11 18:00:06 +00001726 zlog_warn("Link State Update[%s]: LS age is equal to MaxAge.",
1727 dump_lsa_key(lsa));
paul718e3742002-12-13 20:15:29 +00001728 DISCARD_LSA (lsa, 3);
1729 }
1730
1731#ifdef HAVE_OPAQUE_LSA
1732 if (IS_OPAQUE_LSA (lsa->data->type)
paul68980082003-03-25 05:07:42 +00001733 && IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +00001734 {
1735 /*
1736 * Even if initial flushing seems to be completed, there might
1737 * be a case that self-originated LSA with MaxAge still remain
1738 * in the routing domain.
1739 * Just send an LSAck message to cease retransmission.
1740 */
1741 if (IS_LSA_MAXAGE (lsa))
1742 {
1743 zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa));
1744 ospf_ls_ack_send (nbr, lsa);
1745 ospf_lsa_discard (lsa);
1746
1747 if (current != NULL && ! IS_LSA_MAXAGE (current))
1748 ospf_opaque_lsa_refresh_schedule (current);
1749 continue;
1750 }
1751
1752 /*
1753 * If an instance of self-originated Opaque-LSA is not found
1754 * in the LSDB, there are some possible cases here.
1755 *
1756 * 1) This node lost opaque-capability after restart.
1757 * 2) Else, a part of opaque-type is no more supported.
1758 * 3) Else, a part of opaque-id is no more supported.
1759 *
1760 * Anyway, it is still this node's responsibility to flush it.
1761 * Otherwise, the LSA instance remains in the routing domain
1762 * until its age reaches to MaxAge.
1763 */
paul69310a62005-05-11 18:09:59 +00001764 /* XXX: We should deal with this for *ALL* LSAs, not just opaque */
paul718e3742002-12-13 20:15:29 +00001765 if (current == NULL)
1766 {
1767 if (IS_DEBUG_OSPF_EVENT)
paul69310a62005-05-11 18:09:59 +00001768 zlog_debug ("LSA[%s]: Previously originated Opaque-LSA,"
1769 "not found in the LSDB.", dump_lsa_key (lsa));
paul718e3742002-12-13 20:15:29 +00001770
1771 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
paul69310a62005-05-11 18:09:59 +00001772
1773 ospf_opaque_self_originated_lsa_received (nbr, lsa);
1774 ospf_ls_ack_send (nbr, lsa);
1775
paul718e3742002-12-13 20:15:29 +00001776 continue;
1777 }
1778 }
1779#endif /* HAVE_OPAQUE_LSA */
paul69310a62005-05-11 18:09:59 +00001780
hassocb05eb22004-02-11 21:10:19 +00001781 /* It might be happen that received LSA is self-originated network LSA, but
1782 * router ID is cahnged. So, we should check if LSA is a network-LSA whose
1783 * Link State ID is one of the router's own IP interface addresses but whose
1784 * Advertising Router is not equal to the router's own Router ID
1785 * According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed.
1786 */
1787
1788 if(lsa->data->type == OSPF_NETWORK_LSA)
1789 {
paul1eb8ef22005-04-07 07:30:20 +00001790 struct listnode *oinode, *oinnode;
1791 struct ospf_interface *out_if;
hassocb05eb22004-02-11 21:10:19 +00001792 int Flag = 0;
1793
paul1eb8ef22005-04-07 07:30:20 +00001794 for (ALL_LIST_ELEMENTS (oi->ospf->oiflist, oinode, oinnode, out_if))
hassocb05eb22004-02-11 21:10:19 +00001795 {
hassocb05eb22004-02-11 21:10:19 +00001796 if(out_if == NULL)
1797 break;
1798
1799 if((IPV4_ADDR_SAME(&out_if->address->u.prefix4, &lsa->data->id)) &&
1800 (!(IPV4_ADDR_SAME(&oi->ospf->router_id, &lsa->data->adv_router))))
1801 {
1802 if(out_if->network_lsa_self)
1803 {
1804 ospf_lsa_flush_area(lsa,out_if->area);
1805 if(IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001806 zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
hassocb05eb22004-02-11 21:10:19 +00001807 lsa, (int) lsa->data->type);
1808 ospf_lsa_discard (lsa);
1809 Flag = 1;
1810 }
1811 break;
1812 }
1813 }
1814 if(Flag)
1815 continue;
1816 }
paul718e3742002-12-13 20:15:29 +00001817
1818 /* (5) Find the instance of this LSA that is currently contained
1819 in the router's link state database. If there is no
1820 database copy, or the received LSA is more recent than
1821 the database copy the following steps must be performed. */
1822
1823 if (current == NULL ||
1824 (ret = ospf_lsa_more_recent (current, lsa)) < 0)
1825 {
1826 /* Actual flooding procedure. */
paul68980082003-03-25 05:07:42 +00001827 if (ospf_flood (oi->ospf, nbr, current, lsa) < 0) /* Trap NSSA later. */
paul718e3742002-12-13 20:15:29 +00001828 DISCARD_LSA (lsa, 4);
1829 continue;
1830 }
1831
1832 /* (6) Else, If there is an instance of the LSA on the sending
1833 neighbor's Link state request list, an error has occurred in
1834 the Database Exchange process. In this case, restart the
1835 Database Exchange process by generating the neighbor event
1836 BadLSReq for the sending neighbor and stop processing the
1837 Link State Update packet. */
1838
1839 if (ospf_ls_request_lookup (nbr, lsa))
1840 {
1841 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
ajs3aa8d5f2004-12-11 18:00:06 +00001842 zlog_warn("LSA[%s] instance exists on Link state request list",
1843 dump_lsa_key(lsa));
paul718e3742002-12-13 20:15:29 +00001844
1845 /* Clean list of LSAs. */
1846 ospf_upd_list_clean (lsas);
1847 /* this lsa is not on lsas list already. */
1848 ospf_lsa_discard (lsa);
paul718e3742002-12-13 20:15:29 +00001849 return;
1850 }
1851
1852 /* If the received LSA is the same instance as the database copy
1853 (i.e., neither one is more recent) the following two steps
1854 should be performed: */
1855
1856 if (ret == 0)
1857 {
1858 /* If the LSA is listed in the Link state retransmission list
1859 for the receiving adjacency, the router itself is expecting
1860 an acknowledgment for this LSA. The router should treat the
1861 received LSA as an acknowledgment by removing the LSA from
1862 the Link state retransmission list. This is termed an
1863 "implied acknowledgment". */
1864
1865 ls_ret = ospf_ls_retransmit_lookup (nbr, lsa);
1866
1867 if (ls_ret != NULL)
1868 {
1869 ospf_ls_retransmit_delete (nbr, ls_ret);
1870
1871 /* Delayed acknowledgment sent if advertisement received
1872 from Designated Router, otherwise do nothing. */
1873 if (oi->state == ISM_Backup)
1874 if (NBR_IS_DR (nbr))
1875 listnode_add (oi->ls_ack, ospf_lsa_lock (lsa));
1876
1877 DISCARD_LSA (lsa, 5);
1878 }
1879 else
1880 /* Acknowledge the receipt of the LSA by sending a
1881 Link State Acknowledgment packet back out the receiving
1882 interface. */
1883 {
1884 ospf_ls_ack_send (nbr, lsa);
1885 DISCARD_LSA (lsa, 6);
1886 }
1887 }
1888
1889 /* The database copy is more recent. If the database copy
1890 has LS age equal to MaxAge and LS sequence number equal to
1891 MaxSequenceNumber, simply discard the received LSA without
1892 acknowledging it. (In this case, the LSA's LS sequence number is
1893 wrapping, and the MaxSequenceNumber LSA must be completely
1894 flushed before any new LSA instance can be introduced). */
1895
1896 else if (ret > 0) /* Database copy is more recent */
1897 {
1898 if (IS_LSA_MAXAGE (current) &&
1899 current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
1900 {
1901 DISCARD_LSA (lsa, 7);
1902 }
1903 /* Otherwise, as long as the database copy has not been sent in a
1904 Link State Update within the last MinLSArrival seconds, send the
1905 database copy back to the sending neighbor, encapsulated within
1906 a Link State Update Packet. The Link State Update Packet should
1907 be sent directly to the neighbor. In so doing, do not put the
1908 database copy of the LSA on the neighbor's link state
1909 retransmission list, and do not acknowledge the received (less
1910 recent) LSA instance. */
1911 else
1912 {
1913 struct timeval now;
1914
1915 gettimeofday (&now, NULL);
1916
1917 if (tv_cmp (tv_sub (now, current->tv_orig),
1918 int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)
1919 /* Trap NSSA type later.*/
1920 ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
1921 DISCARD_LSA (lsa, 8);
1922 }
1923 }
1924 }
1925
paul718e3742002-12-13 20:15:29 +00001926 assert (listcount (lsas) == 0);
1927 list_delete (lsas);
1928}
1929
1930/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
paul4dadc292005-05-06 21:37:42 +00001931static void
paul718e3742002-12-13 20:15:29 +00001932ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
1933 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1934{
1935 struct ospf_neighbor *nbr;
paul69310a62005-05-11 18:09:59 +00001936
paul718e3742002-12-13 20:15:29 +00001937 /* increment statistics. */
1938 oi->ls_ack_in++;
1939
pauld3f0d622004-05-05 15:27:15 +00001940 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001941 if (nbr == NULL)
1942 {
1943 zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.",
1944 inet_ntoa (ospfh->router_id));
1945 return;
1946 }
1947
1948 if (nbr->state < NSM_Exchange)
1949 {
ajs3aa8d5f2004-12-11 18:00:06 +00001950 zlog_warn ("Link State Acknowledgment: "
1951 "Neighbor[%s] state %s is less than Exchange",
1952 inet_ntoa (ospfh->router_id),
1953 LOOKUP(ospf_nsm_state_msg, nbr->state));
paul718e3742002-12-13 20:15:29 +00001954 return;
1955 }
paul69310a62005-05-11 18:09:59 +00001956
paul718e3742002-12-13 20:15:29 +00001957 while (size >= OSPF_LSA_HEADER_SIZE)
1958 {
1959 struct ospf_lsa *lsa, *lsr;
1960
1961 lsa = ospf_lsa_new ();
1962 lsa->data = (struct lsa_header *) STREAM_PNT (s);
1963
1964 /* lsah = (struct lsa_header *) STREAM_PNT (s); */
1965 size -= OSPF_LSA_HEADER_SIZE;
paul9985f832005-02-09 15:51:56 +00001966 stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00001967
1968 if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
1969 {
1970 lsa->data = NULL;
1971 ospf_lsa_discard (lsa);
1972 continue;
1973 }
1974
1975 lsr = ospf_ls_retransmit_lookup (nbr, lsa);
1976
1977 if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
1978 {
1979#ifdef HAVE_OPAQUE_LSA
paul718e3742002-12-13 20:15:29 +00001980 if (IS_OPAQUE_LSA (lsr->data->type))
paul69310a62005-05-11 18:09:59 +00001981 ospf_opaque_ls_ack_received (nbr, lsr);
paul718e3742002-12-13 20:15:29 +00001982#endif /* HAVE_OPAQUE_LSA */
1983
1984 ospf_ls_retransmit_delete (nbr, lsr);
1985 }
1986
1987 lsa->data = NULL;
1988 ospf_lsa_discard (lsa);
1989 }
1990
paul718e3742002-12-13 20:15:29 +00001991 return;
paul718e3742002-12-13 20:15:29 +00001992}
1993
ajs038163f2005-02-17 19:55:59 +00001994static struct stream *
ajs5c333492005-02-23 15:43:01 +00001995ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
paul718e3742002-12-13 20:15:29 +00001996{
1997 int ret;
ajs5c333492005-02-23 15:43:01 +00001998 struct ip *iph;
paul718e3742002-12-13 20:15:29 +00001999 u_int16_t ip_len;
paul718e3742002-12-13 20:15:29 +00002000 unsigned int ifindex = 0;
2001 struct iovec iov;
gdtd0deca62004-08-26 13:14:07 +00002002 /* Header and data both require alignment. */
gdte3049822004-08-26 13:19:40 +00002003 char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
paul2dd8bb42004-07-23 15:13:48 +00002004 struct msghdr msgh;
2005
paul68defd62004-09-27 07:27:13 +00002006 memset (&msgh, 0, sizeof (struct msghdr));
paul2dd8bb42004-07-23 15:13:48 +00002007 msgh.msg_iov = &iov;
2008 msgh.msg_iovlen = 1;
2009 msgh.msg_control = (caddr_t) buff;
2010 msgh.msg_controllen = sizeof (buff);
paul2dd8bb42004-07-23 15:13:48 +00002011
ajs5c333492005-02-23 15:43:01 +00002012 ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1);
2013 if (ret < 0)
paul718e3742002-12-13 20:15:29 +00002014 {
ajs5c333492005-02-23 15:43:01 +00002015 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
2016 return NULL;
2017 }
paul69310a62005-05-11 18:09:59 +00002018 if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
ajs5c333492005-02-23 15:43:01 +00002019 {
2020 zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
2021 "(ip header size is %u)",
2022 ret, (u_int)sizeof(iph));
paul718e3742002-12-13 20:15:29 +00002023 return NULL;
2024 }
paul18b12c32004-10-05 14:38:29 +00002025
ajs5c333492005-02-23 15:43:01 +00002026 /* Note that there should not be alignment problems with this assignment
2027 because this is at the beginning of the stream data buffer. */
2028 iph = (struct ip *) STREAM_DATA(ibuf);
2029 sockopt_iphdrincl_swab_systoh (iph);
paul18b12c32004-10-05 14:38:29 +00002030
ajs5c333492005-02-23 15:43:01 +00002031 ip_len = iph->ip_len;
paul6b333612004-10-11 10:11:25 +00002032
paul239aecc2003-12-08 10:34:54 +00002033#if !defined(GNU_LINUX) && (OpenBSD < 200311)
paul718e3742002-12-13 20:15:29 +00002034 /*
2035 * Kernel network code touches incoming IP header parameters,
2036 * before protocol specific processing.
2037 *
2038 * 1) Convert byteorder to host representation.
2039 * --> ip_len, ip_id, ip_off
2040 *
2041 * 2) Adjust ip_len to strip IP header size!
2042 * --> If user process receives entire IP packet via RAW
2043 * socket, it must consider adding IP header size to
2044 * the "ip_len" field of "ip" structure.
2045 *
2046 * For more details, see <netinet/ip_input.c>.
2047 */
ajs5c333492005-02-23 15:43:01 +00002048 ip_len = ip_len + (iph->ip_hl << 2);
paul718e3742002-12-13 20:15:29 +00002049#endif
2050
paul863082d2004-08-19 04:43:43 +00002051 ifindex = getsockopt_ifindex (AF_INET, &msgh);
paul718e3742002-12-13 20:15:29 +00002052
2053 *ifp = if_lookup_by_index (ifindex);
2054
2055 if (ret != ip_len)
2056 {
ajs5c333492005-02-23 15:43:01 +00002057 zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, "
2058 "but recvmsg returned %d", ip_len, ret);
paul718e3742002-12-13 20:15:29 +00002059 return NULL;
2060 }
2061
2062 return ibuf;
2063}
2064
paul4dadc292005-05-06 21:37:42 +00002065static struct ospf_interface *
pauld3f0d622004-05-05 15:27:15 +00002066ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
paul718e3742002-12-13 20:15:29 +00002067 struct ip *iph, struct ospf_header *ospfh)
2068{
2069 struct ospf_interface *rcv_oi;
paul718e3742002-12-13 20:15:29 +00002070 struct ospf_vl_data *vl_data;
2071 struct ospf_area *vl_area;
hasso52dc7ee2004-09-23 19:18:23 +00002072 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002073
2074 if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||
2075 !OSPF_IS_AREA_BACKBONE (ospfh))
pauld3f0d622004-05-05 15:27:15 +00002076 return NULL;
paul718e3742002-12-13 20:15:29 +00002077
pauld3f0d622004-05-05 15:27:15 +00002078 /* look for local OSPF interface matching the destination
2079 * to determine Area ID. We presume therefore the destination address
2080 * is unique, or at least (for "unnumbered" links), not used in other
2081 * areas
2082 */
2083 if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL,
2084 iph->ip_dst)) == NULL)
2085 return NULL;
paul718e3742002-12-13 20:15:29 +00002086
paul1eb8ef22005-04-07 07:30:20 +00002087 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
paul718e3742002-12-13 20:15:29 +00002088 {
paul020709f2003-04-04 02:44:16 +00002089 vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);
paul718e3742002-12-13 20:15:29 +00002090 if (!vl_area)
2091 continue;
2092
2093 if (OSPF_AREA_SAME (&vl_area, &rcv_oi->area) &&
2094 IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))
2095 {
2096 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002097 zlog_debug ("associating packet with %s",
paul718e3742002-12-13 20:15:29 +00002098 IF_NAME (vl_data->vl_oi));
2099 if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))
2100 {
2101 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002102 zlog_debug ("This VL is not up yet, sorry");
paul718e3742002-12-13 20:15:29 +00002103 return NULL;
2104 }
2105
2106 return vl_data->vl_oi;
2107 }
2108 }
2109
2110 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002111 zlog_debug ("couldn't find any VL to associate the packet with");
paul718e3742002-12-13 20:15:29 +00002112
pauld3f0d622004-05-05 15:27:15 +00002113 return NULL;
paul718e3742002-12-13 20:15:29 +00002114}
2115
paul4dadc292005-05-06 21:37:42 +00002116static inline int
paul718e3742002-12-13 20:15:29 +00002117ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
2118{
2119 /* Check match the Area ID of the receiving interface. */
2120 if (OSPF_AREA_SAME (&oi->area, &ospfh))
2121 return 1;
2122
2123 return 0;
2124}
2125
2126/* Unbound socket will accept any Raw IP packets if proto is matched.
2127 To prevent it, compare src IP address and i/f address with masking
2128 i/f network mask. */
paul4dadc292005-05-06 21:37:42 +00002129static int
paul718e3742002-12-13 20:15:29 +00002130ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
2131{
2132 struct in_addr mask, me, him;
2133
2134 if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
2135 oi->type == OSPF_IFTYPE_VIRTUALLINK)
2136 return 1;
2137
2138 masklen2ip (oi->address->prefixlen, &mask);
2139
2140 me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
2141 him.s_addr = ip_src.s_addr & mask.s_addr;
2142
2143 if (IPV4_ADDR_SAME (&me, &him))
2144 return 1;
2145
2146 return 0;
2147}
2148
paul4dadc292005-05-06 21:37:42 +00002149static int
paul718e3742002-12-13 20:15:29 +00002150ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
2151 struct ospf_header *ospfh)
2152{
2153 int ret = 0;
2154 struct crypt_key *ck;
2155
2156 switch (ntohs (ospfh->auth_type))
2157 {
2158 case OSPF_AUTH_NULL:
2159 ret = 1;
2160 break;
2161 case OSPF_AUTH_SIMPLE:
2162 if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
2163 ret = 1;
2164 else
2165 ret = 0;
2166 break;
2167 case OSPF_AUTH_CRYPTOGRAPHIC:
paul1eb8ef22005-04-07 07:30:20 +00002168 if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL)
paul718e3742002-12-13 20:15:29 +00002169 {
2170 ret = 0;
2171 break;
2172 }
2173
2174 /* This is very basic, the digest processing is elsewhere */
2175 if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE &&
2176 ospfh->u.crypt.key_id == ck->key_id &&
2177 ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))
2178 ret = 1;
2179 else
2180 ret = 0;
2181 break;
2182 default:
2183 ret = 0;
2184 break;
2185 }
2186
2187 return ret;
2188}
2189
paul4dadc292005-05-06 21:37:42 +00002190static int
paul718e3742002-12-13 20:15:29 +00002191ospf_check_sum (struct ospf_header *ospfh)
2192{
2193 u_int32_t ret;
2194 u_int16_t sum;
paul718e3742002-12-13 20:15:29 +00002195
2196 /* clear auth_data for checksum. */
2197 memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
2198
2199 /* keep checksum and clear. */
2200 sum = ospfh->checksum;
2201 memset (&ospfh->checksum, 0, sizeof (u_int16_t));
2202
2203 /* calculate checksum. */
2204 ret = in_cksum (ospfh, ntohs (ospfh->length));
2205
2206 if (ret != sum)
2207 {
2208 zlog_info ("ospf_check_sum(): checksum mismatch, my %X, his %X",
2209 ret, sum);
2210 return 0;
2211 }
2212
2213 return 1;
2214}
2215
2216/* OSPF Header verification. */
paul4dadc292005-05-06 21:37:42 +00002217static int
paul718e3742002-12-13 20:15:29 +00002218ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
2219 struct ip *iph, struct ospf_header *ospfh)
2220{
2221 /* check version. */
2222 if (ospfh->version != OSPF_VERSION)
2223 {
2224 zlog_warn ("interface %s: ospf_read version number mismatch.",
2225 IF_NAME (oi));
2226 return -1;
2227 }
2228
2229 /* Check Area ID. */
2230 if (!ospf_check_area_id (oi, ospfh))
2231 {
2232 zlog_warn ("interface %s: ospf_read invalid Area ID %s.",
2233 IF_NAME (oi), inet_ntoa (ospfh->area_id));
2234 return -1;
2235 }
2236
2237 /* Check network mask, Silently discarded. */
2238 if (! ospf_check_network_mask (oi, iph->ip_src))
2239 {
2240 zlog_warn ("interface %s: ospf_read network address is not same [%s]",
2241 IF_NAME (oi), inet_ntoa (iph->ip_src));
2242 return -1;
2243 }
2244
2245 /* Check authentication. */
2246 if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
2247 {
2248 zlog_warn ("interface %s: ospf_read authentication type mismatch.",
2249 IF_NAME (oi));
2250 return -1;
2251 }
2252
2253 if (! ospf_check_auth (oi, ibuf, ospfh))
2254 {
2255 zlog_warn ("interface %s: ospf_read authentication failed.",
2256 IF_NAME (oi));
2257 return -1;
2258 }
2259
2260 /* if check sum is invalid, packet is discarded. */
2261 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
2262 {
2263 if (! ospf_check_sum (ospfh))
2264 {
2265 zlog_warn ("interface %s: ospf_read packet checksum error %s",
2266 IF_NAME (oi), inet_ntoa (ospfh->router_id));
2267 return -1;
2268 }
2269 }
2270 else
2271 {
2272 if (ospfh->checksum != 0)
2273 return -1;
2274 if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)
2275 {
2276 zlog_warn ("interface %s: ospf_read md5 authentication failed.",
2277 IF_NAME (oi));
2278 return -1;
2279 }
2280 }
2281
2282 return 0;
2283}
2284
2285/* Starting point of packet process function. */
2286int
2287ospf_read (struct thread *thread)
2288{
2289 int ret;
2290 struct stream *ibuf;
paul68980082003-03-25 05:07:42 +00002291 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002292 struct ospf_interface *oi;
2293 struct ip *iph;
2294 struct ospf_header *ospfh;
2295 u_int16_t length;
2296 struct interface *ifp;
2297
2298 /* first of all get interface pointer. */
paul68980082003-03-25 05:07:42 +00002299 ospf = THREAD_ARG (thread);
ajs038163f2005-02-17 19:55:59 +00002300
2301 /* prepare for next packet. */
2302 ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
paul718e3742002-12-13 20:15:29 +00002303
2304 /* read OSPF packet. */
ajs5c333492005-02-23 15:43:01 +00002305 stream_reset(ospf->ibuf);
2306 if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
paul718e3742002-12-13 20:15:29 +00002307 return -1;
2308
ajs5c333492005-02-23 15:43:01 +00002309 /* Note that there should not be alignment problems with this assignment
2310 because this is at the beginning of the stream data buffer. */
paul06f953f2004-10-22 17:00:38 +00002311 iph = (struct ip *) STREAM_DATA (ibuf);
ajs5c333492005-02-23 15:43:01 +00002312 /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
paul06f953f2004-10-22 17:00:38 +00002313
paulac191232004-10-22 12:05:17 +00002314 if (ifp == NULL)
ajsb87f7722004-12-29 20:41:26 +00002315 /* Handle cases where the platform does not support retrieving the ifindex,
2316 and also platforms (such as Solaris 8) that claim to support ifindex
2317 retrieval but do not. */
paulac191232004-10-22 12:05:17 +00002318 ifp = if_lookup_address (iph->ip_src);
paulac191232004-10-22 12:05:17 +00002319
pauld3f0d622004-05-05 15:27:15 +00002320 if (ifp == NULL)
ajs5c333492005-02-23 15:43:01 +00002321 return 0;
paul718e3742002-12-13 20:15:29 +00002322
2323 /* IP Header dump. */
paul17b78d32003-02-13 22:04:01 +00002324 if (IS_DEBUG_OSPF_PACKET(0, RECV))
paul6b333612004-10-11 10:11:25 +00002325 ospf_ip_header_dump (iph);
paul7d95c612003-01-27 12:00:55 +00002326
paul718e3742002-12-13 20:15:29 +00002327 /* Self-originated packet should be discarded silently. */
paul68980082003-03-25 05:07:42 +00002328 if (ospf_if_lookup_by_local_addr (ospf, NULL, iph->ip_src))
paul718e3742002-12-13 20:15:29 +00002329 {
pauld3241812003-09-29 12:42:39 +00002330 if (IS_DEBUG_OSPF_PACKET (0, RECV))
2331 {
ajs2a42e282004-12-08 18:43:03 +00002332 zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
pauld3241812003-09-29 12:42:39 +00002333 inet_ntoa (iph->ip_src));
2334 }
paul718e3742002-12-13 20:15:29 +00002335 return 0;
2336 }
2337
2338 /* Adjust size to message length. */
paul9985f832005-02-09 15:51:56 +00002339 stream_forward_getp (ibuf, iph->ip_hl * 4);
paul718e3742002-12-13 20:15:29 +00002340
2341 /* Get ospf packet header. */
2342 ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
2343
2344 /* associate packet with ospf interface */
paul68980082003-03-25 05:07:42 +00002345 oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);
pauld3f0d622004-05-05 15:27:15 +00002346
2347 /* if no local ospf_interface,
2348 * or header area is backbone but ospf_interface is not
2349 * check for VLINK interface
2350 */
2351 if ( (oi == NULL) ||
2352 (OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id)
2353 && !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id))
2354 )
2355 {
2356 if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
2357 {
paulf9ad9372005-10-21 00:45:17 +00002358 zlog_debug ("Packet from [%s] received on link %s"
pauld3f0d622004-05-05 15:27:15 +00002359 " but no ospf_interface",
2360 inet_ntoa (iph->ip_src), ifp->name);
pauld3f0d622004-05-05 15:27:15 +00002361 return 0;
2362 }
2363 }
2364
2365 /* else it must be a local ospf interface, check it was received on
2366 * correct link
2367 */
2368 else if (oi->ifp != ifp)
paul718e3742002-12-13 20:15:29 +00002369 {
2370 zlog_warn ("Packet from [%s] received on wrong link %s",
pauld3241812003-09-29 12:42:39 +00002371 inet_ntoa (iph->ip_src), ifp->name);
paul718e3742002-12-13 20:15:29 +00002372 return 0;
2373 }
ajs847947f2005-02-02 18:38:48 +00002374 else if (oi->state == ISM_Down)
ajsc3eab872005-01-29 15:52:07 +00002375 {
ajsba6454e2005-02-08 15:37:30 +00002376 char buf[2][INET_ADDRSTRLEN];
2377 zlog_warn ("Ignoring packet from %s to %s received on interface that is "
ajs847947f2005-02-02 18:38:48 +00002378 "down [%s]; interface flags are %s",
ajsba6454e2005-02-08 15:37:30 +00002379 inet_ntop(AF_INET, &iph->ip_src, buf[0], sizeof(buf[0])),
2380 inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
2381 ifp->name, if_flag_dump(ifp->flags));
ajsba6454e2005-02-08 15:37:30 +00002382 /* Fix multicast memberships? */
2383 if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
2384 SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
2385 else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS))
2386 SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
2387 if (oi->multicast_memberships)
2388 ospf_if_set_multicast(oi);
ajsc3eab872005-01-29 15:52:07 +00002389 return 0;
2390 }
paul718e3742002-12-13 20:15:29 +00002391
2392 /*
2393 * If the received packet is destined for AllDRouters, the packet
2394 * should be accepted only if the received ospf interface state is
2395 * either DR or Backup -- endo.
2396 */
2397 if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)
2398 && (oi->state != ISM_DR && oi->state != ISM_Backup))
2399 {
ajsba6454e2005-02-08 15:37:30 +00002400 zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
paul718e3742002-12-13 20:15:29 +00002401 inet_ntoa (iph->ip_src), IF_NAME (oi),
2402 LOOKUP (ospf_ism_state_msg, oi->state));
ajsba6454e2005-02-08 15:37:30 +00002403 /* Try to fix multicast membership. */
2404 SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
2405 ospf_if_set_multicast(oi);
paul718e3742002-12-13 20:15:29 +00002406 return 0;
2407 }
2408
2409 /* Show debug receiving packet. */
paul1aa7b392003-04-08 08:51:58 +00002410 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
2411 {
paul718e3742002-12-13 20:15:29 +00002412 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
paul1aa7b392003-04-08 08:51:58 +00002413 {
ajs2a42e282004-12-08 18:43:03 +00002414 zlog_debug ("-----------------------------------------------------");
paul1aa7b392003-04-08 08:51:58 +00002415 ospf_packet_dump (ibuf);
2416 }
paul718e3742002-12-13 20:15:29 +00002417
ajs2a42e282004-12-08 18:43:03 +00002418 zlog_debug ("%s received from [%s] via [%s]",
paul1aa7b392003-04-08 08:51:58 +00002419 ospf_packet_type_str[ospfh->type],
2420 inet_ntoa (ospfh->router_id), IF_NAME (oi));
ajs2a42e282004-12-08 18:43:03 +00002421 zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
2422 zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
paul718e3742002-12-13 20:15:29 +00002423
2424 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
ajs2a42e282004-12-08 18:43:03 +00002425 zlog_debug ("-----------------------------------------------------");
paul1aa7b392003-04-08 08:51:58 +00002426 }
paul718e3742002-12-13 20:15:29 +00002427
2428 /* Some header verification. */
2429 ret = ospf_verify_header (ibuf, oi, iph, ospfh);
2430 if (ret < 0)
2431 {
pauld3241812003-09-29 12:42:39 +00002432 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
2433 {
ajs2a42e282004-12-08 18:43:03 +00002434 zlog_debug ("ospf_read[%s/%s]: Header check failed, "
pauld3241812003-09-29 12:42:39 +00002435 "dropping.",
2436 ospf_packet_type_str[ospfh->type],
2437 inet_ntoa (iph->ip_src));
2438 }
paul718e3742002-12-13 20:15:29 +00002439 return ret;
2440 }
2441
paul9985f832005-02-09 15:51:56 +00002442 stream_forward_getp (ibuf, OSPF_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00002443
2444 /* Adjust size to message length. */
2445 length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;
2446
2447 /* Read rest of the packet and call each sort of packet routine. */
2448 switch (ospfh->type)
2449 {
2450 case OSPF_MSG_HELLO:
2451 ospf_hello (iph, ospfh, ibuf, oi, length);
2452 break;
2453 case OSPF_MSG_DB_DESC:
2454 ospf_db_desc (iph, ospfh, ibuf, oi, length);
2455 break;
2456 case OSPF_MSG_LS_REQ:
2457 ospf_ls_req (iph, ospfh, ibuf, oi, length);
2458 break;
2459 case OSPF_MSG_LS_UPD:
2460 ospf_ls_upd (iph, ospfh, ibuf, oi, length);
2461 break;
2462 case OSPF_MSG_LS_ACK:
2463 ospf_ls_ack (iph, ospfh, ibuf, oi, length);
2464 break;
2465 default:
2466 zlog (NULL, LOG_WARNING,
2467 "interface %s: OSPF packet header type %d is illegal",
2468 IF_NAME (oi), ospfh->type);
2469 break;
2470 }
2471
paul718e3742002-12-13 20:15:29 +00002472 return 0;
2473}
2474
2475/* Make OSPF header. */
paul4dadc292005-05-06 21:37:42 +00002476static void
paul718e3742002-12-13 20:15:29 +00002477ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
2478{
2479 struct ospf_header *ospfh;
2480
2481 ospfh = (struct ospf_header *) STREAM_DATA (s);
2482
2483 ospfh->version = (u_char) OSPF_VERSION;
2484 ospfh->type = (u_char) type;
2485
paul68980082003-03-25 05:07:42 +00002486 ospfh->router_id = oi->ospf->router_id;
paul718e3742002-12-13 20:15:29 +00002487
2488 ospfh->checksum = 0;
2489 ospfh->area_id = oi->area->area_id;
2490 ospfh->auth_type = htons (ospf_auth_type (oi));
2491
2492 memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
2493
paul9985f832005-02-09 15:51:56 +00002494 stream_forward_endp (s, OSPF_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00002495}
2496
2497/* Make Authentication Data. */
paul4dadc292005-05-06 21:37:42 +00002498static int
paul718e3742002-12-13 20:15:29 +00002499ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
2500{
2501 struct crypt_key *ck;
2502
2503 switch (ospf_auth_type (oi))
2504 {
2505 case OSPF_AUTH_NULL:
2506 /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
2507 break;
2508 case OSPF_AUTH_SIMPLE:
2509 memcpy (ospfh->u.auth_data, OSPF_IF_PARAM (oi, auth_simple),
2510 OSPF_AUTH_SIMPLE_SIZE);
2511 break;
2512 case OSPF_AUTH_CRYPTOGRAPHIC:
2513 /* If key is not set, then set 0. */
2514 if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
2515 {
2516 ospfh->u.crypt.zero = 0;
2517 ospfh->u.crypt.key_id = 0;
2518 ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
2519 }
2520 else
2521 {
paul1eb8ef22005-04-07 07:30:20 +00002522 ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
paul718e3742002-12-13 20:15:29 +00002523 ospfh->u.crypt.zero = 0;
2524 ospfh->u.crypt.key_id = ck->key_id;
2525 ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
2526 }
2527 /* note: the seq is done in ospf_make_md5_digest() */
2528 break;
2529 default:
2530 /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
2531 break;
2532 }
2533
2534 return 0;
2535}
2536
2537/* Fill rest of OSPF header. */
paul4dadc292005-05-06 21:37:42 +00002538static void
paul718e3742002-12-13 20:15:29 +00002539ospf_fill_header (struct ospf_interface *oi,
2540 struct stream *s, u_int16_t length)
2541{
2542 struct ospf_header *ospfh;
2543
2544 ospfh = (struct ospf_header *) STREAM_DATA (s);
2545
2546 /* Fill length. */
2547 ospfh->length = htons (length);
2548
2549 /* Calculate checksum. */
2550 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
2551 ospfh->checksum = in_cksum (ospfh, length);
2552 else
2553 ospfh->checksum = 0;
2554
2555 /* Add Authentication Data. */
2556 ospf_make_auth (oi, ospfh);
2557}
2558
paul4dadc292005-05-06 21:37:42 +00002559static int
paul718e3742002-12-13 20:15:29 +00002560ospf_make_hello (struct ospf_interface *oi, struct stream *s)
2561{
2562 struct ospf_neighbor *nbr;
2563 struct route_node *rn;
2564 u_int16_t length = OSPF_HELLO_MIN_SIZE;
2565 struct in_addr mask;
2566 unsigned long p;
2567 int flag = 0;
2568
2569 /* Set netmask of interface. */
2570 if (oi->type != OSPF_IFTYPE_POINTOPOINT &&
2571 oi->type != OSPF_IFTYPE_VIRTUALLINK)
2572 masklen2ip (oi->address->prefixlen, &mask);
2573 else
2574 memset ((char *) &mask, 0, sizeof (struct in_addr));
2575 stream_put_ipv4 (s, mask.s_addr);
2576
2577 /* Set Hello Interval. */
paulf9ad9372005-10-21 00:45:17 +00002578 if (OSPF_IF_PARAM (oi, fast_hello) == 0)
2579 stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
2580 else
2581 stream_putw (s, 0); /* hello-interval of 0 for fast-hellos */
paul718e3742002-12-13 20:15:29 +00002582
2583 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002584 zlog_debug ("make_hello: options: %x, int: %s",
paul718e3742002-12-13 20:15:29 +00002585 OPTIONS(oi), IF_NAME (oi));
2586
2587 /* Set Options. */
2588 stream_putc (s, OPTIONS (oi));
2589
2590 /* Set Router Priority. */
2591 stream_putc (s, PRIORITY (oi));
2592
2593 /* Set Router Dead Interval. */
2594 stream_putl (s, OSPF_IF_PARAM (oi, v_wait));
2595
2596 /* Set Designated Router. */
2597 stream_put_ipv4 (s, DR (oi).s_addr);
2598
paul9985f832005-02-09 15:51:56 +00002599 p = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002600
2601 /* Set Backup Designated Router. */
2602 stream_put_ipv4 (s, BDR (oi).s_addr);
2603
2604 /* Add neighbor seen. */
2605 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
paul68980082003-03-25 05:07:42 +00002606 if ((nbr = rn->info))
2607 if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */
2608 if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */
2609 if (nbr->state != NSM_Down) /* This is myself for DR election. */
2610 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +00002611 {
2612 /* Check neighbor is sane? */
paul68980082003-03-25 05:07:42 +00002613 if (nbr->d_router.s_addr != 0
2614 && IPV4_ADDR_SAME (&nbr->d_router, &oi->address->u.prefix4)
2615 && IPV4_ADDR_SAME (&nbr->bd_router, &oi->address->u.prefix4))
2616 flag = 1;
paul718e3742002-12-13 20:15:29 +00002617
2618 stream_put_ipv4 (s, nbr->router_id.s_addr);
2619 length += 4;
2620 }
2621
2622 /* Let neighbor generate BackupSeen. */
2623 if (flag == 1)
paul3a9eb092005-02-08 11:29:41 +00002624 stream_putl_at (s, p, 0); /* ipv4 address, normally */
paul718e3742002-12-13 20:15:29 +00002625
2626 return length;
2627}
2628
paul4dadc292005-05-06 21:37:42 +00002629static int
paul718e3742002-12-13 20:15:29 +00002630ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
2631 struct stream *s)
2632{
2633 struct ospf_lsa *lsa;
2634 u_int16_t length = OSPF_DB_DESC_MIN_SIZE;
2635 u_char options;
2636 unsigned long pp;
2637 int i;
2638 struct ospf_lsdb *lsdb;
2639
2640 /* Set Interface MTU. */
2641 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
2642 stream_putw (s, 0);
2643 else
2644 stream_putw (s, oi->ifp->mtu);
2645
2646 /* Set Options. */
2647 options = OPTIONS (oi);
2648#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00002649 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00002650 {
2651 if (IS_SET_DD_I (nbr->dd_flags)
2652 || CHECK_FLAG (nbr->options, OSPF_OPTION_O))
2653 /*
2654 * Set O-bit in the outgoing DD packet for capablity negotiation,
2655 * if one of following case is applicable.
2656 *
2657 * 1) WaitTimer expiration event triggered the neighbor state to
2658 * change to Exstart, but no (valid) DD packet has received
2659 * from the neighbor yet.
2660 *
2661 * 2) At least one DD packet with O-bit on has received from the
2662 * neighbor.
2663 */
2664 SET_FLAG (options, OSPF_OPTION_O);
2665 }
2666#endif /* HAVE_OPAQUE_LSA */
2667 stream_putc (s, options);
2668
2669 /* Keep pointer to flags. */
paul9985f832005-02-09 15:51:56 +00002670 pp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002671 stream_putc (s, nbr->dd_flags);
2672
2673 /* Set DD Sequence Number. */
2674 stream_putl (s, nbr->dd_seqnum);
2675
2676 if (ospf_db_summary_isempty (nbr))
2677 {
2678 if (nbr->state >= NSM_Exchange)
2679 {
2680 nbr->dd_flags &= ~OSPF_DD_FLAG_M;
2681 /* Set DD flags again */
paul3a9eb092005-02-08 11:29:41 +00002682 stream_putc_at (s, pp, nbr->dd_flags);
paul718e3742002-12-13 20:15:29 +00002683 }
2684 return length;
2685 }
2686
2687 /* Describe LSA Header from Database Summary List. */
2688 lsdb = &nbr->db_sum;
2689
2690 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
2691 {
2692 struct route_table *table = lsdb->type[i].db;
2693 struct route_node *rn;
2694
2695 for (rn = route_top (table); rn; rn = route_next (rn))
2696 if ((lsa = rn->info) != NULL)
2697 {
2698#ifdef HAVE_OPAQUE_LSA
2699 if (IS_OPAQUE_LSA (lsa->data->type)
2700 && (! CHECK_FLAG (options, OSPF_OPTION_O)))
2701 {
2702 /* Suppress advertising opaque-informations. */
2703 /* Remove LSA from DB summary list. */
2704 ospf_lsdb_delete (lsdb, lsa);
2705 continue;
2706 }
2707#endif /* HAVE_OPAQUE_LSA */
2708
2709 if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
2710 {
2711 struct lsa_header *lsah;
2712 u_int16_t ls_age;
2713
2714 /* DD packet overflows interface MTU. */
gdt86f1fd92005-01-10 14:20:43 +00002715 if (length + OSPF_LSA_HEADER_SIZE > ospf_packet_max (oi))
paul718e3742002-12-13 20:15:29 +00002716 break;
2717
2718 /* Keep pointer to LS age. */
2719 lsah = (struct lsa_header *) (STREAM_DATA (s) +
paul9985f832005-02-09 15:51:56 +00002720 stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +00002721
2722 /* Proceed stream pointer. */
2723 stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
2724 length += OSPF_LSA_HEADER_SIZE;
2725
2726 /* Set LS age. */
2727 ls_age = LS_AGE (lsa);
2728 lsah->ls_age = htons (ls_age);
2729
2730 }
2731
2732 /* Remove LSA from DB summary list. */
2733 ospf_lsdb_delete (lsdb, lsa);
2734 }
2735 }
2736
2737 return length;
2738}
2739
paul4dadc292005-05-06 21:37:42 +00002740static int
paul718e3742002-12-13 20:15:29 +00002741ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
2742 unsigned long delta, struct ospf_neighbor *nbr,
2743 struct ospf_lsa *lsa)
2744{
2745 struct ospf_interface *oi;
2746
2747 oi = nbr->oi;
2748
2749 /* LS Request packet overflows interface MTU. */
gdt86f1fd92005-01-10 14:20:43 +00002750 if (*length + delta > ospf_packet_max(oi))
paul718e3742002-12-13 20:15:29 +00002751 return 0;
2752
2753 stream_putl (s, lsa->data->type);
2754 stream_put_ipv4 (s, lsa->data->id.s_addr);
2755 stream_put_ipv4 (s, lsa->data->adv_router.s_addr);
2756
2757 ospf_lsa_unlock (nbr->ls_req_last);
2758 nbr->ls_req_last = ospf_lsa_lock (lsa);
2759
2760 *length += 12;
2761 return 1;
2762}
2763
paul4dadc292005-05-06 21:37:42 +00002764static int
paul718e3742002-12-13 20:15:29 +00002765ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
2766{
2767 struct ospf_lsa *lsa;
2768 u_int16_t length = OSPF_LS_REQ_MIN_SIZE;
paul9985f832005-02-09 15:51:56 +00002769 unsigned long delta = stream_get_endp(s)+12;
paul718e3742002-12-13 20:15:29 +00002770 struct route_table *table;
2771 struct route_node *rn;
2772 int i;
2773 struct ospf_lsdb *lsdb;
2774
2775 lsdb = &nbr->ls_req;
2776
2777 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
2778 {
2779 table = lsdb->type[i].db;
2780 for (rn = route_top (table); rn; rn = route_next (rn))
2781 if ((lsa = (rn->info)) != NULL)
2782 if (ospf_make_ls_req_func (s, &length, delta, nbr, lsa) == 0)
2783 {
2784 route_unlock_node (rn);
2785 break;
2786 }
2787 }
2788 return length;
2789}
2790
paul4dadc292005-05-06 21:37:42 +00002791static int
paul718e3742002-12-13 20:15:29 +00002792ls_age_increment (struct ospf_lsa *lsa, int delay)
2793{
2794 int age;
2795
2796 age = IS_LSA_MAXAGE (lsa) ? OSPF_LSA_MAXAGE : LS_AGE (lsa) + delay;
2797
2798 return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
2799}
2800
paul4dadc292005-05-06 21:37:42 +00002801static int
hasso52dc7ee2004-09-23 19:18:23 +00002802ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s)
paul718e3742002-12-13 20:15:29 +00002803{
2804 struct ospf_lsa *lsa;
hasso52dc7ee2004-09-23 19:18:23 +00002805 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002806 u_int16_t length = OSPF_LS_UPD_MIN_SIZE;
gdt86f1fd92005-01-10 14:20:43 +00002807 unsigned int size_noauth;
paul9985f832005-02-09 15:51:56 +00002808 unsigned long delta = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002809 unsigned long pp;
2810 int count = 0;
2811
2812 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002813 zlog_debug ("ospf_make_ls_upd: Start");
paul59ea14c2004-07-14 20:50:36 +00002814
paul9985f832005-02-09 15:51:56 +00002815 pp = stream_get_endp (s);
2816 stream_forward_endp (s, OSPF_LS_UPD_MIN_SIZE);
paul718e3742002-12-13 20:15:29 +00002817
gdt86f1fd92005-01-10 14:20:43 +00002818 /* Calculate amount of packet usable for data. */
2819 size_noauth = stream_get_size(s) - ospf_packet_authspace(oi);
2820
paul718e3742002-12-13 20:15:29 +00002821 while ((node = listhead (update)) != NULL)
2822 {
2823 struct lsa_header *lsah;
2824 u_int16_t ls_age;
2825
2826 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002827 zlog_debug ("ospf_make_ls_upd: List Iteration");
paul718e3742002-12-13 20:15:29 +00002828
paul1eb8ef22005-04-07 07:30:20 +00002829 lsa = listgetdata (node);
2830
paul718e3742002-12-13 20:15:29 +00002831 assert (lsa->data);
2832
paul68b73392004-09-12 14:21:37 +00002833 /* Will it fit? */
gdt86f1fd92005-01-10 14:20:43 +00002834 if (length + delta + ntohs (lsa->data->length) > size_noauth)
paul59ea14c2004-07-14 20:50:36 +00002835 break;
2836
paul718e3742002-12-13 20:15:29 +00002837 /* Keep pointer to LS age. */
paul9985f832005-02-09 15:51:56 +00002838 lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +00002839
2840 /* Put LSA to Link State Request. */
2841 stream_put (s, lsa->data, ntohs (lsa->data->length));
2842
2843 /* Set LS age. */
2844 /* each hop must increment an lsa_age by transmit_delay
2845 of OSPF interface */
2846 ls_age = ls_age_increment (lsa, OSPF_IF_PARAM (oi, transmit_delay));
2847 lsah->ls_age = htons (ls_age);
2848
2849 length += ntohs (lsa->data->length);
2850 count++;
2851
2852 list_delete_node (update, node);
2853 ospf_lsa_unlock (lsa);
2854 }
2855
2856 /* Now set #LSAs. */
paul3a9eb092005-02-08 11:29:41 +00002857 stream_putl_at (s, pp, count);
paul718e3742002-12-13 20:15:29 +00002858
2859 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002860 zlog_debug ("ospf_make_ls_upd: Stop");
paul718e3742002-12-13 20:15:29 +00002861 return length;
2862}
2863
paul4dadc292005-05-06 21:37:42 +00002864static int
hasso52dc7ee2004-09-23 19:18:23 +00002865ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
paul718e3742002-12-13 20:15:29 +00002866{
hasso52dc7ee2004-09-23 19:18:23 +00002867 struct list *rm_list;
2868 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002869 u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
paul9985f832005-02-09 15:51:56 +00002870 unsigned long delta = stream_get_endp(s) + 24;
paul718e3742002-12-13 20:15:29 +00002871 struct ospf_lsa *lsa;
2872
2873 rm_list = list_new ();
2874
paul1eb8ef22005-04-07 07:30:20 +00002875 for (ALL_LIST_ELEMENTS_RO (ack, node, lsa))
paul718e3742002-12-13 20:15:29 +00002876 {
paul1eb8ef22005-04-07 07:30:20 +00002877 lsa = listgetdata (node);
paul718e3742002-12-13 20:15:29 +00002878 assert (lsa);
2879
gdt86f1fd92005-01-10 14:20:43 +00002880 if (length + delta > ospf_packet_max (oi))
paul718e3742002-12-13 20:15:29 +00002881 break;
2882
2883 stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
2884 length += OSPF_LSA_HEADER_SIZE;
2885
2886 listnode_add (rm_list, lsa);
2887 }
2888
2889 /* Remove LSA from LS-Ack list. */
paul1eb8ef22005-04-07 07:30:20 +00002890 /* XXX: this loop should be removed and the list move done in previous
2891 * loop
2892 */
2893 for (ALL_LIST_ELEMENTS_RO (rm_list, node, lsa))
paul718e3742002-12-13 20:15:29 +00002894 {
paul718e3742002-12-13 20:15:29 +00002895 listnode_delete (ack, lsa);
2896 ospf_lsa_unlock (lsa);
2897 }
2898
2899 list_delete (rm_list);
2900
2901 return length;
2902}
2903
2904void
2905ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
2906{
2907 struct ospf_packet *op;
2908 u_int16_t length = OSPF_HEADER_SIZE;
2909
2910 op = ospf_packet_new (oi->ifp->mtu);
2911
2912 /* Prepare OSPF common header. */
2913 ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
2914
2915 /* Prepare OSPF Hello body. */
2916 length += ospf_make_hello (oi, op->s);
2917
2918 /* Fill OSPF header. */
2919 ospf_fill_header (oi, op->s, length);
2920
2921 /* Set packet length. */
2922 op->length = length;
2923
2924 op->dst.s_addr = addr->s_addr;
2925
2926 /* Add packet to the interface output queue. */
2927 ospf_packet_add (oi, op);
2928
2929 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00002930 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00002931}
2932
paul4dadc292005-05-06 21:37:42 +00002933static void
paul718e3742002-12-13 20:15:29 +00002934ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
2935{
2936 struct ospf_interface *oi;
2937
2938 oi = nbr_nbma->oi;
2939 assert(oi);
2940
2941 /* If this is passive interface, do not send OSPF Hello. */
2942 if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
2943 return;
2944
2945 if (oi->type != OSPF_IFTYPE_NBMA)
2946 return;
2947
2948 if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
2949 return;
2950
2951 if (PRIORITY(oi) == 0)
2952 return;
2953
2954 if (nbr_nbma->priority == 0
2955 && oi->state != ISM_DR && oi->state != ISM_Backup)
2956 return;
2957
2958 ospf_hello_send_sub (oi, &nbr_nbma->addr);
2959}
2960
2961int
2962ospf_poll_timer (struct thread *thread)
2963{
2964 struct ospf_nbr_nbma *nbr_nbma;
2965
2966 nbr_nbma = THREAD_ARG (thread);
2967 nbr_nbma->t_poll = NULL;
2968
2969 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
ajs2a42e282004-12-08 18:43:03 +00002970 zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Poll timer expire)",
paul718e3742002-12-13 20:15:29 +00002971 IF_NAME (nbr_nbma->oi), inet_ntoa (nbr_nbma->addr));
2972
2973 ospf_poll_send (nbr_nbma);
2974
2975 if (nbr_nbma->v_poll > 0)
2976 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
2977 nbr_nbma->v_poll);
2978
2979 return 0;
2980}
2981
2982
2983int
2984ospf_hello_reply_timer (struct thread *thread)
2985{
2986 struct ospf_neighbor *nbr;
2987
2988 nbr = THREAD_ARG (thread);
2989 nbr->t_hello_reply = NULL;
2990
2991 assert (nbr->oi);
2992
2993 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
ajs2a42e282004-12-08 18:43:03 +00002994 zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
paul718e3742002-12-13 20:15:29 +00002995 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
2996
2997 ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
2998
2999 return 0;
3000}
3001
3002/* Send OSPF Hello. */
3003void
3004ospf_hello_send (struct ospf_interface *oi)
3005{
3006 struct ospf_packet *op;
3007 u_int16_t length = OSPF_HEADER_SIZE;
3008
3009 /* If this is passive interface, do not send OSPF Hello. */
3010 if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
3011 return;
3012
3013 op = ospf_packet_new (oi->ifp->mtu);
3014
3015 /* Prepare OSPF common header. */
3016 ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
3017
3018 /* Prepare OSPF Hello body. */
3019 length += ospf_make_hello (oi, op->s);
3020
3021 /* Fill OSPF header. */
3022 ospf_fill_header (oi, op->s, length);
3023
3024 /* Set packet length. */
3025 op->length = length;
3026
3027 if (oi->type == OSPF_IFTYPE_NBMA)
3028 {
3029 struct ospf_neighbor *nbr;
3030 struct route_node *rn;
3031
3032 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
3033 if ((nbr = rn->info))
3034 if (nbr != oi->nbr_self)
3035 if (nbr->state != NSM_Down)
3036 {
3037 /* RFC 2328 Section 9.5.1
3038 If the router is not eligible to become Designated Router,
3039 it must periodically send Hello Packets to both the
3040 Designated Router and the Backup Designated Router (if they
3041 exist). */
3042 if (PRIORITY(oi) == 0 &&
3043 IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
3044 IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
3045 continue;
3046
3047 /* If the router is eligible to become Designated Router, it
3048 must periodically send Hello Packets to all neighbors that
3049 are also eligible. In addition, if the router is itself the
3050 Designated Router or Backup Designated Router, it must also
3051 send periodic Hello Packets to all other neighbors. */
3052
3053 if (nbr->priority == 0 && oi->state == ISM_DROther)
3054 continue;
3055 /* if oi->state == Waiting, send hello to all neighbors */
3056 {
3057 struct ospf_packet *op_dup;
3058
3059 op_dup = ospf_packet_dup(op);
3060 op_dup->dst = nbr->address.u.prefix4;
3061
3062 /* Add packet to the interface output queue. */
3063 ospf_packet_add (oi, op_dup);
3064
paul020709f2003-04-04 02:44:16 +00003065 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003066 }
3067
3068 }
3069 ospf_packet_free (op);
3070 }
3071 else
3072 {
3073 /* Decide destination address. */
3074 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3075 op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
3076 else
3077 op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3078
3079 /* Add packet to the interface output queue. */
3080 ospf_packet_add (oi, op);
3081
3082 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003083 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003084 }
3085}
3086
3087/* Send OSPF Database Description. */
3088void
3089ospf_db_desc_send (struct ospf_neighbor *nbr)
3090{
3091 struct ospf_interface *oi;
3092 struct ospf_packet *op;
3093 u_int16_t length = OSPF_HEADER_SIZE;
3094
3095 oi = nbr->oi;
3096 op = ospf_packet_new (oi->ifp->mtu);
3097
3098 /* Prepare OSPF common header. */
3099 ospf_make_header (OSPF_MSG_DB_DESC, oi, op->s);
3100
3101 /* Prepare OSPF Database Description body. */
3102 length += ospf_make_db_desc (oi, nbr, op->s);
3103
3104 /* Fill OSPF header. */
3105 ospf_fill_header (oi, op->s, length);
3106
3107 /* Set packet length. */
3108 op->length = length;
3109
3110 /* Decide destination address. */
3111 op->dst = nbr->address.u.prefix4;
3112
3113 /* Add packet to the interface output queue. */
3114 ospf_packet_add (oi, op);
3115
3116 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003117 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003118
3119 /* Remove old DD packet, then copy new one and keep in neighbor structure. */
3120 if (nbr->last_send)
3121 ospf_packet_free (nbr->last_send);
3122 nbr->last_send = ospf_packet_dup (op);
3123 gettimeofday (&nbr->last_send_ts, NULL);
3124}
3125
3126/* Re-send Database Description. */
3127void
3128ospf_db_desc_resend (struct ospf_neighbor *nbr)
3129{
3130 struct ospf_interface *oi;
3131
3132 oi = nbr->oi;
3133
3134 /* Add packet to the interface output queue. */
3135 ospf_packet_add (oi, ospf_packet_dup (nbr->last_send));
3136
3137 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003138 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003139}
3140
3141/* Send Link State Request. */
3142void
3143ospf_ls_req_send (struct ospf_neighbor *nbr)
3144{
3145 struct ospf_interface *oi;
3146 struct ospf_packet *op;
3147 u_int16_t length = OSPF_HEADER_SIZE;
3148
3149 oi = nbr->oi;
3150 op = ospf_packet_new (oi->ifp->mtu);
3151
3152 /* Prepare OSPF common header. */
3153 ospf_make_header (OSPF_MSG_LS_REQ, oi, op->s);
3154
3155 /* Prepare OSPF Link State Request body. */
3156 length += ospf_make_ls_req (nbr, op->s);
3157 if (length == OSPF_HEADER_SIZE)
3158 {
3159 ospf_packet_free (op);
3160 return;
3161 }
3162
3163 /* Fill OSPF header. */
3164 ospf_fill_header (oi, op->s, length);
3165
3166 /* Set packet length. */
3167 op->length = length;
3168
3169 /* Decide destination address. */
3170 op->dst = nbr->address.u.prefix4;
3171
3172 /* Add packet to the interface output queue. */
3173 ospf_packet_add (oi, op);
3174
3175 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003176 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003177
3178 /* Add Link State Request Retransmission Timer. */
3179 OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
3180}
3181
3182/* Send Link State Update with an LSA. */
3183void
3184ospf_ls_upd_send_lsa (struct ospf_neighbor *nbr, struct ospf_lsa *lsa,
3185 int flag)
3186{
hasso52dc7ee2004-09-23 19:18:23 +00003187 struct list *update;
paul718e3742002-12-13 20:15:29 +00003188
3189 update = list_new ();
3190
3191 listnode_add (update, lsa);
3192 ospf_ls_upd_send (nbr, update, flag);
3193
3194 list_delete (update);
3195}
3196
paul68b73392004-09-12 14:21:37 +00003197/* Determine size for packet. Must be at least big enough to accomodate next
3198 * LSA on list, which may be bigger than MTU size.
3199 *
3200 * Return pointer to new ospf_packet
3201 * NULL if we can not allocate, eg because LSA is bigger than imposed limit
3202 * on packet sizes (in which case offending LSA is deleted from update list)
3203 */
3204static struct ospf_packet *
3205ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi)
3206{
3207 struct ospf_lsa *lsa;
3208 struct listnode *ln;
3209 size_t size;
3210 static char warned = 0;
3211
paul1eb8ef22005-04-07 07:30:20 +00003212 lsa = listgetdata((ln = listhead (update)));
paul68b73392004-09-12 14:21:37 +00003213 assert (lsa->data);
3214
3215 if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length))
3216 > ospf_packet_max (oi))
3217 {
3218 if (!warned)
3219 {
3220 zlog_warn ("ospf_ls_upd_packet_new: oversized LSA encountered!"
3221 "will need to fragment. Not optimal. Try divide up"
3222 " your network with areas. Use 'debug ospf packet send'"
3223 " to see details, or look at 'show ip ospf database ..'");
3224 warned = 1;
3225 }
3226
3227 if (IS_DEBUG_OSPF_PACKET (0, SEND))
ajs2a42e282004-12-08 18:43:03 +00003228 zlog_debug ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
paul68b73392004-09-12 14:21:37 +00003229 " %d bytes originated by %s, will be fragmented!",
3230 inet_ntoa (lsa->data->id),
3231 ntohs (lsa->data->length),
3232 inet_ntoa (lsa->data->adv_router));
3233
3234 /*
3235 * Allocate just enough to fit this LSA only, to avoid including other
3236 * LSAs in fragmented LSA Updates.
3237 */
3238 size = ntohs (lsa->data->length) + (oi->ifp->mtu - ospf_packet_max (oi))
3239 + OSPF_LS_UPD_MIN_SIZE;
3240 }
3241 else
3242 size = oi->ifp->mtu;
3243
gdt86f1fd92005-01-10 14:20:43 +00003244 /* XXX Should this be - sizeof(struct ip)?? -gdt */
paul68b73392004-09-12 14:21:37 +00003245 if (size > OSPF_MAX_PACKET_SIZE)
3246 {
3247 zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s too big,"
paul64511f32004-10-31 18:01:13 +00003248 " %d bytes, packet size %ld, dropping it completely."
paul68b73392004-09-12 14:21:37 +00003249 " OSPF routing is broken!",
paul37ccfa32004-10-31 11:24:51 +00003250 inet_ntoa (lsa->data->id), ntohs (lsa->data->length),
paul62d8e962004-11-02 20:26:45 +00003251 (long int) size);
paul68b73392004-09-12 14:21:37 +00003252 list_delete_node (update, ln);
3253 return NULL;
3254 }
3255
3256 return ospf_packet_new (size);
3257}
3258
paul718e3742002-12-13 20:15:29 +00003259static void
hasso52dc7ee2004-09-23 19:18:23 +00003260ospf_ls_upd_queue_send (struct ospf_interface *oi, struct list *update,
paul718e3742002-12-13 20:15:29 +00003261 struct in_addr addr)
3262{
3263 struct ospf_packet *op;
3264 u_int16_t length = OSPF_HEADER_SIZE;
3265
3266 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00003267 zlog_debug ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
paul68b73392004-09-12 14:21:37 +00003268
3269 op = ospf_ls_upd_packet_new (update, oi);
paul718e3742002-12-13 20:15:29 +00003270
3271 /* Prepare OSPF common header. */
3272 ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s);
3273
paul59ea14c2004-07-14 20:50:36 +00003274 /* Prepare OSPF Link State Update body.
3275 * Includes Type-7 translation.
3276 */
paul718e3742002-12-13 20:15:29 +00003277 length += ospf_make_ls_upd (oi, update, op->s);
3278
3279 /* Fill OSPF header. */
3280 ospf_fill_header (oi, op->s, length);
3281
3282 /* Set packet length. */
3283 op->length = length;
3284
3285 /* Decide destination address. */
3286 op->dst.s_addr = addr.s_addr;
3287
3288 /* Add packet to the interface output queue. */
3289 ospf_packet_add (oi, op);
3290
3291 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003292 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003293}
3294
3295static int
3296ospf_ls_upd_send_queue_event (struct thread *thread)
3297{
3298 struct ospf_interface *oi = THREAD_ARG(thread);
3299 struct route_node *rn;
paul736d3442003-07-24 23:22:57 +00003300 struct route_node *rnext;
paul59ea14c2004-07-14 20:50:36 +00003301 struct list *update;
paul68b73392004-09-12 14:21:37 +00003302 char again = 0;
paul718e3742002-12-13 20:15:29 +00003303
3304 oi->t_ls_upd_event = NULL;
3305
3306 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00003307 zlog_debug ("ospf_ls_upd_send_queue start");
paul718e3742002-12-13 20:15:29 +00003308
paul736d3442003-07-24 23:22:57 +00003309 for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
paul718e3742002-12-13 20:15:29 +00003310 {
paul736d3442003-07-24 23:22:57 +00003311 rnext = route_next (rn);
3312
paul718e3742002-12-13 20:15:29 +00003313 if (rn->info == NULL)
paul736d3442003-07-24 23:22:57 +00003314 continue;
paul68b73392004-09-12 14:21:37 +00003315
3316 update = (struct list *)rn->info;
paul718e3742002-12-13 20:15:29 +00003317
paul48fe13b2004-07-27 17:40:44 +00003318 ospf_ls_upd_queue_send (oi, update, rn->p.u.prefix4);
paul718e3742002-12-13 20:15:29 +00003319
paul68b73392004-09-12 14:21:37 +00003320 /* list might not be empty. */
paul59ea14c2004-07-14 20:50:36 +00003321 if (listcount(update) == 0)
3322 {
3323 list_delete (rn->info);
3324 rn->info = NULL;
3325 route_unlock_node (rn);
3326 }
3327 else
paul68b73392004-09-12 14:21:37 +00003328 again = 1;
paul59ea14c2004-07-14 20:50:36 +00003329 }
3330
3331 if (again != 0)
3332 {
3333 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00003334 zlog_debug ("ospf_ls_upd_send_queue: update lists not cleared,"
paul59ea14c2004-07-14 20:50:36 +00003335 " %d nodes to try again, raising new event", again);
3336 oi->t_ls_upd_event =
3337 thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
paul718e3742002-12-13 20:15:29 +00003338 }
3339
3340 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00003341 zlog_debug ("ospf_ls_upd_send_queue stop");
paul59ea14c2004-07-14 20:50:36 +00003342
paul718e3742002-12-13 20:15:29 +00003343 return 0;
3344}
3345
3346void
hasso52dc7ee2004-09-23 19:18:23 +00003347ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
paul718e3742002-12-13 20:15:29 +00003348{
3349 struct ospf_interface *oi;
paul1eb8ef22005-04-07 07:30:20 +00003350 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +00003351 struct prefix_ipv4 p;
3352 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +00003353 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003354
3355 oi = nbr->oi;
3356
3357 p.family = AF_INET;
3358 p.prefixlen = IPV4_MAX_BITLEN;
3359
3360 /* Decide destination address. */
3361 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3362 p.prefix = oi->vl_data->peer_addr;
3363 else if (flag == OSPF_SEND_PACKET_DIRECT)
3364 p.prefix = nbr->address.u.prefix4;
3365 else if (oi->state == ISM_DR || oi->state == ISM_Backup)
3366 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
3367 else if ((oi->type == OSPF_IFTYPE_POINTOPOINT)
3368 && (flag == OSPF_SEND_PACKET_INDIRECT))
3369 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul7afa08d2002-12-13 20:59:45 +00003370 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
3371 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul718e3742002-12-13 20:15:29 +00003372 else
3373 p.prefix.s_addr = htonl (OSPF_ALLDROUTERS);
3374
3375 if (oi->type == OSPF_IFTYPE_NBMA)
3376 {
3377 if (flag == OSPF_SEND_PACKET_INDIRECT)
3378 zlog_warn ("* LS-Update is directly sent on NBMA network.");
3379 if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr))
3380 zlog_warn ("* LS-Update is sent to myself.");
3381 }
3382
3383 rn = route_node_get (oi->ls_upd_queue, (struct prefix *) &p);
3384
3385 if (rn->info == NULL)
3386 rn->info = list_new ();
3387
paul1eb8ef22005-04-07 07:30:20 +00003388 for (ALL_LIST_ELEMENTS_RO (update, node, lsa))
3389 {
3390 ospf_lsa_lock (lsa);
3391 listnode_add (rn->info, lsa);
3392 }
paul718e3742002-12-13 20:15:29 +00003393
3394 if (oi->t_ls_upd_event == NULL)
3395 oi->t_ls_upd_event =
3396 thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
3397}
3398
3399static void
hasso52dc7ee2004-09-23 19:18:23 +00003400ospf_ls_ack_send_list (struct ospf_interface *oi, struct list *ack,
3401 struct in_addr dst)
paul718e3742002-12-13 20:15:29 +00003402{
3403 struct ospf_packet *op;
3404 u_int16_t length = OSPF_HEADER_SIZE;
3405
3406 op = ospf_packet_new (oi->ifp->mtu);
3407
3408 /* Prepare OSPF common header. */
3409 ospf_make_header (OSPF_MSG_LS_ACK, oi, op->s);
3410
3411 /* Prepare OSPF Link State Acknowledgment body. */
3412 length += ospf_make_ls_ack (oi, ack, op->s);
3413
3414 /* Fill OSPF header. */
3415 ospf_fill_header (oi, op->s, length);
3416
3417 /* Set packet length. */
3418 op->length = length;
3419
3420 /* Set destination IP address. */
3421 op->dst = dst;
3422
3423 /* Add packet to the interface output queue. */
3424 ospf_packet_add (oi, op);
3425
3426 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003427 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003428}
3429
3430static int
3431ospf_ls_ack_send_event (struct thread *thread)
3432{
3433 struct ospf_interface *oi = THREAD_ARG (thread);
3434
3435 oi->t_ls_ack_direct = NULL;
3436
3437 while (listcount (oi->ls_ack_direct.ls_ack))
3438 ospf_ls_ack_send_list (oi, oi->ls_ack_direct.ls_ack,
3439 oi->ls_ack_direct.dst);
3440
3441 return 0;
3442}
3443
3444void
3445ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
3446{
3447 struct ospf_interface *oi = nbr->oi;
3448
3449 if (listcount (oi->ls_ack_direct.ls_ack) == 0)
3450 oi->ls_ack_direct.dst = nbr->address.u.prefix4;
3451
3452 listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa));
3453
3454 if (oi->t_ls_ack_direct == NULL)
3455 oi->t_ls_ack_direct =
3456 thread_add_event (master, ospf_ls_ack_send_event, oi, 0);
3457}
3458
3459/* Send Link State Acknowledgment delayed. */
3460void
3461ospf_ls_ack_send_delayed (struct ospf_interface *oi)
3462{
3463 struct in_addr dst;
3464
3465 /* Decide destination address. */
3466 /* RFC2328 Section 13.5 On non-broadcast
3467 networks, delayed Link State Acknowledgment packets must be
3468 unicast separately over each adjacency (i.e., neighbor whose
3469 state is >= Exchange). */
3470 if (oi->type == OSPF_IFTYPE_NBMA)
3471 {
3472 struct ospf_neighbor *nbr;
3473 struct route_node *rn;
3474
3475 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
3476 if ((nbr = rn->info) != NULL)
3477 if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
3478 while (listcount (oi->ls_ack))
3479 ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4);
3480 return;
3481 }
3482 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3483 dst.s_addr = oi->vl_data->peer_addr.s_addr;
3484 else if (oi->state == ISM_DR || oi->state == ISM_Backup)
3485 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3486 else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
3487 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
gdt630e4802004-08-31 17:28:41 +00003488 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
3489 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul718e3742002-12-13 20:15:29 +00003490 else
3491 dst.s_addr = htonl (OSPF_ALLDROUTERS);
3492
3493 while (listcount (oi->ls_ack))
3494 ospf_ls_ack_send_list (oi, oi->ls_ack, dst);
3495}