blob: 0cd90360dfd5782f9e6fae2943be342f2cdb8d78 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
hasso508e53e2004-05-18 18:57:06 +000022#include <zebra.h>
23
hasso3b4cd3a2004-05-18 19:28:32 +000024#include "memory.h"
hasso508e53e2004-05-18 18:57:06 +000025#include "log.h"
26#include "vty.h"
27#include "command.h"
28#include "thread.h"
29#include "linklist.h"
30
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
33#include "ospf6_lsdb.h"
34#include "ospf6_network.h"
35#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000036
hasso508e53e2004-05-18 18:57:06 +000037#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_neighbor.h"
40#include "ospf6_interface.h"
41
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040042/* for structures and macros ospf6_lsa_examin() needs */
43#include "ospf6_abr.h"
44#include "ospf6_asbr.h"
45#include "ospf6_intra.h"
46
hasso508e53e2004-05-18 18:57:06 +000047#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000048#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000049
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +040050#include <netinet/ip6.h>
51
hasso508e53e2004-05-18 18:57:06 +000052unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
paul0c083ee2004-10-10 12:54:58 +000053const char *ospf6_message_type_str[] =
hasso508e53e2004-05-18 18:57:06 +000054 { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
55
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040056/* Minimum (besides the standard OSPF packet header) lengths for OSPF
57 packets of particular types, offset is the "type" field. */
58const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
59{
60 0,
61 OSPF6_HELLO_MIN_SIZE,
62 OSPF6_DB_DESC_MIN_SIZE,
63 OSPF6_LS_REQ_MIN_SIZE,
64 OSPF6_LS_UPD_MIN_SIZE,
65 OSPF6_LS_ACK_MIN_SIZE
66};
67
68/* Minimum (besides the standard LSA header) lengths for LSAs of particular
69 types, offset is the "LSA function code" portion of "LSA type" field. */
70const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
71{
72 0,
73 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
74 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
75 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
76 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
77 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
78 /* 0x2006 */ 0,
79 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
80 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
81 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
82};
83
hasso508e53e2004-05-18 18:57:06 +000084/* print functions */
85
86static void
87ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000088{
hasso508e53e2004-05-18 18:57:06 +000089 char router_id[16], area_id[16];
90 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
91 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000092
hassoc6487d62004-12-24 06:00:11 +000093 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +000094 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +000095 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +000096 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +000097}
paul718e3742002-12-13 20:15:29 +000098
99void
hasso508e53e2004-05-18 18:57:06 +0000100ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000101{
paul718e3742002-12-13 20:15:29 +0000102 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +0000103 char options[16];
104 char drouter[16], bdrouter[16], neighbor[16];
105 char *p;
paul718e3742002-12-13 20:15:29 +0000106
hasso508e53e2004-05-18 18:57:06 +0000107 ospf6_header_print (oh);
108 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +0000109
hasso508e53e2004-05-18 18:57:06 +0000110 hello = (struct ospf6_hello *)
111 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000112
hasso508e53e2004-05-18 18:57:06 +0000113 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
114 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
115 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000116
hassoc6487d62004-12-24 06:00:11 +0000117 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +0000118 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +0000119 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +0000120 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +0000121 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +0000122
hasso508e53e2004-05-18 18:57:06 +0000123 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
124 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
125 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000126 {
hasso508e53e2004-05-18 18:57:06 +0000127 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +0000128 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +0000129 }
hasso508e53e2004-05-18 18:57:06 +0000130
Denis Ovsienkofa079662011-10-08 17:22:45 +0400131 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000132}
133
hasso508e53e2004-05-18 18:57:06 +0000134void
135ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000136{
paul718e3742002-12-13 20:15:29 +0000137 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000138 char options[16];
139 char *p;
paul718e3742002-12-13 20:15:29 +0000140
hasso508e53e2004-05-18 18:57:06 +0000141 ospf6_header_print (oh);
142 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000143
hasso508e53e2004-05-18 18:57:06 +0000144 dbdesc = (struct ospf6_dbdesc *)
145 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000146
hasso508e53e2004-05-18 18:57:06 +0000147 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000148
hassoc6487d62004-12-24 06:00:11 +0000149 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000150 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000151 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000152 dbdesc->reserved2,
153 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
154 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
155 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
156 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000157
hasso508e53e2004-05-18 18:57:06 +0000158 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
159 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
160 p += sizeof (struct ospf6_lsa_header))
161 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
162
Denis Ovsienkofa079662011-10-08 17:22:45 +0400163 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000164}
165
hasso508e53e2004-05-18 18:57:06 +0000166void
167ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000168{
hasso508e53e2004-05-18 18:57:06 +0000169 char id[16], adv_router[16];
170 char *p;
paul718e3742002-12-13 20:15:29 +0000171
hasso508e53e2004-05-18 18:57:06 +0000172 ospf6_header_print (oh);
173 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000174
hasso508e53e2004-05-18 18:57:06 +0000175 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
176 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
177 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000178 {
hasso508e53e2004-05-18 18:57:06 +0000179 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
180 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
181 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000182 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000183 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000184 }
hasso508e53e2004-05-18 18:57:06 +0000185
Denis Ovsienkofa079662011-10-08 17:22:45 +0400186 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000187}
188
hasso508e53e2004-05-18 18:57:06 +0000189void
190ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000191{
paul718e3742002-12-13 20:15:29 +0000192 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000193 u_long num;
194 char *p;
paul718e3742002-12-13 20:15:29 +0000195
hasso508e53e2004-05-18 18:57:06 +0000196 ospf6_header_print (oh);
197 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000198
hasso508e53e2004-05-18 18:57:06 +0000199 lsupdate = (struct ospf6_lsupdate *)
200 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000201
hasso508e53e2004-05-18 18:57:06 +0000202 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000203 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000204
hasso508e53e2004-05-18 18:57:06 +0000205 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
206 p < OSPF6_MESSAGE_END (oh) &&
207 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
208 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000209 {
hasso508e53e2004-05-18 18:57:06 +0000210 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +0000211 }
paul718e3742002-12-13 20:15:29 +0000212
Denis Ovsienkofa079662011-10-08 17:22:45 +0400213 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000214}
215
hasso508e53e2004-05-18 18:57:06 +0000216void
217ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000218{
hasso508e53e2004-05-18 18:57:06 +0000219 char *p;
paul718e3742002-12-13 20:15:29 +0000220
hasso508e53e2004-05-18 18:57:06 +0000221 ospf6_header_print (oh);
222 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000223
hasso508e53e2004-05-18 18:57:06 +0000224 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
225 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
226 p += sizeof (struct ospf6_lsa_header))
227 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
228
Denis Ovsienkofa079662011-10-08 17:22:45 +0400229 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000230}
231
Paul Jakma6ac29a52008-08-15 13:45:30 +0100232static void
hasso508e53e2004-05-18 18:57:06 +0000233ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
234 struct ospf6_interface *oi, struct ospf6_header *oh)
235{
236 struct ospf6_hello *hello;
237 struct ospf6_neighbor *on;
238 char *p;
239 int twoway = 0;
240 int neighborchange = 0;
241 int backupseen = 0;
242
hasso508e53e2004-05-18 18:57:06 +0000243 hello = (struct ospf6_hello *)
244 ((caddr_t) oh + sizeof (struct ospf6_header));
245
paul718e3742002-12-13 20:15:29 +0000246 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000247 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000248 {
hasso508e53e2004-05-18 18:57:06 +0000249 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000250 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000251 return;
252 }
253
254 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000255 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000256 {
hasso508e53e2004-05-18 18:57:06 +0000257 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000258 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000259 return;
260 }
261
hasso508e53e2004-05-18 18:57:06 +0000262 /* E-bit check */
263 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
264 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000265 {
hasso508e53e2004-05-18 18:57:06 +0000266 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000267 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000268 return;
269 }
270
hasso508e53e2004-05-18 18:57:06 +0000271 /* Find neighbor, create if not exist */
272 on = ospf6_neighbor_lookup (oh->router_id, oi);
273 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000274 {
hasso508e53e2004-05-18 18:57:06 +0000275 on = ospf6_neighbor_create (oh->router_id, oi);
276 on->prev_drouter = on->drouter = hello->drouter;
277 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
278 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000279 }
280
hasso7b6ae022005-06-24 08:17:51 +0000281 /* always override neighbor's source address and ifindex */
282 on->ifindex = ntohl (hello->interface_id);
283 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
284
paul718e3742002-12-13 20:15:29 +0000285 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000286 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
287 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
288 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000289 {
hasso508e53e2004-05-18 18:57:06 +0000290 u_int32_t *router_id = (u_int32_t *) p;
291
292 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000293 twoway++;
paul718e3742002-12-13 20:15:29 +0000294 }
295
Denis Ovsienkofa079662011-10-08 17:22:45 +0400296 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000297
298 /* RouterPriority check */
299 if (on->priority != hello->priority)
300 {
301 on->priority = hello->priority;
302 neighborchange++;
303 }
304
305 /* DR check */
306 if (on->drouter != hello->drouter)
307 {
308 on->prev_drouter = on->drouter;
309 on->drouter = hello->drouter;
310 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
311 neighborchange++;
312 }
313
314 /* BDR check */
315 if (on->bdrouter != hello->bdrouter)
316 {
317 on->prev_bdrouter = on->bdrouter;
318 on->bdrouter = hello->bdrouter;
319 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
320 neighborchange++;
321 }
paul718e3742002-12-13 20:15:29 +0000322
323 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000324 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000325 {
hasso508e53e2004-05-18 18:57:06 +0000326 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000327 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000328 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000329 backupseen++;
330 }
331
hasso508e53e2004-05-18 18:57:06 +0000332 /* Execute neighbor events */
333 thread_execute (master, hello_received, on, 0);
334 if (twoway)
335 thread_execute (master, twoway_received, on, 0);
336 else
337 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000338
hasso508e53e2004-05-18 18:57:06 +0000339 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000340 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000341 thread_add_event (master, backup_seen, oi, 0);
342 if (neighborchange)
343 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000344}
345
hasso508e53e2004-05-18 18:57:06 +0000346static void
347ospf6_dbdesc_recv_master (struct ospf6_header *oh,
348 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000349{
paul718e3742002-12-13 20:15:29 +0000350 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000351 char *p;
paul718e3742002-12-13 20:15:29 +0000352
hasso508e53e2004-05-18 18:57:06 +0000353 dbdesc = (struct ospf6_dbdesc *)
354 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000355
hasso508e53e2004-05-18 18:57:06 +0000356 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000357 {
hasso508e53e2004-05-18 18:57:06 +0000358 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000359 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000360 return;
361 }
362
hasso508e53e2004-05-18 18:57:06 +0000363 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000364 {
hasso508e53e2004-05-18 18:57:06 +0000365 case OSPF6_NEIGHBOR_TWOWAY:
366 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000367 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000368 return;
369
370 case OSPF6_NEIGHBOR_INIT:
371 thread_execute (master, twoway_received, on, 0);
372 if (on->state != OSPF6_NEIGHBOR_EXSTART)
373 {
374 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000375 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000376 return;
377 }
378 /* else fall through to ExStart */
379
380 case OSPF6_NEIGHBOR_EXSTART:
381 /* if neighbor obeys us as our slave, schedule negotiation_done
382 and process LSA Headers. Otherwise, ignore this message */
383 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
384 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
385 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
386 {
387 /* execute NegotiationDone */
388 thread_execute (master, negotiation_done, on, 0);
389
390 /* Record neighbor options */
391 memcpy (on->options, dbdesc->options, sizeof (on->options));
392 }
393 else
394 {
395 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000396 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000397 return;
398 }
399 /* fall through to exchange */
400
401 case OSPF6_NEIGHBOR_EXCHANGE:
402 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
403 {
404 /* Duplicated DatabaseDescription is dropped by master */
405 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000406 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000407 return;
408 }
409
410 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
411 {
412 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000413 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000414 thread_add_event (master, seqnumber_mismatch, on, 0);
415 return;
416 }
417
418 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
419 {
420 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000421 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000422 thread_add_event (master, seqnumber_mismatch, on, 0);
423 return;
424 }
425
426 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
427 {
428 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000429 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000430 thread_add_event (master, seqnumber_mismatch, on, 0);
431 return;
432 }
433
434 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
435 {
436 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000437 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000438 (u_long) on->dbdesc_seqnum);
439 thread_add_event (master, seqnumber_mismatch, on, 0);
440 return;
441 }
442 break;
443
444 case OSPF6_NEIGHBOR_LOADING:
445 case OSPF6_NEIGHBOR_FULL:
446 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
447 {
448 /* Duplicated DatabaseDescription is dropped by master */
449 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000450 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000451 return;
452 }
453
454 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000455 zlog_debug ("Not duplicate dbdesc in state %s",
456 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000457 thread_add_event (master, seqnumber_mismatch, on, 0);
458 return;
459
460 default:
461 assert (0);
462 break;
463 }
464
465 /* Process LSA headers */
466 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
467 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
468 p += sizeof (struct ospf6_lsa_header))
469 {
470 struct ospf6_lsa *his, *mine;
471 struct ospf6_lsdb *lsdb = NULL;
472
473 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000474
475 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000476 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000477
478 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000479 {
hasso6452df02004-08-15 05:52:07 +0000480 case OSPF6_SCOPE_LINKLOCAL:
481 lsdb = on->ospf6_if->lsdb;
482 break;
483 case OSPF6_SCOPE_AREA:
484 lsdb = on->ospf6_if->area->lsdb;
485 break;
486 case OSPF6_SCOPE_AS:
487 lsdb = on->ospf6_if->area->ospf6->lsdb;
488 break;
489 case OSPF6_SCOPE_RESERVED:
490 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000491 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000492 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000493 continue;
494 break;
hasso508e53e2004-05-18 18:57:06 +0000495 }
496
497 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000498 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000499 {
500 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000501 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000502 ospf6_lsa_delete (his);
503 thread_add_event (master, seqnumber_mismatch, on, 0);
504 return;
505 }
506
507 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
508 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000509 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000510 {
hasso6452df02004-08-15 05:52:07 +0000511 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000512 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000513 ospf6_lsdb_add (his, on->request_list);
514 }
515 else if (ospf6_lsa_compare (his, mine) < 0)
516 {
517 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000518 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000519 ospf6_lsdb_add (his, on->request_list);
520 }
521 else
hasso6452df02004-08-15 05:52:07 +0000522 {
523 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000524 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000525 ospf6_lsa_delete (his);
526 }
hasso508e53e2004-05-18 18:57:06 +0000527 }
528
Denis Ovsienkofa079662011-10-08 17:22:45 +0400529 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000530
531 /* Increment sequence number */
532 on->dbdesc_seqnum ++;
533
534 /* schedule send lsreq */
535 if (on->thread_send_lsreq == NULL)
536 on->thread_send_lsreq =
537 thread_add_event (master, ospf6_lsreq_send, on, 0);
538
539 THREAD_OFF (on->thread_send_dbdesc);
540
541 /* More bit check */
542 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
543 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
544 thread_add_event (master, exchange_done, on, 0);
545 else
546 on->thread_send_dbdesc =
547 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
548
549 /* save last received dbdesc */
550 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
551}
552
553static void
554ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
555 struct ospf6_neighbor *on)
556{
557 struct ospf6_dbdesc *dbdesc;
558 char *p;
559
560 dbdesc = (struct ospf6_dbdesc *)
561 ((caddr_t) oh + sizeof (struct ospf6_header));
562
563 if (on->state < OSPF6_NEIGHBOR_INIT)
564 {
565 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000566 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000567 return;
568 }
569
hasso508e53e2004-05-18 18:57:06 +0000570 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000571 {
hasso508e53e2004-05-18 18:57:06 +0000572 case OSPF6_NEIGHBOR_TWOWAY:
573 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000574 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000575 return;
576
577 case OSPF6_NEIGHBOR_INIT:
578 thread_execute (master, twoway_received, on, 0);
579 if (on->state != OSPF6_NEIGHBOR_EXSTART)
580 {
581 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000582 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000583 return;
584 }
585 /* else fall through to ExStart */
586
587 case OSPF6_NEIGHBOR_EXSTART:
588 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
589 and process LSA Headers. Otherwise, ignore this message */
590 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
591 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
592 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
593 ntohs (oh->length) == sizeof (struct ospf6_header) +
594 sizeof (struct ospf6_dbdesc))
595 {
596 /* set the master/slave bit to slave */
597 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
598
599 /* set the DD sequence number to one specified by master */
600 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
601
602 /* schedule NegotiationDone */
603 thread_execute (master, negotiation_done, on, 0);
604
605 /* Record neighbor options */
606 memcpy (on->options, dbdesc->options, sizeof (on->options));
607 }
608 else
609 {
610 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000611 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000612 return;
613 }
614 break;
615
616 case OSPF6_NEIGHBOR_EXCHANGE:
617 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
618 {
619 /* Duplicated DatabaseDescription causes slave to retransmit */
620 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000621 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000622 THREAD_OFF (on->thread_send_dbdesc);
623 on->thread_send_dbdesc =
624 thread_add_event (master, ospf6_dbdesc_send, on, 0);
625 return;
626 }
627
628 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
629 {
630 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000631 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000632 thread_add_event (master, seqnumber_mismatch, on, 0);
633 return;
634 }
635
636 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
637 {
638 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000639 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000640 thread_add_event (master, seqnumber_mismatch, on, 0);
641 return;
642 }
643
644 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
645 {
646 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000647 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000648 thread_add_event (master, seqnumber_mismatch, on, 0);
649 return;
650 }
651
652 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
653 {
654 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000655 zlog_debug ("Sequence number mismatch (%#lx expected)",
656 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000657 thread_add_event (master, seqnumber_mismatch, on, 0);
658 return;
659 }
660 break;
661
662 case OSPF6_NEIGHBOR_LOADING:
663 case OSPF6_NEIGHBOR_FULL:
664 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
665 {
666 /* Duplicated DatabaseDescription causes slave to retransmit */
667 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000668 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000669 THREAD_OFF (on->thread_send_dbdesc);
670 on->thread_send_dbdesc =
671 thread_add_event (master, ospf6_dbdesc_send, on, 0);
672 return;
673 }
674
675 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000676 zlog_debug ("Not duplicate dbdesc in state %s",
677 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000678 thread_add_event (master, seqnumber_mismatch, on, 0);
679 return;
680
681 default:
682 assert (0);
683 break;
paul718e3742002-12-13 20:15:29 +0000684 }
685
hasso508e53e2004-05-18 18:57:06 +0000686 /* Process LSA headers */
687 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
688 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
689 p += sizeof (struct ospf6_lsa_header))
690 {
691 struct ospf6_lsa *his, *mine;
692 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000693
hasso508e53e2004-05-18 18:57:06 +0000694 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000695
696 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000697 {
hasso6452df02004-08-15 05:52:07 +0000698 case OSPF6_SCOPE_LINKLOCAL:
699 lsdb = on->ospf6_if->lsdb;
700 break;
701 case OSPF6_SCOPE_AREA:
702 lsdb = on->ospf6_if->area->lsdb;
703 break;
704 case OSPF6_SCOPE_AS:
705 lsdb = on->ospf6_if->area->ospf6->lsdb;
706 break;
707 case OSPF6_SCOPE_RESERVED:
708 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000709 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000710 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000711 continue;
712 break;
hasso508e53e2004-05-18 18:57:06 +0000713 }
714
hasso6452df02004-08-15 05:52:07 +0000715 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
716 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000717 {
718 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000719 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000720 ospf6_lsa_delete (his);
721 thread_add_event (master, seqnumber_mismatch, on, 0);
722 return;
723 }
724
725 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
726 his->header->adv_router, lsdb);
727 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
728 {
hasso6452df02004-08-15 05:52:07 +0000729 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000730 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000731 ospf6_lsdb_add (his, on->request_list);
732 }
733 else
734 ospf6_lsa_delete (his);
735 }
736
Denis Ovsienkofa079662011-10-08 17:22:45 +0400737 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000738
739 /* Set sequence number to Master's */
740 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
741
742 /* schedule send lsreq */
743 if (on->thread_send_lsreq == NULL)
744 on->thread_send_lsreq =
745 thread_add_event (master, ospf6_lsreq_send, on, 0);
746
747 THREAD_OFF (on->thread_send_dbdesc);
748 on->thread_send_dbdesc =
749 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
750
751 /* save last received dbdesc */
752 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000753}
754
Paul Jakma6ac29a52008-08-15 13:45:30 +0100755static void
hasso508e53e2004-05-18 18:57:06 +0000756ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
757 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000758{
hasso508e53e2004-05-18 18:57:06 +0000759 struct ospf6_neighbor *on;
760 struct ospf6_dbdesc *dbdesc;
761
hasso508e53e2004-05-18 18:57:06 +0000762 on = ospf6_neighbor_lookup (oh->router_id, oi);
763 if (on == NULL)
764 {
765 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000766 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000767 return;
768 }
769
hasso508e53e2004-05-18 18:57:06 +0000770 dbdesc = (struct ospf6_dbdesc *)
771 ((caddr_t) oh + sizeof (struct ospf6_header));
772
773 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400774 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000775 {
776 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000777 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000778 return;
779 }
780
781 if (dbdesc->reserved1 || dbdesc->reserved2)
782 {
783 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000784 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
785 on->name);
hasso508e53e2004-05-18 18:57:06 +0000786 dbdesc->reserved1 = 0;
787 dbdesc->reserved2 = 0;
788 }
789
790 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
791 ospf6_dbdesc_recv_master (oh, on);
792 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
793 ospf6_dbdesc_recv_slave (oh, on);
794 else
795 {
796 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000797 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000798 }
799}
800
Paul Jakma6ac29a52008-08-15 13:45:30 +0100801static void
hasso508e53e2004-05-18 18:57:06 +0000802ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
803 struct ospf6_interface *oi, struct ospf6_header *oh)
804{
805 struct ospf6_neighbor *on;
806 char *p;
807 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000808 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000809 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000810
hasso508e53e2004-05-18 18:57:06 +0000811 on = ospf6_neighbor_lookup (oh->router_id, oi);
812 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000813 {
hasso508e53e2004-05-18 18:57:06 +0000814 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000815 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000816 return;
817 }
818
hasso508e53e2004-05-18 18:57:06 +0000819 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
820 on->state != OSPF6_NEIGHBOR_LOADING &&
821 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000822 {
hasso508e53e2004-05-18 18:57:06 +0000823 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000824 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000825 return;
826 }
827
hasso508e53e2004-05-18 18:57:06 +0000828 /* Process each request */
829 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
830 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
831 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000832 {
hasso508e53e2004-05-18 18:57:06 +0000833 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000834
835 switch (OSPF6_LSA_SCOPE (e->type))
836 {
837 case OSPF6_SCOPE_LINKLOCAL:
838 lsdb = on->ospf6_if->lsdb;
839 break;
840 case OSPF6_SCOPE_AREA:
841 lsdb = on->ospf6_if->area->lsdb;
842 break;
843 case OSPF6_SCOPE_AS:
844 lsdb = on->ospf6_if->area->ospf6->lsdb;
845 break;
846 default:
847 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000848 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000849 continue;
850 break;
851 }
paul718e3742002-12-13 20:15:29 +0000852
hasso508e53e2004-05-18 18:57:06 +0000853 /* Find database copy */
854 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
855 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000856 {
hasso508e53e2004-05-18 18:57:06 +0000857 char id[16], adv_router[16];
858 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
859 {
860 inet_ntop (AF_INET, &e->id, id, sizeof (id));
861 inet_ntop (AF_INET, &e->adv_router, adv_router,
862 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000863 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
864 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000865 }
866 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000867 return;
868 }
869
hasso508e53e2004-05-18 18:57:06 +0000870 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000871 }
872
Denis Ovsienkofa079662011-10-08 17:22:45 +0400873 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000874
hasso508e53e2004-05-18 18:57:06 +0000875 /* schedule send lsupdate */
876 THREAD_OFF (on->thread_send_lsupdate);
877 on->thread_send_lsupdate =
878 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000879}
880
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +0400881/* Verify, that the specified memory area contains exactly N valid IPv6
882 prefixes as specified by RFC5340, A.4.1. */
883static unsigned
884ospf6_prefixes_examin
885(
886 struct ospf6_prefix *current, /* start of buffer */
887 unsigned length,
888 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
889)
890{
891 u_char requested_pfx_bytes;
892 u_int32_t real_num_pfxs = 0;
893
894 while (length)
895 {
896 if (length < OSPF6_PREFIX_MIN_SIZE)
897 {
898 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
899 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
900 return MSG_NG;
901 }
902 /* safe to look deeper */
903 if (current->prefix_length > IPV6_MAX_BITLEN)
904 {
905 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
906 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
907 return MSG_NG;
908 }
909 /* covers both fixed- and variable-sized fields */
910 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
911 if (requested_pfx_bytes > length)
912 {
913 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
914 zlog_debug ("%s: undersized IPv6 prefix", __func__);
915 return MSG_NG;
916 }
917 /* next prefix */
918 length -= requested_pfx_bytes;
919 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
920 real_num_pfxs++;
921 }
922 if (real_num_pfxs != req_num_pfxs)
923 {
924 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
925 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
926 __func__, req_num_pfxs, real_num_pfxs);
927 return MSG_NG;
928 }
929 return MSG_OK;
930}
931
932/* Verify an LSA to have a valid length and dispatch further (where
933 appropriate) to check if the contents, including nested IPv6 prefixes,
934 is properly sized/aligned within the LSA. Note that this function gets
935 LSA type in network byte order, uses in host byte order and passes to
936 ospf6_lstype_name() in network byte order again. */
937static unsigned
938ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
939{
940 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
941 struct ospf6_as_external_lsa *as_external_lsa;
942 struct ospf6_link_lsa *link_lsa;
943 unsigned exp_length;
944 u_int8_t ltindex;
945 u_int16_t lsatype;
946
947 /* In case an additional minimum length constraint is defined for current
948 LSA type, make sure that this constraint is met. */
949 lsatype = ntohs (lsah->type);
950 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
951 if
952 (
953 ltindex < OSPF6_LSTYPE_SIZE &&
954 ospf6_lsa_minlen[ltindex] &&
955 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
956 )
957 {
958 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
959 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
960 return MSG_NG;
961 }
962 switch (lsatype)
963 {
964 case OSPF6_LSTYPE_ROUTER:
965 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
966 by N>=0 interface descriptions. */
967 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
968 {
969 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
970 zlog_debug ("%s: interface description alignment error", __func__);
971 return MSG_NG;
972 }
973 break;
974 case OSPF6_LSTYPE_NETWORK:
975 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
976 followed by N>=0 attached router descriptions. */
977 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
978 {
979 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
980 zlog_debug ("%s: router description alignment error", __func__);
981 return MSG_NG;
982 }
983 break;
984 case OSPF6_LSTYPE_INTER_PREFIX:
985 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
986 followed by 3-4 fields of a single IPv6 prefix. */
987 if (headeronly)
988 break;
989 return ospf6_prefixes_examin
990 (
991 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
992 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
993 1
994 );
995 case OSPF6_LSTYPE_INTER_ROUTER:
996 /* RFC5340 A.4.6, fixed-size LSA. */
997 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
998 {
999 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1000 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1001 return MSG_NG;
1002 }
1003 break;
1004 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1005 case OSPF6_LSTYPE_TYPE_7:
1006 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1007 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1008 16 bytes of forwarding address, 4 bytes of external route tag,
1009 4 bytes of referenced link state ID. */
1010 if (headeronly)
1011 break;
1012 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1013 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1014 /* To find out if the last optional field (Referenced Link State ID) is
1015 assumed in this LSA, we need to access fixed fields of the IPv6
1016 prefix before ospf6_prefix_examin() confirms its sizing. */
1017 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1018 {
1019 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1020 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1021 return MSG_NG;
1022 }
1023 /* forwarding address */
1024 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1025 exp_length += 16;
1026 /* external route tag */
1027 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1028 exp_length += 4;
1029 /* referenced link state ID */
1030 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1031 exp_length += 4;
1032 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1033 this check does not include any IPv6 prefix fields. */
1034 if (exp_length > lsalen)
1035 {
1036 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1037 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1038 return MSG_NG;
1039 }
1040 /* The last call completely covers the remainder (IPv6 prefix). */
1041 return ospf6_prefixes_examin
1042 (
1043 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1044 lsalen - exp_length,
1045 1
1046 );
1047 case OSPF6_LSTYPE_LINK:
1048 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1049 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1050 if (headeronly)
1051 break;
1052 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1053 return ospf6_prefixes_examin
1054 (
1055 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1056 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1057 ntohl (link_lsa->prefix_num) /* 32 bits */
1058 );
1059 case OSPF6_LSTYPE_INTRA_PREFIX:
1060 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1061 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1062 if (headeronly)
1063 break;
1064 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1065 return ospf6_prefixes_examin
1066 (
1067 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1068 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1069 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1070 );
1071 }
1072 /* No additional validation is possible for unknown LSA types, which are
1073 themselves valid in OPSFv3, hence the default decision is to accept. */
1074 return MSG_OK;
1075}
1076
1077/* Verify if the provided input buffer is a valid sequence of LSAs. This
1078 includes verification of LSA blocks length/alignment and dispatching
1079 of deeper-level checks. */
1080static unsigned
1081ospf6_lsaseq_examin
1082(
1083 struct ospf6_lsa_header *lsah, /* start of buffered data */
1084 size_t length,
1085 const u_char headeronly,
1086 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1087 and treat the difference as an error. */
1088 const u_int32_t declared_num_lsas
1089)
1090{
1091 u_int32_t counted_lsas = 0;
1092
1093 while (length)
1094 {
1095 u_int16_t lsalen;
1096 if (length < OSPF6_LSA_HEADER_SIZE)
1097 {
1098 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1099 zlog_debug ("%s: undersized (%u B) trailing (#%u) LSA header",
1100 __func__, length, counted_lsas);
1101 return MSG_NG;
1102 }
1103 /* save on ntohs() calls here and in the LSA validator */
1104 lsalen = OSPF6_LSA_SIZE (lsah);
1105 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1106 {
1107 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1108 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1109 __func__, counted_lsas, lsalen);
1110 return MSG_NG;
1111 }
1112 if (headeronly)
1113 {
1114 /* less checks here and in ospf6_lsa_examin() */
1115 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1116 {
1117 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1118 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1119 ospf6_lstype_name (lsah->type), counted_lsas);
1120 return MSG_NG;
1121 }
1122 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1123 length -= OSPF6_LSA_HEADER_SIZE;
1124 }
1125 else
1126 {
1127 /* make sure the input buffer is deep enough before further checks */
1128 if (lsalen > length)
1129 {
1130 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1131 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %u B",
1132 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1133 return MSG_NG;
1134 }
1135 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1136 {
1137 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1138 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1139 ospf6_lstype_name (lsah->type), counted_lsas);
1140 return MSG_NG;
1141 }
1142 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1143 length -= lsalen;
1144 }
1145 counted_lsas++;
1146 }
1147
1148 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1149 {
1150 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1151 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1152 __func__, declared_num_lsas, counted_lsas);
1153 return MSG_NG;
1154 }
1155 return MSG_OK;
1156}
1157
1158/* Verify a complete OSPF packet for proper sizing/alignment. */
1159static unsigned
1160ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1161{
1162 struct ospf6_lsupdate *lsupd;
1163 unsigned test;
1164
1165 /* length, 1st approximation */
1166 if (bytesonwire < OSPF6_HEADER_SIZE)
1167 {
1168 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1169 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1170 return MSG_NG;
1171 }
1172 /* Now it is safe to access header fields. */
1173 if (bytesonwire != ntohs (oh->length))
1174 {
1175 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1176 zlog_debug ("%s: packet length error (%u real, %u declared)",
1177 __func__, bytesonwire, ntohs (oh->length));
1178 return MSG_NG;
1179 }
1180 /* version check */
1181 if (oh->version != OSPFV3_VERSION)
1182 {
1183 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1184 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1185 return MSG_NG;
1186 }
1187 /* length, 2nd approximation */
1188 if
1189 (
1190 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1191 ospf6_packet_minlen[oh->type] &&
1192 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1193 )
1194 {
1195 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1196 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
1197 bytesonwire, ospf6_message_type_str[oh->type]);
1198 return MSG_NG;
1199 }
1200 /* type-specific deeper validation */
1201 switch (oh->type)
1202 {
1203 case OSPF6_MESSAGE_TYPE_HELLO:
1204 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1205 by N>=0 router-IDs. */
1206 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1207 return MSG_OK;
1208 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1209 zlog_debug ("%s: alignment error in %s packet",
1210 __func__, ospf6_message_type_str[oh->type]);
1211 return MSG_NG;
1212 case OSPF6_MESSAGE_TYPE_DBDESC:
1213 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1214 by N>=0 header-only LSAs. */
1215 test = ospf6_lsaseq_examin
1216 (
1217 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1218 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1219 1,
1220 0
1221 );
1222 break;
1223 case OSPF6_MESSAGE_TYPE_LSREQ:
1224 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1225 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1226 return MSG_OK;
1227 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1228 zlog_debug ("%s: alignment error in %s packet",
1229 __func__, ospf6_message_type_str[oh->type]);
1230 return MSG_NG;
1231 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1232 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1233 by N>=0 full LSAs (with N declared beforehand). */
1234 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1235 test = ospf6_lsaseq_examin
1236 (
1237 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1238 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1239 0,
1240 ntohl (lsupd->lsa_number) /* 32 bits */
1241 );
1242 break;
1243 case OSPF6_MESSAGE_TYPE_LSACK:
1244 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1245 test = ospf6_lsaseq_examin
1246 (
1247 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1248 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1249 1,
1250 0
1251 );
1252 break;
1253 default:
1254 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1255 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1256 return MSG_NG;
1257 }
1258 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1259 zlog_debug ("%s: anomaly in %s packet", __func__, ospf6_message_type_str[oh->type]);
1260 return test;
1261}
1262
1263/* Verify particular fields of otherwise correct received OSPF packet to
1264 meet the requirements of RFC. */
1265static int
1266ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1267{
1268 char buf[2][INET_ADDRSTRLEN];
1269
1270 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1271 return MSG_NG;
1272
1273 /* Area-ID check */
1274 if (oh->area_id != oi->area->area_id)
1275 {
1276 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1277 {
1278 if (oh->area_id == BACKBONE_AREA_ID)
1279 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1280 else
1281 zlog_debug
1282 (
1283 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1284 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1285 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1286 );
1287 }
1288 return MSG_NG;
1289 }
1290
1291 /* Instance-ID check */
1292 if (oh->instance_id != oi->instance_id)
1293 {
1294 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1295 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1296 return MSG_NG;
1297 }
1298
1299 /* Router-ID check */
1300 if (oh->router_id == oi->area->ospf6->router_id)
1301 {
1302 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1303 return MSG_NG;
1304 }
1305 return MSG_OK;
1306}
1307
Paul Jakma6ac29a52008-08-15 13:45:30 +01001308static void
hasso508e53e2004-05-18 18:57:06 +00001309ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1310 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001311{
hasso508e53e2004-05-18 18:57:06 +00001312 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001313 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001314 char *p;
paul718e3742002-12-13 20:15:29 +00001315
hasso508e53e2004-05-18 18:57:06 +00001316 on = ospf6_neighbor_lookup (oh->router_id, oi);
1317 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001318 {
hasso508e53e2004-05-18 18:57:06 +00001319 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001320 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001321 return;
1322 }
1323
hasso508e53e2004-05-18 18:57:06 +00001324 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1325 on->state != OSPF6_NEIGHBOR_LOADING &&
1326 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001327 {
hasso508e53e2004-05-18 18:57:06 +00001328 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001329 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001330 return;
1331 }
1332
hasso508e53e2004-05-18 18:57:06 +00001333 lsupdate = (struct ospf6_lsupdate *)
1334 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001335
hasso508e53e2004-05-18 18:57:06 +00001336 /* Process LSAs */
1337 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1338 p < OSPF6_MESSAGE_END (oh) &&
1339 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1340 p += OSPF6_LSA_SIZE (p))
1341 {
hasso6452df02004-08-15 05:52:07 +00001342 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001343 }
1344
Denis Ovsienkofa079662011-10-08 17:22:45 +04001345 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001346
1347 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1348 with the proper Link State Update packet(s), the Link state request
1349 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001350 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001351 can be recognized as a response to our previous LS Request */
1352 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1353 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1354 on->state == OSPF6_NEIGHBOR_LOADING))
1355 {
1356 THREAD_OFF (on->thread_send_lsreq);
1357 on->thread_send_lsreq =
1358 thread_add_event (master, ospf6_lsreq_send, on, 0);
1359 }
paul718e3742002-12-13 20:15:29 +00001360}
1361
Paul Jakma6ac29a52008-08-15 13:45:30 +01001362static void
hasso508e53e2004-05-18 18:57:06 +00001363ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1364 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001365{
hasso508e53e2004-05-18 18:57:06 +00001366 struct ospf6_neighbor *on;
1367 char *p;
1368 struct ospf6_lsa *his, *mine;
1369 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001370
hasso508e53e2004-05-18 18:57:06 +00001371 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001372
hasso508e53e2004-05-18 18:57:06 +00001373 on = ospf6_neighbor_lookup (oh->router_id, oi);
1374 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001375 {
hasso508e53e2004-05-18 18:57:06 +00001376 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001377 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001378 return;
1379 }
1380
hasso508e53e2004-05-18 18:57:06 +00001381 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1382 on->state != OSPF6_NEIGHBOR_LOADING &&
1383 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001384 {
hasso508e53e2004-05-18 18:57:06 +00001385 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001386 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001387 return;
1388 }
1389
hasso508e53e2004-05-18 18:57:06 +00001390 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1391 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1392 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001393 {
hasso508e53e2004-05-18 18:57:06 +00001394 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001395
hasso6452df02004-08-15 05:52:07 +00001396 switch (OSPF6_LSA_SCOPE (his->header->type))
1397 {
1398 case OSPF6_SCOPE_LINKLOCAL:
1399 lsdb = on->ospf6_if->lsdb;
1400 break;
1401 case OSPF6_SCOPE_AREA:
1402 lsdb = on->ospf6_if->area->lsdb;
1403 break;
1404 case OSPF6_SCOPE_AS:
1405 lsdb = on->ospf6_if->area->ospf6->lsdb;
1406 break;
1407 case OSPF6_SCOPE_RESERVED:
1408 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001409 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001410 ospf6_lsa_delete (his);
1411 continue;
1412 break;
1413 }
1414
1415 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001416 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001417
1418 /* Find database copy */
1419 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1420 his->header->adv_router, lsdb);
1421 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001422 {
hasso508e53e2004-05-18 18:57:06 +00001423 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001424 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001425 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001426 continue;
1427 }
1428
hasso508e53e2004-05-18 18:57:06 +00001429 /* Check if the LSA is on his retrans-list */
1430 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1431 his->header->adv_router, on->retrans_list);
1432 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001433 {
hasso508e53e2004-05-18 18:57:06 +00001434 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001435 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001436 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001437 continue;
1438 }
1439
hasso508e53e2004-05-18 18:57:06 +00001440 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001441 {
hasso508e53e2004-05-18 18:57:06 +00001442 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001443 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001445 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001446 ospf6_lsa_delete (his);
1447 continue;
paul718e3742002-12-13 20:15:29 +00001448 }
1449
hasso6452df02004-08-15 05:52:07 +00001450 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001451 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1452 on->name);
hasso508e53e2004-05-18 18:57:06 +00001453
Paul Jakma932bf192006-05-15 10:42:24 +00001454 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001455 if (OSPF6_LSA_IS_MAXAGE (mine))
1456 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001457 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001458 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001459 }
1460
Denis Ovsienkofa079662011-10-08 17:22:45 +04001461 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001462}
1463
Paul Jakma6ac29a52008-08-15 13:45:30 +01001464static u_char *recvbuf = NULL;
1465static u_char *sendbuf = NULL;
1466static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001467
1468int
paul0c083ee2004-10-10 12:54:58 +00001469ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001470{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001471 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001472
1473 if (size <= iobuflen)
1474 return iobuflen;
1475
1476 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1477 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1478 if (recvnew == NULL || sendnew == NULL)
1479 {
hassob596c712004-07-09 18:33:43 +00001480 if (recvnew)
1481 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1482 if (sendnew)
1483 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001484 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001485 return iobuflen;
1486 }
1487
1488 if (recvbuf)
1489 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1490 if (sendbuf)
1491 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1492 recvbuf = recvnew;
1493 sendbuf = sendnew;
1494 iobuflen = size;
1495
1496 return iobuflen;
1497}
paul718e3742002-12-13 20:15:29 +00001498
Tom Goffae2254a2010-11-10 13:01:41 -08001499void
1500ospf6_message_terminate (void)
1501{
1502 if (recvbuf)
1503 {
1504 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1505 recvbuf = NULL;
1506 }
1507
1508 if (sendbuf)
1509 {
1510 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1511 sendbuf = NULL;
1512 }
1513
1514 iobuflen = 0;
1515}
1516
paul718e3742002-12-13 20:15:29 +00001517int
1518ospf6_receive (struct thread *thread)
1519{
paul0c083ee2004-10-10 12:54:58 +00001520 int sockfd;
1521 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001522 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001523 struct in6_addr src, dst;
1524 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001525 struct iovec iovector[2];
1526 struct ospf6_interface *oi;
1527 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001528
1529 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001530 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001531 thread_add_read (master, ospf6_receive, NULL, sockfd);
1532
1533 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001534 memset (&src, 0, sizeof (src));
1535 memset (&dst, 0, sizeof (dst));
1536 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001537 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001538 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001539 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001540 iovector[1].iov_base = NULL;
1541 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001542
1543 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001544 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001545 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001546 {
hasso508e53e2004-05-18 18:57:06 +00001547 zlog_err ("Excess message read");
1548 return 0;
1549 }
paul718e3742002-12-13 20:15:29 +00001550
hasso508e53e2004-05-18 18:57:06 +00001551 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1552 if (oi == NULL || oi->area == NULL)
1553 {
hassoc6487d62004-12-24 06:00:11 +00001554 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001555 return 0;
1556 }
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001557 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1558 {
1559 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1560 zlog_debug ("%s: Ignore message on passive interface %s",
1561 __func__, oi->interface->name);
1562 return 0;
1563 }
hasso508e53e2004-05-18 18:57:06 +00001564
1565 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001566 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1567 return 0;
1568
1569 /* Being here means, that no sizing/alignment issues were detected in
1570 the input packet. This renders the additional checks performed below
1571 and also in the type-specific dispatching functions a dead code,
1572 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001573
1574 /* Log */
1575 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1576 {
1577 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1578 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001579 zlog_debug ("%s received on %s",
hasso508e53e2004-05-18 18:57:06 +00001580 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001581 zlog_debug (" src: %s", srcname);
1582 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001583
1584 switch (oh->type)
1585 {
1586 case OSPF6_MESSAGE_TYPE_HELLO:
1587 ospf6_hello_print (oh);
1588 break;
1589 case OSPF6_MESSAGE_TYPE_DBDESC:
1590 ospf6_dbdesc_print (oh);
1591 break;
1592 case OSPF6_MESSAGE_TYPE_LSREQ:
1593 ospf6_lsreq_print (oh);
1594 break;
1595 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1596 ospf6_lsupdate_print (oh);
1597 break;
1598 case OSPF6_MESSAGE_TYPE_LSACK:
1599 ospf6_lsack_print (oh);
1600 break;
1601 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001602 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001603 }
1604 }
1605
hasso508e53e2004-05-18 18:57:06 +00001606 switch (oh->type)
1607 {
1608 case OSPF6_MESSAGE_TYPE_HELLO:
1609 ospf6_hello_recv (&src, &dst, oi, oh);
1610 break;
1611
1612 case OSPF6_MESSAGE_TYPE_DBDESC:
1613 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1614 break;
1615
1616 case OSPF6_MESSAGE_TYPE_LSREQ:
1617 ospf6_lsreq_recv (&src, &dst, oi, oh);
1618 break;
1619
1620 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1621 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1622 break;
1623
1624 case OSPF6_MESSAGE_TYPE_LSACK:
1625 ospf6_lsack_recv (&src, &dst, oi, oh);
1626 break;
1627
1628 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001629 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001630 }
1631
1632 return 0;
1633}
1634
Paul Jakma6ac29a52008-08-15 13:45:30 +01001635static void
hasso508e53e2004-05-18 18:57:06 +00001636ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1637 struct ospf6_interface *oi, struct ospf6_header *oh)
1638{
1639 int len;
1640 char srcname[64], dstname[64];
1641 struct iovec iovector[2];
1642
1643 /* initialize */
1644 iovector[0].iov_base = (caddr_t) oh;
1645 iovector[0].iov_len = ntohs (oh->length);
1646 iovector[1].iov_base = NULL;
1647 iovector[1].iov_len = 0;
1648
1649 /* fill OSPF header */
1650 oh->version = OSPFV3_VERSION;
1651 /* message type must be set before */
1652 /* message length must be set before */
1653 oh->router_id = oi->area->ospf6->router_id;
1654 oh->area_id = oi->area->area_id;
1655 /* checksum is calculated by kernel */
1656 oh->instance_id = oi->instance_id;
1657 oh->reserved = 0;
1658
1659 /* Log */
1660 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1661 {
1662 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1663 if (src)
1664 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1665 else
1666 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001667 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001668 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001669 zlog_debug (" src: %s", srcname);
1670 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001671
1672 switch (oh->type)
1673 {
1674 case OSPF6_MESSAGE_TYPE_HELLO:
1675 ospf6_hello_print (oh);
1676 break;
1677 case OSPF6_MESSAGE_TYPE_DBDESC:
1678 ospf6_dbdesc_print (oh);
1679 break;
1680 case OSPF6_MESSAGE_TYPE_LSREQ:
1681 ospf6_lsreq_print (oh);
1682 break;
1683 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1684 ospf6_lsupdate_print (oh);
1685 break;
1686 case OSPF6_MESSAGE_TYPE_LSACK:
1687 ospf6_lsack_print (oh);
1688 break;
1689 default:
hassoc6487d62004-12-24 06:00:11 +00001690 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001691 assert (0);
1692 break;
1693 }
1694 }
1695
1696 /* send message */
1697 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1698 if (len != ntohs (oh->length))
1699 zlog_err ("Could not send entire message");
1700}
1701
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001702static int
1703ospf6_packet_max(struct ospf6_interface *oi)
1704{
1705 return oi->ifmtu - sizeof(struct ip6_hdr);
1706}
1707
hasso508e53e2004-05-18 18:57:06 +00001708int
1709ospf6_hello_send (struct thread *thread)
1710{
1711 struct ospf6_interface *oi;
1712 struct ospf6_header *oh;
1713 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001714 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001715 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001716 struct ospf6_neighbor *on;
1717
1718 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1719 oi->thread_send_hello = (struct thread *) NULL;
1720
1721 if (oi->state <= OSPF6_INTERFACE_DOWN)
1722 {
1723 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001724 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001725 oi->interface->name);
1726 return 0;
1727 }
1728
1729 /* set next thread */
1730 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1731 oi, oi->hello_interval);
1732
hasso3b4cd3a2004-05-18 19:28:32 +00001733 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001734 oh = (struct ospf6_header *) sendbuf;
1735 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1736
1737 hello->interface_id = htonl (oi->interface->ifindex);
1738 hello->priority = oi->priority;
1739 hello->options[0] = oi->area->options[0];
1740 hello->options[1] = oi->area->options[1];
1741 hello->options[2] = oi->area->options[2];
1742 hello->hello_interval = htons (oi->hello_interval);
1743 hello->dead_interval = htons (oi->dead_interval);
1744 hello->drouter = oi->drouter;
1745 hello->bdrouter = oi->bdrouter;
1746
Paul Jakma6ac29a52008-08-15 13:45:30 +01001747 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001748
paul1eb8ef22005-04-07 07:30:20 +00001749 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001750 {
hasso508e53e2004-05-18 18:57:06 +00001751 if (on->state < OSPF6_NEIGHBOR_INIT)
1752 continue;
1753
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001754 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001755 {
1756 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001757 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001758 break;
1759 }
1760
1761 memcpy (p, &on->router_id, sizeof (u_int32_t));
1762 p += sizeof (u_int32_t);
1763 }
1764
1765 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1766 oh->length = htons (p - sendbuf);
1767
1768 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1769 return 0;
1770}
1771
1772int
1773ospf6_dbdesc_send (struct thread *thread)
1774{
1775 struct ospf6_neighbor *on;
1776 struct ospf6_header *oh;
1777 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001778 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001779 struct ospf6_lsa *lsa;
1780
1781 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1782 on->thread_send_dbdesc = (struct thread *) NULL;
1783
1784 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1785 {
1786 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001787 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1788 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001789 return 0;
1790 }
1791
1792 /* set next thread if master */
1793 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1794 on->thread_send_dbdesc =
1795 thread_add_timer (master, ospf6_dbdesc_send, on,
1796 on->ospf6_if->rxmt_interval);
1797
hasso3b4cd3a2004-05-18 19:28:32 +00001798 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001799 oh = (struct ospf6_header *) sendbuf;
1800 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1801 sizeof (struct ospf6_header));
1802
1803 /* if this is initial one, initialize sequence number for DbDesc */
1804 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1805 {
1806 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001807 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001808 tv.tv_sec = 1;
1809 on->dbdesc_seqnum = tv.tv_sec;
1810 }
1811
1812 dbdesc->options[0] = on->ospf6_if->area->options[0];
1813 dbdesc->options[1] = on->ospf6_if->area->options[1];
1814 dbdesc->options[2] = on->ospf6_if->area->options[2];
1815 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1816 dbdesc->bits = on->dbdesc_bits;
1817 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1818
1819 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001820 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001821 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1822 {
1823 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1824 lsa = ospf6_lsdb_next (lsa))
1825 {
1826 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1827
1828 /* MTU check */
1829 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001830 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001831 {
1832 ospf6_lsa_unlock (lsa);
1833 break;
1834 }
1835 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1836 p += sizeof (struct ospf6_lsa_header);
1837 }
1838 }
1839
1840 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1841 oh->length = htons (p - sendbuf);
1842
1843 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1844 on->ospf6_if, oh);
1845 return 0;
1846}
1847
1848int
1849ospf6_dbdesc_send_newone (struct thread *thread)
1850{
1851 struct ospf6_neighbor *on;
1852 struct ospf6_lsa *lsa;
1853 unsigned int size = 0;
1854
1855 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001856 ospf6_lsdb_remove_all (on->dbdesc_list);
1857
1858 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1859 so that ospf6_send_dbdesc () can send those LSAs */
1860 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1861 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1862 lsa = ospf6_lsdb_next (lsa))
1863 {
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001864 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001865 {
1866 ospf6_lsa_unlock (lsa);
1867 break;
1868 }
1869
hasso508e53e2004-05-18 18:57:06 +00001870 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1871 ospf6_lsdb_remove (lsa, on->summary_list);
1872 size += sizeof (struct ospf6_lsa_header);
1873 }
1874
1875 if (on->summary_list->count == 0)
1876 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1877
1878 /* If slave, More bit check must be done here */
1879 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1880 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1881 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1882 thread_add_event (master, exchange_done, on, 0);
1883
1884 thread_execute (master, ospf6_dbdesc_send, on, 0);
1885 return 0;
1886}
1887
1888int
1889ospf6_lsreq_send (struct thread *thread)
1890{
1891 struct ospf6_neighbor *on;
1892 struct ospf6_header *oh;
1893 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001894 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001895 struct ospf6_lsa *lsa;
1896
1897 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1898 on->thread_send_lsreq = (struct thread *) NULL;
1899
1900 /* LSReq will be sent only in ExStart or Loading */
1901 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1902 on->state != OSPF6_NEIGHBOR_LOADING)
1903 {
1904 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001905 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1906 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001907 return 0;
1908 }
1909
1910 /* schedule loading_done if request list is empty */
1911 if (on->request_list->count == 0)
1912 {
1913 thread_add_event (master, loading_done, on, 0);
1914 return 0;
1915 }
1916
1917 /* set next thread */
1918 on->thread_send_lsreq =
1919 thread_add_timer (master, ospf6_lsreq_send, on,
1920 on->ospf6_if->rxmt_interval);
1921
hasso3b4cd3a2004-05-18 19:28:32 +00001922 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001923 oh = (struct ospf6_header *) sendbuf;
1924
1925 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001926 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001927 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1928 lsa = ospf6_lsdb_next (lsa))
1929 {
1930 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001931 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001932 {
1933 ospf6_lsa_unlock (lsa);
1934 break;
1935 }
1936
1937 e = (struct ospf6_lsreq_entry *) p;
1938 e->type = lsa->header->type;
1939 e->id = lsa->header->id;
1940 e->adv_router = lsa->header->adv_router;
1941 p += sizeof (struct ospf6_lsreq_entry);
1942 }
1943
1944 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1945 oh->length = htons (p - sendbuf);
1946
1947 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1948 on->ospf6_if, oh);
1949 return 0;
1950}
1951
1952int
1953ospf6_lsupdate_send_neighbor (struct thread *thread)
1954{
1955 struct ospf6_neighbor *on;
1956 struct ospf6_header *oh;
1957 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001958 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001959 int num;
1960 struct ospf6_lsa *lsa;
1961
1962 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1963 on->thread_send_lsupdate = (struct thread *) NULL;
1964
hasso6452df02004-08-15 05:52:07 +00001965 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001966 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001967
hasso508e53e2004-05-18 18:57:06 +00001968 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1969 {
1970 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001971 zlog_debug ("Quit to send (neighbor state %s)",
1972 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001973 return 0;
1974 }
1975
1976 /* if we have nothing to send, return */
1977 if (on->lsupdate_list->count == 0 &&
1978 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001979 {
1980 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001981 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001982 return 0;
1983 }
hasso508e53e2004-05-18 18:57:06 +00001984
hasso3b4cd3a2004-05-18 19:28:32 +00001985 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001986 oh = (struct ospf6_header *) sendbuf;
1987 lsupdate = (struct ospf6_lsupdate *)
1988 ((caddr_t) oh + sizeof (struct ospf6_header));
1989
Paul Jakma6ac29a52008-08-15 13:45:30 +01001990 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001991 num = 0;
1992
1993 /* lsupdate_list lists those LSA which doesn't need to be
1994 retransmitted. remove those from the list */
1995 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1996 lsa = ospf6_lsdb_next (lsa))
1997 {
1998 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001999 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002000 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002001 {
2002 ospf6_lsa_unlock (lsa);
2003 break;
2004 }
2005
hasso508e53e2004-05-18 18:57:06 +00002006 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2007 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2008 p += OSPF6_LSA_SIZE (lsa->header);
2009 num++;
2010
2011 assert (lsa->lock == 2);
2012 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2013 }
2014
2015 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2016 lsa = ospf6_lsdb_next (lsa))
2017 {
2018 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002019 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002020 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002021 {
2022 ospf6_lsa_unlock (lsa);
2023 break;
2024 }
2025
hasso508e53e2004-05-18 18:57:06 +00002026 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2027 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2028 p += OSPF6_LSA_SIZE (lsa->header);
2029 num++;
2030 }
2031
2032 lsupdate->lsa_number = htonl (num);
2033
2034 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2035 oh->length = htons (p - sendbuf);
2036
2037 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2038 on->ospf6_if, oh);
2039
2040 if (on->lsupdate_list->count != 0 ||
2041 on->retrans_list->count != 0)
2042 {
2043 if (on->lsupdate_list->count != 0)
2044 on->thread_send_lsupdate =
2045 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2046 else
2047 on->thread_send_lsupdate =
2048 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2049 on->ospf6_if->rxmt_interval);
2050 }
2051
2052 return 0;
2053}
2054
2055int
2056ospf6_lsupdate_send_interface (struct thread *thread)
2057{
2058 struct ospf6_interface *oi;
2059 struct ospf6_header *oh;
2060 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002061 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002062 int num;
2063 struct ospf6_lsa *lsa;
2064
2065 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2066 oi->thread_send_lsupdate = (struct thread *) NULL;
2067
2068 if (oi->state <= OSPF6_INTERFACE_WAITING)
2069 {
2070 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002071 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2072 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002073 return 0;
2074 }
2075
2076 /* if we have nothing to send, return */
2077 if (oi->lsupdate_list->count == 0)
2078 return 0;
2079
hasso3b4cd3a2004-05-18 19:28:32 +00002080 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002081 oh = (struct ospf6_header *) sendbuf;
2082 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
2083 sizeof (struct ospf6_header));
2084
Paul Jakma6ac29a52008-08-15 13:45:30 +01002085 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002086 num = 0;
2087
2088 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2089 lsa = ospf6_lsdb_next (lsa))
2090 {
2091 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002092 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002093 > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002094 {
2095 ospf6_lsa_unlock (lsa);
2096 break;
2097 }
2098
hasso508e53e2004-05-18 18:57:06 +00002099 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2100 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2101 p += OSPF6_LSA_SIZE (lsa->header);
2102 num++;
2103
2104 assert (lsa->lock == 2);
2105 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2106 }
2107
2108 lsupdate->lsa_number = htonl (num);
2109
2110 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2111 oh->length = htons (p - sendbuf);
2112
2113 if (oi->state == OSPF6_INTERFACE_DR ||
2114 oi->state == OSPF6_INTERFACE_BDR)
2115 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2116 else
2117 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2118
2119 if (oi->lsupdate_list->count > 0)
2120 {
2121 oi->thread_send_lsupdate =
2122 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2123 }
2124
2125 return 0;
2126}
2127
2128int
2129ospf6_lsack_send_neighbor (struct thread *thread)
2130{
2131 struct ospf6_neighbor *on;
2132 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002133 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002134 struct ospf6_lsa *lsa;
2135
2136 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2137 on->thread_send_lsack = (struct thread *) NULL;
2138
2139 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2140 {
2141 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002142 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2143 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002144 return 0;
2145 }
2146
2147 /* if we have nothing to send, return */
2148 if (on->lsack_list->count == 0)
2149 return 0;
2150
hasso3b4cd3a2004-05-18 19:28:32 +00002151 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002152 oh = (struct ospf6_header *) sendbuf;
2153
Paul Jakma6ac29a52008-08-15 13:45:30 +01002154 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002155
2156 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2157 lsa = ospf6_lsdb_next (lsa))
2158 {
2159 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002160 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002161 {
2162 /* if we run out of packet size/space here,
2163 better to try again soon. */
2164 THREAD_OFF (on->thread_send_lsack);
2165 on->thread_send_lsack =
2166 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2167
2168 ospf6_lsa_unlock (lsa);
2169 break;
2170 }
2171
2172 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2173 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2174 p += sizeof (struct ospf6_lsa_header);
2175
2176 assert (lsa->lock == 2);
2177 ospf6_lsdb_remove (lsa, on->lsack_list);
2178 }
2179
2180 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2181 oh->length = htons (p - sendbuf);
2182
2183 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2184 on->ospf6_if, oh);
2185 return 0;
2186}
2187
2188int
2189ospf6_lsack_send_interface (struct thread *thread)
2190{
2191 struct ospf6_interface *oi;
2192 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002193 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002194 struct ospf6_lsa *lsa;
2195
2196 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2197 oi->thread_send_lsack = (struct thread *) NULL;
2198
2199 if (oi->state <= OSPF6_INTERFACE_WAITING)
2200 {
2201 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002202 zlog_debug ("Quit to send LSAck to interface %s state %s",
2203 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002204 return 0;
2205 }
2206
2207 /* if we have nothing to send, return */
2208 if (oi->lsack_list->count == 0)
2209 return 0;
2210
hasso3b4cd3a2004-05-18 19:28:32 +00002211 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002212 oh = (struct ospf6_header *) sendbuf;
2213
Paul Jakma6ac29a52008-08-15 13:45:30 +01002214 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002215
2216 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2217 lsa = ospf6_lsdb_next (lsa))
2218 {
2219 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002220 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002221 {
2222 /* if we run out of packet size/space here,
2223 better to try again soon. */
2224 THREAD_OFF (oi->thread_send_lsack);
2225 oi->thread_send_lsack =
2226 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2227
2228 ospf6_lsa_unlock (lsa);
2229 break;
2230 }
2231
2232 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2233 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2234 p += sizeof (struct ospf6_lsa_header);
2235
2236 assert (lsa->lock == 2);
2237 ospf6_lsdb_remove (lsa, oi->lsack_list);
2238 }
2239
2240 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2241 oh->length = htons (p - sendbuf);
2242
2243 if (oi->state == OSPF6_INTERFACE_DR ||
2244 oi->state == OSPF6_INTERFACE_BDR)
2245 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2246 else
2247 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2248
2249 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2250 {
2251 oi->thread_send_lsack =
2252 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2253 }
paul718e3742002-12-13 20:15:29 +00002254
2255 return 0;
2256}
2257
2258
hasso508e53e2004-05-18 18:57:06 +00002259/* Commands */
2260DEFUN (debug_ospf6_message,
2261 debug_ospf6_message_cmd,
2262 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2263 DEBUG_STR
2264 OSPF6_STR
2265 "Debug OSPFv3 message\n"
2266 "Debug Unknown message\n"
2267 "Debug Hello message\n"
2268 "Debug Database Description message\n"
2269 "Debug Link State Request message\n"
2270 "Debug Link State Update message\n"
2271 "Debug Link State Acknowledgement message\n"
2272 "Debug All message\n"
2273 )
paul718e3742002-12-13 20:15:29 +00002274{
hasso508e53e2004-05-18 18:57:06 +00002275 unsigned char level = 0;
2276 int type = 0;
paul718e3742002-12-13 20:15:29 +00002277 int i;
2278
hasso508e53e2004-05-18 18:57:06 +00002279 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002280
hasso508e53e2004-05-18 18:57:06 +00002281 /* check type */
2282 if (! strncmp (argv[0], "u", 1))
2283 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2284 else if (! strncmp (argv[0], "h", 1))
2285 type = OSPF6_MESSAGE_TYPE_HELLO;
2286 else if (! strncmp (argv[0], "d", 1))
2287 type = OSPF6_MESSAGE_TYPE_DBDESC;
2288 else if (! strncmp (argv[0], "lsr", 3))
2289 type = OSPF6_MESSAGE_TYPE_LSREQ;
2290 else if (! strncmp (argv[0], "lsu", 3))
2291 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2292 else if (! strncmp (argv[0], "lsa", 3))
2293 type = OSPF6_MESSAGE_TYPE_LSACK;
2294 else if (! strncmp (argv[0], "a", 1))
2295 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002296
hasso508e53e2004-05-18 18:57:06 +00002297 if (argc == 1)
2298 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2299 else if (! strncmp (argv[1], "s", 1))
2300 level = OSPF6_DEBUG_MESSAGE_SEND;
2301 else if (! strncmp (argv[1], "r", 1))
2302 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002303
hasso508e53e2004-05-18 18:57:06 +00002304 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002305 {
hasso508e53e2004-05-18 18:57:06 +00002306 for (i = 0; i < 6; i++)
2307 OSPF6_DEBUG_MESSAGE_ON (i, level);
2308 }
2309 else
2310 OSPF6_DEBUG_MESSAGE_ON (type, level);
2311
2312 return CMD_SUCCESS;
2313}
2314
2315ALIAS (debug_ospf6_message,
2316 debug_ospf6_message_sendrecv_cmd,
2317 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2318 DEBUG_STR
2319 OSPF6_STR
2320 "Debug OSPFv3 message\n"
2321 "Debug Unknown message\n"
2322 "Debug Hello message\n"
2323 "Debug Database Description message\n"
2324 "Debug Link State Request message\n"
2325 "Debug Link State Update message\n"
2326 "Debug Link State Acknowledgement message\n"
2327 "Debug All message\n"
2328 "Debug only sending message\n"
2329 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002330 )
hasso508e53e2004-05-18 18:57:06 +00002331
2332
2333DEFUN (no_debug_ospf6_message,
2334 no_debug_ospf6_message_cmd,
2335 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2336 NO_STR
2337 DEBUG_STR
2338 OSPF6_STR
2339 "Debug OSPFv3 message\n"
2340 "Debug Unknown message\n"
2341 "Debug Hello message\n"
2342 "Debug Database Description message\n"
2343 "Debug Link State Request message\n"
2344 "Debug Link State Update message\n"
2345 "Debug Link State Acknowledgement message\n"
2346 "Debug All message\n"
2347 )
2348{
2349 unsigned char level = 0;
2350 int type = 0;
2351 int i;
2352
2353 assert (argc > 0);
2354
2355 /* check type */
2356 if (! strncmp (argv[0], "u", 1))
2357 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2358 else if (! strncmp (argv[0], "h", 1))
2359 type = OSPF6_MESSAGE_TYPE_HELLO;
2360 else if (! strncmp (argv[0], "d", 1))
2361 type = OSPF6_MESSAGE_TYPE_DBDESC;
2362 else if (! strncmp (argv[0], "lsr", 3))
2363 type = OSPF6_MESSAGE_TYPE_LSREQ;
2364 else if (! strncmp (argv[0], "lsu", 3))
2365 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2366 else if (! strncmp (argv[0], "lsa", 3))
2367 type = OSPF6_MESSAGE_TYPE_LSACK;
2368 else if (! strncmp (argv[0], "a", 1))
2369 type = OSPF6_MESSAGE_TYPE_ALL;
2370
2371 if (argc == 1)
2372 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2373 else if (! strncmp (argv[1], "s", 1))
2374 level = OSPF6_DEBUG_MESSAGE_SEND;
2375 else if (! strncmp (argv[1], "r", 1))
2376 level = OSPF6_DEBUG_MESSAGE_RECV;
2377
2378 if (type == OSPF6_MESSAGE_TYPE_ALL)
2379 {
2380 for (i = 0; i < 6; i++)
2381 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2382 }
2383 else
2384 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2385
2386 return CMD_SUCCESS;
2387}
2388
2389ALIAS (no_debug_ospf6_message,
2390 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002391 "no debug ospf6 message "
2392 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002393 NO_STR
2394 DEBUG_STR
2395 OSPF6_STR
2396 "Debug OSPFv3 message\n"
2397 "Debug Unknown message\n"
2398 "Debug Hello message\n"
2399 "Debug Database Description message\n"
2400 "Debug Link State Request message\n"
2401 "Debug Link State Update message\n"
2402 "Debug Link State Acknowledgement message\n"
2403 "Debug All message\n"
2404 "Debug only sending message\n"
2405 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002406 )
hasso508e53e2004-05-18 18:57:06 +00002407
2408int
2409config_write_ospf6_debug_message (struct vty *vty)
2410{
paul0c083ee2004-10-10 12:54:58 +00002411 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002412 "lsreq", "lsupdate", "lsack"};
2413 unsigned char s = 0, r = 0;
2414 int i;
2415
2416 for (i = 0; i < 6; i++)
2417 {
2418 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2419 s |= 1 << i;
2420 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2421 r |= 1 << i;
2422 }
2423
2424 if (s == 0x3f && r == 0x3f)
2425 {
hasso049207c2004-08-04 20:02:13 +00002426 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002427 return 0;
2428 }
2429
hasso508e53e2004-05-18 18:57:06 +00002430 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002431 {
hasso049207c2004-08-04 20:02:13 +00002432 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002433 return 0;
2434 }
2435 else if (s == 0 && r == 0x3f)
2436 {
hasso049207c2004-08-04 20:02:13 +00002437 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002438 return 0;
paul718e3742002-12-13 20:15:29 +00002439 }
2440
hasso508e53e2004-05-18 18:57:06 +00002441 /* Unknown message is logged by default */
2442 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2443 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002444 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002445 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002446 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002447 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002448 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002449
hasso508e53e2004-05-18 18:57:06 +00002450 for (i = 1; i < 6; i++)
2451 {
2452 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2453 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002454 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002455 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2456 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002457 VNL);
hasso508e53e2004-05-18 18:57:06 +00002458 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2459 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002460 VNL);
hasso508e53e2004-05-18 18:57:06 +00002461 }
paul718e3742002-12-13 20:15:29 +00002462
2463 return 0;
2464}
2465
paul718e3742002-12-13 20:15:29 +00002466void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002467install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002468{
hasso508e53e2004-05-18 18:57:06 +00002469 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2470 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2471 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2472 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2473 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2474 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2475 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2476 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002477}
2478
paul718e3742002-12-13 20:15:29 +00002479