blob: ed342e7fcd0ddec938505faee02154f3e8be0e13 [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)
Andrew J. Schorr08c83672006-09-25 13:26:14 +0000219 /* XXX size_t */
220 zlog_warn ("ospf_packet_dup stream %lu ospf_packet %u size mismatch",
221 (u_long)STREAM_SIZE(op->s), op->length);
paul30961a12002-12-13 20:56:48 +0000222
223 /* Reserve space for MD5 authentication that may be added later. */
224 new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
paulfa81b712005-02-19 01:19:20 +0000225 stream_copy (new->s, op->s);
paul718e3742002-12-13 20:15:29 +0000226
227 new->dst = op->dst;
228 new->length = op->length;
229
230 return new;
231}
232
gdt86f1fd92005-01-10 14:20:43 +0000233/* XXX inline */
paul4dadc292005-05-06 21:37:42 +0000234static inline unsigned int
gdt86f1fd92005-01-10 14:20:43 +0000235ospf_packet_authspace (struct ospf_interface *oi)
236{
237 int auth = 0;
238
239 if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
240 auth = OSPF_AUTH_MD5_SIZE;
241
242 return auth;
243}
244
paul4dadc292005-05-06 21:37:42 +0000245static unsigned int
paul718e3742002-12-13 20:15:29 +0000246ospf_packet_max (struct ospf_interface *oi)
247{
248 int max;
249
gdt86f1fd92005-01-10 14:20:43 +0000250 max = oi->ifp->mtu - ospf_packet_authspace(oi);
251
paul68b73392004-09-12 14:21:37 +0000252 max -= (OSPF_HEADER_SIZE + sizeof (struct ip));
paul718e3742002-12-13 20:15:29 +0000253
254 return max;
255}
256
257
paul4dadc292005-05-06 21:37:42 +0000258static int
paul718e3742002-12-13 20:15:29 +0000259ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
260 u_int16_t length)
261{
paul6c835672004-10-11 11:00:30 +0000262 unsigned char *ibuf;
vincentc1a03d42005-09-28 15:47:44 +0000263 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000264 unsigned char digest[OSPF_AUTH_MD5_SIZE];
265 unsigned char *pdigest;
266 struct crypt_key *ck;
267 struct ospf_header *ospfh;
268 struct ospf_neighbor *nbr;
269
270
271 ibuf = STREAM_PNT (s);
272 ospfh = (struct ospf_header *) ibuf;
273
274 /* Get pointer to the end of the packet. */
275 pdigest = ibuf + length;
276
277 /* Get secret key. */
278 ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
279 ospfh->u.crypt.key_id);
280 if (ck == NULL)
281 {
282 zlog_warn ("interface %s: ospf_check_md5 no key %d",
283 IF_NAME (oi), ospfh->u.crypt.key_id);
284 return 0;
285 }
286
287 /* check crypto seqnum. */
288 nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id);
289
290 if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum))
291 {
292 zlog_warn ("interface %s: ospf_check_md5 bad sequence %d (expect %d)",
293 IF_NAME (oi),
294 ntohl(ospfh->u.crypt.crypt_seqnum),
295 ntohl(nbr->crypt_seqnum));
296 return 0;
297 }
298
299 /* Generate a digest for the ospf packet - their digest + our digest. */
vincentc1a03d42005-09-28 15:47:44 +0000300 memset(&ctx, 0, sizeof(ctx));
301 MD5Init(&ctx);
302 MD5Update(&ctx, ibuf, length);
303 MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
304 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +0000305
306 /* compare the two */
307 if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
308 {
309 zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
310 IF_NAME (oi));
311 return 0;
312 }
313
314 /* save neighbor's crypt_seqnum */
315 if (nbr)
316 nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
317 return 1;
318}
319
320/* This function is called from ospf_write(), it will detect the
321 authentication scheme and if it is MD5, it will change the sequence
322 and update the MD5 digest. */
paul4dadc292005-05-06 21:37:42 +0000323static int
paul718e3742002-12-13 20:15:29 +0000324ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
325{
326 struct ospf_header *ospfh;
327 unsigned char digest[OSPF_AUTH_MD5_SIZE];
vincentc1a03d42005-09-28 15:47:44 +0000328 MD5_CTX ctx;
paul718e3742002-12-13 20:15:29 +0000329 void *ibuf;
paul9483e152002-12-13 20:55:25 +0000330 u_int32_t t;
paul718e3742002-12-13 20:15:29 +0000331 struct crypt_key *ck;
paul36238142005-10-11 04:12:54 +0000332 const u_int8_t *auth_key;
paul718e3742002-12-13 20:15:29 +0000333
334 ibuf = STREAM_DATA (op->s);
335 ospfh = (struct ospf_header *) ibuf;
336
337 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
338 return 0;
339
340 /* We do this here so when we dup a packet, we don't have to
Paul Jakma2518efd2006-08-27 06:49:29 +0000341 waste CPU rewriting other headers.
342
343 Note that quagga_time /deliberately/ is not used here */
paul9483e152002-12-13 20:55:25 +0000344 t = (time(NULL) & 0xFFFFFFFF);
paul818e56c2006-01-10 23:27:05 +0000345 if (t > oi->crypt_seqnum)
346 oi->crypt_seqnum = t;
347 else
348 oi->crypt_seqnum++;
349
paul9483e152002-12-13 20:55:25 +0000350 ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum);
paul718e3742002-12-13 20:15:29 +0000351
352 /* Get MD5 Authentication key from auth_key list. */
353 if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
paul36238142005-10-11 04:12:54 +0000354 auth_key = (const u_int8_t *) "";
paul718e3742002-12-13 20:15:29 +0000355 else
356 {
paul1eb8ef22005-04-07 07:30:20 +0000357 ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
paul4dadc292005-05-06 21:37:42 +0000358 auth_key = ck->auth_key;
paul718e3742002-12-13 20:15:29 +0000359 }
360
361 /* Generate a digest for the entire packet + our secret key. */
vincentc1a03d42005-09-28 15:47:44 +0000362 memset(&ctx, 0, sizeof(ctx));
363 MD5Init(&ctx);
364 MD5Update(&ctx, ibuf, ntohs (ospfh->length));
365 MD5Update(&ctx, auth_key, OSPF_AUTH_MD5_SIZE);
366 MD5Final(digest, &ctx);
paul718e3742002-12-13 20:15:29 +0000367
368 /* Append md5 digest to the end of the stream. */
paul718e3742002-12-13 20:15:29 +0000369 stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000370
371 /* We do *NOT* increment the OSPF header length. */
paul30961a12002-12-13 20:56:48 +0000372 op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
373
paul37163d62003-02-03 18:40:56 +0000374 if (stream_get_endp(op->s) != op->length)
Andrew J. Schorr08c83672006-09-25 13:26:14 +0000375 /* XXX size_t */
376 zlog_warn("ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u",
377 (u_long)stream_get_endp(op->s), op->length);
paul718e3742002-12-13 20:15:29 +0000378
379 return OSPF_AUTH_MD5_SIZE;
380}
381
382
paul4dadc292005-05-06 21:37:42 +0000383static int
paul718e3742002-12-13 20:15:29 +0000384ospf_ls_req_timer (struct thread *thread)
385{
386 struct ospf_neighbor *nbr;
387
388 nbr = THREAD_ARG (thread);
389 nbr->t_ls_req = NULL;
390
391 /* Send Link State Request. */
392 if (ospf_ls_request_count (nbr))
393 ospf_ls_req_send (nbr);
394
395 /* Set Link State Request retransmission timer. */
396 OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
397
398 return 0;
399}
400
401void
402ospf_ls_req_event (struct ospf_neighbor *nbr)
403{
404 if (nbr->t_ls_req)
405 {
406 thread_cancel (nbr->t_ls_req);
407 nbr->t_ls_req = NULL;
408 }
409 nbr->t_ls_req = thread_add_event (master, ospf_ls_req_timer, nbr, 0);
410}
411
412/* Cyclic timer function. Fist registered in ospf_nbr_new () in
413 ospf_neighbor.c */
414int
415ospf_ls_upd_timer (struct thread *thread)
416{
417 struct ospf_neighbor *nbr;
418
419 nbr = THREAD_ARG (thread);
420 nbr->t_ls_upd = NULL;
421
422 /* Send Link State Update. */
423 if (ospf_ls_retransmit_count (nbr) > 0)
424 {
hasso52dc7ee2004-09-23 19:18:23 +0000425 struct list *update;
paul718e3742002-12-13 20:15:29 +0000426 struct ospf_lsdb *lsdb;
427 int i;
paul718e3742002-12-13 20:15:29 +0000428 int retransmit_interval;
429
paul718e3742002-12-13 20:15:29 +0000430 retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval);
431
432 lsdb = &nbr->ls_rxmt;
433 update = list_new ();
434
435 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
436 {
437 struct route_table *table = lsdb->type[i].db;
438 struct route_node *rn;
439
440 for (rn = route_top (table); rn; rn = route_next (rn))
441 {
442 struct ospf_lsa *lsa;
443
444 if ((lsa = rn->info) != NULL)
445 /* Don't retransmit an LSA if we received it within
446 the last RxmtInterval seconds - this is to allow the
447 neighbour a chance to acknowledge the LSA as it may
448 have ben just received before the retransmit timer
449 fired. This is a small tweak to what is in the RFC,
450 but it will cut out out a lot of retransmit traffic
451 - MAG */
Paul Jakma2518efd2006-08-27 06:49:29 +0000452 if (tv_cmp (tv_sub (recent_relative_time (), lsa->tv_recv),
paul718e3742002-12-13 20:15:29 +0000453 int2tv (retransmit_interval)) >= 0)
454 listnode_add (update, rn->info);
455 }
456 }
457
458 if (listcount (update) > 0)
459 ospf_ls_upd_send (nbr, update, OSPF_SEND_PACKET_DIRECT);
460 list_delete (update);
461 }
462
463 /* Set LS Update retransmission timer. */
464 OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
465
466 return 0;
467}
468
469int
470ospf_ls_ack_timer (struct thread *thread)
471{
472 struct ospf_interface *oi;
473
474 oi = THREAD_ARG (thread);
475 oi->t_ls_ack = NULL;
476
477 /* Send Link State Acknowledgment. */
478 if (listcount (oi->ls_ack) > 0)
479 ospf_ls_ack_send_delayed (oi);
480
481 /* Set LS Ack timer. */
482 OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
483
484 return 0;
485}
486
paul0bfeca32004-09-24 08:07:54 +0000487#ifdef WANT_OSPF_WRITE_FRAGMENT
ajs5dcbdf82005-03-29 16:13:49 +0000488static void
paul6a99f832004-09-27 12:56:30 +0000489ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph,
paul62d8e962004-11-02 20:26:45 +0000490 struct msghdr *msg, unsigned int maxdatasize,
paul37ccfa32004-10-31 11:24:51 +0000491 unsigned int mtu, int flags, u_char type)
paul0bfeca32004-09-24 08:07:54 +0000492{
493#define OSPF_WRITE_FRAG_SHIFT 3
paul6a99f832004-09-27 12:56:30 +0000494 u_int16_t offset;
paul62d8e962004-11-02 20:26:45 +0000495 struct iovec *iovp;
paul6a99f832004-09-27 12:56:30 +0000496 int ret;
paul0bfeca32004-09-24 08:07:54 +0000497
498 assert ( op->length == stream_get_endp(op->s) );
paul62d8e962004-11-02 20:26:45 +0000499 assert (msg->msg_iovlen == 2);
paul0bfeca32004-09-24 08:07:54 +0000500
501 /* we can but try.
502 *
503 * SunOS, BSD and BSD derived kernels likely will clear ip_id, as
504 * well as the IP_MF flag, making this all quite pointless.
505 *
506 * However, for a system on which IP_MF is left alone, and ip_id left
507 * alone or else which sets same ip_id for each fragment this might
508 * work, eg linux.
509 *
510 * XXX-TODO: It would be much nicer to have the kernel's use their
511 * existing fragmentation support to do this for us. Bugs/RFEs need to
512 * be raised against the various kernels.
513 */
514
515 /* set More Frag */
516 iph->ip_off |= IP_MF;
517
518 /* ip frag offset is expressed in units of 8byte words */
519 offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT;
520
paul62d8e962004-11-02 20:26:45 +0000521 iovp = &msg->msg_iov[1];
522
paul0bfeca32004-09-24 08:07:54 +0000523 while ( (stream_get_endp(op->s) - stream_get_getp (op->s))
524 > maxdatasize )
525 {
526 /* data length of this frag is to next offset value */
paul62d8e962004-11-02 20:26:45 +0000527 iovp->iov_len = offset << OSPF_WRITE_FRAG_SHIFT;
528 iph->ip_len = iovp->iov_len + sizeof (struct ip);
paul6a99f832004-09-27 12:56:30 +0000529 assert (iph->ip_len <= mtu);
paul0bfeca32004-09-24 08:07:54 +0000530
paul18b12c32004-10-05 14:38:29 +0000531 sockopt_iphdrincl_swab_htosys (iph);
paul0bfeca32004-09-24 08:07:54 +0000532
paul6a99f832004-09-27 12:56:30 +0000533 ret = sendmsg (fd, msg, flags);
paul0bfeca32004-09-24 08:07:54 +0000534
paul18b12c32004-10-05 14:38:29 +0000535 sockopt_iphdrincl_swab_systoh (iph);
paul0bfeca32004-09-24 08:07:54 +0000536
537 if (ret < 0)
paul37ccfa32004-10-31 11:24:51 +0000538 zlog_warn ("*** ospf_write_frags: sendmsg failed to %s,"
ajs5dcbdf82005-03-29 16:13:49 +0000539 " id %d, off %d, len %d, mtu %u failed with %s",
540 inet_ntoa (iph->ip_dst),
541 iph->ip_id,
542 iph->ip_off,
543 iph->ip_len,
544 mtu,
545 safe_strerror (errno));
paul0bfeca32004-09-24 08:07:54 +0000546
paul37ccfa32004-10-31 11:24:51 +0000547 if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
548 {
ajs2a42e282004-12-08 18:43:03 +0000549 zlog_debug ("ospf_write_frags: sent id %d, off %d, len %d to %s\n",
paul37ccfa32004-10-31 11:24:51 +0000550 iph->ip_id, iph->ip_off, iph->ip_len,
551 inet_ntoa (iph->ip_dst));
552 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
553 {
ajs2a42e282004-12-08 18:43:03 +0000554 zlog_debug ("-----------------IP Header Dump----------------------");
paul37ccfa32004-10-31 11:24:51 +0000555 ospf_ip_header_dump (iph);
ajs2a42e282004-12-08 18:43:03 +0000556 zlog_debug ("-----------------------------------------------------");
paul37ccfa32004-10-31 11:24:51 +0000557 }
558 }
559
paul0bfeca32004-09-24 08:07:54 +0000560 iph->ip_off += offset;
paul9985f832005-02-09 15:51:56 +0000561 stream_forward_getp (op->s, iovp->iov_len);
paul62d8e962004-11-02 20:26:45 +0000562 iovp->iov_base = STREAM_PNT (op->s);
paul0bfeca32004-09-24 08:07:54 +0000563 }
564
565 /* setup for final fragment */
paul62d8e962004-11-02 20:26:45 +0000566 iovp->iov_len = stream_get_endp(op->s) - stream_get_getp (op->s);
567 iph->ip_len = iovp->iov_len + sizeof (struct ip);
paul0bfeca32004-09-24 08:07:54 +0000568 iph->ip_off &= (~IP_MF);
569}
570#endif /* WANT_OSPF_WRITE_FRAGMENT */
571
ajs5dcbdf82005-03-29 16:13:49 +0000572static int
paul718e3742002-12-13 20:15:29 +0000573ospf_write (struct thread *thread)
574{
paul68980082003-03-25 05:07:42 +0000575 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000576 struct ospf_interface *oi;
577 struct ospf_packet *op;
578 struct sockaddr_in sa_dst;
paul718e3742002-12-13 20:15:29 +0000579 struct ip iph;
580 struct msghdr msg;
paul62d8e962004-11-02 20:26:45 +0000581 struct iovec iov[2];
paul68980082003-03-25 05:07:42 +0000582 u_char type;
583 int ret;
584 int flags = 0;
hasso52dc7ee2004-09-23 19:18:23 +0000585 struct listnode *node;
paul0bfeca32004-09-24 08:07:54 +0000586#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000587 static u_int16_t ipid = 0;
paul0bfeca32004-09-24 08:07:54 +0000588#endif /* WANT_OSPF_WRITE_FRAGMENT */
paul6a99f832004-09-27 12:56:30 +0000589 u_int16_t maxdatasize;
paul68b73392004-09-12 14:21:37 +0000590#define OSPF_WRITE_IPHL_SHIFT 2
paul718e3742002-12-13 20:15:29 +0000591
paul68980082003-03-25 05:07:42 +0000592 ospf->t_write = NULL;
paul718e3742002-12-13 20:15:29 +0000593
paul68980082003-03-25 05:07:42 +0000594 node = listhead (ospf->oi_write_q);
paul718e3742002-12-13 20:15:29 +0000595 assert (node);
paul1eb8ef22005-04-07 07:30:20 +0000596 oi = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000597 assert (oi);
paul0bfeca32004-09-24 08:07:54 +0000598
599#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000600 /* seed ipid static with low order bits of time */
601 if (ipid == 0)
602 ipid = (time(NULL) & 0xffff);
paul0bfeca32004-09-24 08:07:54 +0000603#endif /* WANT_OSPF_WRITE_FRAGMENT */
604
Denis Ovsienkob7fe4142007-08-21 16:32:56 +0000605 /* convenience - max OSPF data per packet,
606 * and reliability - not more data, than our
607 * socket can accept
608 */
609 maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -
610 sizeof (struct ip);
paul68b73392004-09-12 14:21:37 +0000611
paul718e3742002-12-13 20:15:29 +0000612 /* Get one packet from queue. */
613 op = ospf_fifo_head (oi->obuf);
614 assert (op);
615 assert (op->length >= OSPF_HEADER_SIZE);
616
paul68980082003-03-25 05:07:42 +0000617 if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
618 || op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
paul68b73392004-09-12 14:21:37 +0000619 ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
620
paul718e3742002-12-13 20:15:29 +0000621 /* Rewrite the md5 signature & update the seq */
622 ospf_make_md5_digest (oi, op);
623
paul37ccfa32004-10-31 11:24:51 +0000624 /* Retrieve OSPF packet type. */
625 stream_set_getp (op->s, 1);
626 type = stream_getc (op->s);
627
paul68b73392004-09-12 14:21:37 +0000628 /* reset get pointer */
629 stream_set_getp (op->s, 0);
630
631 memset (&iph, 0, sizeof (struct ip));
paul718e3742002-12-13 20:15:29 +0000632 memset (&sa_dst, 0, sizeof (sa_dst));
paul68b73392004-09-12 14:21:37 +0000633
paul718e3742002-12-13 20:15:29 +0000634 sa_dst.sin_family = AF_INET;
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000635#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
paul718e3742002-12-13 20:15:29 +0000636 sa_dst.sin_len = sizeof(sa_dst);
Paul Jakma6f0e3f62007-05-10 02:38:51 +0000637#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
paul718e3742002-12-13 20:15:29 +0000638 sa_dst.sin_addr = op->dst;
639 sa_dst.sin_port = htons (0);
640
641 /* Set DONTROUTE flag if dst is unicast. */
642 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
643 if (!IN_MULTICAST (htonl (op->dst.s_addr)))
644 flags = MSG_DONTROUTE;
645
paul68b73392004-09-12 14:21:37 +0000646 iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
647 /* it'd be very strange for header to not be 4byte-word aligned but.. */
paul6c835672004-10-11 11:00:30 +0000648 if ( sizeof (struct ip)
649 > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
paul68b73392004-09-12 14:21:37 +0000650 iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
651
paul718e3742002-12-13 20:15:29 +0000652 iph.ip_v = IPVERSION;
paul68980082003-03-25 05:07:42 +0000653 iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
paul68b73392004-09-12 14:21:37 +0000654 iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
paul68b73392004-09-12 14:21:37 +0000655
paul0bfeca32004-09-24 08:07:54 +0000656#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000657 /* XXX-MT: not thread-safe at all..
658 * XXX: this presumes this is only programme sending OSPF packets
659 * otherwise, no guarantee ipid will be unique
660 */
661 iph.ip_id = ++ipid;
paul0bfeca32004-09-24 08:07:54 +0000662#endif /* WANT_OSPF_WRITE_FRAGMENT */
663
paul718e3742002-12-13 20:15:29 +0000664 iph.ip_off = 0;
665 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
666 iph.ip_ttl = OSPF_VL_IP_TTL;
667 else
668 iph.ip_ttl = OSPF_IP_TTL;
669 iph.ip_p = IPPROTO_OSPFIGP;
670 iph.ip_sum = 0;
671 iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
672 iph.ip_dst.s_addr = op->dst.s_addr;
673
674 memset (&msg, 0, sizeof (msg));
paul68defd62004-09-27 07:27:13 +0000675 msg.msg_name = (caddr_t) &sa_dst;
paul718e3742002-12-13 20:15:29 +0000676 msg.msg_namelen = sizeof (sa_dst);
677 msg.msg_iov = iov;
678 msg.msg_iovlen = 2;
679 iov[0].iov_base = (char*)&iph;
paul68b73392004-09-12 14:21:37 +0000680 iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
681 iov[1].iov_base = STREAM_PNT (op->s);
paul718e3742002-12-13 20:15:29 +0000682 iov[1].iov_len = op->length;
paul68b73392004-09-12 14:21:37 +0000683
684 /* Sadly we can not rely on kernels to fragment packets because of either
685 * IP_HDRINCL and/or multicast destination being set.
686 */
paul0bfeca32004-09-24 08:07:54 +0000687#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000688 if ( op->length > maxdatasize )
paul62d8e962004-11-02 20:26:45 +0000689 ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize,
690 oi->ifp->mtu, flags, type);
paul0bfeca32004-09-24 08:07:54 +0000691#endif /* WANT_OSPF_WRITE_FRAGMENT */
paul68b73392004-09-12 14:21:37 +0000692
693 /* send final fragment (could be first) */
paul18b12c32004-10-05 14:38:29 +0000694 sockopt_iphdrincl_swab_htosys (&iph);
paul68980082003-03-25 05:07:42 +0000695 ret = sendmsg (ospf->fd, &msg, flags);
paul6b333612004-10-11 10:11:25 +0000696 sockopt_iphdrincl_swab_systoh (&iph);
paul718e3742002-12-13 20:15:29 +0000697
698 if (ret < 0)
ajs083ee9d2005-02-09 15:35:50 +0000699 zlog_warn ("*** sendmsg in ospf_write failed to %s, "
ajs5dcbdf82005-03-29 16:13:49 +0000700 "id %d, off %d, len %d, interface %s, mtu %u: %s",
ajs083ee9d2005-02-09 15:35:50 +0000701 inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
ajs5dcbdf82005-03-29 16:13:49 +0000702 oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000703
paul718e3742002-12-13 20:15:29 +0000704 /* Show debug sending packet. */
705 if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
706 {
707 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
708 {
ajs2a42e282004-12-08 18:43:03 +0000709 zlog_debug ("-----------------------------------------------------");
paul37ccfa32004-10-31 11:24:51 +0000710 ospf_ip_header_dump (&iph);
paul718e3742002-12-13 20:15:29 +0000711 stream_set_getp (op->s, 0);
712 ospf_packet_dump (op->s);
713 }
714
ajs2a42e282004-12-08 18:43:03 +0000715 zlog_debug ("%s sent to [%s] via [%s].",
paul718e3742002-12-13 20:15:29 +0000716 ospf_packet_type_str[type], inet_ntoa (op->dst),
717 IF_NAME (oi));
718
719 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
ajs2a42e282004-12-08 18:43:03 +0000720 zlog_debug ("-----------------------------------------------------");
paul718e3742002-12-13 20:15:29 +0000721 }
722
723 /* Now delete packet from queue. */
724 ospf_packet_delete (oi);
725
726 if (ospf_fifo_head (oi->obuf) == NULL)
727 {
728 oi->on_write_q = 0;
paul68980082003-03-25 05:07:42 +0000729 list_delete_node (ospf->oi_write_q, node);
paul718e3742002-12-13 20:15:29 +0000730 }
731
732 /* If packets still remain in queue, call write thread. */
paul68980082003-03-25 05:07:42 +0000733 if (!list_isempty (ospf->oi_write_q))
734 ospf->t_write =
735 thread_add_write (master, ospf_write, ospf, ospf->fd);
paul718e3742002-12-13 20:15:29 +0000736
737 return 0;
738}
739
740/* OSPF Hello message read -- RFC2328 Section 10.5. */
paul4dadc292005-05-06 21:37:42 +0000741static void
paul718e3742002-12-13 20:15:29 +0000742ospf_hello (struct ip *iph, struct ospf_header *ospfh,
743 struct stream * s, struct ospf_interface *oi, int size)
744{
745 struct ospf_hello *hello;
746 struct ospf_neighbor *nbr;
paul718e3742002-12-13 20:15:29 +0000747 int old_state;
pauld3f0d622004-05-05 15:27:15 +0000748 struct prefix p;
paul718e3742002-12-13 20:15:29 +0000749
750 /* increment statistics. */
751 oi->hello_in++;
752
753 hello = (struct ospf_hello *) STREAM_PNT (s);
754
755 /* If Hello is myself, silently discard. */
paul68980082003-03-25 05:07:42 +0000756 if (IPV4_ADDR_SAME (&ospfh->router_id, &oi->ospf->router_id))
pauld3241812003-09-29 12:42:39 +0000757 {
758 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
759 {
ajs2a42e282004-12-08 18:43:03 +0000760 zlog_debug ("ospf_header[%s/%s]: selforiginated, "
pauld3241812003-09-29 12:42:39 +0000761 "dropping.",
762 ospf_packet_type_str[ospfh->type],
763 inet_ntoa (iph->ip_src));
764 }
765 return;
766 }
paul718e3742002-12-13 20:15:29 +0000767
768 /* If incoming interface is passive one, ignore Hello. */
Paul Jakma7ffa8fa2006-10-22 20:07:53 +0000769 if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE) {
ajsba6454e2005-02-08 15:37:30 +0000770 char buf[3][INET_ADDRSTRLEN];
paul6d452762005-11-03 11:15:44 +0000771 zlog_debug ("ignoring HELLO from router %s sent to %s, "
772 "received on a passive interface, %s",
773 inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])),
774 inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
775 inet_ntop(AF_INET, &oi->address->u.prefix4,
776 buf[2], sizeof(buf[2])));
ajsba6454e2005-02-08 15:37:30 +0000777 if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
778 {
779 /* Try to fix multicast membership. */
Paul Jakma429ac782006-06-15 18:40:49 +0000780 OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
ajsba6454e2005-02-08 15:37:30 +0000781 ospf_if_set_multicast(oi);
782 }
paul718e3742002-12-13 20:15:29 +0000783 return;
paulf2c80652002-12-13 21:44:27 +0000784 }
paul718e3742002-12-13 20:15:29 +0000785
786 /* get neighbor prefix. */
787 p.family = AF_INET;
788 p.prefixlen = ip_masklen (hello->network_mask);
789 p.u.prefix4 = iph->ip_src;
790
791 /* Compare network mask. */
792 /* Checking is ignored for Point-to-Point and Virtual link. */
793 if (oi->type != OSPF_IFTYPE_POINTOPOINT
794 && oi->type != OSPF_IFTYPE_VIRTUALLINK)
795 if (oi->address->prefixlen != p.prefixlen)
796 {
Andrew J. Schorr13cd3dc2006-07-11 01:50:30 +0000797 zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).",
798 inet_ntoa(ospfh->router_id), IF_NAME(oi),
799 (int)oi->address->prefixlen, (int)p.prefixlen);
paul718e3742002-12-13 20:15:29 +0000800 return;
801 }
802
paul718e3742002-12-13 20:15:29 +0000803 /* Compare Router Dead Interval. */
804 if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
805 {
Andrew J. Schorr08c83672006-09-25 13:26:14 +0000806 zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch "
807 "(expected %u, but received %u).",
808 inet_ntoa(ospfh->router_id),
809 OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval));
paul718e3742002-12-13 20:15:29 +0000810 return;
811 }
812
paulf9ad9372005-10-21 00:45:17 +0000813 /* Compare Hello Interval - ignored if fast-hellos are set. */
814 if (OSPF_IF_PARAM (oi, fast_hello) == 0)
815 {
816 if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
817 {
Andrew J. Schorr08c83672006-09-25 13:26:14 +0000818 zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch "
819 "(expected %u, but received %u).",
820 inet_ntoa(ospfh->router_id),
821 OSPF_IF_PARAM(oi, v_hello), ntohs(hello->hello_interval));
paulf9ad9372005-10-21 00:45:17 +0000822 return;
823 }
824 }
825
paul718e3742002-12-13 20:15:29 +0000826 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +0000827 zlog_debug ("Packet %s [Hello:RECV]: Options %s",
paul718e3742002-12-13 20:15:29 +0000828 inet_ntoa (ospfh->router_id),
829 ospf_options_dump (hello->options));
830
831 /* Compare options. */
832#define REJECT_IF_TBIT_ON 1 /* XXX */
833#ifdef REJECT_IF_TBIT_ON
834 if (CHECK_FLAG (hello->options, OSPF_OPTION_T))
835 {
836 /*
837 * This router does not support non-zero TOS.
838 * Drop this Hello packet not to establish neighbor relationship.
839 */
840 zlog_warn ("Packet %s [Hello:RECV]: T-bit on, drop it.",
841 inet_ntoa (ospfh->router_id));
842 return;
843 }
844#endif /* REJECT_IF_TBIT_ON */
845
846#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000847 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)
paul718e3742002-12-13 20:15:29 +0000848 && CHECK_FLAG (hello->options, OSPF_OPTION_O))
849 {
850 /*
851 * This router does know the correct usage of O-bit
852 * the bit should be set in DD packet only.
853 */
854 zlog_warn ("Packet %s [Hello:RECV]: O-bit abuse?",
855 inet_ntoa (ospfh->router_id));
856#ifdef STRICT_OBIT_USAGE_CHECK
857 return; /* Reject this packet. */
858#else /* STRICT_OBIT_USAGE_CHECK */
859 UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */
860#endif /* STRICT_OBIT_USAGE_CHECK */
861 }
862#endif /* HAVE_OPAQUE_LSA */
863
864 /* new for NSSA is to ensure that NP is on and E is off */
865
paul718e3742002-12-13 20:15:29 +0000866 if (oi->area->external_routing == OSPF_AREA_NSSA)
867 {
868 if (! (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_NP)
869 && CHECK_FLAG (hello->options, OSPF_OPTION_NP)
870 && ! CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E)
871 && ! CHECK_FLAG (hello->options, OSPF_OPTION_E)))
872 {
873 zlog_warn ("NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", inet_ntoa (ospfh->router_id), OPTIONS (oi), hello->options);
874 return;
875 }
876 if (IS_DEBUG_OSPF_NSSA)
ajs2a42e282004-12-08 18:43:03 +0000877 zlog_debug ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
paul718e3742002-12-13 20:15:29 +0000878 }
879 else
paul718e3742002-12-13 20:15:29 +0000880 /* The setting of the E-bit found in the Hello Packet's Options
881 field must match this area's ExternalRoutingCapability A
882 mismatch causes processing to stop and the packet to be
883 dropped. The setting of the rest of the bits in the Hello
884 Packet's Options field should be ignored. */
885 if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) !=
886 CHECK_FLAG (hello->options, OSPF_OPTION_E))
887 {
ajs3aa8d5f2004-12-11 18:00:06 +0000888 zlog_warn ("Packet %s [Hello:RECV]: my options: %x, his options %x",
889 inet_ntoa(ospfh->router_id), OPTIONS (oi), hello->options);
paul718e3742002-12-13 20:15:29 +0000890 return;
891 }
paul718e3742002-12-13 20:15:29 +0000892
pauld3f0d622004-05-05 15:27:15 +0000893 /* get neighbour struct */
894 nbr = ospf_nbr_get (oi, ospfh, iph, &p);
895
896 /* neighbour must be valid, ospf_nbr_get creates if none existed */
897 assert (nbr);
paul718e3742002-12-13 20:15:29 +0000898
899 old_state = nbr->state;
900
901 /* Add event to thread. */
902 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
903
904 /* RFC2328 Section 9.5.1
905 If the router is not eligible to become Designated Router,
906 (snip) It must also send an Hello Packet in reply to an
907 Hello Packet received from any eligible neighbor (other than
908 the current Designated Router and Backup Designated Router). */
909 if (oi->type == OSPF_IFTYPE_NBMA)
910 if (PRIORITY(oi) == 0 && hello->priority > 0
911 && IPV4_ADDR_CMP(&DR(oi), &iph->ip_src)
912 && IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src))
913 OSPF_NSM_TIMER_ON (nbr->t_hello_reply, ospf_hello_reply_timer,
914 OSPF_HELLO_REPLY_DELAY);
915
916 /* on NBMA network type, it happens to receive bidirectional Hello packet
917 without advance 1-Way Received event.
918 To avoid incorrect DR-seletion, raise 1-Way Received event.*/
919 if (oi->type == OSPF_IFTYPE_NBMA &&
920 (old_state == NSM_Down || old_state == NSM_Attempt))
921 {
922 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
923 nbr->priority = hello->priority;
924 nbr->d_router = hello->d_router;
925 nbr->bd_router = hello->bd_router;
926 return;
927 }
928
paul68980082003-03-25 05:07:42 +0000929 if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
paul718e3742002-12-13 20:15:29 +0000930 size - OSPF_HELLO_MIN_SIZE))
931 {
932 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
933 nbr->options |= hello->options;
934 }
935 else
936 {
937 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
938 /* Set neighbor information. */
939 nbr->priority = hello->priority;
940 nbr->d_router = hello->d_router;
941 nbr->bd_router = hello->bd_router;
942 return;
943 }
944
945 /* If neighbor itself declares DR and no BDR exists,
946 cause event BackupSeen */
947 if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router))
948 if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting)
949 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
950
951 /* neighbor itself declares BDR. */
952 if (oi->state == ISM_Waiting &&
953 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router))
954 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
955
956 /* had not previously. */
957 if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) &&
958 IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) ||
959 (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) &&
960 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router)))
961 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
962
963 /* had not previously. */
964 if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) &&
965 IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) ||
966 (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) &&
967 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router)))
968 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
969
970 /* Neighbor priority check. */
971 if (nbr->priority >= 0 && nbr->priority != hello->priority)
972 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
973
974 /* Set neighbor information. */
975 nbr->priority = hello->priority;
976 nbr->d_router = hello->d_router;
977 nbr->bd_router = hello->bd_router;
978}
979
980/* Save DD flags/options/Seqnum received. */
paul4dadc292005-05-06 21:37:42 +0000981static void
paul718e3742002-12-13 20:15:29 +0000982ospf_db_desc_save_current (struct ospf_neighbor *nbr,
983 struct ospf_db_desc *dd)
984{
985 nbr->last_recv.flags = dd->flags;
986 nbr->last_recv.options = dd->options;
987 nbr->last_recv.dd_seqnum = ntohl (dd->dd_seqnum);
988}
989
990/* Process rest of DD packet. */
991static void
992ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
993 struct ospf_neighbor *nbr, struct ospf_db_desc *dd,
994 u_int16_t size)
995{
996 struct ospf_lsa *new, *find;
997 struct lsa_header *lsah;
998
paul9985f832005-02-09 15:51:56 +0000999 stream_forward_getp (s, OSPF_DB_DESC_MIN_SIZE);
paul718e3742002-12-13 20:15:29 +00001000 for (size -= OSPF_DB_DESC_MIN_SIZE;
1001 size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE)
1002 {
1003 lsah = (struct lsa_header *) STREAM_PNT (s);
paul9985f832005-02-09 15:51:56 +00001004 stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00001005
1006 /* Unknown LS type. */
1007 if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
1008 {
ajsbec595a2004-11-30 22:38:43 +00001009 zlog_warn ("Packet [DD:RECV]: Unknown LS type %d.", lsah->type);
paul718e3742002-12-13 20:15:29 +00001010 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1011 return;
1012 }
1013
1014#ifdef HAVE_OPAQUE_LSA
1015 if (IS_OPAQUE_LSA (lsah->type)
1016 && ! CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1017 {
1018 zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
1019 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1020 return;
1021 }
1022#endif /* HAVE_OPAQUE_LSA */
1023
1024 switch (lsah->type)
1025 {
1026 case OSPF_AS_EXTERNAL_LSA:
1027#ifdef HAVE_OPAQUE_LSA
1028 case OSPF_OPAQUE_AS_LSA:
1029#endif /* HAVE_OPAQUE_LSA */
paul718e3742002-12-13 20:15:29 +00001030 /* Check for stub area. Reject if AS-External from stub but
1031 allow if from NSSA. */
1032 if (oi->area->external_routing == OSPF_AREA_STUB)
paul718e3742002-12-13 20:15:29 +00001033 {
1034 zlog_warn ("Packet [DD:RECV]: LSA[Type%d:%s] from %s area.",
1035 lsah->type, inet_ntoa (lsah->id),
1036 (oi->area->external_routing == OSPF_AREA_STUB) ?\
1037 "STUB" : "NSSA");
1038 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1039 return;
1040 }
1041 break;
1042 default:
1043 break;
1044 }
1045
1046 /* Create LS-request object. */
1047 new = ospf_ls_request_new (lsah);
1048
1049 /* Lookup received LSA, then add LS request list. */
1050 find = ospf_lsa_lookup_by_header (oi->area, lsah);
Paul Jakmaf0894cf2006-08-27 06:40:04 +00001051
1052 /* ospf_lsa_more_recent is fine with NULL pointers */
1053 switch (ospf_lsa_more_recent (find, new))
1054 {
1055 case -1:
1056 /* Neighbour has a more recent LSA, we must request it */
1057 ospf_ls_request_add (nbr, new);
1058 case 0:
1059 /* If we have a copy of this LSA, it's either less recent
1060 * and we're requesting it from neighbour (the case above), or
1061 * it's as recent and we both have same copy (this case).
1062 *
1063 * In neither of these two cases is there any point in
1064 * describing our copy of the LSA to the neighbour in a
1065 * DB-Summary packet, if we're still intending to do so.
1066 *
1067 * See: draft-ogier-ospf-dbex-opt-00.txt, describing the
1068 * backward compatible optimisation to OSPF DB Exchange /
1069 * DB Description process implemented here.
1070 */
1071 if (find)
1072 ospf_lsdb_delete (&nbr->db_sum, find);
1073 ospf_lsa_discard (new);
1074 break;
1075 default:
1076 /* We have the more recent copy, nothing specific to do:
1077 * - no need to request neighbours stale copy
1078 * - must leave DB summary list copy alone
1079 */
1080 if (IS_DEBUG_OSPF_EVENT)
1081 zlog_debug ("Packet [DD:RECV]: LSA received Type %d, "
1082 "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
1083 ospf_lsa_discard (new);
1084 }
paul718e3742002-12-13 20:15:29 +00001085 }
1086
1087 /* Master */
1088 if (IS_SET_DD_MS (nbr->dd_flags))
1089 {
1090 nbr->dd_seqnum++;
Paul Jakma8dd24ee2006-08-27 06:29:30 +00001091
1092 /* Both sides have no More, then we're done with Exchange */
paul718e3742002-12-13 20:15:29 +00001093 if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
1094 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
1095 else
paul718e3742002-12-13 20:15:29 +00001096 ospf_db_desc_send (nbr);
1097 }
1098 /* Slave */
1099 else
1100 {
1101 nbr->dd_seqnum = ntohl (dd->dd_seqnum);
1102
Paul Jakma8dd24ee2006-08-27 06:29:30 +00001103 /* Send DD packet in reply.
1104 *
1105 * Must be done to acknowledge the Master's DD, regardless of
1106 * whether we have more LSAs ourselves to describe.
1107 *
1108 * This function will clear the 'More' bit, if after this DD
1109 * we have no more LSAs to describe to the master..
1110 */
paul718e3742002-12-13 20:15:29 +00001111 ospf_db_desc_send (nbr);
Paul Jakma8dd24ee2006-08-27 06:29:30 +00001112
1113 /* Slave can raise ExchangeDone now, if master is also done */
1114 if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
1115 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
paul718e3742002-12-13 20:15:29 +00001116 }
Paul Jakma8dd24ee2006-08-27 06:29:30 +00001117
paul718e3742002-12-13 20:15:29 +00001118 /* Save received neighbor values from DD. */
1119 ospf_db_desc_save_current (nbr, dd);
1120}
1121
paul4dadc292005-05-06 21:37:42 +00001122static int
paul718e3742002-12-13 20:15:29 +00001123ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
1124{
1125 /* Is DD duplicated? */
1126 if (dd->options == nbr->last_recv.options &&
1127 dd->flags == nbr->last_recv.flags &&
1128 dd->dd_seqnum == htonl (nbr->last_recv.dd_seqnum))
1129 return 1;
1130
1131 return 0;
1132}
1133
1134/* OSPF Database Description message read -- RFC2328 Section 10.6. */
ajs3aa8d5f2004-12-11 18:00:06 +00001135static void
paul718e3742002-12-13 20:15:29 +00001136ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
1137 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1138{
1139 struct ospf_db_desc *dd;
1140 struct ospf_neighbor *nbr;
1141
1142 /* Increment statistics. */
1143 oi->db_desc_in++;
1144
1145 dd = (struct ospf_db_desc *) STREAM_PNT (s);
pauld363df22003-06-19 00:26:34 +00001146
pauld3f0d622004-05-05 15:27:15 +00001147 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001148 if (nbr == NULL)
1149 {
1150 zlog_warn ("Packet[DD]: Unknown Neighbor %s",
1151 inet_ntoa (ospfh->router_id));
1152 return;
1153 }
1154
1155 /* Check MTU. */
vincentba682532005-09-29 13:52:57 +00001156 if ((OSPF_IF_PARAM (oi, mtu_ignore) == 0) &&
1157 (ntohs (dd->mtu) > oi->ifp->mtu))
paul718e3742002-12-13 20:15:29 +00001158 {
ajs3aa8d5f2004-12-11 18:00:06 +00001159 zlog_warn ("Packet[DD]: Neighbor %s MTU %u is larger than [%s]'s MTU %u",
1160 inet_ntoa (nbr->router_id), ntohs (dd->mtu),
1161 IF_NAME (oi), oi->ifp->mtu);
paul718e3742002-12-13 20:15:29 +00001162 return;
1163 }
1164
pauld363df22003-06-19 00:26:34 +00001165 /*
1166 * XXX HACK by Hasso Tepper. Setting N/P bit in NSSA area DD packets is not
1167 * required. In fact at least JunOS sends DD packets with P bit clear.
1168 * Until proper solution is developped, this hack should help.
1169 *
1170 * Update: According to the RFCs, N bit is specified /only/ for Hello
1171 * options, unfortunately its use in DD options is not specified. Hence some
1172 * implementations follow E-bit semantics and set it in DD options, and some
1173 * treat it as unspecified and hence follow the directive "default for
1174 * options is clear", ie unset.
1175 *
1176 * Reset the flag, as ospfd follows E-bit semantics.
1177 */
1178 if ( (oi->area->external_routing == OSPF_AREA_NSSA)
1179 && (CHECK_FLAG (nbr->options, OSPF_OPTION_NP))
1180 && (!CHECK_FLAG (dd->options, OSPF_OPTION_NP)) )
1181 {
1182 if (IS_DEBUG_OSPF_EVENT)
ajs1210fa62004-12-03 16:43:24 +00001183 zlog_debug ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
pauld363df22003-06-19 00:26:34 +00001184 inet_ntoa (nbr->router_id) );
1185 SET_FLAG (dd->options, OSPF_OPTION_NP);
1186 }
pauld363df22003-06-19 00:26:34 +00001187
paul718e3742002-12-13 20:15:29 +00001188#ifdef REJECT_IF_TBIT_ON
1189 if (CHECK_FLAG (dd->options, OSPF_OPTION_T))
1190 {
1191 /*
1192 * In Hello protocol, optional capability must have checked
1193 * to prevent this T-bit enabled router be my neighbor.
1194 */
1195 zlog_warn ("Packet[DD]: Neighbor %s: T-bit on?", inet_ntoa (nbr->router_id));
1196 return;
1197 }
1198#endif /* REJECT_IF_TBIT_ON */
1199
1200#ifdef HAVE_OPAQUE_LSA
1201 if (CHECK_FLAG (dd->options, OSPF_OPTION_O)
paul68980082003-03-25 05:07:42 +00001202 && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00001203 {
1204 /*
1205 * This node is not configured to handle O-bit, for now.
1206 * Clear it to ignore unsupported capability proposed by neighbor.
1207 */
1208 UNSET_FLAG (dd->options, OSPF_OPTION_O);
1209 }
1210#endif /* HAVE_OPAQUE_LSA */
1211
1212 /* Process DD packet by neighbor status. */
1213 switch (nbr->state)
1214 {
1215 case NSM_Down:
1216 case NSM_Attempt:
1217 case NSM_TwoWay:
ajsbec595a2004-11-30 22:38:43 +00001218 zlog_warn ("Packet[DD]: Neighbor %s state is %s, packet discarded.",
ajs3aa8d5f2004-12-11 18:00:06 +00001219 inet_ntoa(nbr->router_id),
paul718e3742002-12-13 20:15:29 +00001220 LOOKUP (ospf_nsm_state_msg, nbr->state));
1221 break;
1222 case NSM_Init:
1223 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
1224 /* If the new state is ExStart, the processing of the current
1225 packet should then continue in this new state by falling
1226 through to case ExStart below. */
1227 if (nbr->state != NSM_ExStart)
1228 break;
1229 case NSM_ExStart:
1230 /* Initial DBD */
1231 if ((IS_SET_DD_ALL (dd->flags) == OSPF_DD_FLAG_ALL) &&
1232 (size == OSPF_DB_DESC_MIN_SIZE))
1233 {
paul68980082003-03-25 05:07:42 +00001234 if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0)
paul718e3742002-12-13 20:15:29 +00001235 {
1236 /* We're Slave---obey */
ajs17eaa722004-12-29 21:04:48 +00001237 zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Slave).",
ajs3aa8d5f2004-12-11 18:00:06 +00001238 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001239 nbr->dd_seqnum = ntohl (dd->dd_seqnum);
Paul Jakma8dd24ee2006-08-27 06:29:30 +00001240
1241 /* Reset I/MS */
1242 UNSET_FLAG (nbr->dd_flags, (OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I));
paul718e3742002-12-13 20:15:29 +00001243 }
1244 else
1245 {
1246 /* We're Master, ignore the initial DBD from Slave */
paul6d452762005-11-03 11:15:44 +00001247 zlog_info ("Packet[DD]: Neighbor %s: Initial DBD from Slave, "
ajs3aa8d5f2004-12-11 18:00:06 +00001248 "ignoring.", inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001249 break;
1250 }
1251 }
1252 /* Ack from the Slave */
1253 else if (!IS_SET_DD_MS (dd->flags) && !IS_SET_DD_I (dd->flags) &&
1254 ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&
paul68980082003-03-25 05:07:42 +00001255 IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0)
paul718e3742002-12-13 20:15:29 +00001256 {
ajs17eaa722004-12-29 21:04:48 +00001257 zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Master).",
ajs3aa8d5f2004-12-11 18:00:06 +00001258 inet_ntoa(nbr->router_id));
Paul Jakma8dd24ee2006-08-27 06:29:30 +00001259 /* Reset I, leaving MS */
1260 UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_I);
paul718e3742002-12-13 20:15:29 +00001261 }
1262 else
1263 {
ajs3aa8d5f2004-12-11 18:00:06 +00001264 zlog_warn ("Packet[DD]: Neighbor %s Negotiation fails.",
1265 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001266 break;
1267 }
1268
1269 /* This is where the real Options are saved */
1270 nbr->options = dd->options;
1271
1272#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00001273 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00001274 {
1275 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001276 zlog_debug ("Neighbor[%s] is %sOpaque-capable.",
paul718e3742002-12-13 20:15:29 +00001277 inet_ntoa (nbr->router_id),
1278 CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");
1279
1280 if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
1281 && IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
1282 {
paul6d452762005-11-03 11:15:44 +00001283 zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; "
1284 "Opaque-LSAs cannot be reliably advertised "
1285 "in this network.",
1286 inet_ntoa (nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001287 /* This situation is undesirable, but not a real error. */
1288 }
1289 }
1290#endif /* HAVE_OPAQUE_LSA */
1291
1292 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);
1293
1294 /* continue processing rest of packet. */
1295 ospf_db_desc_proc (s, oi, nbr, dd, size);
1296 break;
1297 case NSM_Exchange:
1298 if (ospf_db_desc_is_dup (dd, nbr))
1299 {
1300 if (IS_SET_DD_MS (nbr->dd_flags))
1301 /* Master: discard duplicated DD packet. */
paul6d452762005-11-03 11:15:44 +00001302 zlog_info ("Packet[DD] (Master): Neighbor %s packet duplicated.",
ajs3aa8d5f2004-12-11 18:00:06 +00001303 inet_ntoa (nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001304 else
1305 /* Slave: cause to retransmit the last Database Description. */
1306 {
paul6d452762005-11-03 11:15:44 +00001307 zlog_info ("Packet[DD] [Slave]: Neighbor %s packet duplicated.",
ajs3aa8d5f2004-12-11 18:00:06 +00001308 inet_ntoa (nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001309 ospf_db_desc_resend (nbr);
1310 }
1311 break;
1312 }
1313
1314 /* Otherwise DD packet should be checked. */
1315 /* Check Master/Slave bit mismatch */
1316 if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))
1317 {
ajs3aa8d5f2004-12-11 18:00:06 +00001318 zlog_warn ("Packet[DD]: Neighbor %s MS-bit mismatch.",
1319 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001320 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1321 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001322 zlog_debug ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
ajs3aa8d5f2004-12-11 18:00:06 +00001323 dd->flags, nbr->dd_flags);
paul718e3742002-12-13 20:15:29 +00001324 break;
1325 }
1326
1327 /* Check initialize bit is set. */
1328 if (IS_SET_DD_I (dd->flags))
1329 {
paul6d452762005-11-03 11:15:44 +00001330 zlog_info ("Packet[DD]: Neighbor %s I-bit set.",
ajs3aa8d5f2004-12-11 18:00:06 +00001331 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001332 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1333 break;
1334 }
1335
1336 /* Check DD Options. */
1337 if (dd->options != nbr->options)
1338 {
1339#ifdef ORIGINAL_CODING
1340 /* Save the new options for debugging */
1341 nbr->options = dd->options;
1342#endif /* ORIGINAL_CODING */
ajs3aa8d5f2004-12-11 18:00:06 +00001343 zlog_warn ("Packet[DD]: Neighbor %s options mismatch.",
1344 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001345 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1346 break;
1347 }
1348
1349 /* Check DD sequence number. */
1350 if ((IS_SET_DD_MS (nbr->dd_flags) &&
1351 ntohl (dd->dd_seqnum) != nbr->dd_seqnum) ||
1352 (!IS_SET_DD_MS (nbr->dd_flags) &&
1353 ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))
1354 {
ajs3aa8d5f2004-12-11 18:00:06 +00001355 zlog_warn ("Packet[DD]: Neighbor %s sequence number mismatch.",
1356 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001357 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1358 break;
1359 }
1360
1361 /* Continue processing rest of packet. */
1362 ospf_db_desc_proc (s, oi, nbr, dd, size);
1363 break;
1364 case NSM_Loading:
1365 case NSM_Full:
1366 if (ospf_db_desc_is_dup (dd, nbr))
1367 {
1368 if (IS_SET_DD_MS (nbr->dd_flags))
1369 {
1370 /* Master should discard duplicate DD packet. */
paul6d452762005-11-03 11:15:44 +00001371 zlog_info ("Packet[DD]: Neighbor %s duplicated, "
1372 "packet discarded.",
ajs3aa8d5f2004-12-11 18:00:06 +00001373 inet_ntoa(nbr->router_id));
paul718e3742002-12-13 20:15:29 +00001374 break;
1375 }
1376 else
1377 {
1378 struct timeval t, now;
Paul Jakma2518efd2006-08-27 06:49:29 +00001379 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
paul718e3742002-12-13 20:15:29 +00001380 t = tv_sub (now, nbr->last_send_ts);
1381 if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
1382 {
1383 /* In states Loading and Full the slave must resend
1384 its last Database Description packet in response to
1385 duplicate Database Description packets received
1386 from the master. For this reason the slave must
1387 wait RouterDeadInterval seconds before freeing the
1388 last Database Description packet. Reception of a
1389 Database Description packet from the master after
1390 this interval will generate a SeqNumberMismatch
1391 neighbor event. RFC2328 Section 10.8 */
1392 ospf_db_desc_resend (nbr);
1393 break;
1394 }
1395 }
1396 }
1397
1398 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1399 break;
1400 default:
ajs3aa8d5f2004-12-11 18:00:06 +00001401 zlog_warn ("Packet[DD]: Neighbor %s NSM illegal status %u.",
1402 inet_ntoa(nbr->router_id), nbr->state);
paul718e3742002-12-13 20:15:29 +00001403 break;
1404 }
1405}
1406
1407#define OSPF_LSA_KEY_SIZE 12 /* type(4) + id(4) + ar(4) */
1408
1409/* OSPF Link State Request Read -- RFC2328 Section 10.7. */
paul4dadc292005-05-06 21:37:42 +00001410static void
paul718e3742002-12-13 20:15:29 +00001411ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
1412 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1413{
1414 struct ospf_neighbor *nbr;
1415 u_int32_t ls_type;
1416 struct in_addr ls_id;
1417 struct in_addr adv_router;
1418 struct ospf_lsa *find;
hasso52dc7ee2004-09-23 19:18:23 +00001419 struct list *ls_upd;
paul6c835672004-10-11 11:00:30 +00001420 unsigned int length;
paul718e3742002-12-13 20:15:29 +00001421
1422 /* Increment statistics. */
1423 oi->ls_req_in++;
1424
pauld3f0d622004-05-05 15:27:15 +00001425 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001426 if (nbr == NULL)
1427 {
1428 zlog_warn ("Link State Request: Unknown Neighbor %s.",
1429 inet_ntoa (ospfh->router_id));
1430 return;
1431 }
1432
1433 /* Neighbor State should be Exchange or later. */
1434 if (nbr->state != NSM_Exchange &&
1435 nbr->state != NSM_Loading &&
1436 nbr->state != NSM_Full)
1437 {
ajsbec595a2004-11-30 22:38:43 +00001438 zlog_warn ("Link State Request received from %s: "
1439 "Neighbor state is %s, packet discarded.",
1440 inet_ntoa (ospfh->router_id),
paul718e3742002-12-13 20:15:29 +00001441 LOOKUP (ospf_nsm_state_msg, nbr->state));
1442 return;
1443 }
1444
1445 /* Send Link State Update for ALL requested LSAs. */
1446 ls_upd = list_new ();
1447 length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
1448
1449 while (size >= OSPF_LSA_KEY_SIZE)
1450 {
1451 /* Get one slice of Link State Request. */
1452 ls_type = stream_getl (s);
1453 ls_id.s_addr = stream_get_ipv4 (s);
1454 adv_router.s_addr = stream_get_ipv4 (s);
1455
1456 /* Verify LSA type. */
1457 if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA)
1458 {
1459 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
1460 list_delete (ls_upd);
1461 return;
1462 }
1463
1464 /* Search proper LSA in LSDB. */
1465 find = ospf_lsa_lookup (oi->area, ls_type, ls_id, adv_router);
1466 if (find == NULL)
1467 {
1468 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
1469 list_delete (ls_upd);
1470 return;
1471 }
1472
gdt86f1fd92005-01-10 14:20:43 +00001473 /* Packet overflows MTU size, send immediately. */
1474 if (length + ntohs (find->data->length) > ospf_packet_max (oi))
paul718e3742002-12-13 20:15:29 +00001475 {
1476 if (oi->type == OSPF_IFTYPE_NBMA)
1477 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
1478 else
1479 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
1480
1481 /* Only remove list contents. Keep ls_upd. */
1482 list_delete_all_node (ls_upd);
1483
1484 length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
1485 }
1486
1487 /* Append LSA to update list. */
1488 listnode_add (ls_upd, find);
1489 length += ntohs (find->data->length);
1490
1491 size -= OSPF_LSA_KEY_SIZE;
1492 }
1493
1494 /* Send rest of Link State Update. */
1495 if (listcount (ls_upd) > 0)
1496 {
1497 if (oi->type == OSPF_IFTYPE_NBMA)
1498 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
1499 else
1500 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
1501
1502 list_delete (ls_upd);
1503 }
1504 else
1505 list_free (ls_upd);
1506}
1507
1508/* Get the list of LSAs from Link State Update packet.
1509 And process some validation -- RFC2328 Section 13. (1)-(2). */
hasso52dc7ee2004-09-23 19:18:23 +00001510static struct list *
paul718e3742002-12-13 20:15:29 +00001511ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
1512 struct ospf_interface *oi, size_t size)
1513{
1514 u_int16_t count, sum;
1515 u_int32_t length;
1516 struct lsa_header *lsah;
1517 struct ospf_lsa *lsa;
hasso52dc7ee2004-09-23 19:18:23 +00001518 struct list *lsas;
paul718e3742002-12-13 20:15:29 +00001519
1520 lsas = list_new ();
1521
1522 count = stream_getl (s);
1523 size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */
1524
1525 for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;
paul9985f832005-02-09 15:51:56 +00001526 size -= length, stream_forward_getp (s, length), count--)
paul718e3742002-12-13 20:15:29 +00001527 {
1528 lsah = (struct lsa_header *) STREAM_PNT (s);
1529 length = ntohs (lsah->length);
1530
1531 if (length > size)
1532 {
1533 zlog_warn ("Link State Update: LSA length exceeds packet size.");
1534 break;
1535 }
1536
1537 /* Validate the LSA's LS checksum. */
1538 sum = lsah->checksum;
1539 if (sum != ospf_lsa_checksum (lsah))
1540 {
1541 zlog_warn ("Link State Update: LSA checksum error %x, %x.",
1542 sum, lsah->checksum);
1543 continue;
1544 }
1545
1546 /* Examine the LSA's LS type. */
1547 if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
1548 {
1549 zlog_warn ("Link State Update: Unknown LS type %d", lsah->type);
1550 continue;
1551 }
1552
1553 /*
1554 * What if the received LSA's age is greater than MaxAge?
1555 * Treat it as a MaxAge case -- endo.
1556 */
1557 if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)
1558 lsah->ls_age = htons (OSPF_LSA_MAXAGE);
1559
1560#ifdef HAVE_OPAQUE_LSA
1561 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1562 {
1563#ifdef STRICT_OBIT_USAGE_CHECK
1564 if ((IS_OPAQUE_LSA(lsah->type) &&
1565 ! CHECK_FLAG (lsah->options, OSPF_OPTION_O))
1566 || (! IS_OPAQUE_LSA(lsah->type) &&
1567 CHECK_FLAG (lsah->options, OSPF_OPTION_O)))
1568 {
1569 /*
1570 * This neighbor must know the exact usage of O-bit;
1571 * the bit will be set in Type-9,10,11 LSAs only.
1572 */
1573 zlog_warn ("LSA[Type%d:%s]: O-bit abuse?", lsah->type, inet_ntoa (lsah->id));
1574 continue;
1575 }
1576#endif /* STRICT_OBIT_USAGE_CHECK */
1577
1578 /* Do not take in AS External Opaque-LSAs if we are a stub. */
1579 if (lsah->type == OSPF_OPAQUE_AS_LSA
1580 && nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
1581 {
1582 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001583 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 +00001584 continue;
1585 }
1586 }
1587 else if (IS_OPAQUE_LSA(lsah->type))
1588 {
1589 zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
1590 continue;
1591 }
1592#endif /* HAVE_OPAQUE_LSA */
1593
1594 /* Create OSPF LSA instance. */
1595 lsa = ospf_lsa_new ();
1596
1597 /* We may wish to put some error checking if type NSSA comes in
1598 and area not in NSSA mode */
1599 switch (lsah->type)
1600 {
1601 case OSPF_AS_EXTERNAL_LSA:
1602#ifdef HAVE_OPAQUE_LSA
1603 case OSPF_OPAQUE_AS_LSA:
1604 lsa->area = NULL;
1605 break;
1606 case OSPF_OPAQUE_LINK_LSA:
1607 lsa->oi = oi; /* Remember incoming interface for flooding control. */
1608 /* Fallthrough */
1609#endif /* HAVE_OPAQUE_LSA */
1610 default:
1611 lsa->area = oi->area;
1612 break;
1613 }
1614
1615 lsa->data = ospf_lsa_data_new (length);
1616 memcpy (lsa->data, lsah, length);
1617
1618 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001619 zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update",
paul718e3742002-12-13 20:15:29 +00001620 lsa->data->type, inet_ntoa (lsa->data->id), lsa);
1621 listnode_add (lsas, lsa);
1622 }
1623
1624 return lsas;
1625}
1626
1627/* Cleanup Update list. */
paul4dadc292005-05-06 21:37:42 +00001628static void
hasso52dc7ee2004-09-23 19:18:23 +00001629ospf_upd_list_clean (struct list *lsas)
paul718e3742002-12-13 20:15:29 +00001630{
paul1eb8ef22005-04-07 07:30:20 +00001631 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001632 struct ospf_lsa *lsa;
1633
paul1eb8ef22005-04-07 07:30:20 +00001634 for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
1635 ospf_lsa_discard (lsa);
paul718e3742002-12-13 20:15:29 +00001636
1637 list_delete (lsas);
1638}
1639
1640/* OSPF Link State Update message read -- RFC2328 Section 13. */
paul4dadc292005-05-06 21:37:42 +00001641static void
paul718e3742002-12-13 20:15:29 +00001642ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
1643 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1644{
1645 struct ospf_neighbor *nbr;
hasso52dc7ee2004-09-23 19:18:23 +00001646 struct list *lsas;
paul1eb8ef22005-04-07 07:30:20 +00001647 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001648 struct ospf_lsa *lsa = NULL;
1649 /* unsigned long ls_req_found = 0; */
1650
1651 /* Dis-assemble the stream, update each entry, re-encapsulate for flooding */
1652
1653 /* Increment statistics. */
1654 oi->ls_upd_in++;
1655
1656 /* Check neighbor. */
pauld3f0d622004-05-05 15:27:15 +00001657 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001658 if (nbr == NULL)
1659 {
1660 zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s",
1661 inet_ntoa (ospfh->router_id), IF_NAME (oi));
1662 return;
1663 }
1664
1665 /* Check neighbor state. */
1666 if (nbr->state < NSM_Exchange)
1667 {
ajs3aa8d5f2004-12-11 18:00:06 +00001668 zlog_warn ("Link State Update: "
1669 "Neighbor[%s] state %s is less than Exchange",
1670 inet_ntoa (ospfh->router_id),
1671 LOOKUP(ospf_nsm_state_msg, nbr->state));
paul718e3742002-12-13 20:15:29 +00001672 return;
1673 }
1674
1675 /* Get list of LSAs from Link State Update packet. - Also perorms Stages
1676 * 1 (validate LSA checksum) and 2 (check for LSA consistent type)
1677 * of section 13.
1678 */
1679 lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
1680
1681#ifdef HAVE_OPAQUE_LSA
1682 /*
paul718e3742002-12-13 20:15:29 +00001683 * If self-originated Opaque-LSAs that have flooded before restart
1684 * are contained in the received LSUpd message, corresponding LSReq
1685 * messages to be sent may have to be modified.
1686 * To eliminate possible race conditions such that flushing and normal
1687 * updating for the same LSA would take place alternately, this trick
1688 * must be done before entering to the loop below.
1689 */
paul69310a62005-05-11 18:09:59 +00001690 /* XXX: Why is this Opaque specific? Either our core code is deficient
1691 * and this should be fixed generally, or Opaque is inventing strawman
1692 * problems */
paul718e3742002-12-13 20:15:29 +00001693 ospf_opaque_adjust_lsreq (nbr, lsas);
1694#endif /* HAVE_OPAQUE_LSA */
1695
1696#define DISCARD_LSA(L,N) {\
1697 if (IS_DEBUG_OSPF_EVENT) \
ajs2a42e282004-12-08 18:43:03 +00001698 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 +00001699 ospf_lsa_discard (L); \
1700 continue; }
1701
1702 /* Process each LSA received in the one packet. */
paul1eb8ef22005-04-07 07:30:20 +00001703 for (ALL_LIST_ELEMENTS (lsas, node, nnode, lsa))
paul718e3742002-12-13 20:15:29 +00001704 {
1705 struct ospf_lsa *ls_ret, *current;
1706 int ret = 1;
1707
paul718e3742002-12-13 20:15:29 +00001708 if (IS_DEBUG_OSPF_NSSA)
1709 {
1710 char buf1[INET_ADDRSTRLEN];
1711 char buf2[INET_ADDRSTRLEN];
1712 char buf3[INET_ADDRSTRLEN];
1713
ajs2a42e282004-12-08 18:43:03 +00001714 zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s",
paul718e3742002-12-13 20:15:29 +00001715 lsa->data->type,
1716 inet_ntop (AF_INET, &ospfh->router_id,
1717 buf1, INET_ADDRSTRLEN),
1718 inet_ntop (AF_INET, &lsa->data->id,
1719 buf2, INET_ADDRSTRLEN),
1720 inet_ntop (AF_INET, &lsa->data->adv_router,
1721 buf3, INET_ADDRSTRLEN));
1722 }
paul718e3742002-12-13 20:15:29 +00001723
1724 listnode_delete (lsas, lsa); /* We don't need it in list anymore */
1725
1726 /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */
1727
1728 /* LSA Type - Done above by ospf_ls_upd_list_lsa() */
1729
1730 /* Do not take in AS External LSAs if we are a stub or NSSA. */
1731
1732 /* Do not take in AS NSSA if this neighbor and we are not NSSA */
1733
1734 /* Do take in Type-7's if we are an NSSA */
1735
1736 /* If we are also an ABR, later translate them to a Type-5 packet */
1737
1738 /* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will
1739 translate them to a separate Type-5 packet. */
1740
1741 if (lsa->data->type == OSPF_AS_EXTERNAL_LSA)
1742 /* Reject from STUB or NSSA */
1743 if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
1744 {
1745 DISCARD_LSA (lsa, 1);
paul718e3742002-12-13 20:15:29 +00001746 if (IS_DEBUG_OSPF_NSSA)
ajs2a42e282004-12-08 18:43:03 +00001747 zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area");
paul718e3742002-12-13 20:15:29 +00001748 }
1749
paul718e3742002-12-13 20:15:29 +00001750 if (lsa->data->type == OSPF_AS_NSSA_LSA)
1751 if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)
1752 {
1753 DISCARD_LSA (lsa,2);
1754 if (IS_DEBUG_OSPF_NSSA)
ajs2a42e282004-12-08 18:43:03 +00001755 zlog_debug("Incoming NSSA LSA Discarded: Not NSSA Area");
paul718e3742002-12-13 20:15:29 +00001756 }
paul718e3742002-12-13 20:15:29 +00001757
1758 /* Find the LSA in the current database. */
1759
1760 current = ospf_lsa_lookup_by_header (oi->area, lsa->data);
1761
1762 /* If the LSA's LS age is equal to MaxAge, and there is currently
1763 no instance of the LSA in the router's link state database,
1764 and none of router's neighbors are in states Exchange or Loading,
1765 then take the following actions. */
1766
1767 if (IS_LSA_MAXAGE (lsa) && !current &&
paul68980082003-03-25 05:07:42 +00001768 (ospf_nbr_count (oi, NSM_Exchange) +
1769 ospf_nbr_count (oi, NSM_Loading)) == 0)
paul718e3742002-12-13 20:15:29 +00001770 {
1771 /* Response Link State Acknowledgment. */
1772 ospf_ls_ack_send (nbr, lsa);
1773
1774 /* Discard LSA. */
paul6d452762005-11-03 11:15:44 +00001775 zlog_info ("Link State Update[%s]: LS age is equal to MaxAge.",
1776 dump_lsa_key(lsa));
paul718e3742002-12-13 20:15:29 +00001777 DISCARD_LSA (lsa, 3);
1778 }
1779
1780#ifdef HAVE_OPAQUE_LSA
1781 if (IS_OPAQUE_LSA (lsa->data->type)
paul68980082003-03-25 05:07:42 +00001782 && IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +00001783 {
1784 /*
1785 * Even if initial flushing seems to be completed, there might
1786 * be a case that self-originated LSA with MaxAge still remain
1787 * in the routing domain.
1788 * Just send an LSAck message to cease retransmission.
1789 */
1790 if (IS_LSA_MAXAGE (lsa))
1791 {
1792 zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa));
1793 ospf_ls_ack_send (nbr, lsa);
1794 ospf_lsa_discard (lsa);
1795
1796 if (current != NULL && ! IS_LSA_MAXAGE (current))
1797 ospf_opaque_lsa_refresh_schedule (current);
1798 continue;
1799 }
1800
1801 /*
1802 * If an instance of self-originated Opaque-LSA is not found
1803 * in the LSDB, there are some possible cases here.
1804 *
1805 * 1) This node lost opaque-capability after restart.
1806 * 2) Else, a part of opaque-type is no more supported.
1807 * 3) Else, a part of opaque-id is no more supported.
1808 *
1809 * Anyway, it is still this node's responsibility to flush it.
1810 * Otherwise, the LSA instance remains in the routing domain
1811 * until its age reaches to MaxAge.
1812 */
paul69310a62005-05-11 18:09:59 +00001813 /* XXX: We should deal with this for *ALL* LSAs, not just opaque */
paul718e3742002-12-13 20:15:29 +00001814 if (current == NULL)
1815 {
1816 if (IS_DEBUG_OSPF_EVENT)
paul69310a62005-05-11 18:09:59 +00001817 zlog_debug ("LSA[%s]: Previously originated Opaque-LSA,"
1818 "not found in the LSDB.", dump_lsa_key (lsa));
paul718e3742002-12-13 20:15:29 +00001819
1820 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
paul69310a62005-05-11 18:09:59 +00001821
1822 ospf_opaque_self_originated_lsa_received (nbr, lsa);
1823 ospf_ls_ack_send (nbr, lsa);
1824
paul718e3742002-12-13 20:15:29 +00001825 continue;
1826 }
1827 }
1828#endif /* HAVE_OPAQUE_LSA */
paul69310a62005-05-11 18:09:59 +00001829
hassocb05eb22004-02-11 21:10:19 +00001830 /* It might be happen that received LSA is self-originated network LSA, but
1831 * router ID is cahnged. So, we should check if LSA is a network-LSA whose
1832 * Link State ID is one of the router's own IP interface addresses but whose
1833 * Advertising Router is not equal to the router's own Router ID
1834 * According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed.
1835 */
1836
1837 if(lsa->data->type == OSPF_NETWORK_LSA)
1838 {
paul1eb8ef22005-04-07 07:30:20 +00001839 struct listnode *oinode, *oinnode;
1840 struct ospf_interface *out_if;
hassocb05eb22004-02-11 21:10:19 +00001841 int Flag = 0;
1842
paul1eb8ef22005-04-07 07:30:20 +00001843 for (ALL_LIST_ELEMENTS (oi->ospf->oiflist, oinode, oinnode, out_if))
hassocb05eb22004-02-11 21:10:19 +00001844 {
hassocb05eb22004-02-11 21:10:19 +00001845 if(out_if == NULL)
1846 break;
1847
1848 if((IPV4_ADDR_SAME(&out_if->address->u.prefix4, &lsa->data->id)) &&
1849 (!(IPV4_ADDR_SAME(&oi->ospf->router_id, &lsa->data->adv_router))))
1850 {
1851 if(out_if->network_lsa_self)
1852 {
1853 ospf_lsa_flush_area(lsa,out_if->area);
1854 if(IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00001855 zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
hassocb05eb22004-02-11 21:10:19 +00001856 lsa, (int) lsa->data->type);
1857 ospf_lsa_discard (lsa);
1858 Flag = 1;
1859 }
1860 break;
1861 }
1862 }
1863 if(Flag)
1864 continue;
1865 }
paul718e3742002-12-13 20:15:29 +00001866
1867 /* (5) Find the instance of this LSA that is currently contained
1868 in the router's link state database. If there is no
1869 database copy, or the received LSA is more recent than
1870 the database copy the following steps must be performed. */
1871
1872 if (current == NULL ||
1873 (ret = ospf_lsa_more_recent (current, lsa)) < 0)
1874 {
1875 /* Actual flooding procedure. */
paul68980082003-03-25 05:07:42 +00001876 if (ospf_flood (oi->ospf, nbr, current, lsa) < 0) /* Trap NSSA later. */
paul718e3742002-12-13 20:15:29 +00001877 DISCARD_LSA (lsa, 4);
1878 continue;
1879 }
1880
1881 /* (6) Else, If there is an instance of the LSA on the sending
1882 neighbor's Link state request list, an error has occurred in
1883 the Database Exchange process. In this case, restart the
1884 Database Exchange process by generating the neighbor event
1885 BadLSReq for the sending neighbor and stop processing the
1886 Link State Update packet. */
1887
1888 if (ospf_ls_request_lookup (nbr, lsa))
1889 {
1890 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
ajs3aa8d5f2004-12-11 18:00:06 +00001891 zlog_warn("LSA[%s] instance exists on Link state request list",
1892 dump_lsa_key(lsa));
paul718e3742002-12-13 20:15:29 +00001893
1894 /* Clean list of LSAs. */
1895 ospf_upd_list_clean (lsas);
1896 /* this lsa is not on lsas list already. */
1897 ospf_lsa_discard (lsa);
paul718e3742002-12-13 20:15:29 +00001898 return;
1899 }
1900
1901 /* If the received LSA is the same instance as the database copy
1902 (i.e., neither one is more recent) the following two steps
1903 should be performed: */
1904
1905 if (ret == 0)
1906 {
1907 /* If the LSA is listed in the Link state retransmission list
1908 for the receiving adjacency, the router itself is expecting
1909 an acknowledgment for this LSA. The router should treat the
1910 received LSA as an acknowledgment by removing the LSA from
1911 the Link state retransmission list. This is termed an
1912 "implied acknowledgment". */
1913
1914 ls_ret = ospf_ls_retransmit_lookup (nbr, lsa);
1915
1916 if (ls_ret != NULL)
1917 {
1918 ospf_ls_retransmit_delete (nbr, ls_ret);
1919
1920 /* Delayed acknowledgment sent if advertisement received
1921 from Designated Router, otherwise do nothing. */
1922 if (oi->state == ISM_Backup)
1923 if (NBR_IS_DR (nbr))
1924 listnode_add (oi->ls_ack, ospf_lsa_lock (lsa));
1925
1926 DISCARD_LSA (lsa, 5);
1927 }
1928 else
1929 /* Acknowledge the receipt of the LSA by sending a
1930 Link State Acknowledgment packet back out the receiving
1931 interface. */
1932 {
1933 ospf_ls_ack_send (nbr, lsa);
1934 DISCARD_LSA (lsa, 6);
1935 }
1936 }
1937
1938 /* The database copy is more recent. If the database copy
1939 has LS age equal to MaxAge and LS sequence number equal to
1940 MaxSequenceNumber, simply discard the received LSA without
1941 acknowledging it. (In this case, the LSA's LS sequence number is
1942 wrapping, and the MaxSequenceNumber LSA must be completely
1943 flushed before any new LSA instance can be introduced). */
1944
1945 else if (ret > 0) /* Database copy is more recent */
1946 {
1947 if (IS_LSA_MAXAGE (current) &&
1948 current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
1949 {
1950 DISCARD_LSA (lsa, 7);
1951 }
1952 /* Otherwise, as long as the database copy has not been sent in a
1953 Link State Update within the last MinLSArrival seconds, send the
1954 database copy back to the sending neighbor, encapsulated within
1955 a Link State Update Packet. The Link State Update Packet should
1956 be sent directly to the neighbor. In so doing, do not put the
1957 database copy of the LSA on the neighbor's link state
1958 retransmission list, and do not acknowledge the received (less
1959 recent) LSA instance. */
1960 else
1961 {
1962 struct timeval now;
1963
Paul Jakma2518efd2006-08-27 06:49:29 +00001964 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
paul718e3742002-12-13 20:15:29 +00001965
1966 if (tv_cmp (tv_sub (now, current->tv_orig),
1967 int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)
1968 /* Trap NSSA type later.*/
1969 ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
1970 DISCARD_LSA (lsa, 8);
1971 }
1972 }
1973 }
1974
paul718e3742002-12-13 20:15:29 +00001975 assert (listcount (lsas) == 0);
1976 list_delete (lsas);
1977}
1978
1979/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
paul4dadc292005-05-06 21:37:42 +00001980static void
paul718e3742002-12-13 20:15:29 +00001981ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
1982 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1983{
1984 struct ospf_neighbor *nbr;
paul69310a62005-05-11 18:09:59 +00001985
paul718e3742002-12-13 20:15:29 +00001986 /* increment statistics. */
1987 oi->ls_ack_in++;
1988
pauld3f0d622004-05-05 15:27:15 +00001989 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001990 if (nbr == NULL)
1991 {
1992 zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.",
1993 inet_ntoa (ospfh->router_id));
1994 return;
1995 }
1996
1997 if (nbr->state < NSM_Exchange)
1998 {
ajs3aa8d5f2004-12-11 18:00:06 +00001999 zlog_warn ("Link State Acknowledgment: "
2000 "Neighbor[%s] state %s is less than Exchange",
2001 inet_ntoa (ospfh->router_id),
2002 LOOKUP(ospf_nsm_state_msg, nbr->state));
paul718e3742002-12-13 20:15:29 +00002003 return;
2004 }
paul69310a62005-05-11 18:09:59 +00002005
paul718e3742002-12-13 20:15:29 +00002006 while (size >= OSPF_LSA_HEADER_SIZE)
2007 {
2008 struct ospf_lsa *lsa, *lsr;
2009
2010 lsa = ospf_lsa_new ();
2011 lsa->data = (struct lsa_header *) STREAM_PNT (s);
2012
2013 /* lsah = (struct lsa_header *) STREAM_PNT (s); */
2014 size -= OSPF_LSA_HEADER_SIZE;
paul9985f832005-02-09 15:51:56 +00002015 stream_forward_getp (s, OSPF_LSA_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00002016
2017 if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
2018 {
2019 lsa->data = NULL;
2020 ospf_lsa_discard (lsa);
2021 continue;
2022 }
2023
2024 lsr = ospf_ls_retransmit_lookup (nbr, lsa);
2025
2026 if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
2027 {
2028#ifdef HAVE_OPAQUE_LSA
paul718e3742002-12-13 20:15:29 +00002029 if (IS_OPAQUE_LSA (lsr->data->type))
paul69310a62005-05-11 18:09:59 +00002030 ospf_opaque_ls_ack_received (nbr, lsr);
paul718e3742002-12-13 20:15:29 +00002031#endif /* HAVE_OPAQUE_LSA */
2032
2033 ospf_ls_retransmit_delete (nbr, lsr);
2034 }
2035
2036 lsa->data = NULL;
2037 ospf_lsa_discard (lsa);
2038 }
2039
paul718e3742002-12-13 20:15:29 +00002040 return;
paul718e3742002-12-13 20:15:29 +00002041}
2042
ajs038163f2005-02-17 19:55:59 +00002043static struct stream *
ajs5c333492005-02-23 15:43:01 +00002044ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
paul718e3742002-12-13 20:15:29 +00002045{
2046 int ret;
ajs5c333492005-02-23 15:43:01 +00002047 struct ip *iph;
paul718e3742002-12-13 20:15:29 +00002048 u_int16_t ip_len;
paul718e3742002-12-13 20:15:29 +00002049 unsigned int ifindex = 0;
2050 struct iovec iov;
gdtd0deca62004-08-26 13:14:07 +00002051 /* Header and data both require alignment. */
gdte3049822004-08-26 13:19:40 +00002052 char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
paul2dd8bb42004-07-23 15:13:48 +00002053 struct msghdr msgh;
2054
paul68defd62004-09-27 07:27:13 +00002055 memset (&msgh, 0, sizeof (struct msghdr));
paul2dd8bb42004-07-23 15:13:48 +00002056 msgh.msg_iov = &iov;
2057 msgh.msg_iovlen = 1;
2058 msgh.msg_control = (caddr_t) buff;
2059 msgh.msg_controllen = sizeof (buff);
paul2dd8bb42004-07-23 15:13:48 +00002060
ajs5c333492005-02-23 15:43:01 +00002061 ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1);
2062 if (ret < 0)
paul718e3742002-12-13 20:15:29 +00002063 {
ajs5c333492005-02-23 15:43:01 +00002064 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
2065 return NULL;
2066 }
paul69310a62005-05-11 18:09:59 +00002067 if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */
ajs5c333492005-02-23 15:43:01 +00002068 {
2069 zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
2070 "(ip header size is %u)",
2071 ret, (u_int)sizeof(iph));
paul718e3742002-12-13 20:15:29 +00002072 return NULL;
2073 }
paul18b12c32004-10-05 14:38:29 +00002074
ajs5c333492005-02-23 15:43:01 +00002075 /* Note that there should not be alignment problems with this assignment
2076 because this is at the beginning of the stream data buffer. */
2077 iph = (struct ip *) STREAM_DATA(ibuf);
2078 sockopt_iphdrincl_swab_systoh (iph);
paul18b12c32004-10-05 14:38:29 +00002079
ajs5c333492005-02-23 15:43:01 +00002080 ip_len = iph->ip_len;
paul6b333612004-10-11 10:11:25 +00002081
paul239aecc2003-12-08 10:34:54 +00002082#if !defined(GNU_LINUX) && (OpenBSD < 200311)
paul718e3742002-12-13 20:15:29 +00002083 /*
2084 * Kernel network code touches incoming IP header parameters,
2085 * before protocol specific processing.
2086 *
2087 * 1) Convert byteorder to host representation.
2088 * --> ip_len, ip_id, ip_off
2089 *
2090 * 2) Adjust ip_len to strip IP header size!
2091 * --> If user process receives entire IP packet via RAW
2092 * socket, it must consider adding IP header size to
2093 * the "ip_len" field of "ip" structure.
2094 *
2095 * For more details, see <netinet/ip_input.c>.
2096 */
ajs5c333492005-02-23 15:43:01 +00002097 ip_len = ip_len + (iph->ip_hl << 2);
paul718e3742002-12-13 20:15:29 +00002098#endif
2099
paul863082d2004-08-19 04:43:43 +00002100 ifindex = getsockopt_ifindex (AF_INET, &msgh);
paul718e3742002-12-13 20:15:29 +00002101
2102 *ifp = if_lookup_by_index (ifindex);
2103
2104 if (ret != ip_len)
2105 {
ajs5c333492005-02-23 15:43:01 +00002106 zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, "
2107 "but recvmsg returned %d", ip_len, ret);
paul718e3742002-12-13 20:15:29 +00002108 return NULL;
2109 }
2110
2111 return ibuf;
2112}
2113
paul4dadc292005-05-06 21:37:42 +00002114static struct ospf_interface *
pauld3f0d622004-05-05 15:27:15 +00002115ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
paul718e3742002-12-13 20:15:29 +00002116 struct ip *iph, struct ospf_header *ospfh)
2117{
2118 struct ospf_interface *rcv_oi;
paul718e3742002-12-13 20:15:29 +00002119 struct ospf_vl_data *vl_data;
2120 struct ospf_area *vl_area;
hasso52dc7ee2004-09-23 19:18:23 +00002121 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002122
2123 if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||
2124 !OSPF_IS_AREA_BACKBONE (ospfh))
pauld3f0d622004-05-05 15:27:15 +00002125 return NULL;
paul718e3742002-12-13 20:15:29 +00002126
pauld3f0d622004-05-05 15:27:15 +00002127 /* look for local OSPF interface matching the destination
2128 * to determine Area ID. We presume therefore the destination address
2129 * is unique, or at least (for "unnumbered" links), not used in other
2130 * areas
2131 */
2132 if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL,
2133 iph->ip_dst)) == NULL)
2134 return NULL;
paul718e3742002-12-13 20:15:29 +00002135
paul1eb8ef22005-04-07 07:30:20 +00002136 for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
paul718e3742002-12-13 20:15:29 +00002137 {
paul020709f2003-04-04 02:44:16 +00002138 vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);
paul718e3742002-12-13 20:15:29 +00002139 if (!vl_area)
2140 continue;
2141
2142 if (OSPF_AREA_SAME (&vl_area, &rcv_oi->area) &&
2143 IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))
2144 {
2145 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002146 zlog_debug ("associating packet with %s",
paul718e3742002-12-13 20:15:29 +00002147 IF_NAME (vl_data->vl_oi));
2148 if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))
2149 {
2150 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002151 zlog_debug ("This VL is not up yet, sorry");
paul718e3742002-12-13 20:15:29 +00002152 return NULL;
2153 }
2154
2155 return vl_data->vl_oi;
2156 }
2157 }
2158
2159 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002160 zlog_debug ("couldn't find any VL to associate the packet with");
paul718e3742002-12-13 20:15:29 +00002161
pauld3f0d622004-05-05 15:27:15 +00002162 return NULL;
paul718e3742002-12-13 20:15:29 +00002163}
2164
paul4dadc292005-05-06 21:37:42 +00002165static inline int
paul718e3742002-12-13 20:15:29 +00002166ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
2167{
2168 /* Check match the Area ID of the receiving interface. */
2169 if (OSPF_AREA_SAME (&oi->area, &ospfh))
2170 return 1;
2171
2172 return 0;
2173}
2174
2175/* Unbound socket will accept any Raw IP packets if proto is matched.
2176 To prevent it, compare src IP address and i/f address with masking
2177 i/f network mask. */
paul4dadc292005-05-06 21:37:42 +00002178static int
paul718e3742002-12-13 20:15:29 +00002179ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
2180{
2181 struct in_addr mask, me, him;
2182
2183 if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
2184 oi->type == OSPF_IFTYPE_VIRTUALLINK)
2185 return 1;
2186
2187 masklen2ip (oi->address->prefixlen, &mask);
2188
2189 me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
2190 him.s_addr = ip_src.s_addr & mask.s_addr;
2191
2192 if (IPV4_ADDR_SAME (&me, &him))
2193 return 1;
2194
2195 return 0;
2196}
2197
paul4dadc292005-05-06 21:37:42 +00002198static int
paul718e3742002-12-13 20:15:29 +00002199ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
2200 struct ospf_header *ospfh)
2201{
2202 int ret = 0;
2203 struct crypt_key *ck;
2204
2205 switch (ntohs (ospfh->auth_type))
2206 {
2207 case OSPF_AUTH_NULL:
2208 ret = 1;
2209 break;
2210 case OSPF_AUTH_SIMPLE:
2211 if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
2212 ret = 1;
2213 else
2214 ret = 0;
2215 break;
2216 case OSPF_AUTH_CRYPTOGRAPHIC:
paul1eb8ef22005-04-07 07:30:20 +00002217 if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL)
paul718e3742002-12-13 20:15:29 +00002218 {
2219 ret = 0;
2220 break;
2221 }
2222
2223 /* This is very basic, the digest processing is elsewhere */
2224 if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE &&
2225 ospfh->u.crypt.key_id == ck->key_id &&
2226 ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))
2227 ret = 1;
2228 else
2229 ret = 0;
2230 break;
2231 default:
2232 ret = 0;
2233 break;
2234 }
2235
2236 return ret;
2237}
2238
paul4dadc292005-05-06 21:37:42 +00002239static int
paul718e3742002-12-13 20:15:29 +00002240ospf_check_sum (struct ospf_header *ospfh)
2241{
2242 u_int32_t ret;
2243 u_int16_t sum;
paul718e3742002-12-13 20:15:29 +00002244
2245 /* clear auth_data for checksum. */
2246 memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
2247
2248 /* keep checksum and clear. */
2249 sum = ospfh->checksum;
2250 memset (&ospfh->checksum, 0, sizeof (u_int16_t));
2251
2252 /* calculate checksum. */
2253 ret = in_cksum (ospfh, ntohs (ospfh->length));
2254
2255 if (ret != sum)
2256 {
2257 zlog_info ("ospf_check_sum(): checksum mismatch, my %X, his %X",
2258 ret, sum);
2259 return 0;
2260 }
2261
2262 return 1;
2263}
2264
2265/* OSPF Header verification. */
paul4dadc292005-05-06 21:37:42 +00002266static int
paul718e3742002-12-13 20:15:29 +00002267ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
2268 struct ip *iph, struct ospf_header *ospfh)
2269{
2270 /* check version. */
2271 if (ospfh->version != OSPF_VERSION)
2272 {
2273 zlog_warn ("interface %s: ospf_read version number mismatch.",
2274 IF_NAME (oi));
2275 return -1;
2276 }
2277
2278 /* Check Area ID. */
2279 if (!ospf_check_area_id (oi, ospfh))
2280 {
2281 zlog_warn ("interface %s: ospf_read invalid Area ID %s.",
2282 IF_NAME (oi), inet_ntoa (ospfh->area_id));
2283 return -1;
2284 }
2285
2286 /* Check network mask, Silently discarded. */
2287 if (! ospf_check_network_mask (oi, iph->ip_src))
2288 {
2289 zlog_warn ("interface %s: ospf_read network address is not same [%s]",
2290 IF_NAME (oi), inet_ntoa (iph->ip_src));
2291 return -1;
2292 }
2293
2294 /* Check authentication. */
2295 if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
2296 {
paulc6371712006-01-17 17:49:53 +00002297 zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d",
2298 IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type));
paul718e3742002-12-13 20:15:29 +00002299 return -1;
2300 }
2301
2302 if (! ospf_check_auth (oi, ibuf, ospfh))
2303 {
2304 zlog_warn ("interface %s: ospf_read authentication failed.",
2305 IF_NAME (oi));
2306 return -1;
2307 }
2308
2309 /* if check sum is invalid, packet is discarded. */
2310 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
2311 {
2312 if (! ospf_check_sum (ospfh))
2313 {
2314 zlog_warn ("interface %s: ospf_read packet checksum error %s",
2315 IF_NAME (oi), inet_ntoa (ospfh->router_id));
2316 return -1;
2317 }
2318 }
2319 else
2320 {
2321 if (ospfh->checksum != 0)
2322 return -1;
2323 if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)
2324 {
2325 zlog_warn ("interface %s: ospf_read md5 authentication failed.",
2326 IF_NAME (oi));
2327 return -1;
2328 }
2329 }
2330
2331 return 0;
2332}
2333
2334/* Starting point of packet process function. */
2335int
2336ospf_read (struct thread *thread)
2337{
2338 int ret;
2339 struct stream *ibuf;
paul68980082003-03-25 05:07:42 +00002340 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002341 struct ospf_interface *oi;
2342 struct ip *iph;
2343 struct ospf_header *ospfh;
2344 u_int16_t length;
2345 struct interface *ifp;
2346
2347 /* first of all get interface pointer. */
paul68980082003-03-25 05:07:42 +00002348 ospf = THREAD_ARG (thread);
ajs038163f2005-02-17 19:55:59 +00002349
2350 /* prepare for next packet. */
2351 ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
paul718e3742002-12-13 20:15:29 +00002352
2353 /* read OSPF packet. */
ajs5c333492005-02-23 15:43:01 +00002354 stream_reset(ospf->ibuf);
2355 if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
paul718e3742002-12-13 20:15:29 +00002356 return -1;
2357
ajs5c333492005-02-23 15:43:01 +00002358 /* Note that there should not be alignment problems with this assignment
2359 because this is at the beginning of the stream data buffer. */
paul06f953f2004-10-22 17:00:38 +00002360 iph = (struct ip *) STREAM_DATA (ibuf);
ajs5c333492005-02-23 15:43:01 +00002361 /* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
paul06f953f2004-10-22 17:00:38 +00002362
paulac191232004-10-22 12:05:17 +00002363 if (ifp == NULL)
ajsb87f7722004-12-29 20:41:26 +00002364 /* Handle cases where the platform does not support retrieving the ifindex,
2365 and also platforms (such as Solaris 8) that claim to support ifindex
2366 retrieval but do not. */
paulac191232004-10-22 12:05:17 +00002367 ifp = if_lookup_address (iph->ip_src);
paulac191232004-10-22 12:05:17 +00002368
pauld3f0d622004-05-05 15:27:15 +00002369 if (ifp == NULL)
ajs5c333492005-02-23 15:43:01 +00002370 return 0;
paul718e3742002-12-13 20:15:29 +00002371
2372 /* IP Header dump. */
paul17b78d32003-02-13 22:04:01 +00002373 if (IS_DEBUG_OSPF_PACKET(0, RECV))
paul6b333612004-10-11 10:11:25 +00002374 ospf_ip_header_dump (iph);
paul7d95c612003-01-27 12:00:55 +00002375
paul718e3742002-12-13 20:15:29 +00002376 /* Self-originated packet should be discarded silently. */
paul68980082003-03-25 05:07:42 +00002377 if (ospf_if_lookup_by_local_addr (ospf, NULL, iph->ip_src))
paul718e3742002-12-13 20:15:29 +00002378 {
pauld3241812003-09-29 12:42:39 +00002379 if (IS_DEBUG_OSPF_PACKET (0, RECV))
2380 {
ajs2a42e282004-12-08 18:43:03 +00002381 zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
pauld3241812003-09-29 12:42:39 +00002382 inet_ntoa (iph->ip_src));
2383 }
paul718e3742002-12-13 20:15:29 +00002384 return 0;
2385 }
2386
2387 /* Adjust size to message length. */
paul9985f832005-02-09 15:51:56 +00002388 stream_forward_getp (ibuf, iph->ip_hl * 4);
paul718e3742002-12-13 20:15:29 +00002389
2390 /* Get ospf packet header. */
2391 ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
2392
2393 /* associate packet with ospf interface */
paul68980082003-03-25 05:07:42 +00002394 oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);
pauld3f0d622004-05-05 15:27:15 +00002395
2396 /* if no local ospf_interface,
2397 * or header area is backbone but ospf_interface is not
2398 * check for VLINK interface
2399 */
2400 if ( (oi == NULL) ||
2401 (OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id)
2402 && !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id))
2403 )
2404 {
2405 if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
2406 {
Paul Jakma88871b12006-06-15 11:41:19 +00002407 if (IS_DEBUG_OSPF_EVENT)
2408 zlog_debug ("Packet from [%s] received on link %s"
2409 " but no ospf_interface",
2410 inet_ntoa (iph->ip_src), ifp->name);
pauld3f0d622004-05-05 15:27:15 +00002411 return 0;
2412 }
2413 }
2414
2415 /* else it must be a local ospf interface, check it was received on
2416 * correct link
2417 */
2418 else if (oi->ifp != ifp)
paul718e3742002-12-13 20:15:29 +00002419 {
2420 zlog_warn ("Packet from [%s] received on wrong link %s",
pauld3241812003-09-29 12:42:39 +00002421 inet_ntoa (iph->ip_src), ifp->name);
paul718e3742002-12-13 20:15:29 +00002422 return 0;
2423 }
ajs847947f2005-02-02 18:38:48 +00002424 else if (oi->state == ISM_Down)
ajsc3eab872005-01-29 15:52:07 +00002425 {
ajsba6454e2005-02-08 15:37:30 +00002426 char buf[2][INET_ADDRSTRLEN];
2427 zlog_warn ("Ignoring packet from %s to %s received on interface that is "
ajs847947f2005-02-02 18:38:48 +00002428 "down [%s]; interface flags are %s",
ajsba6454e2005-02-08 15:37:30 +00002429 inet_ntop(AF_INET, &iph->ip_src, buf[0], sizeof(buf[0])),
2430 inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
2431 ifp->name, if_flag_dump(ifp->flags));
ajsba6454e2005-02-08 15:37:30 +00002432 /* Fix multicast memberships? */
2433 if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
Paul Jakma429ac782006-06-15 18:40:49 +00002434 OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
ajsba6454e2005-02-08 15:37:30 +00002435 else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS))
Paul Jakma429ac782006-06-15 18:40:49 +00002436 OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
ajsba6454e2005-02-08 15:37:30 +00002437 if (oi->multicast_memberships)
2438 ospf_if_set_multicast(oi);
ajsc3eab872005-01-29 15:52:07 +00002439 return 0;
2440 }
paul718e3742002-12-13 20:15:29 +00002441
2442 /*
2443 * If the received packet is destined for AllDRouters, the packet
2444 * should be accepted only if the received ospf interface state is
2445 * either DR or Backup -- endo.
2446 */
2447 if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)
2448 && (oi->state != ISM_DR && oi->state != ISM_Backup))
2449 {
ajsba6454e2005-02-08 15:37:30 +00002450 zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
paul718e3742002-12-13 20:15:29 +00002451 inet_ntoa (iph->ip_src), IF_NAME (oi),
2452 LOOKUP (ospf_ism_state_msg, oi->state));
ajsba6454e2005-02-08 15:37:30 +00002453 /* Try to fix multicast membership. */
2454 SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
2455 ospf_if_set_multicast(oi);
paul718e3742002-12-13 20:15:29 +00002456 return 0;
2457 }
2458
2459 /* Show debug receiving packet. */
paul1aa7b392003-04-08 08:51:58 +00002460 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
2461 {
paul718e3742002-12-13 20:15:29 +00002462 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
paul1aa7b392003-04-08 08:51:58 +00002463 {
ajs2a42e282004-12-08 18:43:03 +00002464 zlog_debug ("-----------------------------------------------------");
paul1aa7b392003-04-08 08:51:58 +00002465 ospf_packet_dump (ibuf);
2466 }
paul718e3742002-12-13 20:15:29 +00002467
ajs2a42e282004-12-08 18:43:03 +00002468 zlog_debug ("%s received from [%s] via [%s]",
paul1aa7b392003-04-08 08:51:58 +00002469 ospf_packet_type_str[ospfh->type],
2470 inet_ntoa (ospfh->router_id), IF_NAME (oi));
ajs2a42e282004-12-08 18:43:03 +00002471 zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
2472 zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
paul718e3742002-12-13 20:15:29 +00002473
2474 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
ajs2a42e282004-12-08 18:43:03 +00002475 zlog_debug ("-----------------------------------------------------");
paul1aa7b392003-04-08 08:51:58 +00002476 }
paul718e3742002-12-13 20:15:29 +00002477
2478 /* Some header verification. */
2479 ret = ospf_verify_header (ibuf, oi, iph, ospfh);
2480 if (ret < 0)
2481 {
pauld3241812003-09-29 12:42:39 +00002482 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
2483 {
ajs2a42e282004-12-08 18:43:03 +00002484 zlog_debug ("ospf_read[%s/%s]: Header check failed, "
pauld3241812003-09-29 12:42:39 +00002485 "dropping.",
2486 ospf_packet_type_str[ospfh->type],
2487 inet_ntoa (iph->ip_src));
2488 }
paul718e3742002-12-13 20:15:29 +00002489 return ret;
2490 }
2491
paul9985f832005-02-09 15:51:56 +00002492 stream_forward_getp (ibuf, OSPF_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00002493
2494 /* Adjust size to message length. */
2495 length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;
2496
2497 /* Read rest of the packet and call each sort of packet routine. */
2498 switch (ospfh->type)
2499 {
2500 case OSPF_MSG_HELLO:
2501 ospf_hello (iph, ospfh, ibuf, oi, length);
2502 break;
2503 case OSPF_MSG_DB_DESC:
2504 ospf_db_desc (iph, ospfh, ibuf, oi, length);
2505 break;
2506 case OSPF_MSG_LS_REQ:
2507 ospf_ls_req (iph, ospfh, ibuf, oi, length);
2508 break;
2509 case OSPF_MSG_LS_UPD:
2510 ospf_ls_upd (iph, ospfh, ibuf, oi, length);
2511 break;
2512 case OSPF_MSG_LS_ACK:
2513 ospf_ls_ack (iph, ospfh, ibuf, oi, length);
2514 break;
2515 default:
2516 zlog (NULL, LOG_WARNING,
2517 "interface %s: OSPF packet header type %d is illegal",
2518 IF_NAME (oi), ospfh->type);
2519 break;
2520 }
2521
paul718e3742002-12-13 20:15:29 +00002522 return 0;
2523}
2524
2525/* Make OSPF header. */
paul4dadc292005-05-06 21:37:42 +00002526static void
paul718e3742002-12-13 20:15:29 +00002527ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
2528{
2529 struct ospf_header *ospfh;
2530
2531 ospfh = (struct ospf_header *) STREAM_DATA (s);
2532
2533 ospfh->version = (u_char) OSPF_VERSION;
2534 ospfh->type = (u_char) type;
2535
paul68980082003-03-25 05:07:42 +00002536 ospfh->router_id = oi->ospf->router_id;
paul718e3742002-12-13 20:15:29 +00002537
2538 ospfh->checksum = 0;
2539 ospfh->area_id = oi->area->area_id;
2540 ospfh->auth_type = htons (ospf_auth_type (oi));
2541
2542 memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
2543
paul9985f832005-02-09 15:51:56 +00002544 stream_forward_endp (s, OSPF_HEADER_SIZE);
paul718e3742002-12-13 20:15:29 +00002545}
2546
2547/* Make Authentication Data. */
paul4dadc292005-05-06 21:37:42 +00002548static int
paul718e3742002-12-13 20:15:29 +00002549ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
2550{
2551 struct crypt_key *ck;
2552
2553 switch (ospf_auth_type (oi))
2554 {
2555 case OSPF_AUTH_NULL:
2556 /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
2557 break;
2558 case OSPF_AUTH_SIMPLE:
2559 memcpy (ospfh->u.auth_data, OSPF_IF_PARAM (oi, auth_simple),
2560 OSPF_AUTH_SIMPLE_SIZE);
2561 break;
2562 case OSPF_AUTH_CRYPTOGRAPHIC:
2563 /* If key is not set, then set 0. */
2564 if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
2565 {
2566 ospfh->u.crypt.zero = 0;
2567 ospfh->u.crypt.key_id = 0;
2568 ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
2569 }
2570 else
2571 {
paul1eb8ef22005-04-07 07:30:20 +00002572 ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
paul718e3742002-12-13 20:15:29 +00002573 ospfh->u.crypt.zero = 0;
2574 ospfh->u.crypt.key_id = ck->key_id;
2575 ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
2576 }
2577 /* note: the seq is done in ospf_make_md5_digest() */
2578 break;
2579 default:
2580 /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
2581 break;
2582 }
2583
2584 return 0;
2585}
2586
2587/* Fill rest of OSPF header. */
paul4dadc292005-05-06 21:37:42 +00002588static void
paul718e3742002-12-13 20:15:29 +00002589ospf_fill_header (struct ospf_interface *oi,
2590 struct stream *s, u_int16_t length)
2591{
2592 struct ospf_header *ospfh;
2593
2594 ospfh = (struct ospf_header *) STREAM_DATA (s);
2595
2596 /* Fill length. */
2597 ospfh->length = htons (length);
2598
2599 /* Calculate checksum. */
2600 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
2601 ospfh->checksum = in_cksum (ospfh, length);
2602 else
2603 ospfh->checksum = 0;
2604
2605 /* Add Authentication Data. */
2606 ospf_make_auth (oi, ospfh);
2607}
2608
paul4dadc292005-05-06 21:37:42 +00002609static int
paul718e3742002-12-13 20:15:29 +00002610ospf_make_hello (struct ospf_interface *oi, struct stream *s)
2611{
2612 struct ospf_neighbor *nbr;
2613 struct route_node *rn;
2614 u_int16_t length = OSPF_HELLO_MIN_SIZE;
2615 struct in_addr mask;
2616 unsigned long p;
2617 int flag = 0;
2618
2619 /* Set netmask of interface. */
2620 if (oi->type != OSPF_IFTYPE_POINTOPOINT &&
2621 oi->type != OSPF_IFTYPE_VIRTUALLINK)
2622 masklen2ip (oi->address->prefixlen, &mask);
2623 else
2624 memset ((char *) &mask, 0, sizeof (struct in_addr));
2625 stream_put_ipv4 (s, mask.s_addr);
2626
2627 /* Set Hello Interval. */
paulf9ad9372005-10-21 00:45:17 +00002628 if (OSPF_IF_PARAM (oi, fast_hello) == 0)
2629 stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
2630 else
2631 stream_putw (s, 0); /* hello-interval of 0 for fast-hellos */
paul718e3742002-12-13 20:15:29 +00002632
2633 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002634 zlog_debug ("make_hello: options: %x, int: %s",
paul718e3742002-12-13 20:15:29 +00002635 OPTIONS(oi), IF_NAME (oi));
2636
2637 /* Set Options. */
2638 stream_putc (s, OPTIONS (oi));
2639
2640 /* Set Router Priority. */
2641 stream_putc (s, PRIORITY (oi));
2642
2643 /* Set Router Dead Interval. */
2644 stream_putl (s, OSPF_IF_PARAM (oi, v_wait));
2645
2646 /* Set Designated Router. */
2647 stream_put_ipv4 (s, DR (oi).s_addr);
2648
paul9985f832005-02-09 15:51:56 +00002649 p = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002650
2651 /* Set Backup Designated Router. */
2652 stream_put_ipv4 (s, BDR (oi).s_addr);
2653
2654 /* Add neighbor seen. */
2655 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
paul68980082003-03-25 05:07:42 +00002656 if ((nbr = rn->info))
2657 if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */
2658 if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */
2659 if (nbr->state != NSM_Down) /* This is myself for DR election. */
2660 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +00002661 {
2662 /* Check neighbor is sane? */
paul68980082003-03-25 05:07:42 +00002663 if (nbr->d_router.s_addr != 0
2664 && IPV4_ADDR_SAME (&nbr->d_router, &oi->address->u.prefix4)
2665 && IPV4_ADDR_SAME (&nbr->bd_router, &oi->address->u.prefix4))
2666 flag = 1;
paul718e3742002-12-13 20:15:29 +00002667
2668 stream_put_ipv4 (s, nbr->router_id.s_addr);
2669 length += 4;
2670 }
2671
2672 /* Let neighbor generate BackupSeen. */
2673 if (flag == 1)
paul3a9eb092005-02-08 11:29:41 +00002674 stream_putl_at (s, p, 0); /* ipv4 address, normally */
paul718e3742002-12-13 20:15:29 +00002675
2676 return length;
2677}
2678
paul4dadc292005-05-06 21:37:42 +00002679static int
paul718e3742002-12-13 20:15:29 +00002680ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
2681 struct stream *s)
2682{
2683 struct ospf_lsa *lsa;
2684 u_int16_t length = OSPF_DB_DESC_MIN_SIZE;
2685 u_char options;
2686 unsigned long pp;
2687 int i;
2688 struct ospf_lsdb *lsdb;
2689
2690 /* Set Interface MTU. */
2691 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
2692 stream_putw (s, 0);
2693 else
2694 stream_putw (s, oi->ifp->mtu);
2695
2696 /* Set Options. */
2697 options = OPTIONS (oi);
2698#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00002699 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00002700 {
2701 if (IS_SET_DD_I (nbr->dd_flags)
2702 || CHECK_FLAG (nbr->options, OSPF_OPTION_O))
2703 /*
2704 * Set O-bit in the outgoing DD packet for capablity negotiation,
2705 * if one of following case is applicable.
2706 *
2707 * 1) WaitTimer expiration event triggered the neighbor state to
2708 * change to Exstart, but no (valid) DD packet has received
2709 * from the neighbor yet.
2710 *
2711 * 2) At least one DD packet with O-bit on has received from the
2712 * neighbor.
2713 */
2714 SET_FLAG (options, OSPF_OPTION_O);
2715 }
2716#endif /* HAVE_OPAQUE_LSA */
2717 stream_putc (s, options);
2718
Paul Jakma8dd24ee2006-08-27 06:29:30 +00002719 /* DD flags */
paul9985f832005-02-09 15:51:56 +00002720 pp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002721 stream_putc (s, nbr->dd_flags);
2722
2723 /* Set DD Sequence Number. */
2724 stream_putl (s, nbr->dd_seqnum);
2725
Paul Jakmab5aeb442006-08-30 18:47:37 +00002726 /* shortcut unneeded walk of (empty) summary LSDBs */
paul718e3742002-12-13 20:15:29 +00002727 if (ospf_db_summary_isempty (nbr))
Paul Jakmab5aeb442006-08-30 18:47:37 +00002728 goto empty;
paul718e3742002-12-13 20:15:29 +00002729
2730 /* Describe LSA Header from Database Summary List. */
2731 lsdb = &nbr->db_sum;
2732
2733 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
2734 {
2735 struct route_table *table = lsdb->type[i].db;
2736 struct route_node *rn;
2737
2738 for (rn = route_top (table); rn; rn = route_next (rn))
2739 if ((lsa = rn->info) != NULL)
2740 {
2741#ifdef HAVE_OPAQUE_LSA
2742 if (IS_OPAQUE_LSA (lsa->data->type)
2743 && (! CHECK_FLAG (options, OSPF_OPTION_O)))
2744 {
2745 /* Suppress advertising opaque-informations. */
2746 /* Remove LSA from DB summary list. */
2747 ospf_lsdb_delete (lsdb, lsa);
2748 continue;
2749 }
2750#endif /* HAVE_OPAQUE_LSA */
2751
2752 if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
2753 {
2754 struct lsa_header *lsah;
2755 u_int16_t ls_age;
2756
2757 /* DD packet overflows interface MTU. */
gdt86f1fd92005-01-10 14:20:43 +00002758 if (length + OSPF_LSA_HEADER_SIZE > ospf_packet_max (oi))
paul718e3742002-12-13 20:15:29 +00002759 break;
2760
2761 /* Keep pointer to LS age. */
2762 lsah = (struct lsa_header *) (STREAM_DATA (s) +
paul9985f832005-02-09 15:51:56 +00002763 stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +00002764
2765 /* Proceed stream pointer. */
2766 stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
2767 length += OSPF_LSA_HEADER_SIZE;
2768
2769 /* Set LS age. */
2770 ls_age = LS_AGE (lsa);
2771 lsah->ls_age = htons (ls_age);
2772
2773 }
2774
2775 /* Remove LSA from DB summary list. */
2776 ospf_lsdb_delete (lsdb, lsa);
2777 }
2778 }
2779
Paul Jakma8dd24ee2006-08-27 06:29:30 +00002780 /* Update 'More' bit */
2781 if (ospf_db_summary_isempty (nbr))
2782 {
Paul Jakmab5aeb442006-08-30 18:47:37 +00002783empty:
2784 if (nbr->state >= NSM_Exchange)
2785 {
2786 UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M);
2787 /* Rewrite DD flags */
2788 stream_putc_at (s, pp, nbr->dd_flags);
2789 }
2790 else
2791 {
2792 assert (IS_SET_DD_M(nbr->dd_flags));
2793 }
Paul Jakma8dd24ee2006-08-27 06:29:30 +00002794 }
paul718e3742002-12-13 20:15:29 +00002795 return length;
2796}
2797
paul4dadc292005-05-06 21:37:42 +00002798static int
paul718e3742002-12-13 20:15:29 +00002799ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
2800 unsigned long delta, struct ospf_neighbor *nbr,
2801 struct ospf_lsa *lsa)
2802{
2803 struct ospf_interface *oi;
2804
2805 oi = nbr->oi;
2806
2807 /* LS Request packet overflows interface MTU. */
gdt86f1fd92005-01-10 14:20:43 +00002808 if (*length + delta > ospf_packet_max(oi))
paul718e3742002-12-13 20:15:29 +00002809 return 0;
2810
2811 stream_putl (s, lsa->data->type);
2812 stream_put_ipv4 (s, lsa->data->id.s_addr);
2813 stream_put_ipv4 (s, lsa->data->adv_router.s_addr);
2814
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002815 ospf_lsa_unlock (&nbr->ls_req_last);
paul718e3742002-12-13 20:15:29 +00002816 nbr->ls_req_last = ospf_lsa_lock (lsa);
2817
2818 *length += 12;
2819 return 1;
2820}
2821
paul4dadc292005-05-06 21:37:42 +00002822static int
paul718e3742002-12-13 20:15:29 +00002823ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
2824{
2825 struct ospf_lsa *lsa;
2826 u_int16_t length = OSPF_LS_REQ_MIN_SIZE;
paul9985f832005-02-09 15:51:56 +00002827 unsigned long delta = stream_get_endp(s)+12;
paul718e3742002-12-13 20:15:29 +00002828 struct route_table *table;
2829 struct route_node *rn;
2830 int i;
2831 struct ospf_lsdb *lsdb;
2832
2833 lsdb = &nbr->ls_req;
2834
2835 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
2836 {
2837 table = lsdb->type[i].db;
2838 for (rn = route_top (table); rn; rn = route_next (rn))
2839 if ((lsa = (rn->info)) != NULL)
2840 if (ospf_make_ls_req_func (s, &length, delta, nbr, lsa) == 0)
2841 {
2842 route_unlock_node (rn);
2843 break;
2844 }
2845 }
2846 return length;
2847}
2848
paul4dadc292005-05-06 21:37:42 +00002849static int
paul718e3742002-12-13 20:15:29 +00002850ls_age_increment (struct ospf_lsa *lsa, int delay)
2851{
2852 int age;
2853
2854 age = IS_LSA_MAXAGE (lsa) ? OSPF_LSA_MAXAGE : LS_AGE (lsa) + delay;
2855
2856 return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
2857}
2858
paul4dadc292005-05-06 21:37:42 +00002859static int
hasso52dc7ee2004-09-23 19:18:23 +00002860ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s)
paul718e3742002-12-13 20:15:29 +00002861{
2862 struct ospf_lsa *lsa;
hasso52dc7ee2004-09-23 19:18:23 +00002863 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002864 u_int16_t length = OSPF_LS_UPD_MIN_SIZE;
gdt86f1fd92005-01-10 14:20:43 +00002865 unsigned int size_noauth;
paul9985f832005-02-09 15:51:56 +00002866 unsigned long delta = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00002867 unsigned long pp;
2868 int count = 0;
2869
2870 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002871 zlog_debug ("ospf_make_ls_upd: Start");
paul59ea14c2004-07-14 20:50:36 +00002872
paul9985f832005-02-09 15:51:56 +00002873 pp = stream_get_endp (s);
2874 stream_forward_endp (s, OSPF_LS_UPD_MIN_SIZE);
paul718e3742002-12-13 20:15:29 +00002875
gdt86f1fd92005-01-10 14:20:43 +00002876 /* Calculate amount of packet usable for data. */
2877 size_noauth = stream_get_size(s) - ospf_packet_authspace(oi);
2878
paul718e3742002-12-13 20:15:29 +00002879 while ((node = listhead (update)) != NULL)
2880 {
2881 struct lsa_header *lsah;
2882 u_int16_t ls_age;
2883
2884 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002885 zlog_debug ("ospf_make_ls_upd: List Iteration");
paul718e3742002-12-13 20:15:29 +00002886
paul1eb8ef22005-04-07 07:30:20 +00002887 lsa = listgetdata (node);
2888
paul718e3742002-12-13 20:15:29 +00002889 assert (lsa->data);
2890
paul68b73392004-09-12 14:21:37 +00002891 /* Will it fit? */
gdt86f1fd92005-01-10 14:20:43 +00002892 if (length + delta + ntohs (lsa->data->length) > size_noauth)
paul59ea14c2004-07-14 20:50:36 +00002893 break;
2894
paul718e3742002-12-13 20:15:29 +00002895 /* Keep pointer to LS age. */
paul9985f832005-02-09 15:51:56 +00002896 lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +00002897
2898 /* Put LSA to Link State Request. */
2899 stream_put (s, lsa->data, ntohs (lsa->data->length));
2900
2901 /* Set LS age. */
2902 /* each hop must increment an lsa_age by transmit_delay
2903 of OSPF interface */
2904 ls_age = ls_age_increment (lsa, OSPF_IF_PARAM (oi, transmit_delay));
2905 lsah->ls_age = htons (ls_age);
2906
2907 length += ntohs (lsa->data->length);
2908 count++;
2909
2910 list_delete_node (update, node);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002911 ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +00002912 }
2913
2914 /* Now set #LSAs. */
paul3a9eb092005-02-08 11:29:41 +00002915 stream_putl_at (s, pp, count);
paul718e3742002-12-13 20:15:29 +00002916
2917 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00002918 zlog_debug ("ospf_make_ls_upd: Stop");
paul718e3742002-12-13 20:15:29 +00002919 return length;
2920}
2921
paul4dadc292005-05-06 21:37:42 +00002922static int
hasso52dc7ee2004-09-23 19:18:23 +00002923ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
paul718e3742002-12-13 20:15:29 +00002924{
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002925 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002926 u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
paul9985f832005-02-09 15:51:56 +00002927 unsigned long delta = stream_get_endp(s) + 24;
paul718e3742002-12-13 20:15:29 +00002928 struct ospf_lsa *lsa;
2929
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002930 for (ALL_LIST_ELEMENTS (ack, node, nnode, lsa))
paul718e3742002-12-13 20:15:29 +00002931 {
paul718e3742002-12-13 20:15:29 +00002932 assert (lsa);
2933
gdt86f1fd92005-01-10 14:20:43 +00002934 if (length + delta > ospf_packet_max (oi))
paul718e3742002-12-13 20:15:29 +00002935 break;
2936
2937 stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
2938 length += OSPF_LSA_HEADER_SIZE;
2939
paul718e3742002-12-13 20:15:29 +00002940 listnode_delete (ack, lsa);
Paul Jakma1fe6ed32006-07-26 09:37:26 +00002941 ospf_lsa_unlock (&lsa); /* oi->ls_ack_direct.ls_ack */
paul718e3742002-12-13 20:15:29 +00002942 }
2943
paul718e3742002-12-13 20:15:29 +00002944 return length;
2945}
2946
2947void
2948ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
2949{
2950 struct ospf_packet *op;
2951 u_int16_t length = OSPF_HEADER_SIZE;
2952
2953 op = ospf_packet_new (oi->ifp->mtu);
2954
2955 /* Prepare OSPF common header. */
2956 ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
2957
2958 /* Prepare OSPF Hello body. */
2959 length += ospf_make_hello (oi, op->s);
2960
2961 /* Fill OSPF header. */
2962 ospf_fill_header (oi, op->s, length);
2963
2964 /* Set packet length. */
2965 op->length = length;
2966
2967 op->dst.s_addr = addr->s_addr;
2968
2969 /* Add packet to the interface output queue. */
2970 ospf_packet_add (oi, op);
2971
2972 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00002973 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00002974}
2975
paul4dadc292005-05-06 21:37:42 +00002976static void
paul718e3742002-12-13 20:15:29 +00002977ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
2978{
2979 struct ospf_interface *oi;
2980
2981 oi = nbr_nbma->oi;
2982 assert(oi);
2983
2984 /* If this is passive interface, do not send OSPF Hello. */
Paul Jakma7ffa8fa2006-10-22 20:07:53 +00002985 if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
paul718e3742002-12-13 20:15:29 +00002986 return;
2987
2988 if (oi->type != OSPF_IFTYPE_NBMA)
2989 return;
2990
2991 if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
2992 return;
2993
2994 if (PRIORITY(oi) == 0)
2995 return;
2996
2997 if (nbr_nbma->priority == 0
2998 && oi->state != ISM_DR && oi->state != ISM_Backup)
2999 return;
3000
3001 ospf_hello_send_sub (oi, &nbr_nbma->addr);
3002}
3003
3004int
3005ospf_poll_timer (struct thread *thread)
3006{
3007 struct ospf_nbr_nbma *nbr_nbma;
3008
3009 nbr_nbma = THREAD_ARG (thread);
3010 nbr_nbma->t_poll = NULL;
3011
3012 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
ajs2a42e282004-12-08 18:43:03 +00003013 zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (Poll timer expire)",
paul718e3742002-12-13 20:15:29 +00003014 IF_NAME (nbr_nbma->oi), inet_ntoa (nbr_nbma->addr));
3015
3016 ospf_poll_send (nbr_nbma);
3017
3018 if (nbr_nbma->v_poll > 0)
3019 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
3020 nbr_nbma->v_poll);
3021
3022 return 0;
3023}
3024
3025
3026int
3027ospf_hello_reply_timer (struct thread *thread)
3028{
3029 struct ospf_neighbor *nbr;
3030
3031 nbr = THREAD_ARG (thread);
3032 nbr->t_hello_reply = NULL;
3033
3034 assert (nbr->oi);
3035
3036 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
ajs2a42e282004-12-08 18:43:03 +00003037 zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
paul718e3742002-12-13 20:15:29 +00003038 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
3039
3040 ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
3041
3042 return 0;
3043}
3044
3045/* Send OSPF Hello. */
3046void
3047ospf_hello_send (struct ospf_interface *oi)
3048{
3049 struct ospf_packet *op;
3050 u_int16_t length = OSPF_HEADER_SIZE;
3051
3052 /* If this is passive interface, do not send OSPF Hello. */
Paul Jakma7ffa8fa2006-10-22 20:07:53 +00003053 if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
paul718e3742002-12-13 20:15:29 +00003054 return;
3055
3056 op = ospf_packet_new (oi->ifp->mtu);
3057
3058 /* Prepare OSPF common header. */
3059 ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
3060
3061 /* Prepare OSPF Hello body. */
3062 length += ospf_make_hello (oi, op->s);
3063
3064 /* Fill OSPF header. */
3065 ospf_fill_header (oi, op->s, length);
3066
3067 /* Set packet length. */
3068 op->length = length;
3069
3070 if (oi->type == OSPF_IFTYPE_NBMA)
3071 {
3072 struct ospf_neighbor *nbr;
3073 struct route_node *rn;
3074
3075 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
3076 if ((nbr = rn->info))
3077 if (nbr != oi->nbr_self)
3078 if (nbr->state != NSM_Down)
3079 {
3080 /* RFC 2328 Section 9.5.1
3081 If the router is not eligible to become Designated Router,
3082 it must periodically send Hello Packets to both the
3083 Designated Router and the Backup Designated Router (if they
3084 exist). */
3085 if (PRIORITY(oi) == 0 &&
3086 IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
3087 IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
3088 continue;
3089
3090 /* If the router is eligible to become Designated Router, it
3091 must periodically send Hello Packets to all neighbors that
3092 are also eligible. In addition, if the router is itself the
3093 Designated Router or Backup Designated Router, it must also
3094 send periodic Hello Packets to all other neighbors. */
3095
3096 if (nbr->priority == 0 && oi->state == ISM_DROther)
3097 continue;
3098 /* if oi->state == Waiting, send hello to all neighbors */
3099 {
3100 struct ospf_packet *op_dup;
3101
3102 op_dup = ospf_packet_dup(op);
3103 op_dup->dst = nbr->address.u.prefix4;
3104
3105 /* Add packet to the interface output queue. */
3106 ospf_packet_add (oi, op_dup);
3107
paul020709f2003-04-04 02:44:16 +00003108 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003109 }
3110
3111 }
3112 ospf_packet_free (op);
3113 }
3114 else
3115 {
3116 /* Decide destination address. */
3117 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3118 op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
3119 else
3120 op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3121
3122 /* Add packet to the interface output queue. */
3123 ospf_packet_add (oi, op);
3124
3125 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003126 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003127 }
3128}
3129
3130/* Send OSPF Database Description. */
3131void
3132ospf_db_desc_send (struct ospf_neighbor *nbr)
3133{
3134 struct ospf_interface *oi;
3135 struct ospf_packet *op;
3136 u_int16_t length = OSPF_HEADER_SIZE;
3137
3138 oi = nbr->oi;
3139 op = ospf_packet_new (oi->ifp->mtu);
3140
3141 /* Prepare OSPF common header. */
3142 ospf_make_header (OSPF_MSG_DB_DESC, oi, op->s);
3143
3144 /* Prepare OSPF Database Description body. */
3145 length += ospf_make_db_desc (oi, nbr, op->s);
3146
3147 /* Fill OSPF header. */
3148 ospf_fill_header (oi, op->s, length);
3149
3150 /* Set packet length. */
3151 op->length = length;
3152
3153 /* Decide destination address. */
Joakim Tjernlund53d0dec2008-05-30 16:04:39 +02003154 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
3155 op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3156 else
3157 op->dst = nbr->address.u.prefix4;
paul718e3742002-12-13 20:15:29 +00003158
3159 /* Add packet to the interface output queue. */
3160 ospf_packet_add (oi, op);
3161
3162 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003163 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003164
3165 /* Remove old DD packet, then copy new one and keep in neighbor structure. */
3166 if (nbr->last_send)
3167 ospf_packet_free (nbr->last_send);
3168 nbr->last_send = ospf_packet_dup (op);
Paul Jakma2518efd2006-08-27 06:49:29 +00003169 quagga_gettime (QUAGGA_CLK_MONOTONIC, &nbr->last_send_ts);
paul718e3742002-12-13 20:15:29 +00003170}
3171
3172/* Re-send Database Description. */
3173void
3174ospf_db_desc_resend (struct ospf_neighbor *nbr)
3175{
3176 struct ospf_interface *oi;
3177
3178 oi = nbr->oi;
3179
3180 /* Add packet to the interface output queue. */
3181 ospf_packet_add (oi, ospf_packet_dup (nbr->last_send));
3182
3183 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003184 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003185}
3186
3187/* Send Link State Request. */
3188void
3189ospf_ls_req_send (struct ospf_neighbor *nbr)
3190{
3191 struct ospf_interface *oi;
3192 struct ospf_packet *op;
3193 u_int16_t length = OSPF_HEADER_SIZE;
3194
3195 oi = nbr->oi;
3196 op = ospf_packet_new (oi->ifp->mtu);
3197
3198 /* Prepare OSPF common header. */
3199 ospf_make_header (OSPF_MSG_LS_REQ, oi, op->s);
3200
3201 /* Prepare OSPF Link State Request body. */
3202 length += ospf_make_ls_req (nbr, op->s);
3203 if (length == OSPF_HEADER_SIZE)
3204 {
3205 ospf_packet_free (op);
3206 return;
3207 }
3208
3209 /* Fill OSPF header. */
3210 ospf_fill_header (oi, op->s, length);
3211
3212 /* Set packet length. */
3213 op->length = length;
3214
3215 /* Decide destination address. */
Joakim Tjernlund53d0dec2008-05-30 16:04:39 +02003216 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
3217 op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3218 else
3219 op->dst = nbr->address.u.prefix4;
paul718e3742002-12-13 20:15:29 +00003220
3221 /* Add packet to the interface output queue. */
3222 ospf_packet_add (oi, op);
3223
3224 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003225 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003226
3227 /* Add Link State Request Retransmission Timer. */
3228 OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
3229}
3230
3231/* Send Link State Update with an LSA. */
3232void
3233ospf_ls_upd_send_lsa (struct ospf_neighbor *nbr, struct ospf_lsa *lsa,
3234 int flag)
3235{
hasso52dc7ee2004-09-23 19:18:23 +00003236 struct list *update;
paul718e3742002-12-13 20:15:29 +00003237
3238 update = list_new ();
3239
3240 listnode_add (update, lsa);
3241 ospf_ls_upd_send (nbr, update, flag);
3242
3243 list_delete (update);
3244}
3245
paul68b73392004-09-12 14:21:37 +00003246/* Determine size for packet. Must be at least big enough to accomodate next
3247 * LSA on list, which may be bigger than MTU size.
3248 *
3249 * Return pointer to new ospf_packet
3250 * NULL if we can not allocate, eg because LSA is bigger than imposed limit
3251 * on packet sizes (in which case offending LSA is deleted from update list)
3252 */
3253static struct ospf_packet *
3254ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi)
3255{
3256 struct ospf_lsa *lsa;
3257 struct listnode *ln;
3258 size_t size;
3259 static char warned = 0;
3260
paul1eb8ef22005-04-07 07:30:20 +00003261 lsa = listgetdata((ln = listhead (update)));
paul68b73392004-09-12 14:21:37 +00003262 assert (lsa->data);
3263
3264 if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length))
3265 > ospf_packet_max (oi))
3266 {
3267 if (!warned)
3268 {
3269 zlog_warn ("ospf_ls_upd_packet_new: oversized LSA encountered!"
3270 "will need to fragment. Not optimal. Try divide up"
3271 " your network with areas. Use 'debug ospf packet send'"
3272 " to see details, or look at 'show ip ospf database ..'");
3273 warned = 1;
3274 }
3275
3276 if (IS_DEBUG_OSPF_PACKET (0, SEND))
ajs2a42e282004-12-08 18:43:03 +00003277 zlog_debug ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
paul68b73392004-09-12 14:21:37 +00003278 " %d bytes originated by %s, will be fragmented!",
3279 inet_ntoa (lsa->data->id),
3280 ntohs (lsa->data->length),
3281 inet_ntoa (lsa->data->adv_router));
3282
3283 /*
3284 * Allocate just enough to fit this LSA only, to avoid including other
3285 * LSAs in fragmented LSA Updates.
3286 */
3287 size = ntohs (lsa->data->length) + (oi->ifp->mtu - ospf_packet_max (oi))
3288 + OSPF_LS_UPD_MIN_SIZE;
3289 }
3290 else
3291 size = oi->ifp->mtu;
3292
gdt86f1fd92005-01-10 14:20:43 +00003293 /* XXX Should this be - sizeof(struct ip)?? -gdt */
paul68b73392004-09-12 14:21:37 +00003294 if (size > OSPF_MAX_PACKET_SIZE)
3295 {
3296 zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s too big,"
paul64511f32004-10-31 18:01:13 +00003297 " %d bytes, packet size %ld, dropping it completely."
paul68b73392004-09-12 14:21:37 +00003298 " OSPF routing is broken!",
paul37ccfa32004-10-31 11:24:51 +00003299 inet_ntoa (lsa->data->id), ntohs (lsa->data->length),
paul62d8e962004-11-02 20:26:45 +00003300 (long int) size);
paul68b73392004-09-12 14:21:37 +00003301 list_delete_node (update, ln);
3302 return NULL;
3303 }
3304
3305 return ospf_packet_new (size);
3306}
3307
paul718e3742002-12-13 20:15:29 +00003308static void
hasso52dc7ee2004-09-23 19:18:23 +00003309ospf_ls_upd_queue_send (struct ospf_interface *oi, struct list *update,
paul718e3742002-12-13 20:15:29 +00003310 struct in_addr addr)
3311{
3312 struct ospf_packet *op;
3313 u_int16_t length = OSPF_HEADER_SIZE;
3314
3315 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00003316 zlog_debug ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
paul68b73392004-09-12 14:21:37 +00003317
3318 op = ospf_ls_upd_packet_new (update, oi);
paul718e3742002-12-13 20:15:29 +00003319
3320 /* Prepare OSPF common header. */
3321 ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s);
3322
paul59ea14c2004-07-14 20:50:36 +00003323 /* Prepare OSPF Link State Update body.
3324 * Includes Type-7 translation.
3325 */
paul718e3742002-12-13 20:15:29 +00003326 length += ospf_make_ls_upd (oi, update, op->s);
3327
3328 /* Fill OSPF header. */
3329 ospf_fill_header (oi, op->s, length);
3330
3331 /* Set packet length. */
3332 op->length = length;
3333
3334 /* Decide destination address. */
Joakim Tjernlund53d0dec2008-05-30 16:04:39 +02003335 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
3336 op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3337 else
3338 op->dst.s_addr = addr.s_addr;
paul718e3742002-12-13 20:15:29 +00003339
3340 /* Add packet to the interface output queue. */
3341 ospf_packet_add (oi, op);
3342
3343 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003344 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003345}
3346
3347static int
3348ospf_ls_upd_send_queue_event (struct thread *thread)
3349{
3350 struct ospf_interface *oi = THREAD_ARG(thread);
3351 struct route_node *rn;
paul736d3442003-07-24 23:22:57 +00003352 struct route_node *rnext;
paul59ea14c2004-07-14 20:50:36 +00003353 struct list *update;
paul68b73392004-09-12 14:21:37 +00003354 char again = 0;
paul718e3742002-12-13 20:15:29 +00003355
3356 oi->t_ls_upd_event = NULL;
3357
3358 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00003359 zlog_debug ("ospf_ls_upd_send_queue start");
paul718e3742002-12-13 20:15:29 +00003360
paul736d3442003-07-24 23:22:57 +00003361 for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
paul718e3742002-12-13 20:15:29 +00003362 {
paul736d3442003-07-24 23:22:57 +00003363 rnext = route_next (rn);
3364
paul718e3742002-12-13 20:15:29 +00003365 if (rn->info == NULL)
paul736d3442003-07-24 23:22:57 +00003366 continue;
paul68b73392004-09-12 14:21:37 +00003367
3368 update = (struct list *)rn->info;
paul718e3742002-12-13 20:15:29 +00003369
paul48fe13b2004-07-27 17:40:44 +00003370 ospf_ls_upd_queue_send (oi, update, rn->p.u.prefix4);
paul718e3742002-12-13 20:15:29 +00003371
paul68b73392004-09-12 14:21:37 +00003372 /* list might not be empty. */
paul59ea14c2004-07-14 20:50:36 +00003373 if (listcount(update) == 0)
3374 {
3375 list_delete (rn->info);
3376 rn->info = NULL;
3377 route_unlock_node (rn);
3378 }
3379 else
paul68b73392004-09-12 14:21:37 +00003380 again = 1;
paul59ea14c2004-07-14 20:50:36 +00003381 }
3382
3383 if (again != 0)
3384 {
3385 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00003386 zlog_debug ("ospf_ls_upd_send_queue: update lists not cleared,"
paul59ea14c2004-07-14 20:50:36 +00003387 " %d nodes to try again, raising new event", again);
3388 oi->t_ls_upd_event =
3389 thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
paul718e3742002-12-13 20:15:29 +00003390 }
3391
3392 if (IS_DEBUG_OSPF_EVENT)
ajs2a42e282004-12-08 18:43:03 +00003393 zlog_debug ("ospf_ls_upd_send_queue stop");
paul59ea14c2004-07-14 20:50:36 +00003394
paul718e3742002-12-13 20:15:29 +00003395 return 0;
3396}
3397
3398void
hasso52dc7ee2004-09-23 19:18:23 +00003399ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
paul718e3742002-12-13 20:15:29 +00003400{
3401 struct ospf_interface *oi;
paul1eb8ef22005-04-07 07:30:20 +00003402 struct ospf_lsa *lsa;
paul718e3742002-12-13 20:15:29 +00003403 struct prefix_ipv4 p;
3404 struct route_node *rn;
paul1eb8ef22005-04-07 07:30:20 +00003405 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00003406
3407 oi = nbr->oi;
3408
3409 p.family = AF_INET;
3410 p.prefixlen = IPV4_MAX_BITLEN;
3411
3412 /* Decide destination address. */
3413 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3414 p.prefix = oi->vl_data->peer_addr;
Joakim Tjernlund53d0dec2008-05-30 16:04:39 +02003415 else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
3416 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul718e3742002-12-13 20:15:29 +00003417 else if (flag == OSPF_SEND_PACKET_DIRECT)
3418 p.prefix = nbr->address.u.prefix4;
3419 else if (oi->state == ISM_DR || oi->state == ISM_Backup)
3420 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul7afa08d2002-12-13 20:59:45 +00003421 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
3422 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul718e3742002-12-13 20:15:29 +00003423 else
3424 p.prefix.s_addr = htonl (OSPF_ALLDROUTERS);
3425
3426 if (oi->type == OSPF_IFTYPE_NBMA)
3427 {
3428 if (flag == OSPF_SEND_PACKET_INDIRECT)
3429 zlog_warn ("* LS-Update is directly sent on NBMA network.");
3430 if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr))
3431 zlog_warn ("* LS-Update is sent to myself.");
3432 }
3433
3434 rn = route_node_get (oi->ls_upd_queue, (struct prefix *) &p);
3435
3436 if (rn->info == NULL)
3437 rn->info = list_new ();
3438
paul1eb8ef22005-04-07 07:30:20 +00003439 for (ALL_LIST_ELEMENTS_RO (update, node, lsa))
Paul Jakma1fe6ed32006-07-26 09:37:26 +00003440 listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */
paul718e3742002-12-13 20:15:29 +00003441
3442 if (oi->t_ls_upd_event == NULL)
3443 oi->t_ls_upd_event =
3444 thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
3445}
3446
3447static void
hasso52dc7ee2004-09-23 19:18:23 +00003448ospf_ls_ack_send_list (struct ospf_interface *oi, struct list *ack,
3449 struct in_addr dst)
paul718e3742002-12-13 20:15:29 +00003450{
3451 struct ospf_packet *op;
3452 u_int16_t length = OSPF_HEADER_SIZE;
3453
3454 op = ospf_packet_new (oi->ifp->mtu);
3455
3456 /* Prepare OSPF common header. */
3457 ospf_make_header (OSPF_MSG_LS_ACK, oi, op->s);
3458
3459 /* Prepare OSPF Link State Acknowledgment body. */
3460 length += ospf_make_ls_ack (oi, ack, op->s);
3461
3462 /* Fill OSPF header. */
3463 ospf_fill_header (oi, op->s, length);
3464
3465 /* Set packet length. */
3466 op->length = length;
3467
3468 /* Set destination IP address. */
3469 op->dst = dst;
3470
3471 /* Add packet to the interface output queue. */
3472 ospf_packet_add (oi, op);
3473
3474 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003475 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003476}
3477
3478static int
3479ospf_ls_ack_send_event (struct thread *thread)
3480{
3481 struct ospf_interface *oi = THREAD_ARG (thread);
3482
3483 oi->t_ls_ack_direct = NULL;
3484
3485 while (listcount (oi->ls_ack_direct.ls_ack))
3486 ospf_ls_ack_send_list (oi, oi->ls_ack_direct.ls_ack,
3487 oi->ls_ack_direct.dst);
3488
3489 return 0;
3490}
3491
3492void
3493ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
3494{
3495 struct ospf_interface *oi = nbr->oi;
3496
3497 if (listcount (oi->ls_ack_direct.ls_ack) == 0)
3498 oi->ls_ack_direct.dst = nbr->address.u.prefix4;
3499
3500 listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa));
3501
3502 if (oi->t_ls_ack_direct == NULL)
3503 oi->t_ls_ack_direct =
3504 thread_add_event (master, ospf_ls_ack_send_event, oi, 0);
3505}
3506
3507/* Send Link State Acknowledgment delayed. */
3508void
3509ospf_ls_ack_send_delayed (struct ospf_interface *oi)
3510{
3511 struct in_addr dst;
3512
3513 /* Decide destination address. */
3514 /* RFC2328 Section 13.5 On non-broadcast
3515 networks, delayed Link State Acknowledgment packets must be
3516 unicast separately over each adjacency (i.e., neighbor whose
3517 state is >= Exchange). */
3518 if (oi->type == OSPF_IFTYPE_NBMA)
3519 {
3520 struct ospf_neighbor *nbr;
3521 struct route_node *rn;
3522
3523 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
3524 if ((nbr = rn->info) != NULL)
3525 if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
3526 while (listcount (oi->ls_ack))
3527 ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4);
3528 return;
3529 }
3530 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3531 dst.s_addr = oi->vl_data->peer_addr.s_addr;
3532 else if (oi->state == ISM_DR || oi->state == ISM_Backup)
3533 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3534 else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
3535 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
gdt630e4802004-08-31 17:28:41 +00003536 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
3537 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul718e3742002-12-13 20:15:29 +00003538 else
3539 dst.s_addr = htonl (OSPF_ALLDROUTERS);
3540
3541 while (listcount (oi->ls_ack))
3542 ospf_ls_ack_send_list (oi, oi->ls_ack, dst);
3543}