blob: eaf8b76979be0ec0a47f957a1516f9c5ebe612e0 [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"
paul718e3742002-12-13 20:15:29 +000035#include "md5-gnu.h"
36
37#include "ospfd/ospfd.h"
38#include "ospfd/ospf_network.h"
39#include "ospfd/ospf_interface.h"
40#include "ospfd/ospf_ism.h"
41#include "ospfd/ospf_asbr.h"
42#include "ospfd/ospf_lsa.h"
43#include "ospfd/ospf_lsdb.h"
44#include "ospfd/ospf_neighbor.h"
45#include "ospfd/ospf_nsm.h"
46#include "ospfd/ospf_packet.h"
47#include "ospfd/ospf_spf.h"
48#include "ospfd/ospf_flood.h"
49#include "ospfd/ospf_dump.h"
50
hasso52dc7ee2004-09-23 19:18:23 +000051static void ospf_ls_ack_send_list (struct ospf_interface *, struct list *,
paul718e3742002-12-13 20:15:29 +000052 struct in_addr);
53
54/* Packet Type String. */
55char *ospf_packet_type_str[] =
56{
57 "unknown",
58 "Hello",
59 "Database Description",
60 "Link State Request",
61 "Link State Update",
62 "Link State Acknowledgment",
63};
64
65extern int in_cksum (void *ptr, int nbytes);
66
67/* OSPF authentication checking function */
68int
69ospf_auth_type (struct ospf_interface *oi)
70{
71 int auth_type;
72
73 if (OSPF_IF_PARAM (oi, auth_type) == OSPF_AUTH_NOTSET)
74 auth_type = oi->area->auth_type;
75 else
76 auth_type = OSPF_IF_PARAM (oi, auth_type);
77
78 /* Handle case where MD5 key list is not configured aka Cisco */
79 if (auth_type == OSPF_AUTH_CRYPTOGRAPHIC &&
80 list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
81 return OSPF_AUTH_NULL;
82
83 return auth_type;
84
85}
86
87/* forward output pointer. */
88void
89ospf_output_forward (struct stream *s, int size)
90{
91 s->putp += size;
92}
93
94struct ospf_packet *
95ospf_packet_new (size_t size)
96{
97 struct ospf_packet *new;
98
99 new = XCALLOC (MTYPE_OSPF_PACKET, sizeof (struct ospf_packet));
100 new->s = stream_new (size);
101
102 return new;
103}
104
105void
106ospf_packet_free (struct ospf_packet *op)
107{
108 if (op->s)
109 stream_free (op->s);
110
111 XFREE (MTYPE_OSPF_PACKET, op);
112
113 op = NULL;
114}
115
116struct ospf_fifo *
117ospf_fifo_new ()
118{
119 struct ospf_fifo *new;
120
121 new = XCALLOC (MTYPE_OSPF_FIFO, sizeof (struct ospf_fifo));
122 return new;
123}
124
125/* Add new packet to fifo. */
126void
127ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
128{
129 if (fifo->tail)
130 fifo->tail->next = op;
131 else
132 fifo->head = op;
133
134 fifo->tail = op;
135
136 fifo->count++;
137}
138
139/* Delete first packet from fifo. */
140struct ospf_packet *
141ospf_fifo_pop (struct ospf_fifo *fifo)
142{
143 struct ospf_packet *op;
144
145 op = fifo->head;
146
147 if (op)
148 {
149 fifo->head = op->next;
150
151 if (fifo->head == NULL)
152 fifo->tail = NULL;
153
154 fifo->count--;
155 }
156
157 return op;
158}
159
160/* Return first fifo entry. */
161struct ospf_packet *
162ospf_fifo_head (struct ospf_fifo *fifo)
163{
164 return fifo->head;
165}
166
167/* Flush ospf packet fifo. */
168void
169ospf_fifo_flush (struct ospf_fifo *fifo)
170{
171 struct ospf_packet *op;
172 struct ospf_packet *next;
173
174 for (op = fifo->head; op; op = next)
175 {
176 next = op->next;
177 ospf_packet_free (op);
178 }
179 fifo->head = fifo->tail = NULL;
180 fifo->count = 0;
181}
182
183/* Free ospf packet fifo. */
184void
185ospf_fifo_free (struct ospf_fifo *fifo)
186{
187 ospf_fifo_flush (fifo);
188
189 XFREE (MTYPE_OSPF_FIFO, fifo);
190}
191
192void
193ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
194{
195 /* 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
213struct stream *
214ospf_stream_copy (struct stream *new, struct stream *s)
215{
216 new->endp = s->endp;
217 new->putp = s->putp;
218 new->getp = s->getp;
219
220 memcpy (new->data, s->data, stream_get_endp (s));
221
222 return new;
223}
224
225struct ospf_packet *
226ospf_packet_dup (struct ospf_packet *op)
227{
228 struct ospf_packet *new;
229
paul37163d62003-02-03 18:40:56 +0000230 if (stream_get_endp(op->s) != op->length)
231 zlog_warn ("ospf_packet_dup stream %ld ospf_packet %d size mismatch",
paul30961a12002-12-13 20:56:48 +0000232 STREAM_SIZE(op->s), op->length);
paul30961a12002-12-13 20:56:48 +0000233
234 /* Reserve space for MD5 authentication that may be added later. */
235 new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
paul718e3742002-12-13 20:15:29 +0000236 ospf_stream_copy (new->s, op->s);
237
238 new->dst = op->dst;
239 new->length = op->length;
240
241 return new;
242}
243
244int
245ospf_packet_max (struct ospf_interface *oi)
246{
247 int max;
248
249 if ( ospf_auth_type (oi) == OSPF_AUTH_CRYPTOGRAPHIC)
paul68b73392004-09-12 14:21:37 +0000250 max = oi->ifp->mtu - OSPF_AUTH_MD5_SIZE;
paul718e3742002-12-13 20:15:29 +0000251 else
paul68b73392004-09-12 14:21:37 +0000252 max = oi->ifp->mtu;
253
254 max -= (OSPF_HEADER_SIZE + sizeof (struct ip));
paul718e3742002-12-13 20:15:29 +0000255
256 return max;
257}
258
259
260int
261ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
262 u_int16_t length)
263{
264 void *ibuf;
265 struct md5_ctx ctx;
266 unsigned char digest[OSPF_AUTH_MD5_SIZE];
267 unsigned char *pdigest;
268 struct crypt_key *ck;
269 struct ospf_header *ospfh;
270 struct ospf_neighbor *nbr;
271
272
273 ibuf = STREAM_PNT (s);
274 ospfh = (struct ospf_header *) ibuf;
275
276 /* Get pointer to the end of the packet. */
277 pdigest = ibuf + length;
278
279 /* Get secret key. */
280 ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
281 ospfh->u.crypt.key_id);
282 if (ck == NULL)
283 {
284 zlog_warn ("interface %s: ospf_check_md5 no key %d",
285 IF_NAME (oi), ospfh->u.crypt.key_id);
286 return 0;
287 }
288
289 /* check crypto seqnum. */
290 nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id);
291
292 if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(ospfh->u.crypt.crypt_seqnum))
293 {
294 zlog_warn ("interface %s: ospf_check_md5 bad sequence %d (expect %d)",
295 IF_NAME (oi),
296 ntohl(ospfh->u.crypt.crypt_seqnum),
297 ntohl(nbr->crypt_seqnum));
298 return 0;
299 }
300
301 /* Generate a digest for the ospf packet - their digest + our digest. */
302 md5_init_ctx (&ctx);
303 md5_process_bytes (ibuf, length, &ctx);
304 md5_process_bytes (ck->auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
305 md5_finish_ctx (&ctx, digest);
306
307 /* compare the two */
308 if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
309 {
310 zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
311 IF_NAME (oi));
312 return 0;
313 }
314
315 /* save neighbor's crypt_seqnum */
316 if (nbr)
317 nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
318 return 1;
319}
320
321/* This function is called from ospf_write(), it will detect the
322 authentication scheme and if it is MD5, it will change the sequence
323 and update the MD5 digest. */
324int
325ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
326{
327 struct ospf_header *ospfh;
328 unsigned char digest[OSPF_AUTH_MD5_SIZE];
329 struct md5_ctx ctx;
330 void *ibuf;
331 unsigned long oldputp;
paul9483e152002-12-13 20:55:25 +0000332 u_int32_t t;
paul718e3742002-12-13 20:15:29 +0000333 struct crypt_key *ck;
334 char *auth_key;
335
336 ibuf = STREAM_DATA (op->s);
337 ospfh = (struct ospf_header *) ibuf;
338
339 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
340 return 0;
341
342 /* We do this here so when we dup a packet, we don't have to
343 waste CPU rewriting other headers. */
paul9483e152002-12-13 20:55:25 +0000344 t = (time(NULL) & 0xFFFFFFFF);
345 oi->crypt_seqnum = ( t > oi->crypt_seqnum ? t : oi->crypt_seqnum++);
346 ospfh->u.crypt.crypt_seqnum = htonl (oi->crypt_seqnum);
paul718e3742002-12-13 20:15:29 +0000347
348 /* Get MD5 Authentication key from auth_key list. */
349 if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
350 auth_key = "";
351 else
352 {
353 ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
hassoc9e52be2004-09-26 16:09:34 +0000354 auth_key = (char *) ck->auth_key;
paul718e3742002-12-13 20:15:29 +0000355 }
356
357 /* Generate a digest for the entire packet + our secret key. */
358 md5_init_ctx (&ctx);
359 md5_process_bytes (ibuf, ntohs (ospfh->length), &ctx);
360 md5_process_bytes (auth_key, OSPF_AUTH_MD5_SIZE, &ctx);
361 md5_finish_ctx (&ctx, digest);
362
363 /* Append md5 digest to the end of the stream. */
364 oldputp = stream_get_putp (op->s);
365 stream_set_putp (op->s, ntohs (ospfh->length));
366 stream_put (op->s, digest, OSPF_AUTH_MD5_SIZE);
367 stream_set_putp (op->s, oldputp);
368
369 /* We do *NOT* increment the OSPF header length. */
paul30961a12002-12-13 20:56:48 +0000370 op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
371
paul37163d62003-02-03 18:40:56 +0000372 if (stream_get_endp(op->s) != op->length)
373 zlog_warn("ospf_make_md5_digest: length mismatch stream %ld ospf_packet %d", stream_get_endp(op->s), op->length);
paul718e3742002-12-13 20:15:29 +0000374
375 return OSPF_AUTH_MD5_SIZE;
376}
377
378
379int
380ospf_ls_req_timer (struct thread *thread)
381{
382 struct ospf_neighbor *nbr;
383
384 nbr = THREAD_ARG (thread);
385 nbr->t_ls_req = NULL;
386
387 /* Send Link State Request. */
388 if (ospf_ls_request_count (nbr))
389 ospf_ls_req_send (nbr);
390
391 /* Set Link State Request retransmission timer. */
392 OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
393
394 return 0;
395}
396
397void
398ospf_ls_req_event (struct ospf_neighbor *nbr)
399{
400 if (nbr->t_ls_req)
401 {
402 thread_cancel (nbr->t_ls_req);
403 nbr->t_ls_req = NULL;
404 }
405 nbr->t_ls_req = thread_add_event (master, ospf_ls_req_timer, nbr, 0);
406}
407
408/* Cyclic timer function. Fist registered in ospf_nbr_new () in
409 ospf_neighbor.c */
410int
411ospf_ls_upd_timer (struct thread *thread)
412{
413 struct ospf_neighbor *nbr;
414
415 nbr = THREAD_ARG (thread);
416 nbr->t_ls_upd = NULL;
417
418 /* Send Link State Update. */
419 if (ospf_ls_retransmit_count (nbr) > 0)
420 {
hasso52dc7ee2004-09-23 19:18:23 +0000421 struct list *update;
paul718e3742002-12-13 20:15:29 +0000422 struct ospf_lsdb *lsdb;
423 int i;
424 struct timeval now;
425 int retransmit_interval;
426
427 gettimeofday (&now, NULL);
428 retransmit_interval = OSPF_IF_PARAM (nbr->oi, retransmit_interval);
429
430 lsdb = &nbr->ls_rxmt;
431 update = list_new ();
432
433 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
434 {
435 struct route_table *table = lsdb->type[i].db;
436 struct route_node *rn;
437
438 for (rn = route_top (table); rn; rn = route_next (rn))
439 {
440 struct ospf_lsa *lsa;
441
442 if ((lsa = rn->info) != NULL)
443 /* Don't retransmit an LSA if we received it within
444 the last RxmtInterval seconds - this is to allow the
445 neighbour a chance to acknowledge the LSA as it may
446 have ben just received before the retransmit timer
447 fired. This is a small tweak to what is in the RFC,
448 but it will cut out out a lot of retransmit traffic
449 - MAG */
450 if (tv_cmp (tv_sub (now, lsa->tv_recv),
451 int2tv (retransmit_interval)) >= 0)
452 listnode_add (update, rn->info);
453 }
454 }
455
456 if (listcount (update) > 0)
457 ospf_ls_upd_send (nbr, update, OSPF_SEND_PACKET_DIRECT);
458 list_delete (update);
459 }
460
461 /* Set LS Update retransmission timer. */
462 OSPF_NSM_TIMER_ON (nbr->t_ls_upd, ospf_ls_upd_timer, nbr->v_ls_upd);
463
464 return 0;
465}
466
467int
468ospf_ls_ack_timer (struct thread *thread)
469{
470 struct ospf_interface *oi;
471
472 oi = THREAD_ARG (thread);
473 oi->t_ls_ack = NULL;
474
475 /* Send Link State Acknowledgment. */
476 if (listcount (oi->ls_ack) > 0)
477 ospf_ls_ack_send_delayed (oi);
478
479 /* Set LS Ack timer. */
480 OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack);
481
482 return 0;
483}
484
paul68b73392004-09-12 14:21:37 +0000485/* swab ip header fields to required order for sendmsg */
486void
487ospf_swab_iph_ton (struct ip *iph)
488{
489 /* BSD and derived take iph in network order, except for
490 * ip_len and ip_off
491 */
paul6a99f832004-09-27 12:56:30 +0000492#ifndef HAVE_IP_HDRINCL_BSD_ORDER
paul68b73392004-09-12 14:21:37 +0000493 iph->ip_len = htons(iph->ip_len);
494 iph->ip_off = htons(iph->ip_off);
paul6a99f832004-09-27 12:56:30 +0000495#endif /* HAVE_IP_HDRINCL_BSD_ORDER */
496
paul68b73392004-09-12 14:21:37 +0000497 iph->ip_id = htons(iph->ip_id);
498}
499
500/* swab ip header fields to host order, as required */
501void
502ospf_swab_iph_toh (struct ip *iph)
503{
paul6a99f832004-09-27 12:56:30 +0000504#ifdef HAVE_IP_HDRINCL_BSD_ORDER
paul68b73392004-09-12 14:21:37 +0000505 iph->ip_len = ntohs(iph->ip_len);
506 iph->ip_off = ntohs(iph->ip_off);
paul6a99f832004-09-27 12:56:30 +0000507#endif /* HAVE_IP_HDRINCL_BSD_ORDER */
508
paul68b73392004-09-12 14:21:37 +0000509 iph->ip_id = ntohs(iph->ip_id);
510}
511
paul0bfeca32004-09-24 08:07:54 +0000512#ifdef WANT_OSPF_WRITE_FRAGMENT
513void
paul6a99f832004-09-27 12:56:30 +0000514ospf_write_frags (int fd, struct ospf_packet *op, struct ip *iph,
515 struct msghdr *msg, struct iovec **iov,
516 int maxdatasize, int mtu, int flags)
paul0bfeca32004-09-24 08:07:54 +0000517{
518#define OSPF_WRITE_FRAG_SHIFT 3
paul6a99f832004-09-27 12:56:30 +0000519 u_int16_t offset;
520 int ret;
paul0bfeca32004-09-24 08:07:54 +0000521
522 assert ( op->length == stream_get_endp(op->s) );
523
524 /* we can but try.
525 *
526 * SunOS, BSD and BSD derived kernels likely will clear ip_id, as
527 * well as the IP_MF flag, making this all quite pointless.
528 *
529 * However, for a system on which IP_MF is left alone, and ip_id left
530 * alone or else which sets same ip_id for each fragment this might
531 * work, eg linux.
532 *
533 * XXX-TODO: It would be much nicer to have the kernel's use their
534 * existing fragmentation support to do this for us. Bugs/RFEs need to
535 * be raised against the various kernels.
536 */
537
538 /* set More Frag */
539 iph->ip_off |= IP_MF;
540
541 /* ip frag offset is expressed in units of 8byte words */
542 offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT;
543
544 while ( (stream_get_endp(op->s) - stream_get_getp (op->s))
545 > maxdatasize )
546 {
547 /* data length of this frag is to next offset value */
548 iov[1]->iov_len = offset << OSPF_WRITE_FRAG_SHIFT;
549 iph->ip_len = iov[1]->iov_len + sizeof (struct ip);
paul6a99f832004-09-27 12:56:30 +0000550 assert (iph->ip_len <= mtu);
paul0bfeca32004-09-24 08:07:54 +0000551
552 ospf_swab_iph_ton (iph);
553
paul6a99f832004-09-27 12:56:30 +0000554 ret = sendmsg (fd, msg, flags);
paul0bfeca32004-09-24 08:07:54 +0000555
556 ospf_swab_iph_toh (iph);
557
558 if (ret < 0)
559 zlog_warn ("*** sendmsg in ospf_write to %s,"
560 " id %d, off %d, len %d failed with %s",
561 inet_ntoa (iph->ip_dst),
562 iph->ip_id,
563 iph->ip_off,
564 iph->ip_len,
565 strerror (errno));
566
567 iph->ip_off += offset;
568 stream_forward (op->s, iov[1]->iov_len);
569 iov[1]->iov_base = STREAM_PNT (op->s);
570 }
571
572 /* setup for final fragment */
573 iov[1]->iov_len = stream_get_endp(op->s) - stream_get_getp (op->s);
574 iph->ip_len = iov[1]->iov_len + sizeof (struct ip);
575 iph->ip_off &= (~IP_MF);
576}
577#endif /* WANT_OSPF_WRITE_FRAGMENT */
578
paul718e3742002-12-13 20:15:29 +0000579int
580ospf_write (struct thread *thread)
581{
paul68980082003-03-25 05:07:42 +0000582 struct ospf *ospf = THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000583 struct ospf_interface *oi;
584 struct ospf_packet *op;
585 struct sockaddr_in sa_dst;
paul718e3742002-12-13 20:15:29 +0000586 struct ip iph;
587 struct msghdr msg;
paul6a99f832004-09-27 12:56:30 +0000588 struct iovec iov[2], *iovp;
paul68980082003-03-25 05:07:42 +0000589 u_char type;
590 int ret;
591 int flags = 0;
hasso52dc7ee2004-09-23 19:18:23 +0000592 struct listnode *node;
paul0bfeca32004-09-24 08:07:54 +0000593#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000594 static u_int16_t ipid = 0;
paul0bfeca32004-09-24 08:07:54 +0000595#endif /* WANT_OSPF_WRITE_FRAGMENT */
paul6a99f832004-09-27 12:56:30 +0000596 u_int16_t maxdatasize;
paul68b73392004-09-12 14:21:37 +0000597#define OSPF_WRITE_IPHL_SHIFT 2
paul718e3742002-12-13 20:15:29 +0000598
paul68980082003-03-25 05:07:42 +0000599 ospf->t_write = NULL;
paul718e3742002-12-13 20:15:29 +0000600
paul68980082003-03-25 05:07:42 +0000601 node = listhead (ospf->oi_write_q);
paul718e3742002-12-13 20:15:29 +0000602 assert (node);
603 oi = getdata (node);
604 assert (oi);
paul0bfeca32004-09-24 08:07:54 +0000605
606#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000607 /* seed ipid static with low order bits of time */
608 if (ipid == 0)
609 ipid = (time(NULL) & 0xffff);
paul0bfeca32004-09-24 08:07:54 +0000610#endif /* WANT_OSPF_WRITE_FRAGMENT */
611
paul68b73392004-09-12 14:21:37 +0000612 /* convenience - max OSPF data per packet */
613 maxdatasize = oi->ifp->mtu - sizeof (struct ip);
614
paul718e3742002-12-13 20:15:29 +0000615 /* Get one packet from queue. */
616 op = ospf_fifo_head (oi->obuf);
617 assert (op);
618 assert (op->length >= OSPF_HEADER_SIZE);
619
paul68980082003-03-25 05:07:42 +0000620 if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
621 || op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
paul68b73392004-09-12 14:21:37 +0000622 ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
623
paul718e3742002-12-13 20:15:29 +0000624 /* Rewrite the md5 signature & update the seq */
625 ospf_make_md5_digest (oi, op);
626
paul68b73392004-09-12 14:21:37 +0000627 /* reset get pointer */
628 stream_set_getp (op->s, 0);
629
630 memset (&iph, 0, sizeof (struct ip));
paul718e3742002-12-13 20:15:29 +0000631 memset (&sa_dst, 0, sizeof (sa_dst));
paul68b73392004-09-12 14:21:37 +0000632
paul718e3742002-12-13 20:15:29 +0000633 sa_dst.sin_family = AF_INET;
634#ifdef HAVE_SIN_LEN
635 sa_dst.sin_len = sizeof(sa_dst);
636#endif /* HAVE_SIN_LEN */
637 sa_dst.sin_addr = op->dst;
638 sa_dst.sin_port = htons (0);
639
640 /* Set DONTROUTE flag if dst is unicast. */
641 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
642 if (!IN_MULTICAST (htonl (op->dst.s_addr)))
643 flags = MSG_DONTROUTE;
644
paul68b73392004-09-12 14:21:37 +0000645 iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
646 /* it'd be very strange for header to not be 4byte-word aligned but.. */
647 if ( sizeof (struct ip) > (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
648 iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
649
paul718e3742002-12-13 20:15:29 +0000650 iph.ip_v = IPVERSION;
paul68980082003-03-25 05:07:42 +0000651 iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
paul68b73392004-09-12 14:21:37 +0000652 iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
paul68b73392004-09-12 14:21:37 +0000653
paul0bfeca32004-09-24 08:07:54 +0000654#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000655 /* XXX-MT: not thread-safe at all..
656 * XXX: this presumes this is only programme sending OSPF packets
657 * otherwise, no guarantee ipid will be unique
658 */
659 iph.ip_id = ++ipid;
paul0bfeca32004-09-24 08:07:54 +0000660#endif /* WANT_OSPF_WRITE_FRAGMENT */
661
paul718e3742002-12-13 20:15:29 +0000662 iph.ip_off = 0;
663 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
664 iph.ip_ttl = OSPF_VL_IP_TTL;
665 else
666 iph.ip_ttl = OSPF_IP_TTL;
667 iph.ip_p = IPPROTO_OSPFIGP;
668 iph.ip_sum = 0;
669 iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
670 iph.ip_dst.s_addr = op->dst.s_addr;
671
672 memset (&msg, 0, sizeof (msg));
paul68defd62004-09-27 07:27:13 +0000673 msg.msg_name = (caddr_t) &sa_dst;
paul718e3742002-12-13 20:15:29 +0000674 msg.msg_namelen = sizeof (sa_dst);
675 msg.msg_iov = iov;
676 msg.msg_iovlen = 2;
677 iov[0].iov_base = (char*)&iph;
paul68b73392004-09-12 14:21:37 +0000678 iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
679 iov[1].iov_base = STREAM_PNT (op->s);
paul718e3742002-12-13 20:15:29 +0000680 iov[1].iov_len = op->length;
paul68b73392004-09-12 14:21:37 +0000681
682 /* Sadly we can not rely on kernels to fragment packets because of either
683 * IP_HDRINCL and/or multicast destination being set.
684 */
paul0bfeca32004-09-24 08:07:54 +0000685#ifdef WANT_OSPF_WRITE_FRAGMENT
paul68b73392004-09-12 14:21:37 +0000686 if ( op->length > maxdatasize )
paul6a99f832004-09-27 12:56:30 +0000687 {
688 iovp = iov;
689 ospf_write_frags (ospf->fd, op, &iph, &msg, &iovp, maxdatasize,
690 oi->ifp->mtu, flags);
691 }
paul0bfeca32004-09-24 08:07:54 +0000692#endif /* WANT_OSPF_WRITE_FRAGMENT */
paul68b73392004-09-12 14:21:37 +0000693
694 /* send final fragment (could be first) */
695 ospf_swab_iph_ton (&iph);
paul68980082003-03-25 05:07:42 +0000696 ret = sendmsg (ospf->fd, &msg, flags);
paul68b73392004-09-12 14:21:37 +0000697 ospf_swab_iph_toh (&iph);
paul718e3742002-12-13 20:15:29 +0000698
699 if (ret < 0)
paul68b73392004-09-12 14:21:37 +0000700 zlog_warn ("*** sendmsg in ospf_write to %s failed with %s",
701 inet_ntoa (iph.ip_dst), strerror (errno));
paul718e3742002-12-13 20:15:29 +0000702
703 /* Retrieve OSPF packet type. */
704 stream_set_getp (op->s, 1);
705 type = stream_getc (op->s);
706
707 /* Show debug sending packet. */
708 if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
709 {
710 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
711 {
712 zlog_info ("-----------------------------------------------------");
713 stream_set_getp (op->s, 0);
714 ospf_packet_dump (op->s);
715 }
716
717 zlog_info ("%s sent to [%s] via [%s].",
718 ospf_packet_type_str[type], inet_ntoa (op->dst),
719 IF_NAME (oi));
720
721 if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
722 zlog_info ("-----------------------------------------------------");
723 }
724
725 /* Now delete packet from queue. */
726 ospf_packet_delete (oi);
727
728 if (ospf_fifo_head (oi->obuf) == NULL)
729 {
730 oi->on_write_q = 0;
paul68980082003-03-25 05:07:42 +0000731 list_delete_node (ospf->oi_write_q, node);
paul718e3742002-12-13 20:15:29 +0000732 }
733
734 /* If packets still remain in queue, call write thread. */
paul68980082003-03-25 05:07:42 +0000735 if (!list_isempty (ospf->oi_write_q))
736 ospf->t_write =
737 thread_add_write (master, ospf_write, ospf, ospf->fd);
paul718e3742002-12-13 20:15:29 +0000738
739 return 0;
740}
741
742/* OSPF Hello message read -- RFC2328 Section 10.5. */
743void
744ospf_hello (struct ip *iph, struct ospf_header *ospfh,
745 struct stream * s, struct ospf_interface *oi, int size)
746{
747 struct ospf_hello *hello;
748 struct ospf_neighbor *nbr;
paul718e3742002-12-13 20:15:29 +0000749 int old_state;
pauld3f0d622004-05-05 15:27:15 +0000750 struct prefix p;
paul718e3742002-12-13 20:15:29 +0000751
752 /* increment statistics. */
753 oi->hello_in++;
754
755 hello = (struct ospf_hello *) STREAM_PNT (s);
756
757 /* If Hello is myself, silently discard. */
paul68980082003-03-25 05:07:42 +0000758 if (IPV4_ADDR_SAME (&ospfh->router_id, &oi->ospf->router_id))
pauld3241812003-09-29 12:42:39 +0000759 {
760 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
761 {
762 zlog_info ("ospf_header[%s/%s]: selforiginated, "
763 "dropping.",
764 ospf_packet_type_str[ospfh->type],
765 inet_ntoa (iph->ip_src));
766 }
767 return;
768 }
paul718e3742002-12-13 20:15:29 +0000769
770 /* If incoming interface is passive one, ignore Hello. */
paulf2c80652002-12-13 21:44:27 +0000771 if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
paulc2191ea2003-04-18 23:59:35 +0000772 zlog_info ("Packet %s [HELLO:RECV]: oi is passive",
773 inet_ntoa (ospfh->router_id));
paul718e3742002-12-13 20:15:29 +0000774 return;
paulf2c80652002-12-13 21:44:27 +0000775 }
paul718e3742002-12-13 20:15:29 +0000776
777 /* get neighbor prefix. */
778 p.family = AF_INET;
779 p.prefixlen = ip_masklen (hello->network_mask);
780 p.u.prefix4 = iph->ip_src;
781
782 /* Compare network mask. */
783 /* Checking is ignored for Point-to-Point and Virtual link. */
784 if (oi->type != OSPF_IFTYPE_POINTOPOINT
785 && oi->type != OSPF_IFTYPE_VIRTUALLINK)
786 if (oi->address->prefixlen != p.prefixlen)
787 {
788 zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.",
789 inet_ntoa (ospfh->router_id));
790 return;
791 }
792
793 /* Compare Hello Interval. */
794 if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
795 {
796 zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.",
797 inet_ntoa (ospfh->router_id));
798 return;
799 }
800
801 /* Compare Router Dead Interval. */
802 if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
803 {
804 zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch.",
805 inet_ntoa (ospfh->router_id));
806 return;
807 }
808
809 if (IS_DEBUG_OSPF_EVENT)
810 zlog_info ("Packet %s [Hello:RECV]: Options %s",
811 inet_ntoa (ospfh->router_id),
812 ospf_options_dump (hello->options));
813
814 /* Compare options. */
815#define REJECT_IF_TBIT_ON 1 /* XXX */
816#ifdef REJECT_IF_TBIT_ON
817 if (CHECK_FLAG (hello->options, OSPF_OPTION_T))
818 {
819 /*
820 * This router does not support non-zero TOS.
821 * Drop this Hello packet not to establish neighbor relationship.
822 */
823 zlog_warn ("Packet %s [Hello:RECV]: T-bit on, drop it.",
824 inet_ntoa (ospfh->router_id));
825 return;
826 }
827#endif /* REJECT_IF_TBIT_ON */
828
829#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +0000830 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE)
paul718e3742002-12-13 20:15:29 +0000831 && CHECK_FLAG (hello->options, OSPF_OPTION_O))
832 {
833 /*
834 * This router does know the correct usage of O-bit
835 * the bit should be set in DD packet only.
836 */
837 zlog_warn ("Packet %s [Hello:RECV]: O-bit abuse?",
838 inet_ntoa (ospfh->router_id));
839#ifdef STRICT_OBIT_USAGE_CHECK
840 return; /* Reject this packet. */
841#else /* STRICT_OBIT_USAGE_CHECK */
842 UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */
843#endif /* STRICT_OBIT_USAGE_CHECK */
844 }
845#endif /* HAVE_OPAQUE_LSA */
846
847 /* new for NSSA is to ensure that NP is on and E is off */
848
paul718e3742002-12-13 20:15:29 +0000849 if (oi->area->external_routing == OSPF_AREA_NSSA)
850 {
851 if (! (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_NP)
852 && CHECK_FLAG (hello->options, OSPF_OPTION_NP)
853 && ! CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E)
854 && ! CHECK_FLAG (hello->options, OSPF_OPTION_E)))
855 {
856 zlog_warn ("NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", inet_ntoa (ospfh->router_id), OPTIONS (oi), hello->options);
857 return;
858 }
859 if (IS_DEBUG_OSPF_NSSA)
860 zlog_info ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id));
861 }
862 else
paul718e3742002-12-13 20:15:29 +0000863 /* The setting of the E-bit found in the Hello Packet's Options
864 field must match this area's ExternalRoutingCapability A
865 mismatch causes processing to stop and the packet to be
866 dropped. The setting of the rest of the bits in the Hello
867 Packet's Options field should be ignored. */
868 if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) !=
869 CHECK_FLAG (hello->options, OSPF_OPTION_E))
870 {
871 zlog_warn ("Packet[Hello:RECV]: my options: %x, his options %x",
872 OPTIONS (oi), hello->options);
873 return;
874 }
paul718e3742002-12-13 20:15:29 +0000875
pauld3f0d622004-05-05 15:27:15 +0000876 /* get neighbour struct */
877 nbr = ospf_nbr_get (oi, ospfh, iph, &p);
878
879 /* neighbour must be valid, ospf_nbr_get creates if none existed */
880 assert (nbr);
paul718e3742002-12-13 20:15:29 +0000881
882 old_state = nbr->state;
883
884 /* Add event to thread. */
885 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
886
887 /* RFC2328 Section 9.5.1
888 If the router is not eligible to become Designated Router,
889 (snip) It must also send an Hello Packet in reply to an
890 Hello Packet received from any eligible neighbor (other than
891 the current Designated Router and Backup Designated Router). */
892 if (oi->type == OSPF_IFTYPE_NBMA)
893 if (PRIORITY(oi) == 0 && hello->priority > 0
894 && IPV4_ADDR_CMP(&DR(oi), &iph->ip_src)
895 && IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src))
896 OSPF_NSM_TIMER_ON (nbr->t_hello_reply, ospf_hello_reply_timer,
897 OSPF_HELLO_REPLY_DELAY);
898
899 /* on NBMA network type, it happens to receive bidirectional Hello packet
900 without advance 1-Way Received event.
901 To avoid incorrect DR-seletion, raise 1-Way Received event.*/
902 if (oi->type == OSPF_IFTYPE_NBMA &&
903 (old_state == NSM_Down || old_state == NSM_Attempt))
904 {
905 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
906 nbr->priority = hello->priority;
907 nbr->d_router = hello->d_router;
908 nbr->bd_router = hello->bd_router;
909 return;
910 }
911
paul68980082003-03-25 05:07:42 +0000912 if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
paul718e3742002-12-13 20:15:29 +0000913 size - OSPF_HELLO_MIN_SIZE))
914 {
915 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
916 nbr->options |= hello->options;
917 }
918 else
919 {
920 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
921 /* Set neighbor information. */
922 nbr->priority = hello->priority;
923 nbr->d_router = hello->d_router;
924 nbr->bd_router = hello->bd_router;
925 return;
926 }
927
928 /* If neighbor itself declares DR and no BDR exists,
929 cause event BackupSeen */
930 if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router))
931 if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting)
932 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
933
934 /* neighbor itself declares BDR. */
935 if (oi->state == ISM_Waiting &&
936 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router))
937 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
938
939 /* had not previously. */
940 if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) &&
941 IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) ||
942 (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) &&
943 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router)))
944 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
945
946 /* had not previously. */
947 if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) &&
948 IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) ||
949 (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) &&
950 IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router)))
951 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
952
953 /* Neighbor priority check. */
954 if (nbr->priority >= 0 && nbr->priority != hello->priority)
955 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
956
957 /* Set neighbor information. */
958 nbr->priority = hello->priority;
959 nbr->d_router = hello->d_router;
960 nbr->bd_router = hello->bd_router;
961}
962
963/* Save DD flags/options/Seqnum received. */
964void
965ospf_db_desc_save_current (struct ospf_neighbor *nbr,
966 struct ospf_db_desc *dd)
967{
968 nbr->last_recv.flags = dd->flags;
969 nbr->last_recv.options = dd->options;
970 nbr->last_recv.dd_seqnum = ntohl (dd->dd_seqnum);
971}
972
973/* Process rest of DD packet. */
974static void
975ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi,
976 struct ospf_neighbor *nbr, struct ospf_db_desc *dd,
977 u_int16_t size)
978{
979 struct ospf_lsa *new, *find;
980 struct lsa_header *lsah;
981
982 stream_forward (s, OSPF_DB_DESC_MIN_SIZE);
983 for (size -= OSPF_DB_DESC_MIN_SIZE;
984 size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE)
985 {
986 lsah = (struct lsa_header *) STREAM_PNT (s);
987 stream_forward (s, OSPF_LSA_HEADER_SIZE);
988
989 /* Unknown LS type. */
990 if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
991 {
992 zlog_warn ("Pakcet [DD:RECV]: Unknown LS type %d.", lsah->type);
993 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
994 return;
995 }
996
997#ifdef HAVE_OPAQUE_LSA
998 if (IS_OPAQUE_LSA (lsah->type)
999 && ! CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1000 {
1001 zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
1002 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1003 return;
1004 }
1005#endif /* HAVE_OPAQUE_LSA */
1006
1007 switch (lsah->type)
1008 {
1009 case OSPF_AS_EXTERNAL_LSA:
1010#ifdef HAVE_OPAQUE_LSA
1011 case OSPF_OPAQUE_AS_LSA:
1012#endif /* HAVE_OPAQUE_LSA */
paul718e3742002-12-13 20:15:29 +00001013 /* Check for stub area. Reject if AS-External from stub but
1014 allow if from NSSA. */
1015 if (oi->area->external_routing == OSPF_AREA_STUB)
paul718e3742002-12-13 20:15:29 +00001016 {
1017 zlog_warn ("Packet [DD:RECV]: LSA[Type%d:%s] from %s area.",
1018 lsah->type, inet_ntoa (lsah->id),
1019 (oi->area->external_routing == OSPF_AREA_STUB) ?\
1020 "STUB" : "NSSA");
1021 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1022 return;
1023 }
1024 break;
1025 default:
1026 break;
1027 }
1028
1029 /* Create LS-request object. */
1030 new = ospf_ls_request_new (lsah);
1031
1032 /* Lookup received LSA, then add LS request list. */
1033 find = ospf_lsa_lookup_by_header (oi->area, lsah);
1034 if (!find || ospf_lsa_more_recent (find, new) < 0)
1035 {
1036 ospf_ls_request_add (nbr, new);
1037 ospf_lsa_discard (new);
1038 }
1039 else
1040 {
1041 /* Received LSA is not recent. */
1042 if (IS_DEBUG_OSPF_EVENT)
1043 zlog_info ("Packet [DD:RECV]: LSA received Type %d, "
1044 "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
1045 ospf_lsa_discard (new);
1046 continue;
1047 }
1048 }
1049
1050 /* Master */
1051 if (IS_SET_DD_MS (nbr->dd_flags))
1052 {
1053 nbr->dd_seqnum++;
1054 /* Entire DD packet sent. */
1055 if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
1056 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
1057 else
1058 /* Send new DD packet. */
1059 ospf_db_desc_send (nbr);
1060 }
1061 /* Slave */
1062 else
1063 {
1064 nbr->dd_seqnum = ntohl (dd->dd_seqnum);
1065
1066 /* When master's more flags is not set. */
1067 if (!IS_SET_DD_M (dd->flags) && ospf_db_summary_isempty (nbr))
1068 {
1069 nbr->dd_flags &= ~(OSPF_DD_FLAG_M);
1070 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
1071 }
1072
1073 /* Send DD pakcet in reply. */
1074 ospf_db_desc_send (nbr);
1075 }
1076
1077 /* Save received neighbor values from DD. */
1078 ospf_db_desc_save_current (nbr, dd);
1079}
1080
1081int
1082ospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr)
1083{
1084 /* Is DD duplicated? */
1085 if (dd->options == nbr->last_recv.options &&
1086 dd->flags == nbr->last_recv.flags &&
1087 dd->dd_seqnum == htonl (nbr->last_recv.dd_seqnum))
1088 return 1;
1089
1090 return 0;
1091}
1092
1093/* OSPF Database Description message read -- RFC2328 Section 10.6. */
1094void
1095ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
1096 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1097{
1098 struct ospf_db_desc *dd;
1099 struct ospf_neighbor *nbr;
1100
1101 /* Increment statistics. */
1102 oi->db_desc_in++;
1103
1104 dd = (struct ospf_db_desc *) STREAM_PNT (s);
pauld363df22003-06-19 00:26:34 +00001105
pauld3f0d622004-05-05 15:27:15 +00001106 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001107 if (nbr == NULL)
1108 {
1109 zlog_warn ("Packet[DD]: Unknown Neighbor %s",
1110 inet_ntoa (ospfh->router_id));
1111 return;
1112 }
1113
1114 /* Check MTU. */
1115 if (ntohs (dd->mtu) > oi->ifp->mtu)
1116 {
1117 zlog_warn ("Packet[DD]: MTU is larger than [%s]'s MTU", IF_NAME (oi));
1118 return;
1119 }
1120
pauld363df22003-06-19 00:26:34 +00001121 /*
1122 * XXX HACK by Hasso Tepper. Setting N/P bit in NSSA area DD packets is not
1123 * required. In fact at least JunOS sends DD packets with P bit clear.
1124 * Until proper solution is developped, this hack should help.
1125 *
1126 * Update: According to the RFCs, N bit is specified /only/ for Hello
1127 * options, unfortunately its use in DD options is not specified. Hence some
1128 * implementations follow E-bit semantics and set it in DD options, and some
1129 * treat it as unspecified and hence follow the directive "default for
1130 * options is clear", ie unset.
1131 *
1132 * Reset the flag, as ospfd follows E-bit semantics.
1133 */
1134 if ( (oi->area->external_routing == OSPF_AREA_NSSA)
1135 && (CHECK_FLAG (nbr->options, OSPF_OPTION_NP))
1136 && (!CHECK_FLAG (dd->options, OSPF_OPTION_NP)) )
1137 {
1138 if (IS_DEBUG_OSPF_EVENT)
paul3db0a772003-06-19 01:07:40 +00001139 zlog_notice ("Packet[DD]: Neighbour %s: Has NSSA capability, sends with N bit clear in DD options",
pauld363df22003-06-19 00:26:34 +00001140 inet_ntoa (nbr->router_id) );
1141 SET_FLAG (dd->options, OSPF_OPTION_NP);
1142 }
pauld363df22003-06-19 00:26:34 +00001143
paul718e3742002-12-13 20:15:29 +00001144#ifdef REJECT_IF_TBIT_ON
1145 if (CHECK_FLAG (dd->options, OSPF_OPTION_T))
1146 {
1147 /*
1148 * In Hello protocol, optional capability must have checked
1149 * to prevent this T-bit enabled router be my neighbor.
1150 */
1151 zlog_warn ("Packet[DD]: Neighbor %s: T-bit on?", inet_ntoa (nbr->router_id));
1152 return;
1153 }
1154#endif /* REJECT_IF_TBIT_ON */
1155
1156#ifdef HAVE_OPAQUE_LSA
1157 if (CHECK_FLAG (dd->options, OSPF_OPTION_O)
paul68980082003-03-25 05:07:42 +00001158 && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00001159 {
1160 /*
1161 * This node is not configured to handle O-bit, for now.
1162 * Clear it to ignore unsupported capability proposed by neighbor.
1163 */
1164 UNSET_FLAG (dd->options, OSPF_OPTION_O);
1165 }
1166#endif /* HAVE_OPAQUE_LSA */
1167
1168 /* Process DD packet by neighbor status. */
1169 switch (nbr->state)
1170 {
1171 case NSM_Down:
1172 case NSM_Attempt:
1173 case NSM_TwoWay:
1174 zlog_warn ("Packet[DD]: Neighbor state is %s, packet discarded.",
1175 LOOKUP (ospf_nsm_state_msg, nbr->state));
1176 break;
1177 case NSM_Init:
1178 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
1179 /* If the new state is ExStart, the processing of the current
1180 packet should then continue in this new state by falling
1181 through to case ExStart below. */
1182 if (nbr->state != NSM_ExStart)
1183 break;
1184 case NSM_ExStart:
1185 /* Initial DBD */
1186 if ((IS_SET_DD_ALL (dd->flags) == OSPF_DD_FLAG_ALL) &&
1187 (size == OSPF_DB_DESC_MIN_SIZE))
1188 {
paul68980082003-03-25 05:07:42 +00001189 if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0)
paul718e3742002-12-13 20:15:29 +00001190 {
1191 /* We're Slave---obey */
1192 zlog_warn ("Packet[DD]: Negotiation done (Slave).");
1193 nbr->dd_seqnum = ntohl (dd->dd_seqnum);
1194 nbr->dd_flags &= ~(OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I); /* Reset I/MS */
1195 }
1196 else
1197 {
1198 /* We're Master, ignore the initial DBD from Slave */
1199 zlog_warn ("Packet[DD]: Initial DBD from Slave, ignoring.");
1200 break;
1201 }
1202 }
1203 /* Ack from the Slave */
1204 else if (!IS_SET_DD_MS (dd->flags) && !IS_SET_DD_I (dd->flags) &&
1205 ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&
paul68980082003-03-25 05:07:42 +00001206 IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0)
paul718e3742002-12-13 20:15:29 +00001207 {
1208 zlog_warn ("Packet[DD]: Negotiation done (Master).");
1209 nbr->dd_flags &= ~OSPF_DD_FLAG_I;
1210 }
1211 else
1212 {
1213 zlog_warn ("Packet[DD]: Negotiation fails.");
1214 break;
1215 }
1216
1217 /* This is where the real Options are saved */
1218 nbr->options = dd->options;
1219
1220#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00001221 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00001222 {
1223 if (IS_DEBUG_OSPF_EVENT)
1224 zlog_info ("Neighbor[%s] is %sOpaque-capable.",
1225 inet_ntoa (nbr->router_id),
1226 CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");
1227
1228 if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
1229 && IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
1230 {
1231 zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; Opaque-LSAs cannot be reliably advertised in this network.", inet_ntoa (nbr->router_id));
1232 /* This situation is undesirable, but not a real error. */
1233 }
1234 }
1235#endif /* HAVE_OPAQUE_LSA */
1236
1237 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);
1238
1239 /* continue processing rest of packet. */
1240 ospf_db_desc_proc (s, oi, nbr, dd, size);
1241 break;
1242 case NSM_Exchange:
1243 if (ospf_db_desc_is_dup (dd, nbr))
1244 {
1245 if (IS_SET_DD_MS (nbr->dd_flags))
1246 /* Master: discard duplicated DD packet. */
1247 zlog_warn ("Packet[DD] (Master): packet duplicated.");
1248 else
1249 /* Slave: cause to retransmit the last Database Description. */
1250 {
1251 zlog_warn ("Packet[DD] [Slave]: packet duplicated.");
1252 ospf_db_desc_resend (nbr);
1253 }
1254 break;
1255 }
1256
1257 /* Otherwise DD packet should be checked. */
1258 /* Check Master/Slave bit mismatch */
1259 if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))
1260 {
1261 zlog_warn ("Packet[DD]: MS-bit mismatch.");
1262 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1263 if (IS_DEBUG_OSPF_EVENT)
1264 zlog_info ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",
1265 dd->flags, nbr->dd_flags);
1266 break;
1267 }
1268
1269 /* Check initialize bit is set. */
1270 if (IS_SET_DD_I (dd->flags))
1271 {
1272 zlog_warn ("Packet[DD]: I-bit set.");
1273 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1274 break;
1275 }
1276
1277 /* Check DD Options. */
1278 if (dd->options != nbr->options)
1279 {
1280#ifdef ORIGINAL_CODING
1281 /* Save the new options for debugging */
1282 nbr->options = dd->options;
1283#endif /* ORIGINAL_CODING */
1284 zlog_warn ("Packet[DD]: options mismatch.");
1285 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1286 break;
1287 }
1288
1289 /* Check DD sequence number. */
1290 if ((IS_SET_DD_MS (nbr->dd_flags) &&
1291 ntohl (dd->dd_seqnum) != nbr->dd_seqnum) ||
1292 (!IS_SET_DD_MS (nbr->dd_flags) &&
1293 ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))
1294 {
1295 zlog_warn ("Pakcet[DD]: sequence number mismatch.");
1296 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1297 break;
1298 }
1299
1300 /* Continue processing rest of packet. */
1301 ospf_db_desc_proc (s, oi, nbr, dd, size);
1302 break;
1303 case NSM_Loading:
1304 case NSM_Full:
1305 if (ospf_db_desc_is_dup (dd, nbr))
1306 {
1307 if (IS_SET_DD_MS (nbr->dd_flags))
1308 {
1309 /* Master should discard duplicate DD packet. */
1310 zlog_warn ("Pakcet[DD]: duplicated, packet discarded.");
1311 break;
1312 }
1313 else
1314 {
1315 struct timeval t, now;
1316 gettimeofday (&now, NULL);
1317 t = tv_sub (now, nbr->last_send_ts);
1318 if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
1319 {
1320 /* In states Loading and Full the slave must resend
1321 its last Database Description packet in response to
1322 duplicate Database Description packets received
1323 from the master. For this reason the slave must
1324 wait RouterDeadInterval seconds before freeing the
1325 last Database Description packet. Reception of a
1326 Database Description packet from the master after
1327 this interval will generate a SeqNumberMismatch
1328 neighbor event. RFC2328 Section 10.8 */
1329 ospf_db_desc_resend (nbr);
1330 break;
1331 }
1332 }
1333 }
1334
1335 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
1336 break;
1337 default:
1338 zlog_warn ("Packet[DD]: NSM illegal status.");
1339 break;
1340 }
1341}
1342
1343#define OSPF_LSA_KEY_SIZE 12 /* type(4) + id(4) + ar(4) */
1344
1345/* OSPF Link State Request Read -- RFC2328 Section 10.7. */
1346void
1347ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
1348 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1349{
1350 struct ospf_neighbor *nbr;
1351 u_int32_t ls_type;
1352 struct in_addr ls_id;
1353 struct in_addr adv_router;
1354 struct ospf_lsa *find;
hasso52dc7ee2004-09-23 19:18:23 +00001355 struct list *ls_upd;
paul718e3742002-12-13 20:15:29 +00001356 int length;
1357
1358 /* Increment statistics. */
1359 oi->ls_req_in++;
1360
pauld3f0d622004-05-05 15:27:15 +00001361 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001362 if (nbr == NULL)
1363 {
1364 zlog_warn ("Link State Request: Unknown Neighbor %s.",
1365 inet_ntoa (ospfh->router_id));
1366 return;
1367 }
1368
1369 /* Neighbor State should be Exchange or later. */
1370 if (nbr->state != NSM_Exchange &&
1371 nbr->state != NSM_Loading &&
1372 nbr->state != NSM_Full)
1373 {
1374 zlog_warn ("Link State Request: Neighbor state is %s, packet discarded.",
1375 LOOKUP (ospf_nsm_state_msg, nbr->state));
1376 return;
1377 }
1378
1379 /* Send Link State Update for ALL requested LSAs. */
1380 ls_upd = list_new ();
1381 length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
1382
1383 while (size >= OSPF_LSA_KEY_SIZE)
1384 {
1385 /* Get one slice of Link State Request. */
1386 ls_type = stream_getl (s);
1387 ls_id.s_addr = stream_get_ipv4 (s);
1388 adv_router.s_addr = stream_get_ipv4 (s);
1389
1390 /* Verify LSA type. */
1391 if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA)
1392 {
1393 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
1394 list_delete (ls_upd);
1395 return;
1396 }
1397
1398 /* Search proper LSA in LSDB. */
1399 find = ospf_lsa_lookup (oi->area, ls_type, ls_id, adv_router);
1400 if (find == NULL)
1401 {
1402 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
1403 list_delete (ls_upd);
1404 return;
1405 }
1406
1407 /* Packet overflows MTU size, send immediatly. */
1408 if (length + ntohs (find->data->length) > OSPF_PACKET_MAX (oi))
1409 {
1410 if (oi->type == OSPF_IFTYPE_NBMA)
1411 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
1412 else
1413 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
1414
1415 /* Only remove list contents. Keep ls_upd. */
1416 list_delete_all_node (ls_upd);
1417
1418 length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;
1419 }
1420
1421 /* Append LSA to update list. */
1422 listnode_add (ls_upd, find);
1423 length += ntohs (find->data->length);
1424
1425 size -= OSPF_LSA_KEY_SIZE;
1426 }
1427
1428 /* Send rest of Link State Update. */
1429 if (listcount (ls_upd) > 0)
1430 {
1431 if (oi->type == OSPF_IFTYPE_NBMA)
1432 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);
1433 else
1434 ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);
1435
1436 list_delete (ls_upd);
1437 }
1438 else
1439 list_free (ls_upd);
1440}
1441
1442/* Get the list of LSAs from Link State Update packet.
1443 And process some validation -- RFC2328 Section 13. (1)-(2). */
hasso52dc7ee2004-09-23 19:18:23 +00001444static struct list *
paul718e3742002-12-13 20:15:29 +00001445ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,
1446 struct ospf_interface *oi, size_t size)
1447{
1448 u_int16_t count, sum;
1449 u_int32_t length;
1450 struct lsa_header *lsah;
1451 struct ospf_lsa *lsa;
hasso52dc7ee2004-09-23 19:18:23 +00001452 struct list *lsas;
paul718e3742002-12-13 20:15:29 +00001453
1454 lsas = list_new ();
1455
1456 count = stream_getl (s);
1457 size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */
1458
1459 for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;
1460 size -= length, stream_forward (s, length), count--)
1461 {
1462 lsah = (struct lsa_header *) STREAM_PNT (s);
1463 length = ntohs (lsah->length);
1464
1465 if (length > size)
1466 {
1467 zlog_warn ("Link State Update: LSA length exceeds packet size.");
1468 break;
1469 }
1470
1471 /* Validate the LSA's LS checksum. */
1472 sum = lsah->checksum;
1473 if (sum != ospf_lsa_checksum (lsah))
1474 {
1475 zlog_warn ("Link State Update: LSA checksum error %x, %x.",
1476 sum, lsah->checksum);
1477 continue;
1478 }
1479
1480 /* Examine the LSA's LS type. */
1481 if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)
1482 {
1483 zlog_warn ("Link State Update: Unknown LS type %d", lsah->type);
1484 continue;
1485 }
1486
1487 /*
1488 * What if the received LSA's age is greater than MaxAge?
1489 * Treat it as a MaxAge case -- endo.
1490 */
1491 if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)
1492 lsah->ls_age = htons (OSPF_LSA_MAXAGE);
1493
1494#ifdef HAVE_OPAQUE_LSA
1495 if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))
1496 {
1497#ifdef STRICT_OBIT_USAGE_CHECK
1498 if ((IS_OPAQUE_LSA(lsah->type) &&
1499 ! CHECK_FLAG (lsah->options, OSPF_OPTION_O))
1500 || (! IS_OPAQUE_LSA(lsah->type) &&
1501 CHECK_FLAG (lsah->options, OSPF_OPTION_O)))
1502 {
1503 /*
1504 * This neighbor must know the exact usage of O-bit;
1505 * the bit will be set in Type-9,10,11 LSAs only.
1506 */
1507 zlog_warn ("LSA[Type%d:%s]: O-bit abuse?", lsah->type, inet_ntoa (lsah->id));
1508 continue;
1509 }
1510#endif /* STRICT_OBIT_USAGE_CHECK */
1511
1512 /* Do not take in AS External Opaque-LSAs if we are a stub. */
1513 if (lsah->type == OSPF_OPAQUE_AS_LSA
1514 && nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
1515 {
1516 if (IS_DEBUG_OSPF_EVENT)
1517 zlog_info ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));
1518 continue;
1519 }
1520 }
1521 else if (IS_OPAQUE_LSA(lsah->type))
1522 {
1523 zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));
1524 continue;
1525 }
1526#endif /* HAVE_OPAQUE_LSA */
1527
1528 /* Create OSPF LSA instance. */
1529 lsa = ospf_lsa_new ();
1530
1531 /* We may wish to put some error checking if type NSSA comes in
1532 and area not in NSSA mode */
1533 switch (lsah->type)
1534 {
1535 case OSPF_AS_EXTERNAL_LSA:
1536#ifdef HAVE_OPAQUE_LSA
1537 case OSPF_OPAQUE_AS_LSA:
1538 lsa->area = NULL;
1539 break;
1540 case OSPF_OPAQUE_LINK_LSA:
1541 lsa->oi = oi; /* Remember incoming interface for flooding control. */
1542 /* Fallthrough */
1543#endif /* HAVE_OPAQUE_LSA */
1544 default:
1545 lsa->area = oi->area;
1546 break;
1547 }
1548
1549 lsa->data = ospf_lsa_data_new (length);
1550 memcpy (lsa->data, lsah, length);
1551
1552 if (IS_DEBUG_OSPF_EVENT)
1553 zlog_info("LSA[Type%d:%s]: %p new LSA created with Link State Update",
1554 lsa->data->type, inet_ntoa (lsa->data->id), lsa);
1555 listnode_add (lsas, lsa);
1556 }
1557
1558 return lsas;
1559}
1560
1561/* Cleanup Update list. */
1562void
hasso52dc7ee2004-09-23 19:18:23 +00001563ospf_upd_list_clean (struct list *lsas)
paul718e3742002-12-13 20:15:29 +00001564{
hasso52dc7ee2004-09-23 19:18:23 +00001565 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001566 struct ospf_lsa *lsa;
1567
1568 for (node = listhead (lsas); node; nextnode (node))
1569 if ((lsa = getdata (node)) != NULL)
1570 ospf_lsa_discard (lsa);
1571
1572 list_delete (lsas);
1573}
1574
1575/* OSPF Link State Update message read -- RFC2328 Section 13. */
1576void
1577ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
1578 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1579{
1580 struct ospf_neighbor *nbr;
hasso52dc7ee2004-09-23 19:18:23 +00001581 struct list *lsas;
paul718e3742002-12-13 20:15:29 +00001582#ifdef HAVE_OPAQUE_LSA
hasso52dc7ee2004-09-23 19:18:23 +00001583 struct list *mylsa_acks, *mylsa_upds;
paul718e3742002-12-13 20:15:29 +00001584#endif /* HAVE_OPAQUE_LSA */
hasso52dc7ee2004-09-23 19:18:23 +00001585 struct listnode *node, *next;
paul718e3742002-12-13 20:15:29 +00001586 struct ospf_lsa *lsa = NULL;
1587 /* unsigned long ls_req_found = 0; */
1588
1589 /* Dis-assemble the stream, update each entry, re-encapsulate for flooding */
1590
1591 /* Increment statistics. */
1592 oi->ls_upd_in++;
1593
1594 /* Check neighbor. */
pauld3f0d622004-05-05 15:27:15 +00001595 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001596 if (nbr == NULL)
1597 {
1598 zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s",
1599 inet_ntoa (ospfh->router_id), IF_NAME (oi));
1600 return;
1601 }
1602
1603 /* Check neighbor state. */
1604 if (nbr->state < NSM_Exchange)
1605 {
1606 zlog_warn ("Link State Update: Neighbor[%s] state is less than Exchange",
1607 inet_ntoa (ospfh->router_id));
1608 return;
1609 }
1610
1611 /* Get list of LSAs from Link State Update packet. - Also perorms Stages
1612 * 1 (validate LSA checksum) and 2 (check for LSA consistent type)
1613 * of section 13.
1614 */
1615 lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);
1616
1617#ifdef HAVE_OPAQUE_LSA
1618 /*
1619 * Prepare two kinds of lists to clean up unwanted self-originated
1620 * Opaque-LSAs from the routing domain as soon as possible.
1621 */
1622 mylsa_acks = list_new (); /* Let the sender cease retransmission. */
1623 mylsa_upds = list_new (); /* Flush target LSAs if necessary. */
1624
1625 /*
1626 * If self-originated Opaque-LSAs that have flooded before restart
1627 * are contained in the received LSUpd message, corresponding LSReq
1628 * messages to be sent may have to be modified.
1629 * To eliminate possible race conditions such that flushing and normal
1630 * updating for the same LSA would take place alternately, this trick
1631 * must be done before entering to the loop below.
1632 */
1633 ospf_opaque_adjust_lsreq (nbr, lsas);
1634#endif /* HAVE_OPAQUE_LSA */
1635
1636#define DISCARD_LSA(L,N) {\
1637 if (IS_DEBUG_OSPF_EVENT) \
1638 zlog_info ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \
1639 ospf_lsa_discard (L); \
1640 continue; }
1641
1642 /* Process each LSA received in the one packet. */
1643 for (node = listhead (lsas); node; node = next)
1644 {
1645 struct ospf_lsa *ls_ret, *current;
1646 int ret = 1;
1647
1648 next = node->next;
1649
1650 lsa = getdata (node);
1651
paul718e3742002-12-13 20:15:29 +00001652 if (IS_DEBUG_OSPF_NSSA)
1653 {
1654 char buf1[INET_ADDRSTRLEN];
1655 char buf2[INET_ADDRSTRLEN];
1656 char buf3[INET_ADDRSTRLEN];
1657
1658 zlog_info("LSA Type-%d from %s, ID: %s, ADV: %s",
1659 lsa->data->type,
1660 inet_ntop (AF_INET, &ospfh->router_id,
1661 buf1, INET_ADDRSTRLEN),
1662 inet_ntop (AF_INET, &lsa->data->id,
1663 buf2, INET_ADDRSTRLEN),
1664 inet_ntop (AF_INET, &lsa->data->adv_router,
1665 buf3, INET_ADDRSTRLEN));
1666 }
paul718e3742002-12-13 20:15:29 +00001667
1668 listnode_delete (lsas, lsa); /* We don't need it in list anymore */
1669
1670 /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */
1671
1672 /* LSA Type - Done above by ospf_ls_upd_list_lsa() */
1673
1674 /* Do not take in AS External LSAs if we are a stub or NSSA. */
1675
1676 /* Do not take in AS NSSA if this neighbor and we are not NSSA */
1677
1678 /* Do take in Type-7's if we are an NSSA */
1679
1680 /* If we are also an ABR, later translate them to a Type-5 packet */
1681
1682 /* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will
1683 translate them to a separate Type-5 packet. */
1684
1685 if (lsa->data->type == OSPF_AS_EXTERNAL_LSA)
1686 /* Reject from STUB or NSSA */
1687 if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
1688 {
1689 DISCARD_LSA (lsa, 1);
paul718e3742002-12-13 20:15:29 +00001690 if (IS_DEBUG_OSPF_NSSA)
1691 zlog_info("Incoming External LSA Discarded: We are NSSA/STUB Area");
paul718e3742002-12-13 20:15:29 +00001692 }
1693
paul718e3742002-12-13 20:15:29 +00001694 if (lsa->data->type == OSPF_AS_NSSA_LSA)
1695 if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)
1696 {
1697 DISCARD_LSA (lsa,2);
1698 if (IS_DEBUG_OSPF_NSSA)
1699 zlog_info("Incoming NSSA LSA Discarded: Not NSSA Area");
1700 }
paul718e3742002-12-13 20:15:29 +00001701
1702 /* Find the LSA in the current database. */
1703
1704 current = ospf_lsa_lookup_by_header (oi->area, lsa->data);
1705
1706 /* If the LSA's LS age is equal to MaxAge, and there is currently
1707 no instance of the LSA in the router's link state database,
1708 and none of router's neighbors are in states Exchange or Loading,
1709 then take the following actions. */
1710
1711 if (IS_LSA_MAXAGE (lsa) && !current &&
paul68980082003-03-25 05:07:42 +00001712 (ospf_nbr_count (oi, NSM_Exchange) +
1713 ospf_nbr_count (oi, NSM_Loading)) == 0)
paul718e3742002-12-13 20:15:29 +00001714 {
1715 /* Response Link State Acknowledgment. */
1716 ospf_ls_ack_send (nbr, lsa);
1717
1718 /* Discard LSA. */
1719 zlog_warn ("Link State Update: LS age is equal to MaxAge.");
1720 DISCARD_LSA (lsa, 3);
1721 }
1722
1723#ifdef HAVE_OPAQUE_LSA
1724 if (IS_OPAQUE_LSA (lsa->data->type)
paul68980082003-03-25 05:07:42 +00001725 && IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +00001726 {
1727 /*
1728 * Even if initial flushing seems to be completed, there might
1729 * be a case that self-originated LSA with MaxAge still remain
1730 * in the routing domain.
1731 * Just send an LSAck message to cease retransmission.
1732 */
1733 if (IS_LSA_MAXAGE (lsa))
1734 {
1735 zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa));
1736 ospf_ls_ack_send (nbr, lsa);
1737 ospf_lsa_discard (lsa);
1738
1739 if (current != NULL && ! IS_LSA_MAXAGE (current))
1740 ospf_opaque_lsa_refresh_schedule (current);
1741 continue;
1742 }
1743
1744 /*
1745 * If an instance of self-originated Opaque-LSA is not found
1746 * in the LSDB, there are some possible cases here.
1747 *
1748 * 1) This node lost opaque-capability after restart.
1749 * 2) Else, a part of opaque-type is no more supported.
1750 * 3) Else, a part of opaque-id is no more supported.
1751 *
1752 * Anyway, it is still this node's responsibility to flush it.
1753 * Otherwise, the LSA instance remains in the routing domain
1754 * until its age reaches to MaxAge.
1755 */
1756 if (current == NULL)
1757 {
1758 if (IS_DEBUG_OSPF_EVENT)
1759 zlog_info ("LSA[%s]: Previously originated Opaque-LSA, not found in the LSDB.", dump_lsa_key (lsa));
1760
1761 SET_FLAG (lsa->flags, OSPF_LSA_SELF);
1762 listnode_add (mylsa_upds, ospf_lsa_dup (lsa));
1763 listnode_add (mylsa_acks, ospf_lsa_lock (lsa));
1764 continue;
1765 }
1766 }
1767#endif /* HAVE_OPAQUE_LSA */
hassocb05eb22004-02-11 21:10:19 +00001768 /* It might be happen that received LSA is self-originated network LSA, but
1769 * router ID is cahnged. So, we should check if LSA is a network-LSA whose
1770 * Link State ID is one of the router's own IP interface addresses but whose
1771 * Advertising Router is not equal to the router's own Router ID
1772 * According to RFC 2328 12.4.2 and 13.4 this LSA should be flushed.
1773 */
1774
1775 if(lsa->data->type == OSPF_NETWORK_LSA)
1776 {
hasso52dc7ee2004-09-23 19:18:23 +00001777 struct listnode *oi_node;
hassocb05eb22004-02-11 21:10:19 +00001778 int Flag = 0;
1779
1780 for(oi_node = listhead(oi->ospf->oiflist); oi_node; oi_node = nextnode(oi_node))
1781 {
1782 struct ospf_interface *out_if = getdata(oi_node);
1783 if(out_if == NULL)
1784 break;
1785
1786 if((IPV4_ADDR_SAME(&out_if->address->u.prefix4, &lsa->data->id)) &&
1787 (!(IPV4_ADDR_SAME(&oi->ospf->router_id, &lsa->data->adv_router))))
1788 {
1789 if(out_if->network_lsa_self)
1790 {
1791 ospf_lsa_flush_area(lsa,out_if->area);
1792 if(IS_DEBUG_OSPF_EVENT)
1793 zlog_info ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d",
1794 lsa, (int) lsa->data->type);
1795 ospf_lsa_discard (lsa);
1796 Flag = 1;
1797 }
1798 break;
1799 }
1800 }
1801 if(Flag)
1802 continue;
1803 }
paul718e3742002-12-13 20:15:29 +00001804
1805 /* (5) Find the instance of this LSA that is currently contained
1806 in the router's link state database. If there is no
1807 database copy, or the received LSA is more recent than
1808 the database copy the following steps must be performed. */
1809
1810 if (current == NULL ||
1811 (ret = ospf_lsa_more_recent (current, lsa)) < 0)
1812 {
1813 /* Actual flooding procedure. */
paul68980082003-03-25 05:07:42 +00001814 if (ospf_flood (oi->ospf, nbr, current, lsa) < 0) /* Trap NSSA later. */
paul718e3742002-12-13 20:15:29 +00001815 DISCARD_LSA (lsa, 4);
1816 continue;
1817 }
1818
1819 /* (6) Else, If there is an instance of the LSA on the sending
1820 neighbor's Link state request list, an error has occurred in
1821 the Database Exchange process. In this case, restart the
1822 Database Exchange process by generating the neighbor event
1823 BadLSReq for the sending neighbor and stop processing the
1824 Link State Update packet. */
1825
1826 if (ospf_ls_request_lookup (nbr, lsa))
1827 {
1828 OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);
1829 zlog_warn ("LSA instance exists on Link state request list");
1830
1831 /* Clean list of LSAs. */
1832 ospf_upd_list_clean (lsas);
1833 /* this lsa is not on lsas list already. */
1834 ospf_lsa_discard (lsa);
1835#ifdef HAVE_OPAQUE_LSA
1836 list_delete (mylsa_acks);
1837 list_delete (mylsa_upds);
1838#endif /* HAVE_OPAQUE_LSA */
1839 return;
1840 }
1841
1842 /* If the received LSA is the same instance as the database copy
1843 (i.e., neither one is more recent) the following two steps
1844 should be performed: */
1845
1846 if (ret == 0)
1847 {
1848 /* If the LSA is listed in the Link state retransmission list
1849 for the receiving adjacency, the router itself is expecting
1850 an acknowledgment for this LSA. The router should treat the
1851 received LSA as an acknowledgment by removing the LSA from
1852 the Link state retransmission list. This is termed an
1853 "implied acknowledgment". */
1854
1855 ls_ret = ospf_ls_retransmit_lookup (nbr, lsa);
1856
1857 if (ls_ret != NULL)
1858 {
1859 ospf_ls_retransmit_delete (nbr, ls_ret);
1860
1861 /* Delayed acknowledgment sent if advertisement received
1862 from Designated Router, otherwise do nothing. */
1863 if (oi->state == ISM_Backup)
1864 if (NBR_IS_DR (nbr))
1865 listnode_add (oi->ls_ack, ospf_lsa_lock (lsa));
1866
1867 DISCARD_LSA (lsa, 5);
1868 }
1869 else
1870 /* Acknowledge the receipt of the LSA by sending a
1871 Link State Acknowledgment packet back out the receiving
1872 interface. */
1873 {
1874 ospf_ls_ack_send (nbr, lsa);
1875 DISCARD_LSA (lsa, 6);
1876 }
1877 }
1878
1879 /* The database copy is more recent. If the database copy
1880 has LS age equal to MaxAge and LS sequence number equal to
1881 MaxSequenceNumber, simply discard the received LSA without
1882 acknowledging it. (In this case, the LSA's LS sequence number is
1883 wrapping, and the MaxSequenceNumber LSA must be completely
1884 flushed before any new LSA instance can be introduced). */
1885
1886 else if (ret > 0) /* Database copy is more recent */
1887 {
1888 if (IS_LSA_MAXAGE (current) &&
1889 current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
1890 {
1891 DISCARD_LSA (lsa, 7);
1892 }
1893 /* Otherwise, as long as the database copy has not been sent in a
1894 Link State Update within the last MinLSArrival seconds, send the
1895 database copy back to the sending neighbor, encapsulated within
1896 a Link State Update Packet. The Link State Update Packet should
1897 be sent directly to the neighbor. In so doing, do not put the
1898 database copy of the LSA on the neighbor's link state
1899 retransmission list, and do not acknowledge the received (less
1900 recent) LSA instance. */
1901 else
1902 {
1903 struct timeval now;
1904
1905 gettimeofday (&now, NULL);
1906
1907 if (tv_cmp (tv_sub (now, current->tv_orig),
1908 int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)
1909 /* Trap NSSA type later.*/
1910 ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
1911 DISCARD_LSA (lsa, 8);
1912 }
1913 }
1914 }
1915
1916#ifdef HAVE_OPAQUE_LSA
1917 /*
1918 * Now that previously originated Opaque-LSAs those which not yet
1919 * installed into LSDB are captured, take several steps to clear
1920 * them completely from the routing domain, before proceeding to
1921 * origination for the current target Opaque-LSAs.
1922 */
1923 while (listcount (mylsa_acks) > 0)
1924 ospf_ls_ack_send_list (oi, mylsa_acks, nbr->address.u.prefix4);
1925
1926 if (listcount (mylsa_upds) > 0)
1927 ospf_opaque_self_originated_lsa_received (nbr, mylsa_upds);
1928
1929 list_delete (mylsa_upds);
paul683b2262003-03-28 00:43:48 +00001930 list_delete (mylsa_acks);
paul718e3742002-12-13 20:15:29 +00001931#endif /* HAVE_OPAQUE_LSA */
1932
1933 assert (listcount (lsas) == 0);
1934 list_delete (lsas);
1935}
1936
1937/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
1938void
1939ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
1940 struct stream *s, struct ospf_interface *oi, u_int16_t size)
1941{
1942 struct ospf_neighbor *nbr;
1943#ifdef HAVE_OPAQUE_LSA
paul87d6f872004-09-24 08:01:38 +00001944 struct list *opaque_acks;
paul718e3742002-12-13 20:15:29 +00001945#endif /* HAVE_OPAQUE_LSA */
1946
1947 /* increment statistics. */
1948 oi->ls_ack_in++;
1949
pauld3f0d622004-05-05 15:27:15 +00001950 nbr = ospf_nbr_lookup (oi, iph, ospfh);
paul718e3742002-12-13 20:15:29 +00001951 if (nbr == NULL)
1952 {
1953 zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.",
1954 inet_ntoa (ospfh->router_id));
1955 return;
1956 }
1957
1958 if (nbr->state < NSM_Exchange)
1959 {
1960 zlog_warn ("Link State Acknowledgment: State is less than Exchange.");
1961 return;
1962 }
1963
1964#ifdef HAVE_OPAQUE_LSA
1965 opaque_acks = list_new ();
1966#endif /* HAVE_OPAQUE_LSA */
1967
1968 while (size >= OSPF_LSA_HEADER_SIZE)
1969 {
1970 struct ospf_lsa *lsa, *lsr;
1971
1972 lsa = ospf_lsa_new ();
1973 lsa->data = (struct lsa_header *) STREAM_PNT (s);
1974
1975 /* lsah = (struct lsa_header *) STREAM_PNT (s); */
1976 size -= OSPF_LSA_HEADER_SIZE;
1977 stream_forward (s, OSPF_LSA_HEADER_SIZE);
1978
1979 if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)
1980 {
1981 lsa->data = NULL;
1982 ospf_lsa_discard (lsa);
1983 continue;
1984 }
1985
1986 lsr = ospf_ls_retransmit_lookup (nbr, lsa);
1987
1988 if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)
1989 {
1990#ifdef HAVE_OPAQUE_LSA
1991 /* Keep this LSA entry for later reference. */
1992 if (IS_OPAQUE_LSA (lsr->data->type))
1993 listnode_add (opaque_acks, ospf_lsa_dup (lsr));
1994#endif /* HAVE_OPAQUE_LSA */
1995
1996 ospf_ls_retransmit_delete (nbr, lsr);
1997 }
1998
1999 lsa->data = NULL;
2000 ospf_lsa_discard (lsa);
2001 }
2002
2003#ifdef HAVE_OPAQUE_LSA
2004 if (listcount (opaque_acks) > 0)
2005 ospf_opaque_ls_ack_received (nbr, opaque_acks);
2006
2007 list_delete (opaque_acks);
2008 return;
2009#endif /* HAVE_OPAQUE_LSA */
2010}
2011
2012struct stream *
2013ospf_recv_packet (int fd, struct interface **ifp)
2014{
2015 int ret;
2016 struct ip iph;
2017 u_int16_t ip_len;
2018 struct stream *ibuf;
2019 unsigned int ifindex = 0;
2020 struct iovec iov;
2021 struct cmsghdr *cmsg;
gdtd0deca62004-08-26 13:14:07 +00002022#if defined(CMSG_SPACE)
2023 /* Header and data both require alignment. */
gdte3049822004-08-26 13:19:40 +00002024 char buff [CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
gdtd0deca62004-08-26 13:14:07 +00002025#else
2026 char buff [sizeof (*cmsg) + SOPT_SIZE_CMSG_IFINDEX_IPV4()];
2027#endif
paul2dd8bb42004-07-23 15:13:48 +00002028 struct msghdr msgh;
2029
paul68defd62004-09-27 07:27:13 +00002030 memset (&msgh, 0, sizeof (struct msghdr));
paul2dd8bb42004-07-23 15:13:48 +00002031 msgh.msg_iov = &iov;
2032 msgh.msg_iovlen = 1;
2033 msgh.msg_control = (caddr_t) buff;
2034 msgh.msg_controllen = sizeof (buff);
paul2dd8bb42004-07-23 15:13:48 +00002035
paul718e3742002-12-13 20:15:29 +00002036 ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);
2037
2038 if (ret != sizeof (iph))
2039 {
2040 zlog_warn ("ospf_recv_packet packet smaller than ip header");
2041 return NULL;
2042 }
2043
paul6a99f832004-09-27 12:56:30 +00002044#ifdef HAVE_IP_HDRINCL_BSD_ORDER
paul718e3742002-12-13 20:15:29 +00002045 ip_len = iph.ip_len;
2046#else
2047 ip_len = ntohs (iph.ip_len);
2048#endif
2049
paul239aecc2003-12-08 10:34:54 +00002050#if !defined(GNU_LINUX) && (OpenBSD < 200311)
paul718e3742002-12-13 20:15:29 +00002051 /*
2052 * Kernel network code touches incoming IP header parameters,
2053 * before protocol specific processing.
2054 *
2055 * 1) Convert byteorder to host representation.
2056 * --> ip_len, ip_id, ip_off
2057 *
2058 * 2) Adjust ip_len to strip IP header size!
2059 * --> If user process receives entire IP packet via RAW
2060 * socket, it must consider adding IP header size to
2061 * the "ip_len" field of "ip" structure.
2062 *
2063 * For more details, see <netinet/ip_input.c>.
2064 */
2065 ip_len = ip_len + (iph.ip_hl << 2);
2066#endif
2067
2068 ibuf = stream_new (ip_len);
2069 iov.iov_base = STREAM_DATA (ibuf);
2070 iov.iov_len = ip_len;
2071 ret = recvmsg (fd, &msgh, 0);
2072
paul863082d2004-08-19 04:43:43 +00002073 ifindex = getsockopt_ifindex (AF_INET, &msgh);
paul718e3742002-12-13 20:15:29 +00002074
2075 *ifp = if_lookup_by_index (ifindex);
2076
2077 if (ret != ip_len)
2078 {
2079 zlog_warn ("ospf_recv_packet short read. "
2080 "ip_len %d bytes read %d", ip_len, ret);
2081 stream_free (ibuf);
2082 return NULL;
2083 }
2084
2085 return ibuf;
2086}
2087
2088struct ospf_interface *
pauld3f0d622004-05-05 15:27:15 +00002089ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
paul718e3742002-12-13 20:15:29 +00002090 struct ip *iph, struct ospf_header *ospfh)
2091{
2092 struct ospf_interface *rcv_oi;
paul718e3742002-12-13 20:15:29 +00002093 struct ospf_vl_data *vl_data;
2094 struct ospf_area *vl_area;
hasso52dc7ee2004-09-23 19:18:23 +00002095 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002096
2097 if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||
2098 !OSPF_IS_AREA_BACKBONE (ospfh))
pauld3f0d622004-05-05 15:27:15 +00002099 return NULL;
paul718e3742002-12-13 20:15:29 +00002100
pauld3f0d622004-05-05 15:27:15 +00002101 /* look for local OSPF interface matching the destination
2102 * to determine Area ID. We presume therefore the destination address
2103 * is unique, or at least (for "unnumbered" links), not used in other
2104 * areas
2105 */
2106 if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL,
2107 iph->ip_dst)) == NULL)
2108 return NULL;
paul718e3742002-12-13 20:15:29 +00002109
paul020709f2003-04-04 02:44:16 +00002110 for (node = listhead (ospf->vlinks); node; nextnode (node))
paul718e3742002-12-13 20:15:29 +00002111 {
2112 if ((vl_data = getdata (node)) == NULL)
2113 continue;
2114
paul020709f2003-04-04 02:44:16 +00002115 vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);
paul718e3742002-12-13 20:15:29 +00002116 if (!vl_area)
2117 continue;
2118
2119 if (OSPF_AREA_SAME (&vl_area, &rcv_oi->area) &&
2120 IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))
2121 {
2122 if (IS_DEBUG_OSPF_EVENT)
2123 zlog_info ("associating packet with %s",
2124 IF_NAME (vl_data->vl_oi));
2125 if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))
2126 {
2127 if (IS_DEBUG_OSPF_EVENT)
2128 zlog_info ("This VL is not up yet, sorry");
2129 return NULL;
2130 }
2131
2132 return vl_data->vl_oi;
2133 }
2134 }
2135
2136 if (IS_DEBUG_OSPF_EVENT)
2137 zlog_info ("couldn't find any VL to associate the packet with");
2138
pauld3f0d622004-05-05 15:27:15 +00002139 return NULL;
paul718e3742002-12-13 20:15:29 +00002140}
2141
2142int
2143ospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh)
2144{
2145 /* Check match the Area ID of the receiving interface. */
2146 if (OSPF_AREA_SAME (&oi->area, &ospfh))
2147 return 1;
2148
2149 return 0;
2150}
2151
2152/* Unbound socket will accept any Raw IP packets if proto is matched.
2153 To prevent it, compare src IP address and i/f address with masking
2154 i/f network mask. */
2155int
2156ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
2157{
2158 struct in_addr mask, me, him;
2159
2160 if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
2161 oi->type == OSPF_IFTYPE_VIRTUALLINK)
2162 return 1;
2163
2164 masklen2ip (oi->address->prefixlen, &mask);
2165
2166 me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
2167 him.s_addr = ip_src.s_addr & mask.s_addr;
2168
2169 if (IPV4_ADDR_SAME (&me, &him))
2170 return 1;
2171
2172 return 0;
2173}
2174
2175int
2176ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
2177 struct ospf_header *ospfh)
2178{
2179 int ret = 0;
2180 struct crypt_key *ck;
2181
2182 switch (ntohs (ospfh->auth_type))
2183 {
2184 case OSPF_AUTH_NULL:
2185 ret = 1;
2186 break;
2187 case OSPF_AUTH_SIMPLE:
2188 if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
2189 ret = 1;
2190 else
2191 ret = 0;
2192 break;
2193 case OSPF_AUTH_CRYPTOGRAPHIC:
2194 if ((ck = getdata (OSPF_IF_PARAM (oi,auth_crypt)->tail)) == NULL)
2195 {
2196 ret = 0;
2197 break;
2198 }
2199
2200 /* This is very basic, the digest processing is elsewhere */
2201 if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE &&
2202 ospfh->u.crypt.key_id == ck->key_id &&
2203 ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))
2204 ret = 1;
2205 else
2206 ret = 0;
2207 break;
2208 default:
2209 ret = 0;
2210 break;
2211 }
2212
2213 return ret;
2214}
2215
2216int
2217ospf_check_sum (struct ospf_header *ospfh)
2218{
2219 u_int32_t ret;
2220 u_int16_t sum;
2221 int in_cksum (void *ptr, int nbytes);
2222
2223 /* clear auth_data for checksum. */
2224 memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
2225
2226 /* keep checksum and clear. */
2227 sum = ospfh->checksum;
2228 memset (&ospfh->checksum, 0, sizeof (u_int16_t));
2229
2230 /* calculate checksum. */
2231 ret = in_cksum (ospfh, ntohs (ospfh->length));
2232
2233 if (ret != sum)
2234 {
2235 zlog_info ("ospf_check_sum(): checksum mismatch, my %X, his %X",
2236 ret, sum);
2237 return 0;
2238 }
2239
2240 return 1;
2241}
2242
2243/* OSPF Header verification. */
2244int
2245ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
2246 struct ip *iph, struct ospf_header *ospfh)
2247{
2248 /* check version. */
2249 if (ospfh->version != OSPF_VERSION)
2250 {
2251 zlog_warn ("interface %s: ospf_read version number mismatch.",
2252 IF_NAME (oi));
2253 return -1;
2254 }
2255
2256 /* Check Area ID. */
2257 if (!ospf_check_area_id (oi, ospfh))
2258 {
2259 zlog_warn ("interface %s: ospf_read invalid Area ID %s.",
2260 IF_NAME (oi), inet_ntoa (ospfh->area_id));
2261 return -1;
2262 }
2263
2264 /* Check network mask, Silently discarded. */
2265 if (! ospf_check_network_mask (oi, iph->ip_src))
2266 {
2267 zlog_warn ("interface %s: ospf_read network address is not same [%s]",
2268 IF_NAME (oi), inet_ntoa (iph->ip_src));
2269 return -1;
2270 }
2271
2272 /* Check authentication. */
2273 if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
2274 {
2275 zlog_warn ("interface %s: ospf_read authentication type mismatch.",
2276 IF_NAME (oi));
2277 return -1;
2278 }
2279
2280 if (! ospf_check_auth (oi, ibuf, ospfh))
2281 {
2282 zlog_warn ("interface %s: ospf_read authentication failed.",
2283 IF_NAME (oi));
2284 return -1;
2285 }
2286
2287 /* if check sum is invalid, packet is discarded. */
2288 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
2289 {
2290 if (! ospf_check_sum (ospfh))
2291 {
2292 zlog_warn ("interface %s: ospf_read packet checksum error %s",
2293 IF_NAME (oi), inet_ntoa (ospfh->router_id));
2294 return -1;
2295 }
2296 }
2297 else
2298 {
2299 if (ospfh->checksum != 0)
2300 return -1;
2301 if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)
2302 {
2303 zlog_warn ("interface %s: ospf_read md5 authentication failed.",
2304 IF_NAME (oi));
2305 return -1;
2306 }
2307 }
2308
2309 return 0;
2310}
2311
2312/* Starting point of packet process function. */
2313int
2314ospf_read (struct thread *thread)
2315{
2316 int ret;
2317 struct stream *ibuf;
paul68980082003-03-25 05:07:42 +00002318 struct ospf *ospf;
paul718e3742002-12-13 20:15:29 +00002319 struct ospf_interface *oi;
2320 struct ip *iph;
2321 struct ospf_header *ospfh;
2322 u_int16_t length;
2323 struct interface *ifp;
2324
2325 /* first of all get interface pointer. */
paul68980082003-03-25 05:07:42 +00002326 ospf = THREAD_ARG (thread);
2327 ospf->t_read = NULL;
paul718e3742002-12-13 20:15:29 +00002328
2329 /* read OSPF packet. */
paul68980082003-03-25 05:07:42 +00002330 ibuf = ospf_recv_packet (ospf->fd, &ifp);
paul718e3742002-12-13 20:15:29 +00002331 if (ibuf == NULL)
2332 return -1;
2333
pauld3f0d622004-05-05 15:27:15 +00002334 if (ifp == NULL)
2335 {
2336 stream_free (ibuf);
2337 return 0;
2338 }
2339
paul718e3742002-12-13 20:15:29 +00002340 iph = (struct ip *) STREAM_DATA (ibuf);
2341
2342 /* prepare for next packet. */
paul68980082003-03-25 05:07:42 +00002343 ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
paul718e3742002-12-13 20:15:29 +00002344
2345 /* IP Header dump. */
paul17b78d32003-02-13 22:04:01 +00002346 if (IS_DEBUG_OSPF_PACKET(0, RECV))
paul7d95c612003-01-27 12:00:55 +00002347 ospf_ip_header_dump (ibuf);
2348
paul718e3742002-12-13 20:15:29 +00002349 /* Self-originated packet should be discarded silently. */
paul68980082003-03-25 05:07:42 +00002350 if (ospf_if_lookup_by_local_addr (ospf, NULL, iph->ip_src))
paul718e3742002-12-13 20:15:29 +00002351 {
pauld3241812003-09-29 12:42:39 +00002352 if (IS_DEBUG_OSPF_PACKET (0, RECV))
2353 {
2354 zlog_info ("ospf_read[%s]: Dropping self-originated packet",
2355 inet_ntoa (iph->ip_src));
2356 }
paul718e3742002-12-13 20:15:29 +00002357 stream_free (ibuf);
2358 return 0;
2359 }
2360
2361 /* Adjust size to message length. */
2362 stream_forward (ibuf, iph->ip_hl * 4);
2363
2364 /* Get ospf packet header. */
2365 ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
2366
2367 /* associate packet with ospf interface */
paul68980082003-03-25 05:07:42 +00002368 oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);
pauld3f0d622004-05-05 15:27:15 +00002369
2370 /* if no local ospf_interface,
2371 * or header area is backbone but ospf_interface is not
2372 * check for VLINK interface
2373 */
2374 if ( (oi == NULL) ||
2375 (OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id)
2376 && !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id))
2377 )
2378 {
2379 if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
2380 {
2381 zlog_warn ("Packet from [%s] received on link %s"
2382 " but no ospf_interface",
2383 inet_ntoa (iph->ip_src), ifp->name);
2384 stream_free (ibuf);
2385 return 0;
2386 }
2387 }
2388
2389 /* else it must be a local ospf interface, check it was received on
2390 * correct link
2391 */
2392 else if (oi->ifp != ifp)
paul718e3742002-12-13 20:15:29 +00002393 {
2394 zlog_warn ("Packet from [%s] received on wrong link %s",
pauld3241812003-09-29 12:42:39 +00002395 inet_ntoa (iph->ip_src), ifp->name);
paul718e3742002-12-13 20:15:29 +00002396 stream_free (ibuf);
2397 return 0;
2398 }
paul718e3742002-12-13 20:15:29 +00002399
2400 /*
2401 * If the received packet is destined for AllDRouters, the packet
2402 * should be accepted only if the received ospf interface state is
2403 * either DR or Backup -- endo.
2404 */
2405 if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)
2406 && (oi->state != ISM_DR && oi->state != ISM_Backup))
2407 {
2408 zlog_info ("Packet for AllDRouters from [%s] via [%s] (ISM: %s)",
2409 inet_ntoa (iph->ip_src), IF_NAME (oi),
2410 LOOKUP (ospf_ism_state_msg, oi->state));
2411 stream_free (ibuf);
2412 return 0;
2413 }
2414
2415 /* Show debug receiving packet. */
paul1aa7b392003-04-08 08:51:58 +00002416 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
2417 {
paul718e3742002-12-13 20:15:29 +00002418 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
paul1aa7b392003-04-08 08:51:58 +00002419 {
2420 zlog_info ("-----------------------------------------------------");
2421 ospf_packet_dump (ibuf);
2422 }
paul718e3742002-12-13 20:15:29 +00002423
2424 zlog_info ("%s received from [%s] via [%s]",
paul1aa7b392003-04-08 08:51:58 +00002425 ospf_packet_type_str[ospfh->type],
2426 inet_ntoa (ospfh->router_id), IF_NAME (oi));
paul718e3742002-12-13 20:15:29 +00002427 zlog_info (" src [%s],", inet_ntoa (iph->ip_src));
2428 zlog_info (" dst [%s]", inet_ntoa (iph->ip_dst));
2429
2430 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))
2431 zlog_info ("-----------------------------------------------------");
paul1aa7b392003-04-08 08:51:58 +00002432 }
paul718e3742002-12-13 20:15:29 +00002433
2434 /* Some header verification. */
2435 ret = ospf_verify_header (ibuf, oi, iph, ospfh);
2436 if (ret < 0)
2437 {
pauld3241812003-09-29 12:42:39 +00002438 if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
2439 {
2440 zlog_info ("ospf_read[%s/%s]: Header check failed, "
2441 "dropping.",
2442 ospf_packet_type_str[ospfh->type],
2443 inet_ntoa (iph->ip_src));
2444 }
paul718e3742002-12-13 20:15:29 +00002445 stream_free (ibuf);
2446 return ret;
2447 }
2448
2449 stream_forward (ibuf, OSPF_HEADER_SIZE);
2450
2451 /* Adjust size to message length. */
2452 length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;
2453
2454 /* Read rest of the packet and call each sort of packet routine. */
2455 switch (ospfh->type)
2456 {
2457 case OSPF_MSG_HELLO:
2458 ospf_hello (iph, ospfh, ibuf, oi, length);
2459 break;
2460 case OSPF_MSG_DB_DESC:
2461 ospf_db_desc (iph, ospfh, ibuf, oi, length);
2462 break;
2463 case OSPF_MSG_LS_REQ:
2464 ospf_ls_req (iph, ospfh, ibuf, oi, length);
2465 break;
2466 case OSPF_MSG_LS_UPD:
2467 ospf_ls_upd (iph, ospfh, ibuf, oi, length);
2468 break;
2469 case OSPF_MSG_LS_ACK:
2470 ospf_ls_ack (iph, ospfh, ibuf, oi, length);
2471 break;
2472 default:
2473 zlog (NULL, LOG_WARNING,
2474 "interface %s: OSPF packet header type %d is illegal",
2475 IF_NAME (oi), ospfh->type);
2476 break;
2477 }
2478
2479 stream_free (ibuf);
2480 return 0;
2481}
2482
2483/* Make OSPF header. */
2484void
2485ospf_make_header (int type, struct ospf_interface *oi, struct stream *s)
2486{
2487 struct ospf_header *ospfh;
2488
2489 ospfh = (struct ospf_header *) STREAM_DATA (s);
2490
2491 ospfh->version = (u_char) OSPF_VERSION;
2492 ospfh->type = (u_char) type;
2493
paul68980082003-03-25 05:07:42 +00002494 ospfh->router_id = oi->ospf->router_id;
paul718e3742002-12-13 20:15:29 +00002495
2496 ospfh->checksum = 0;
2497 ospfh->area_id = oi->area->area_id;
2498 ospfh->auth_type = htons (ospf_auth_type (oi));
2499
2500 memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);
2501
2502 ospf_output_forward (s, OSPF_HEADER_SIZE);
2503}
2504
2505/* Make Authentication Data. */
2506int
2507ospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
2508{
2509 struct crypt_key *ck;
2510
2511 switch (ospf_auth_type (oi))
2512 {
2513 case OSPF_AUTH_NULL:
2514 /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
2515 break;
2516 case OSPF_AUTH_SIMPLE:
2517 memcpy (ospfh->u.auth_data, OSPF_IF_PARAM (oi, auth_simple),
2518 OSPF_AUTH_SIMPLE_SIZE);
2519 break;
2520 case OSPF_AUTH_CRYPTOGRAPHIC:
2521 /* If key is not set, then set 0. */
2522 if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
2523 {
2524 ospfh->u.crypt.zero = 0;
2525 ospfh->u.crypt.key_id = 0;
2526 ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
2527 }
2528 else
2529 {
2530 ck = getdata (OSPF_IF_PARAM (oi, auth_crypt)->tail);
2531 ospfh->u.crypt.zero = 0;
2532 ospfh->u.crypt.key_id = ck->key_id;
2533 ospfh->u.crypt.auth_data_len = OSPF_AUTH_MD5_SIZE;
2534 }
2535 /* note: the seq is done in ospf_make_md5_digest() */
2536 break;
2537 default:
2538 /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */
2539 break;
2540 }
2541
2542 return 0;
2543}
2544
2545/* Fill rest of OSPF header. */
2546void
2547ospf_fill_header (struct ospf_interface *oi,
2548 struct stream *s, u_int16_t length)
2549{
2550 struct ospf_header *ospfh;
2551
2552 ospfh = (struct ospf_header *) STREAM_DATA (s);
2553
2554 /* Fill length. */
2555 ospfh->length = htons (length);
2556
2557 /* Calculate checksum. */
2558 if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
2559 ospfh->checksum = in_cksum (ospfh, length);
2560 else
2561 ospfh->checksum = 0;
2562
2563 /* Add Authentication Data. */
2564 ospf_make_auth (oi, ospfh);
2565}
2566
2567int
2568ospf_make_hello (struct ospf_interface *oi, struct stream *s)
2569{
2570 struct ospf_neighbor *nbr;
2571 struct route_node *rn;
2572 u_int16_t length = OSPF_HELLO_MIN_SIZE;
2573 struct in_addr mask;
2574 unsigned long p;
2575 int flag = 0;
2576
2577 /* Set netmask of interface. */
2578 if (oi->type != OSPF_IFTYPE_POINTOPOINT &&
2579 oi->type != OSPF_IFTYPE_VIRTUALLINK)
2580 masklen2ip (oi->address->prefixlen, &mask);
2581 else
2582 memset ((char *) &mask, 0, sizeof (struct in_addr));
2583 stream_put_ipv4 (s, mask.s_addr);
2584
2585 /* Set Hello Interval. */
2586 stream_putw (s, OSPF_IF_PARAM (oi, v_hello));
2587
2588 if (IS_DEBUG_OSPF_EVENT)
2589 zlog_info ("make_hello: options: %x, int: %s",
2590 OPTIONS(oi), IF_NAME (oi));
2591
2592 /* Set Options. */
2593 stream_putc (s, OPTIONS (oi));
2594
2595 /* Set Router Priority. */
2596 stream_putc (s, PRIORITY (oi));
2597
2598 /* Set Router Dead Interval. */
2599 stream_putl (s, OSPF_IF_PARAM (oi, v_wait));
2600
2601 /* Set Designated Router. */
2602 stream_put_ipv4 (s, DR (oi).s_addr);
2603
2604 p = s->putp;
2605
2606 /* Set Backup Designated Router. */
2607 stream_put_ipv4 (s, BDR (oi).s_addr);
2608
2609 /* Add neighbor seen. */
2610 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
paul68980082003-03-25 05:07:42 +00002611 if ((nbr = rn->info))
2612 if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */
2613 if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */
2614 if (nbr->state != NSM_Down) /* This is myself for DR election. */
2615 if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
paul718e3742002-12-13 20:15:29 +00002616 {
2617 /* Check neighbor is sane? */
paul68980082003-03-25 05:07:42 +00002618 if (nbr->d_router.s_addr != 0
2619 && IPV4_ADDR_SAME (&nbr->d_router, &oi->address->u.prefix4)
2620 && IPV4_ADDR_SAME (&nbr->bd_router, &oi->address->u.prefix4))
2621 flag = 1;
paul718e3742002-12-13 20:15:29 +00002622
2623 stream_put_ipv4 (s, nbr->router_id.s_addr);
2624 length += 4;
2625 }
2626
2627 /* Let neighbor generate BackupSeen. */
2628 if (flag == 1)
2629 {
2630 stream_set_putp (s, p);
2631 stream_put_ipv4 (s, 0);
2632 }
2633
2634 return length;
2635}
2636
2637int
2638ospf_make_db_desc (struct ospf_interface *oi, struct ospf_neighbor *nbr,
2639 struct stream *s)
2640{
2641 struct ospf_lsa *lsa;
2642 u_int16_t length = OSPF_DB_DESC_MIN_SIZE;
2643 u_char options;
2644 unsigned long pp;
2645 int i;
2646 struct ospf_lsdb *lsdb;
2647
2648 /* Set Interface MTU. */
2649 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
2650 stream_putw (s, 0);
2651 else
2652 stream_putw (s, oi->ifp->mtu);
2653
2654 /* Set Options. */
2655 options = OPTIONS (oi);
2656#ifdef HAVE_OPAQUE_LSA
paul68980082003-03-25 05:07:42 +00002657 if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))
paul718e3742002-12-13 20:15:29 +00002658 {
2659 if (IS_SET_DD_I (nbr->dd_flags)
2660 || CHECK_FLAG (nbr->options, OSPF_OPTION_O))
2661 /*
2662 * Set O-bit in the outgoing DD packet for capablity negotiation,
2663 * if one of following case is applicable.
2664 *
2665 * 1) WaitTimer expiration event triggered the neighbor state to
2666 * change to Exstart, but no (valid) DD packet has received
2667 * from the neighbor yet.
2668 *
2669 * 2) At least one DD packet with O-bit on has received from the
2670 * neighbor.
2671 */
2672 SET_FLAG (options, OSPF_OPTION_O);
2673 }
2674#endif /* HAVE_OPAQUE_LSA */
2675 stream_putc (s, options);
2676
2677 /* Keep pointer to flags. */
2678 pp = stream_get_putp (s);
2679 stream_putc (s, nbr->dd_flags);
2680
2681 /* Set DD Sequence Number. */
2682 stream_putl (s, nbr->dd_seqnum);
2683
2684 if (ospf_db_summary_isempty (nbr))
2685 {
2686 if (nbr->state >= NSM_Exchange)
2687 {
2688 nbr->dd_flags &= ~OSPF_DD_FLAG_M;
2689 /* Set DD flags again */
2690 stream_set_putp (s, pp);
2691 stream_putc (s, nbr->dd_flags);
2692 }
2693 return length;
2694 }
2695
2696 /* Describe LSA Header from Database Summary List. */
2697 lsdb = &nbr->db_sum;
2698
2699 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
2700 {
2701 struct route_table *table = lsdb->type[i].db;
2702 struct route_node *rn;
2703
2704 for (rn = route_top (table); rn; rn = route_next (rn))
2705 if ((lsa = rn->info) != NULL)
2706 {
2707#ifdef HAVE_OPAQUE_LSA
2708 if (IS_OPAQUE_LSA (lsa->data->type)
2709 && (! CHECK_FLAG (options, OSPF_OPTION_O)))
2710 {
2711 /* Suppress advertising opaque-informations. */
2712 /* Remove LSA from DB summary list. */
2713 ospf_lsdb_delete (lsdb, lsa);
2714 continue;
2715 }
2716#endif /* HAVE_OPAQUE_LSA */
2717
2718 if (!CHECK_FLAG (lsa->flags, OSPF_LSA_DISCARD))
2719 {
2720 struct lsa_header *lsah;
2721 u_int16_t ls_age;
2722
2723 /* DD packet overflows interface MTU. */
2724 if (length + OSPF_LSA_HEADER_SIZE > OSPF_PACKET_MAX (oi))
2725 break;
2726
2727 /* Keep pointer to LS age. */
2728 lsah = (struct lsa_header *) (STREAM_DATA (s) +
2729 stream_get_putp (s));
2730
2731 /* Proceed stream pointer. */
2732 stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
2733 length += OSPF_LSA_HEADER_SIZE;
2734
2735 /* Set LS age. */
2736 ls_age = LS_AGE (lsa);
2737 lsah->ls_age = htons (ls_age);
2738
2739 }
2740
2741 /* Remove LSA from DB summary list. */
2742 ospf_lsdb_delete (lsdb, lsa);
2743 }
2744 }
2745
2746 return length;
2747}
2748
2749int
2750ospf_make_ls_req_func (struct stream *s, u_int16_t *length,
2751 unsigned long delta, struct ospf_neighbor *nbr,
2752 struct ospf_lsa *lsa)
2753{
2754 struct ospf_interface *oi;
2755
2756 oi = nbr->oi;
2757
2758 /* LS Request packet overflows interface MTU. */
2759 if (*length + delta > OSPF_PACKET_MAX(oi))
2760 return 0;
2761
2762 stream_putl (s, lsa->data->type);
2763 stream_put_ipv4 (s, lsa->data->id.s_addr);
2764 stream_put_ipv4 (s, lsa->data->adv_router.s_addr);
2765
2766 ospf_lsa_unlock (nbr->ls_req_last);
2767 nbr->ls_req_last = ospf_lsa_lock (lsa);
2768
2769 *length += 12;
2770 return 1;
2771}
2772
2773int
2774ospf_make_ls_req (struct ospf_neighbor *nbr, struct stream *s)
2775{
2776 struct ospf_lsa *lsa;
2777 u_int16_t length = OSPF_LS_REQ_MIN_SIZE;
2778 unsigned long delta = stream_get_putp(s)+12;
2779 struct route_table *table;
2780 struct route_node *rn;
2781 int i;
2782 struct ospf_lsdb *lsdb;
2783
2784 lsdb = &nbr->ls_req;
2785
2786 for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++)
2787 {
2788 table = lsdb->type[i].db;
2789 for (rn = route_top (table); rn; rn = route_next (rn))
2790 if ((lsa = (rn->info)) != NULL)
2791 if (ospf_make_ls_req_func (s, &length, delta, nbr, lsa) == 0)
2792 {
2793 route_unlock_node (rn);
2794 break;
2795 }
2796 }
2797 return length;
2798}
2799
2800int
2801ls_age_increment (struct ospf_lsa *lsa, int delay)
2802{
2803 int age;
2804
2805 age = IS_LSA_MAXAGE (lsa) ? OSPF_LSA_MAXAGE : LS_AGE (lsa) + delay;
2806
2807 return (age > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : age);
2808}
2809
2810int
hasso52dc7ee2004-09-23 19:18:23 +00002811ospf_make_ls_upd (struct ospf_interface *oi, struct list *update, struct stream *s)
paul718e3742002-12-13 20:15:29 +00002812{
2813 struct ospf_lsa *lsa;
hasso52dc7ee2004-09-23 19:18:23 +00002814 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002815 u_int16_t length = OSPF_LS_UPD_MIN_SIZE;
2816 unsigned long delta = stream_get_putp (s);
2817 unsigned long pp;
2818 int count = 0;
2819
2820 if (IS_DEBUG_OSPF_EVENT)
paul59ea14c2004-07-14 20:50:36 +00002821 zlog_info ("ospf_make_ls_upd: Start");
2822
paul718e3742002-12-13 20:15:29 +00002823 pp = stream_get_putp (s);
paul68b73392004-09-12 14:21:37 +00002824 ospf_output_forward (s, OSPF_LS_UPD_MIN_SIZE);
paul718e3742002-12-13 20:15:29 +00002825
2826 while ((node = listhead (update)) != NULL)
2827 {
2828 struct lsa_header *lsah;
2829 u_int16_t ls_age;
2830
2831 if (IS_DEBUG_OSPF_EVENT)
paul59ea14c2004-07-14 20:50:36 +00002832 zlog_info ("ospf_make_ls_upd: List Iteration");
paul718e3742002-12-13 20:15:29 +00002833
2834 lsa = getdata (node);
2835 assert (lsa);
2836 assert (lsa->data);
2837
paul68b73392004-09-12 14:21:37 +00002838 /* Will it fit? */
2839 if (length + delta + ntohs (lsa->data->length) > stream_get_size (s))
paul59ea14c2004-07-14 20:50:36 +00002840 break;
2841
paul718e3742002-12-13 20:15:29 +00002842 /* Keep pointer to LS age. */
2843 lsah = (struct lsa_header *) (STREAM_DATA (s) + stream_get_putp (s));
2844
2845 /* Put LSA to Link State Request. */
2846 stream_put (s, lsa->data, ntohs (lsa->data->length));
2847
2848 /* Set LS age. */
2849 /* each hop must increment an lsa_age by transmit_delay
2850 of OSPF interface */
2851 ls_age = ls_age_increment (lsa, OSPF_IF_PARAM (oi, transmit_delay));
2852 lsah->ls_age = htons (ls_age);
2853
2854 length += ntohs (lsa->data->length);
2855 count++;
2856
2857 list_delete_node (update, node);
2858 ospf_lsa_unlock (lsa);
2859 }
2860
2861 /* Now set #LSAs. */
2862 stream_set_putp (s, pp);
2863 stream_putl (s, count);
2864
2865 stream_set_putp (s, s->endp);
2866
2867 if (IS_DEBUG_OSPF_EVENT)
paul59ea14c2004-07-14 20:50:36 +00002868 zlog_info ("ospf_make_ls_upd: Stop");
paul718e3742002-12-13 20:15:29 +00002869 return length;
2870}
2871
2872int
hasso52dc7ee2004-09-23 19:18:23 +00002873ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
paul718e3742002-12-13 20:15:29 +00002874{
hasso52dc7ee2004-09-23 19:18:23 +00002875 struct list *rm_list;
2876 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002877 u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
2878 unsigned long delta = stream_get_putp(s) + 24;
2879 struct ospf_lsa *lsa;
2880
2881 rm_list = list_new ();
2882
2883 for (node = listhead (ack); node; nextnode (node))
2884 {
2885 lsa = getdata (node);
2886 assert (lsa);
2887
2888 if (length + delta > OSPF_PACKET_MAX (oi))
2889 break;
2890
2891 stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
2892 length += OSPF_LSA_HEADER_SIZE;
2893
2894 listnode_add (rm_list, lsa);
2895 }
2896
2897 /* Remove LSA from LS-Ack list. */
2898 for (node = listhead (rm_list); node; nextnode (node))
2899 {
2900 lsa = (struct ospf_lsa *) getdata (node);
2901
2902 listnode_delete (ack, lsa);
2903 ospf_lsa_unlock (lsa);
2904 }
2905
2906 list_delete (rm_list);
2907
2908 return length;
2909}
2910
2911void
2912ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
2913{
2914 struct ospf_packet *op;
2915 u_int16_t length = OSPF_HEADER_SIZE;
2916
2917 op = ospf_packet_new (oi->ifp->mtu);
2918
2919 /* Prepare OSPF common header. */
2920 ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
2921
2922 /* Prepare OSPF Hello body. */
2923 length += ospf_make_hello (oi, op->s);
2924
2925 /* Fill OSPF header. */
2926 ospf_fill_header (oi, op->s, length);
2927
2928 /* Set packet length. */
2929 op->length = length;
2930
2931 op->dst.s_addr = addr->s_addr;
2932
2933 /* Add packet to the interface output queue. */
2934 ospf_packet_add (oi, op);
2935
2936 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00002937 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00002938}
2939
2940void
2941ospf_poll_send (struct ospf_nbr_nbma *nbr_nbma)
2942{
2943 struct ospf_interface *oi;
2944
2945 oi = nbr_nbma->oi;
2946 assert(oi);
2947
2948 /* If this is passive interface, do not send OSPF Hello. */
2949 if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
2950 return;
2951
2952 if (oi->type != OSPF_IFTYPE_NBMA)
2953 return;
2954
2955 if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
2956 return;
2957
2958 if (PRIORITY(oi) == 0)
2959 return;
2960
2961 if (nbr_nbma->priority == 0
2962 && oi->state != ISM_DR && oi->state != ISM_Backup)
2963 return;
2964
2965 ospf_hello_send_sub (oi, &nbr_nbma->addr);
2966}
2967
2968int
2969ospf_poll_timer (struct thread *thread)
2970{
2971 struct ospf_nbr_nbma *nbr_nbma;
2972
2973 nbr_nbma = THREAD_ARG (thread);
2974 nbr_nbma->t_poll = NULL;
2975
2976 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
2977 zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (Poll timer expire)",
2978 IF_NAME (nbr_nbma->oi), inet_ntoa (nbr_nbma->addr));
2979
2980 ospf_poll_send (nbr_nbma);
2981
2982 if (nbr_nbma->v_poll > 0)
2983 OSPF_POLL_TIMER_ON (nbr_nbma->t_poll, ospf_poll_timer,
2984 nbr_nbma->v_poll);
2985
2986 return 0;
2987}
2988
2989
2990int
2991ospf_hello_reply_timer (struct thread *thread)
2992{
2993 struct ospf_neighbor *nbr;
2994
2995 nbr = THREAD_ARG (thread);
2996 nbr->t_hello_reply = NULL;
2997
2998 assert (nbr->oi);
2999
3000 if (IS_DEBUG_OSPF (nsm, NSM_TIMERS))
3001 zlog (NULL, LOG_INFO, "NSM[%s:%s]: Timer (hello-reply timer expire)",
3002 IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
3003
3004 ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
3005
3006 return 0;
3007}
3008
3009/* Send OSPF Hello. */
3010void
3011ospf_hello_send (struct ospf_interface *oi)
3012{
3013 struct ospf_packet *op;
3014 u_int16_t length = OSPF_HEADER_SIZE;
3015
3016 /* If this is passive interface, do not send OSPF Hello. */
3017 if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
3018 return;
3019
3020 op = ospf_packet_new (oi->ifp->mtu);
3021
3022 /* Prepare OSPF common header. */
3023 ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
3024
3025 /* Prepare OSPF Hello body. */
3026 length += ospf_make_hello (oi, op->s);
3027
3028 /* Fill OSPF header. */
3029 ospf_fill_header (oi, op->s, length);
3030
3031 /* Set packet length. */
3032 op->length = length;
3033
3034 if (oi->type == OSPF_IFTYPE_NBMA)
3035 {
3036 struct ospf_neighbor *nbr;
3037 struct route_node *rn;
3038
3039 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
3040 if ((nbr = rn->info))
3041 if (nbr != oi->nbr_self)
3042 if (nbr->state != NSM_Down)
3043 {
3044 /* RFC 2328 Section 9.5.1
3045 If the router is not eligible to become Designated Router,
3046 it must periodically send Hello Packets to both the
3047 Designated Router and the Backup Designated Router (if they
3048 exist). */
3049 if (PRIORITY(oi) == 0 &&
3050 IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
3051 IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
3052 continue;
3053
3054 /* If the router is eligible to become Designated Router, it
3055 must periodically send Hello Packets to all neighbors that
3056 are also eligible. In addition, if the router is itself the
3057 Designated Router or Backup Designated Router, it must also
3058 send periodic Hello Packets to all other neighbors. */
3059
3060 if (nbr->priority == 0 && oi->state == ISM_DROther)
3061 continue;
3062 /* if oi->state == Waiting, send hello to all neighbors */
3063 {
3064 struct ospf_packet *op_dup;
3065
3066 op_dup = ospf_packet_dup(op);
3067 op_dup->dst = nbr->address.u.prefix4;
3068
3069 /* Add packet to the interface output queue. */
3070 ospf_packet_add (oi, op_dup);
3071
paul020709f2003-04-04 02:44:16 +00003072 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003073 }
3074
3075 }
3076 ospf_packet_free (op);
3077 }
3078 else
3079 {
3080 /* Decide destination address. */
3081 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3082 op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
3083 else
3084 op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3085
3086 /* Add packet to the interface output queue. */
3087 ospf_packet_add (oi, op);
3088
3089 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003090 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003091 }
3092}
3093
3094/* Send OSPF Database Description. */
3095void
3096ospf_db_desc_send (struct ospf_neighbor *nbr)
3097{
3098 struct ospf_interface *oi;
3099 struct ospf_packet *op;
3100 u_int16_t length = OSPF_HEADER_SIZE;
3101
3102 oi = nbr->oi;
3103 op = ospf_packet_new (oi->ifp->mtu);
3104
3105 /* Prepare OSPF common header. */
3106 ospf_make_header (OSPF_MSG_DB_DESC, oi, op->s);
3107
3108 /* Prepare OSPF Database Description body. */
3109 length += ospf_make_db_desc (oi, nbr, op->s);
3110
3111 /* Fill OSPF header. */
3112 ospf_fill_header (oi, op->s, length);
3113
3114 /* Set packet length. */
3115 op->length = length;
3116
3117 /* Decide destination address. */
3118 op->dst = nbr->address.u.prefix4;
3119
3120 /* Add packet to the interface output queue. */
3121 ospf_packet_add (oi, op);
3122
3123 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003124 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003125
3126 /* Remove old DD packet, then copy new one and keep in neighbor structure. */
3127 if (nbr->last_send)
3128 ospf_packet_free (nbr->last_send);
3129 nbr->last_send = ospf_packet_dup (op);
3130 gettimeofday (&nbr->last_send_ts, NULL);
3131}
3132
3133/* Re-send Database Description. */
3134void
3135ospf_db_desc_resend (struct ospf_neighbor *nbr)
3136{
3137 struct ospf_interface *oi;
3138
3139 oi = nbr->oi;
3140
3141 /* Add packet to the interface output queue. */
3142 ospf_packet_add (oi, ospf_packet_dup (nbr->last_send));
3143
3144 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003145 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003146}
3147
3148/* Send Link State Request. */
3149void
3150ospf_ls_req_send (struct ospf_neighbor *nbr)
3151{
3152 struct ospf_interface *oi;
3153 struct ospf_packet *op;
3154 u_int16_t length = OSPF_HEADER_SIZE;
3155
3156 oi = nbr->oi;
3157 op = ospf_packet_new (oi->ifp->mtu);
3158
3159 /* Prepare OSPF common header. */
3160 ospf_make_header (OSPF_MSG_LS_REQ, oi, op->s);
3161
3162 /* Prepare OSPF Link State Request body. */
3163 length += ospf_make_ls_req (nbr, op->s);
3164 if (length == OSPF_HEADER_SIZE)
3165 {
3166 ospf_packet_free (op);
3167 return;
3168 }
3169
3170 /* Fill OSPF header. */
3171 ospf_fill_header (oi, op->s, length);
3172
3173 /* Set packet length. */
3174 op->length = length;
3175
3176 /* Decide destination address. */
3177 op->dst = nbr->address.u.prefix4;
3178
3179 /* Add packet to the interface output queue. */
3180 ospf_packet_add (oi, op);
3181
3182 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003183 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003184
3185 /* Add Link State Request Retransmission Timer. */
3186 OSPF_NSM_TIMER_ON (nbr->t_ls_req, ospf_ls_req_timer, nbr->v_ls_req);
3187}
3188
3189/* Send Link State Update with an LSA. */
3190void
3191ospf_ls_upd_send_lsa (struct ospf_neighbor *nbr, struct ospf_lsa *lsa,
3192 int flag)
3193{
hasso52dc7ee2004-09-23 19:18:23 +00003194 struct list *update;
paul718e3742002-12-13 20:15:29 +00003195
3196 update = list_new ();
3197
3198 listnode_add (update, lsa);
3199 ospf_ls_upd_send (nbr, update, flag);
3200
3201 list_delete (update);
3202}
3203
paul68b73392004-09-12 14:21:37 +00003204/* Determine size for packet. Must be at least big enough to accomodate next
3205 * LSA on list, which may be bigger than MTU size.
3206 *
3207 * Return pointer to new ospf_packet
3208 * NULL if we can not allocate, eg because LSA is bigger than imposed limit
3209 * on packet sizes (in which case offending LSA is deleted from update list)
3210 */
3211static struct ospf_packet *
3212ospf_ls_upd_packet_new (struct list *update, struct ospf_interface *oi)
3213{
3214 struct ospf_lsa *lsa;
3215 struct listnode *ln;
3216 size_t size;
3217 static char warned = 0;
3218
3219 ln = listhead (update);
3220 lsa = getdata (ln);
3221 assert (lsa);
3222 assert (lsa->data);
3223
3224 if ((OSPF_LS_UPD_MIN_SIZE + ntohs (lsa->data->length))
3225 > ospf_packet_max (oi))
3226 {
3227 if (!warned)
3228 {
3229 zlog_warn ("ospf_ls_upd_packet_new: oversized LSA encountered!"
3230 "will need to fragment. Not optimal. Try divide up"
3231 " your network with areas. Use 'debug ospf packet send'"
3232 " to see details, or look at 'show ip ospf database ..'");
3233 warned = 1;
3234 }
3235
3236 if (IS_DEBUG_OSPF_PACKET (0, SEND))
3237 zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s,"
3238 " %d bytes originated by %s, will be fragmented!",
3239 inet_ntoa (lsa->data->id),
3240 ntohs (lsa->data->length),
3241 inet_ntoa (lsa->data->adv_router));
3242
3243 /*
3244 * Allocate just enough to fit this LSA only, to avoid including other
3245 * LSAs in fragmented LSA Updates.
3246 */
3247 size = ntohs (lsa->data->length) + (oi->ifp->mtu - ospf_packet_max (oi))
3248 + OSPF_LS_UPD_MIN_SIZE;
3249 }
3250 else
3251 size = oi->ifp->mtu;
3252
3253 if (size > OSPF_MAX_PACKET_SIZE)
3254 {
3255 zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s too big,"
3256 " %d bytes, dropping it completely."
3257 " OSPF routing is broken!",
3258 inet_ntoa (lsa->data->id), ntohs (lsa->data->length));
3259 list_delete_node (update, ln);
3260 return NULL;
3261 }
3262
3263 return ospf_packet_new (size);
3264}
3265
paul718e3742002-12-13 20:15:29 +00003266static void
hasso52dc7ee2004-09-23 19:18:23 +00003267ospf_ls_upd_queue_send (struct ospf_interface *oi, struct list *update,
paul718e3742002-12-13 20:15:29 +00003268 struct in_addr addr)
3269{
3270 struct ospf_packet *op;
3271 u_int16_t length = OSPF_HEADER_SIZE;
3272
3273 if (IS_DEBUG_OSPF_EVENT)
3274 zlog_info ("listcount = %d, dst %s", listcount (update), inet_ntoa(addr));
paul68b73392004-09-12 14:21:37 +00003275
3276 op = ospf_ls_upd_packet_new (update, oi);
paul718e3742002-12-13 20:15:29 +00003277
3278 /* Prepare OSPF common header. */
3279 ospf_make_header (OSPF_MSG_LS_UPD, oi, op->s);
3280
paul59ea14c2004-07-14 20:50:36 +00003281 /* Prepare OSPF Link State Update body.
3282 * Includes Type-7 translation.
3283 */
paul718e3742002-12-13 20:15:29 +00003284 length += ospf_make_ls_upd (oi, update, op->s);
3285
3286 /* Fill OSPF header. */
3287 ospf_fill_header (oi, op->s, length);
3288
3289 /* Set packet length. */
3290 op->length = length;
3291
3292 /* Decide destination address. */
3293 op->dst.s_addr = addr.s_addr;
3294
3295 /* Add packet to the interface output queue. */
3296 ospf_packet_add (oi, op);
3297
3298 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003299 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003300}
3301
3302static int
3303ospf_ls_upd_send_queue_event (struct thread *thread)
3304{
3305 struct ospf_interface *oi = THREAD_ARG(thread);
3306 struct route_node *rn;
paul736d3442003-07-24 23:22:57 +00003307 struct route_node *rnext;
paul59ea14c2004-07-14 20:50:36 +00003308 struct list *update;
paul68b73392004-09-12 14:21:37 +00003309 char again = 0;
paul718e3742002-12-13 20:15:29 +00003310
3311 oi->t_ls_upd_event = NULL;
3312
3313 if (IS_DEBUG_OSPF_EVENT)
3314 zlog_info ("ospf_ls_upd_send_queue start");
3315
paul736d3442003-07-24 23:22:57 +00003316 for (rn = route_top (oi->ls_upd_queue); rn; rn = rnext)
paul718e3742002-12-13 20:15:29 +00003317 {
paul736d3442003-07-24 23:22:57 +00003318 rnext = route_next (rn);
3319
paul718e3742002-12-13 20:15:29 +00003320 if (rn->info == NULL)
paul736d3442003-07-24 23:22:57 +00003321 continue;
paul68b73392004-09-12 14:21:37 +00003322
3323 update = (struct list *)rn->info;
paul718e3742002-12-13 20:15:29 +00003324
paul48fe13b2004-07-27 17:40:44 +00003325 ospf_ls_upd_queue_send (oi, update, rn->p.u.prefix4);
paul718e3742002-12-13 20:15:29 +00003326
paul68b73392004-09-12 14:21:37 +00003327 /* list might not be empty. */
paul59ea14c2004-07-14 20:50:36 +00003328 if (listcount(update) == 0)
3329 {
3330 list_delete (rn->info);
3331 rn->info = NULL;
3332 route_unlock_node (rn);
3333 }
3334 else
paul68b73392004-09-12 14:21:37 +00003335 again = 1;
paul59ea14c2004-07-14 20:50:36 +00003336 }
3337
3338 if (again != 0)
3339 {
3340 if (IS_DEBUG_OSPF_EVENT)
3341 zlog_info ("ospf_ls_upd_send_queue: update lists not cleared,"
3342 " %d nodes to try again, raising new event", again);
3343 oi->t_ls_upd_event =
3344 thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
paul718e3742002-12-13 20:15:29 +00003345 }
3346
3347 if (IS_DEBUG_OSPF_EVENT)
3348 zlog_info ("ospf_ls_upd_send_queue stop");
paul59ea14c2004-07-14 20:50:36 +00003349
paul718e3742002-12-13 20:15:29 +00003350 return 0;
3351}
3352
3353void
hasso52dc7ee2004-09-23 19:18:23 +00003354ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
paul718e3742002-12-13 20:15:29 +00003355{
3356 struct ospf_interface *oi;
3357 struct prefix_ipv4 p;
3358 struct route_node *rn;
hasso52dc7ee2004-09-23 19:18:23 +00003359 struct listnode *n;
paul718e3742002-12-13 20:15:29 +00003360
3361 oi = nbr->oi;
3362
3363 p.family = AF_INET;
3364 p.prefixlen = IPV4_MAX_BITLEN;
3365
3366 /* Decide destination address. */
3367 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3368 p.prefix = oi->vl_data->peer_addr;
3369 else if (flag == OSPF_SEND_PACKET_DIRECT)
3370 p.prefix = nbr->address.u.prefix4;
3371 else if (oi->state == ISM_DR || oi->state == ISM_Backup)
3372 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
3373 else if ((oi->type == OSPF_IFTYPE_POINTOPOINT)
3374 && (flag == OSPF_SEND_PACKET_INDIRECT))
3375 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul7afa08d2002-12-13 20:59:45 +00003376 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
3377 p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul718e3742002-12-13 20:15:29 +00003378 else
3379 p.prefix.s_addr = htonl (OSPF_ALLDROUTERS);
3380
3381 if (oi->type == OSPF_IFTYPE_NBMA)
3382 {
3383 if (flag == OSPF_SEND_PACKET_INDIRECT)
3384 zlog_warn ("* LS-Update is directly sent on NBMA network.");
3385 if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix.s_addr))
3386 zlog_warn ("* LS-Update is sent to myself.");
3387 }
3388
3389 rn = route_node_get (oi->ls_upd_queue, (struct prefix *) &p);
3390
3391 if (rn->info == NULL)
3392 rn->info = list_new ();
3393
3394 for (n = listhead (update); n; nextnode (n))
3395 listnode_add (rn->info, ospf_lsa_lock (getdata (n)));
3396
3397 if (oi->t_ls_upd_event == NULL)
3398 oi->t_ls_upd_event =
3399 thread_add_event (master, ospf_ls_upd_send_queue_event, oi, 0);
3400}
3401
3402static void
hasso52dc7ee2004-09-23 19:18:23 +00003403ospf_ls_ack_send_list (struct ospf_interface *oi, struct list *ack,
3404 struct in_addr dst)
paul718e3742002-12-13 20:15:29 +00003405{
3406 struct ospf_packet *op;
3407 u_int16_t length = OSPF_HEADER_SIZE;
3408
3409 op = ospf_packet_new (oi->ifp->mtu);
3410
3411 /* Prepare OSPF common header. */
3412 ospf_make_header (OSPF_MSG_LS_ACK, oi, op->s);
3413
3414 /* Prepare OSPF Link State Acknowledgment body. */
3415 length += ospf_make_ls_ack (oi, ack, op->s);
3416
3417 /* Fill OSPF header. */
3418 ospf_fill_header (oi, op->s, length);
3419
3420 /* Set packet length. */
3421 op->length = length;
3422
3423 /* Set destination IP address. */
3424 op->dst = dst;
3425
3426 /* Add packet to the interface output queue. */
3427 ospf_packet_add (oi, op);
3428
3429 /* Hook thread to write packet. */
paul020709f2003-04-04 02:44:16 +00003430 OSPF_ISM_WRITE_ON (oi->ospf);
paul718e3742002-12-13 20:15:29 +00003431}
3432
3433static int
3434ospf_ls_ack_send_event (struct thread *thread)
3435{
3436 struct ospf_interface *oi = THREAD_ARG (thread);
3437
3438 oi->t_ls_ack_direct = NULL;
3439
3440 while (listcount (oi->ls_ack_direct.ls_ack))
3441 ospf_ls_ack_send_list (oi, oi->ls_ack_direct.ls_ack,
3442 oi->ls_ack_direct.dst);
3443
3444 return 0;
3445}
3446
3447void
3448ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
3449{
3450 struct ospf_interface *oi = nbr->oi;
3451
3452 if (listcount (oi->ls_ack_direct.ls_ack) == 0)
3453 oi->ls_ack_direct.dst = nbr->address.u.prefix4;
3454
3455 listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa));
3456
3457 if (oi->t_ls_ack_direct == NULL)
3458 oi->t_ls_ack_direct =
3459 thread_add_event (master, ospf_ls_ack_send_event, oi, 0);
3460}
3461
3462/* Send Link State Acknowledgment delayed. */
3463void
3464ospf_ls_ack_send_delayed (struct ospf_interface *oi)
3465{
3466 struct in_addr dst;
3467
3468 /* Decide destination address. */
3469 /* RFC2328 Section 13.5 On non-broadcast
3470 networks, delayed Link State Acknowledgment packets must be
3471 unicast separately over each adjacency (i.e., neighbor whose
3472 state is >= Exchange). */
3473 if (oi->type == OSPF_IFTYPE_NBMA)
3474 {
3475 struct ospf_neighbor *nbr;
3476 struct route_node *rn;
3477
3478 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
3479 if ((nbr = rn->info) != NULL)
3480 if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
3481 while (listcount (oi->ls_ack))
3482 ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4);
3483 return;
3484 }
3485 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
3486 dst.s_addr = oi->vl_data->peer_addr.s_addr;
3487 else if (oi->state == ISM_DR || oi->state == ISM_Backup)
3488 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
3489 else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
3490 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
gdt630e4802004-08-31 17:28:41 +00003491 else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
3492 dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
paul718e3742002-12-13 20:15:29 +00003493 else
3494 dst.s_addr = htonl (OSPF_ALLDROUTERS);
3495
3496 while (listcount (oi->ls_ack))
3497 ospf_ls_ack_send_list (oi, oi->ls_ack, dst);
3498}