blob: 01d61263e66b1a78b3c8295e0961daa68ea4ed8e [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};
Denis Ovsienko5031ed12011-10-14 21:59:58 +040053static const struct message ospf6_message_type_str [] =
54{
55 { OSPF6_MESSAGE_TYPE_HELLO, "Hello" },
56 { OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc" },
57 { OSPF6_MESSAGE_TYPE_LSREQ, "LSReq" },
58 { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" },
59 { OSPF6_MESSAGE_TYPE_LSACK, "LSAck" },
60};
61static const size_t ospf6_message_type_str_max =
62 sizeof (ospf6_message_type_str) / sizeof (ospf6_message_type_str[0]);
hasso508e53e2004-05-18 18:57:06 +000063
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040064/* Minimum (besides the standard OSPF packet header) lengths for OSPF
65 packets of particular types, offset is the "type" field. */
66const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
67{
68 0,
69 OSPF6_HELLO_MIN_SIZE,
70 OSPF6_DB_DESC_MIN_SIZE,
71 OSPF6_LS_REQ_MIN_SIZE,
72 OSPF6_LS_UPD_MIN_SIZE,
73 OSPF6_LS_ACK_MIN_SIZE
74};
75
76/* Minimum (besides the standard LSA header) lengths for LSAs of particular
77 types, offset is the "LSA function code" portion of "LSA type" field. */
78const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
79{
80 0,
81 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
82 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
83 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
84 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
85 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
86 /* 0x2006 */ 0,
87 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
88 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
89 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
90};
91
hasso508e53e2004-05-18 18:57:06 +000092/* print functions */
93
94static void
95ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000096{
hasso508e53e2004-05-18 18:57:06 +000097 char router_id[16], area_id[16];
98 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
99 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +0000100
hassoc6487d62004-12-24 06:00:11 +0000101 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +0000102 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +0000103 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +0000104 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +0000105}
paul718e3742002-12-13 20:15:29 +0000106
107void
hasso508e53e2004-05-18 18:57:06 +0000108ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000109{
paul718e3742002-12-13 20:15:29 +0000110 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +0000111 char options[16];
112 char drouter[16], bdrouter[16], neighbor[16];
113 char *p;
paul718e3742002-12-13 20:15:29 +0000114
hasso508e53e2004-05-18 18:57:06 +0000115 ospf6_header_print (oh);
116 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +0000117
hasso508e53e2004-05-18 18:57:06 +0000118 hello = (struct ospf6_hello *)
119 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000120
hasso508e53e2004-05-18 18:57:06 +0000121 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
122 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
123 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000124
hassoc6487d62004-12-24 06:00:11 +0000125 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +0000126 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +0000127 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +0000128 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +0000129 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +0000130
hasso508e53e2004-05-18 18:57:06 +0000131 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
132 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
133 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000134 {
hasso508e53e2004-05-18 18:57:06 +0000135 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +0000136 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +0000137 }
hasso508e53e2004-05-18 18:57:06 +0000138
Denis Ovsienkofa079662011-10-08 17:22:45 +0400139 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000140}
141
hasso508e53e2004-05-18 18:57:06 +0000142void
143ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000144{
paul718e3742002-12-13 20:15:29 +0000145 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000146 char options[16];
147 char *p;
paul718e3742002-12-13 20:15:29 +0000148
hasso508e53e2004-05-18 18:57:06 +0000149 ospf6_header_print (oh);
150 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000151
hasso508e53e2004-05-18 18:57:06 +0000152 dbdesc = (struct ospf6_dbdesc *)
153 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000154
hasso508e53e2004-05-18 18:57:06 +0000155 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000156
hassoc6487d62004-12-24 06:00:11 +0000157 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000158 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000159 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000160 dbdesc->reserved2,
161 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
162 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
163 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
164 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000165
hasso508e53e2004-05-18 18:57:06 +0000166 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
167 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
168 p += sizeof (struct ospf6_lsa_header))
169 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
170
Denis Ovsienkofa079662011-10-08 17:22:45 +0400171 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000172}
173
hasso508e53e2004-05-18 18:57:06 +0000174void
175ospf6_lsreq_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000176{
hasso508e53e2004-05-18 18:57:06 +0000177 char id[16], adv_router[16];
178 char *p;
paul718e3742002-12-13 20:15:29 +0000179
hasso508e53e2004-05-18 18:57:06 +0000180 ospf6_header_print (oh);
181 assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
paul718e3742002-12-13 20:15:29 +0000182
hasso508e53e2004-05-18 18:57:06 +0000183 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
184 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
185 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000186 {
hasso508e53e2004-05-18 18:57:06 +0000187 struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
188 inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
189 inet_ntop (AF_INET, &e->id, id, sizeof (id));
hassoc6487d62004-12-24 06:00:11 +0000190 zlog_debug (" [%s Id:%s Adv:%s]",
hasso1e058382004-09-01 21:36:14 +0000191 ospf6_lstype_name (e->type), id, adv_router);
paul718e3742002-12-13 20:15:29 +0000192 }
hasso508e53e2004-05-18 18:57:06 +0000193
Denis Ovsienkofa079662011-10-08 17:22:45 +0400194 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000195}
196
hasso508e53e2004-05-18 18:57:06 +0000197void
198ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000199{
paul718e3742002-12-13 20:15:29 +0000200 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000201 u_long num;
202 char *p;
paul718e3742002-12-13 20:15:29 +0000203
hasso508e53e2004-05-18 18:57:06 +0000204 ospf6_header_print (oh);
205 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000206
hasso508e53e2004-05-18 18:57:06 +0000207 lsupdate = (struct ospf6_lsupdate *)
208 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000209
hasso508e53e2004-05-18 18:57:06 +0000210 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000211 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000212
hasso508e53e2004-05-18 18:57:06 +0000213 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
214 p < OSPF6_MESSAGE_END (oh) &&
215 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
216 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000217 {
hasso508e53e2004-05-18 18:57:06 +0000218 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +0000219 }
paul718e3742002-12-13 20:15:29 +0000220
Denis Ovsienkofa079662011-10-08 17:22:45 +0400221 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000222}
223
hasso508e53e2004-05-18 18:57:06 +0000224void
225ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000226{
hasso508e53e2004-05-18 18:57:06 +0000227 char *p;
paul718e3742002-12-13 20:15:29 +0000228
hasso508e53e2004-05-18 18:57:06 +0000229 ospf6_header_print (oh);
230 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000231
hasso508e53e2004-05-18 18:57:06 +0000232 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
233 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
234 p += sizeof (struct ospf6_lsa_header))
235 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
236
Denis Ovsienkofa079662011-10-08 17:22:45 +0400237 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000238}
239
Paul Jakma6ac29a52008-08-15 13:45:30 +0100240static void
hasso508e53e2004-05-18 18:57:06 +0000241ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
242 struct ospf6_interface *oi, struct ospf6_header *oh)
243{
244 struct ospf6_hello *hello;
245 struct ospf6_neighbor *on;
246 char *p;
247 int twoway = 0;
248 int neighborchange = 0;
249 int backupseen = 0;
250
hasso508e53e2004-05-18 18:57:06 +0000251 hello = (struct ospf6_hello *)
252 ((caddr_t) oh + sizeof (struct ospf6_header));
253
paul718e3742002-12-13 20:15:29 +0000254 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000255 if (ntohs (hello->hello_interval) != oi->hello_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 ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000259 return;
260 }
261
262 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000263 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000264 {
hasso508e53e2004-05-18 18:57:06 +0000265 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000266 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000267 return;
268 }
269
hasso508e53e2004-05-18 18:57:06 +0000270 /* E-bit check */
271 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
272 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000273 {
hasso508e53e2004-05-18 18:57:06 +0000274 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000275 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000276 return;
277 }
278
hasso508e53e2004-05-18 18:57:06 +0000279 /* Find neighbor, create if not exist */
280 on = ospf6_neighbor_lookup (oh->router_id, oi);
281 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000282 {
hasso508e53e2004-05-18 18:57:06 +0000283 on = ospf6_neighbor_create (oh->router_id, oi);
284 on->prev_drouter = on->drouter = hello->drouter;
285 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
286 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000287 }
288
hasso7b6ae022005-06-24 08:17:51 +0000289 /* always override neighbor's source address and ifindex */
290 on->ifindex = ntohl (hello->interface_id);
291 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
292
paul718e3742002-12-13 20:15:29 +0000293 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000294 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
295 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
296 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000297 {
hasso508e53e2004-05-18 18:57:06 +0000298 u_int32_t *router_id = (u_int32_t *) p;
299
300 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000301 twoway++;
paul718e3742002-12-13 20:15:29 +0000302 }
303
Denis Ovsienkofa079662011-10-08 17:22:45 +0400304 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000305
306 /* RouterPriority check */
307 if (on->priority != hello->priority)
308 {
309 on->priority = hello->priority;
310 neighborchange++;
311 }
312
313 /* DR check */
314 if (on->drouter != hello->drouter)
315 {
316 on->prev_drouter = on->drouter;
317 on->drouter = hello->drouter;
318 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
319 neighborchange++;
320 }
321
322 /* BDR check */
323 if (on->bdrouter != hello->bdrouter)
324 {
325 on->prev_bdrouter = on->bdrouter;
326 on->bdrouter = hello->bdrouter;
327 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
328 neighborchange++;
329 }
paul718e3742002-12-13 20:15:29 +0000330
331 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000332 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000333 {
hasso508e53e2004-05-18 18:57:06 +0000334 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000335 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000336 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000337 backupseen++;
338 }
339
hasso508e53e2004-05-18 18:57:06 +0000340 /* Execute neighbor events */
341 thread_execute (master, hello_received, on, 0);
342 if (twoway)
343 thread_execute (master, twoway_received, on, 0);
344 else
345 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000346
hasso508e53e2004-05-18 18:57:06 +0000347 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000348 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000349 thread_add_event (master, backup_seen, oi, 0);
350 if (neighborchange)
351 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000352}
353
hasso508e53e2004-05-18 18:57:06 +0000354static void
355ospf6_dbdesc_recv_master (struct ospf6_header *oh,
356 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000357{
paul718e3742002-12-13 20:15:29 +0000358 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000359 char *p;
paul718e3742002-12-13 20:15:29 +0000360
hasso508e53e2004-05-18 18:57:06 +0000361 dbdesc = (struct ospf6_dbdesc *)
362 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000363
hasso508e53e2004-05-18 18:57:06 +0000364 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000365 {
hasso508e53e2004-05-18 18:57:06 +0000366 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000367 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000368 return;
369 }
370
hasso508e53e2004-05-18 18:57:06 +0000371 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000372 {
hasso508e53e2004-05-18 18:57:06 +0000373 case OSPF6_NEIGHBOR_TWOWAY:
374 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000375 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000376 return;
377
378 case OSPF6_NEIGHBOR_INIT:
379 thread_execute (master, twoway_received, on, 0);
380 if (on->state != OSPF6_NEIGHBOR_EXSTART)
381 {
382 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000383 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000384 return;
385 }
386 /* else fall through to ExStart */
387
388 case OSPF6_NEIGHBOR_EXSTART:
389 /* if neighbor obeys us as our slave, schedule negotiation_done
390 and process LSA Headers. Otherwise, ignore this message */
391 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
392 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
393 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
394 {
395 /* execute NegotiationDone */
396 thread_execute (master, negotiation_done, on, 0);
397
398 /* Record neighbor options */
399 memcpy (on->options, dbdesc->options, sizeof (on->options));
400 }
401 else
402 {
403 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000404 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000405 return;
406 }
407 /* fall through to exchange */
408
409 case OSPF6_NEIGHBOR_EXCHANGE:
410 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
411 {
412 /* Duplicated DatabaseDescription is dropped by master */
413 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000414 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000415 return;
416 }
417
418 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
419 {
420 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000421 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000422 thread_add_event (master, seqnumber_mismatch, on, 0);
423 return;
424 }
425
426 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
427 {
428 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000429 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000430 thread_add_event (master, seqnumber_mismatch, on, 0);
431 return;
432 }
433
434 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
435 {
436 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000437 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000438 thread_add_event (master, seqnumber_mismatch, on, 0);
439 return;
440 }
441
442 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
443 {
444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000445 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000446 (u_long) on->dbdesc_seqnum);
447 thread_add_event (master, seqnumber_mismatch, on, 0);
448 return;
449 }
450 break;
451
452 case OSPF6_NEIGHBOR_LOADING:
453 case OSPF6_NEIGHBOR_FULL:
454 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
455 {
456 /* Duplicated DatabaseDescription is dropped by master */
457 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000458 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000459 return;
460 }
461
462 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000463 zlog_debug ("Not duplicate dbdesc in state %s",
464 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000465 thread_add_event (master, seqnumber_mismatch, on, 0);
466 return;
467
468 default:
469 assert (0);
470 break;
471 }
472
473 /* Process LSA headers */
474 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
475 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
476 p += sizeof (struct ospf6_lsa_header))
477 {
478 struct ospf6_lsa *his, *mine;
479 struct ospf6_lsdb *lsdb = NULL;
480
481 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000482
483 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000484 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000485
486 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000487 {
hasso6452df02004-08-15 05:52:07 +0000488 case OSPF6_SCOPE_LINKLOCAL:
489 lsdb = on->ospf6_if->lsdb;
490 break;
491 case OSPF6_SCOPE_AREA:
492 lsdb = on->ospf6_if->area->lsdb;
493 break;
494 case OSPF6_SCOPE_AS:
495 lsdb = on->ospf6_if->area->ospf6->lsdb;
496 break;
497 case OSPF6_SCOPE_RESERVED:
498 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000499 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000500 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000501 continue;
502 break;
hasso508e53e2004-05-18 18:57:06 +0000503 }
504
505 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000506 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000507 {
508 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000509 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000510 ospf6_lsa_delete (his);
511 thread_add_event (master, seqnumber_mismatch, on, 0);
512 return;
513 }
514
515 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
516 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000517 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000518 {
hasso6452df02004-08-15 05:52:07 +0000519 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000520 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000521 ospf6_lsdb_add (his, on->request_list);
522 }
523 else if (ospf6_lsa_compare (his, mine) < 0)
524 {
525 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000526 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000527 ospf6_lsdb_add (his, on->request_list);
528 }
529 else
hasso6452df02004-08-15 05:52:07 +0000530 {
531 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000532 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000533 ospf6_lsa_delete (his);
534 }
hasso508e53e2004-05-18 18:57:06 +0000535 }
536
Denis Ovsienkofa079662011-10-08 17:22:45 +0400537 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000538
539 /* Increment sequence number */
540 on->dbdesc_seqnum ++;
541
542 /* schedule send lsreq */
543 if (on->thread_send_lsreq == NULL)
544 on->thread_send_lsreq =
545 thread_add_event (master, ospf6_lsreq_send, on, 0);
546
547 THREAD_OFF (on->thread_send_dbdesc);
548
549 /* More bit check */
550 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
551 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
552 thread_add_event (master, exchange_done, on, 0);
553 else
554 on->thread_send_dbdesc =
555 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
556
557 /* save last received dbdesc */
558 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
559}
560
561static void
562ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
563 struct ospf6_neighbor *on)
564{
565 struct ospf6_dbdesc *dbdesc;
566 char *p;
567
568 dbdesc = (struct ospf6_dbdesc *)
569 ((caddr_t) oh + sizeof (struct ospf6_header));
570
571 if (on->state < OSPF6_NEIGHBOR_INIT)
572 {
573 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000574 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000575 return;
576 }
577
hasso508e53e2004-05-18 18:57:06 +0000578 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000579 {
hasso508e53e2004-05-18 18:57:06 +0000580 case OSPF6_NEIGHBOR_TWOWAY:
581 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000582 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000583 return;
584
585 case OSPF6_NEIGHBOR_INIT:
586 thread_execute (master, twoway_received, on, 0);
587 if (on->state != OSPF6_NEIGHBOR_EXSTART)
588 {
589 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000590 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000591 return;
592 }
593 /* else fall through to ExStart */
594
595 case OSPF6_NEIGHBOR_EXSTART:
596 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
597 and process LSA Headers. Otherwise, ignore this message */
598 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
599 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
600 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
601 ntohs (oh->length) == sizeof (struct ospf6_header) +
602 sizeof (struct ospf6_dbdesc))
603 {
604 /* set the master/slave bit to slave */
605 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
606
607 /* set the DD sequence number to one specified by master */
608 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
609
610 /* schedule NegotiationDone */
611 thread_execute (master, negotiation_done, on, 0);
612
613 /* Record neighbor options */
614 memcpy (on->options, dbdesc->options, sizeof (on->options));
615 }
616 else
617 {
618 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000619 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000620 return;
621 }
622 break;
623
624 case OSPF6_NEIGHBOR_EXCHANGE:
625 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
626 {
627 /* Duplicated DatabaseDescription causes slave to retransmit */
628 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000629 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000630 THREAD_OFF (on->thread_send_dbdesc);
631 on->thread_send_dbdesc =
632 thread_add_event (master, ospf6_dbdesc_send, on, 0);
633 return;
634 }
635
636 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
637 {
638 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000639 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000640 thread_add_event (master, seqnumber_mismatch, on, 0);
641 return;
642 }
643
644 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
645 {
646 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000647 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000648 thread_add_event (master, seqnumber_mismatch, on, 0);
649 return;
650 }
651
652 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
653 {
654 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000655 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000656 thread_add_event (master, seqnumber_mismatch, on, 0);
657 return;
658 }
659
660 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
661 {
662 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000663 zlog_debug ("Sequence number mismatch (%#lx expected)",
664 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000665 thread_add_event (master, seqnumber_mismatch, on, 0);
666 return;
667 }
668 break;
669
670 case OSPF6_NEIGHBOR_LOADING:
671 case OSPF6_NEIGHBOR_FULL:
672 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
673 {
674 /* Duplicated DatabaseDescription causes slave to retransmit */
675 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000676 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000677 THREAD_OFF (on->thread_send_dbdesc);
678 on->thread_send_dbdesc =
679 thread_add_event (master, ospf6_dbdesc_send, on, 0);
680 return;
681 }
682
683 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000684 zlog_debug ("Not duplicate dbdesc in state %s",
685 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000686 thread_add_event (master, seqnumber_mismatch, on, 0);
687 return;
688
689 default:
690 assert (0);
691 break;
paul718e3742002-12-13 20:15:29 +0000692 }
693
hasso508e53e2004-05-18 18:57:06 +0000694 /* Process LSA headers */
695 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
696 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
697 p += sizeof (struct ospf6_lsa_header))
698 {
699 struct ospf6_lsa *his, *mine;
700 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000701
hasso508e53e2004-05-18 18:57:06 +0000702 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000703
704 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000705 {
hasso6452df02004-08-15 05:52:07 +0000706 case OSPF6_SCOPE_LINKLOCAL:
707 lsdb = on->ospf6_if->lsdb;
708 break;
709 case OSPF6_SCOPE_AREA:
710 lsdb = on->ospf6_if->area->lsdb;
711 break;
712 case OSPF6_SCOPE_AS:
713 lsdb = on->ospf6_if->area->ospf6->lsdb;
714 break;
715 case OSPF6_SCOPE_RESERVED:
716 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000717 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000718 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000719 continue;
720 break;
hasso508e53e2004-05-18 18:57:06 +0000721 }
722
hasso6452df02004-08-15 05:52:07 +0000723 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
724 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000725 {
726 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000727 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000728 ospf6_lsa_delete (his);
729 thread_add_event (master, seqnumber_mismatch, on, 0);
730 return;
731 }
732
733 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
734 his->header->adv_router, lsdb);
735 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
736 {
hasso6452df02004-08-15 05:52:07 +0000737 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000738 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000739 ospf6_lsdb_add (his, on->request_list);
740 }
741 else
742 ospf6_lsa_delete (his);
743 }
744
Denis Ovsienkofa079662011-10-08 17:22:45 +0400745 assert (p == OSPF6_MESSAGE_END (oh));
hasso508e53e2004-05-18 18:57:06 +0000746
747 /* Set sequence number to Master's */
748 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
749
750 /* schedule send lsreq */
751 if (on->thread_send_lsreq == NULL)
752 on->thread_send_lsreq =
753 thread_add_event (master, ospf6_lsreq_send, on, 0);
754
755 THREAD_OFF (on->thread_send_dbdesc);
756 on->thread_send_dbdesc =
757 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
758
759 /* save last received dbdesc */
760 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000761}
762
Paul Jakma6ac29a52008-08-15 13:45:30 +0100763static void
hasso508e53e2004-05-18 18:57:06 +0000764ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
765 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000766{
hasso508e53e2004-05-18 18:57:06 +0000767 struct ospf6_neighbor *on;
768 struct ospf6_dbdesc *dbdesc;
769
hasso508e53e2004-05-18 18:57:06 +0000770 on = ospf6_neighbor_lookup (oh->router_id, oi);
771 if (on == NULL)
772 {
773 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000774 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000775 return;
776 }
777
hasso508e53e2004-05-18 18:57:06 +0000778 dbdesc = (struct ospf6_dbdesc *)
779 ((caddr_t) oh + sizeof (struct ospf6_header));
780
781 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400782 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000783 {
784 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000785 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000786 return;
787 }
788
789 if (dbdesc->reserved1 || dbdesc->reserved2)
790 {
791 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000792 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
793 on->name);
hasso508e53e2004-05-18 18:57:06 +0000794 dbdesc->reserved1 = 0;
795 dbdesc->reserved2 = 0;
796 }
797
798 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
799 ospf6_dbdesc_recv_master (oh, on);
800 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
801 ospf6_dbdesc_recv_slave (oh, on);
802 else
803 {
804 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000805 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000806 }
807}
808
Paul Jakma6ac29a52008-08-15 13:45:30 +0100809static void
hasso508e53e2004-05-18 18:57:06 +0000810ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
811 struct ospf6_interface *oi, struct ospf6_header *oh)
812{
813 struct ospf6_neighbor *on;
814 char *p;
815 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000816 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000817 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000818
hasso508e53e2004-05-18 18:57:06 +0000819 on = ospf6_neighbor_lookup (oh->router_id, oi);
820 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000821 {
hasso508e53e2004-05-18 18:57:06 +0000822 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000823 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000824 return;
825 }
826
hasso508e53e2004-05-18 18:57:06 +0000827 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
828 on->state != OSPF6_NEIGHBOR_LOADING &&
829 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000830 {
hasso508e53e2004-05-18 18:57:06 +0000831 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000832 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000833 return;
834 }
835
hasso508e53e2004-05-18 18:57:06 +0000836 /* Process each request */
837 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
838 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
839 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000840 {
hasso508e53e2004-05-18 18:57:06 +0000841 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000842
843 switch (OSPF6_LSA_SCOPE (e->type))
844 {
845 case OSPF6_SCOPE_LINKLOCAL:
846 lsdb = on->ospf6_if->lsdb;
847 break;
848 case OSPF6_SCOPE_AREA:
849 lsdb = on->ospf6_if->area->lsdb;
850 break;
851 case OSPF6_SCOPE_AS:
852 lsdb = on->ospf6_if->area->ospf6->lsdb;
853 break;
854 default:
855 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000856 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000857 continue;
858 break;
859 }
paul718e3742002-12-13 20:15:29 +0000860
hasso508e53e2004-05-18 18:57:06 +0000861 /* Find database copy */
862 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
863 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000864 {
hasso508e53e2004-05-18 18:57:06 +0000865 char id[16], adv_router[16];
866 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
867 {
868 inet_ntop (AF_INET, &e->id, id, sizeof (id));
869 inet_ntop (AF_INET, &e->adv_router, adv_router,
870 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000871 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
872 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000873 }
874 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000875 return;
876 }
877
hasso508e53e2004-05-18 18:57:06 +0000878 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000879 }
880
Denis Ovsienkofa079662011-10-08 17:22:45 +0400881 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +0000882
hasso508e53e2004-05-18 18:57:06 +0000883 /* schedule send lsupdate */
884 THREAD_OFF (on->thread_send_lsupdate);
885 on->thread_send_lsupdate =
886 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000887}
888
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +0400889/* Verify, that the specified memory area contains exactly N valid IPv6
890 prefixes as specified by RFC5340, A.4.1. */
891static unsigned
892ospf6_prefixes_examin
893(
894 struct ospf6_prefix *current, /* start of buffer */
895 unsigned length,
896 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
897)
898{
899 u_char requested_pfx_bytes;
900 u_int32_t real_num_pfxs = 0;
901
902 while (length)
903 {
904 if (length < OSPF6_PREFIX_MIN_SIZE)
905 {
906 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
907 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
908 return MSG_NG;
909 }
910 /* safe to look deeper */
911 if (current->prefix_length > IPV6_MAX_BITLEN)
912 {
913 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
914 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
915 return MSG_NG;
916 }
917 /* covers both fixed- and variable-sized fields */
918 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
919 if (requested_pfx_bytes > length)
920 {
921 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
922 zlog_debug ("%s: undersized IPv6 prefix", __func__);
923 return MSG_NG;
924 }
925 /* next prefix */
926 length -= requested_pfx_bytes;
927 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
928 real_num_pfxs++;
929 }
930 if (real_num_pfxs != req_num_pfxs)
931 {
932 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
933 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
934 __func__, req_num_pfxs, real_num_pfxs);
935 return MSG_NG;
936 }
937 return MSG_OK;
938}
939
940/* Verify an LSA to have a valid length and dispatch further (where
941 appropriate) to check if the contents, including nested IPv6 prefixes,
942 is properly sized/aligned within the LSA. Note that this function gets
943 LSA type in network byte order, uses in host byte order and passes to
944 ospf6_lstype_name() in network byte order again. */
945static unsigned
946ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
947{
948 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
949 struct ospf6_as_external_lsa *as_external_lsa;
950 struct ospf6_link_lsa *link_lsa;
951 unsigned exp_length;
952 u_int8_t ltindex;
953 u_int16_t lsatype;
954
955 /* In case an additional minimum length constraint is defined for current
956 LSA type, make sure that this constraint is met. */
957 lsatype = ntohs (lsah->type);
958 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
959 if
960 (
961 ltindex < OSPF6_LSTYPE_SIZE &&
962 ospf6_lsa_minlen[ltindex] &&
963 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
964 )
965 {
966 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
967 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
968 return MSG_NG;
969 }
970 switch (lsatype)
971 {
972 case OSPF6_LSTYPE_ROUTER:
973 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
974 by N>=0 interface descriptions. */
975 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
976 {
977 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
978 zlog_debug ("%s: interface description alignment error", __func__);
979 return MSG_NG;
980 }
981 break;
982 case OSPF6_LSTYPE_NETWORK:
983 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
984 followed by N>=0 attached router descriptions. */
985 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
986 {
987 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
988 zlog_debug ("%s: router description alignment error", __func__);
989 return MSG_NG;
990 }
991 break;
992 case OSPF6_LSTYPE_INTER_PREFIX:
993 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
994 followed by 3-4 fields of a single IPv6 prefix. */
995 if (headeronly)
996 break;
997 return ospf6_prefixes_examin
998 (
999 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1000 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1001 1
1002 );
1003 case OSPF6_LSTYPE_INTER_ROUTER:
1004 /* RFC5340 A.4.6, fixed-size LSA. */
1005 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1006 {
1007 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1008 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1009 return MSG_NG;
1010 }
1011 break;
1012 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1013 case OSPF6_LSTYPE_TYPE_7:
1014 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1015 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1016 16 bytes of forwarding address, 4 bytes of external route tag,
1017 4 bytes of referenced link state ID. */
1018 if (headeronly)
1019 break;
1020 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1021 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1022 /* To find out if the last optional field (Referenced Link State ID) is
1023 assumed in this LSA, we need to access fixed fields of the IPv6
1024 prefix before ospf6_prefix_examin() confirms its sizing. */
1025 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1026 {
1027 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1028 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1029 return MSG_NG;
1030 }
1031 /* forwarding address */
1032 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1033 exp_length += 16;
1034 /* external route tag */
1035 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1036 exp_length += 4;
1037 /* referenced link state ID */
1038 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1039 exp_length += 4;
1040 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1041 this check does not include any IPv6 prefix fields. */
1042 if (exp_length > lsalen)
1043 {
1044 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1045 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1046 return MSG_NG;
1047 }
1048 /* The last call completely covers the remainder (IPv6 prefix). */
1049 return ospf6_prefixes_examin
1050 (
1051 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1052 lsalen - exp_length,
1053 1
1054 );
1055 case OSPF6_LSTYPE_LINK:
1056 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1057 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1058 if (headeronly)
1059 break;
1060 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1061 return ospf6_prefixes_examin
1062 (
1063 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1064 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1065 ntohl (link_lsa->prefix_num) /* 32 bits */
1066 );
1067 case OSPF6_LSTYPE_INTRA_PREFIX:
1068 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1069 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1070 if (headeronly)
1071 break;
1072 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1073 return ospf6_prefixes_examin
1074 (
1075 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1076 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1077 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1078 );
1079 }
1080 /* No additional validation is possible for unknown LSA types, which are
1081 themselves valid in OPSFv3, hence the default decision is to accept. */
1082 return MSG_OK;
1083}
1084
1085/* Verify if the provided input buffer is a valid sequence of LSAs. This
1086 includes verification of LSA blocks length/alignment and dispatching
1087 of deeper-level checks. */
1088static unsigned
1089ospf6_lsaseq_examin
1090(
1091 struct ospf6_lsa_header *lsah, /* start of buffered data */
1092 size_t length,
1093 const u_char headeronly,
1094 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1095 and treat the difference as an error. */
1096 const u_int32_t declared_num_lsas
1097)
1098{
1099 u_int32_t counted_lsas = 0;
1100
1101 while (length)
1102 {
1103 u_int16_t lsalen;
1104 if (length < OSPF6_LSA_HEADER_SIZE)
1105 {
1106 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001107 zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001108 __func__, length, counted_lsas);
1109 return MSG_NG;
1110 }
1111 /* save on ntohs() calls here and in the LSA validator */
1112 lsalen = OSPF6_LSA_SIZE (lsah);
1113 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1114 {
1115 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1116 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1117 __func__, counted_lsas, lsalen);
1118 return MSG_NG;
1119 }
1120 if (headeronly)
1121 {
1122 /* less checks here and in ospf6_lsa_examin() */
1123 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1124 {
1125 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1126 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1127 ospf6_lstype_name (lsah->type), counted_lsas);
1128 return MSG_NG;
1129 }
1130 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1131 length -= OSPF6_LSA_HEADER_SIZE;
1132 }
1133 else
1134 {
1135 /* make sure the input buffer is deep enough before further checks */
1136 if (lsalen > length)
1137 {
1138 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001139 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001140 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1141 return MSG_NG;
1142 }
1143 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1144 {
1145 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1146 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1147 ospf6_lstype_name (lsah->type), counted_lsas);
1148 return MSG_NG;
1149 }
1150 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1151 length -= lsalen;
1152 }
1153 counted_lsas++;
1154 }
1155
1156 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1157 {
1158 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1159 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1160 __func__, declared_num_lsas, counted_lsas);
1161 return MSG_NG;
1162 }
1163 return MSG_OK;
1164}
1165
1166/* Verify a complete OSPF packet for proper sizing/alignment. */
1167static unsigned
1168ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1169{
1170 struct ospf6_lsupdate *lsupd;
1171 unsigned test;
1172
1173 /* length, 1st approximation */
1174 if (bytesonwire < OSPF6_HEADER_SIZE)
1175 {
1176 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1177 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1178 return MSG_NG;
1179 }
1180 /* Now it is safe to access header fields. */
1181 if (bytesonwire != ntohs (oh->length))
1182 {
1183 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1184 zlog_debug ("%s: packet length error (%u real, %u declared)",
1185 __func__, bytesonwire, ntohs (oh->length));
1186 return MSG_NG;
1187 }
1188 /* version check */
1189 if (oh->version != OSPFV3_VERSION)
1190 {
1191 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1192 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1193 return MSG_NG;
1194 }
1195 /* length, 2nd approximation */
1196 if
1197 (
1198 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1199 ospf6_packet_minlen[oh->type] &&
1200 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1201 )
1202 {
1203 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1204 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001205 bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001206 return MSG_NG;
1207 }
1208 /* type-specific deeper validation */
1209 switch (oh->type)
1210 {
1211 case OSPF6_MESSAGE_TYPE_HELLO:
1212 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1213 by N>=0 router-IDs. */
1214 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1215 return MSG_OK;
1216 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1217 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001218 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001219 return MSG_NG;
1220 case OSPF6_MESSAGE_TYPE_DBDESC:
1221 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1222 by N>=0 header-only LSAs. */
1223 test = ospf6_lsaseq_examin
1224 (
1225 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1226 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1227 1,
1228 0
1229 );
1230 break;
1231 case OSPF6_MESSAGE_TYPE_LSREQ:
1232 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1233 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1234 return MSG_OK;
1235 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1236 zlog_debug ("%s: alignment error in %s packet",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001237 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001238 return MSG_NG;
1239 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1240 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1241 by N>=0 full LSAs (with N declared beforehand). */
1242 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1243 test = ospf6_lsaseq_examin
1244 (
1245 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1246 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1247 0,
1248 ntohl (lsupd->lsa_number) /* 32 bits */
1249 );
1250 break;
1251 case OSPF6_MESSAGE_TYPE_LSACK:
1252 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1253 test = ospf6_lsaseq_examin
1254 (
1255 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1256 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1257 1,
1258 0
1259 );
1260 break;
1261 default:
1262 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1263 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1264 return MSG_NG;
1265 }
1266 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001267 zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001268 return test;
1269}
1270
1271/* Verify particular fields of otherwise correct received OSPF packet to
1272 meet the requirements of RFC. */
1273static int
1274ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1275{
1276 char buf[2][INET_ADDRSTRLEN];
1277
1278 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1279 return MSG_NG;
1280
1281 /* Area-ID check */
1282 if (oh->area_id != oi->area->area_id)
1283 {
1284 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1285 {
1286 if (oh->area_id == BACKBONE_AREA_ID)
1287 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1288 else
1289 zlog_debug
1290 (
1291 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1292 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1293 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1294 );
1295 }
1296 return MSG_NG;
1297 }
1298
1299 /* Instance-ID check */
1300 if (oh->instance_id != oi->instance_id)
1301 {
1302 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1303 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1304 return MSG_NG;
1305 }
1306
1307 /* Router-ID check */
1308 if (oh->router_id == oi->area->ospf6->router_id)
1309 {
1310 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1311 return MSG_NG;
1312 }
1313 return MSG_OK;
1314}
1315
Paul Jakma6ac29a52008-08-15 13:45:30 +01001316static void
hasso508e53e2004-05-18 18:57:06 +00001317ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1318 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001319{
hasso508e53e2004-05-18 18:57:06 +00001320 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001321 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001322 char *p;
paul718e3742002-12-13 20:15:29 +00001323
hasso508e53e2004-05-18 18:57:06 +00001324 on = ospf6_neighbor_lookup (oh->router_id, oi);
1325 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001326 {
hasso508e53e2004-05-18 18:57:06 +00001327 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001328 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001329 return;
1330 }
1331
hasso508e53e2004-05-18 18:57:06 +00001332 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1333 on->state != OSPF6_NEIGHBOR_LOADING &&
1334 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001335 {
hasso508e53e2004-05-18 18:57:06 +00001336 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001337 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001338 return;
1339 }
1340
hasso508e53e2004-05-18 18:57:06 +00001341 lsupdate = (struct ospf6_lsupdate *)
1342 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001343
hasso508e53e2004-05-18 18:57:06 +00001344 /* Process LSAs */
1345 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1346 p < OSPF6_MESSAGE_END (oh) &&
1347 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1348 p += OSPF6_LSA_SIZE (p))
1349 {
hasso6452df02004-08-15 05:52:07 +00001350 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001351 }
1352
Denis Ovsienkofa079662011-10-08 17:22:45 +04001353 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001354
1355 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1356 with the proper Link State Update packet(s), the Link state request
1357 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001358 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001359 can be recognized as a response to our previous LS Request */
1360 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1361 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1362 on->state == OSPF6_NEIGHBOR_LOADING))
1363 {
1364 THREAD_OFF (on->thread_send_lsreq);
1365 on->thread_send_lsreq =
1366 thread_add_event (master, ospf6_lsreq_send, on, 0);
1367 }
paul718e3742002-12-13 20:15:29 +00001368}
1369
Paul Jakma6ac29a52008-08-15 13:45:30 +01001370static void
hasso508e53e2004-05-18 18:57:06 +00001371ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1372 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001373{
hasso508e53e2004-05-18 18:57:06 +00001374 struct ospf6_neighbor *on;
1375 char *p;
1376 struct ospf6_lsa *his, *mine;
1377 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001378
hasso508e53e2004-05-18 18:57:06 +00001379 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001380
hasso508e53e2004-05-18 18:57:06 +00001381 on = ospf6_neighbor_lookup (oh->router_id, oi);
1382 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001383 {
hasso508e53e2004-05-18 18:57:06 +00001384 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001385 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001386 return;
1387 }
1388
hasso508e53e2004-05-18 18:57:06 +00001389 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1390 on->state != OSPF6_NEIGHBOR_LOADING &&
1391 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001392 {
hasso508e53e2004-05-18 18:57:06 +00001393 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001394 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001395 return;
1396 }
1397
hasso508e53e2004-05-18 18:57:06 +00001398 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1399 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1400 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001401 {
hasso508e53e2004-05-18 18:57:06 +00001402 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001403
hasso6452df02004-08-15 05:52:07 +00001404 switch (OSPF6_LSA_SCOPE (his->header->type))
1405 {
1406 case OSPF6_SCOPE_LINKLOCAL:
1407 lsdb = on->ospf6_if->lsdb;
1408 break;
1409 case OSPF6_SCOPE_AREA:
1410 lsdb = on->ospf6_if->area->lsdb;
1411 break;
1412 case OSPF6_SCOPE_AS:
1413 lsdb = on->ospf6_if->area->ospf6->lsdb;
1414 break;
1415 case OSPF6_SCOPE_RESERVED:
1416 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001417 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001418 ospf6_lsa_delete (his);
1419 continue;
1420 break;
1421 }
1422
1423 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001424 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001425
1426 /* Find database copy */
1427 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1428 his->header->adv_router, lsdb);
1429 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001430 {
hasso508e53e2004-05-18 18:57:06 +00001431 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001432 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001433 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001434 continue;
1435 }
1436
hasso508e53e2004-05-18 18:57:06 +00001437 /* Check if the LSA is on his retrans-list */
1438 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1439 his->header->adv_router, on->retrans_list);
1440 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001441 {
hasso508e53e2004-05-18 18:57:06 +00001442 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001443 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001444 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001445 continue;
1446 }
1447
hasso508e53e2004-05-18 18:57:06 +00001448 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001449 {
hasso508e53e2004-05-18 18:57:06 +00001450 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001451 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001452 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001453 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001454 ospf6_lsa_delete (his);
1455 continue;
paul718e3742002-12-13 20:15:29 +00001456 }
1457
hasso6452df02004-08-15 05:52:07 +00001458 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001459 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1460 on->name);
hasso508e53e2004-05-18 18:57:06 +00001461
Paul Jakma932bf192006-05-15 10:42:24 +00001462 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001463 if (OSPF6_LSA_IS_MAXAGE (mine))
1464 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001465 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001466 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001467 }
1468
Denis Ovsienkofa079662011-10-08 17:22:45 +04001469 assert (p == OSPF6_MESSAGE_END (oh));
paul718e3742002-12-13 20:15:29 +00001470}
1471
Paul Jakma6ac29a52008-08-15 13:45:30 +01001472static u_char *recvbuf = NULL;
1473static u_char *sendbuf = NULL;
1474static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001475
1476int
paul0c083ee2004-10-10 12:54:58 +00001477ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001478{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001479 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001480
1481 if (size <= iobuflen)
1482 return iobuflen;
1483
1484 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1485 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1486 if (recvnew == NULL || sendnew == NULL)
1487 {
hassob596c712004-07-09 18:33:43 +00001488 if (recvnew)
1489 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1490 if (sendnew)
1491 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001492 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001493 return iobuflen;
1494 }
1495
1496 if (recvbuf)
1497 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1498 if (sendbuf)
1499 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1500 recvbuf = recvnew;
1501 sendbuf = sendnew;
1502 iobuflen = size;
1503
1504 return iobuflen;
1505}
paul718e3742002-12-13 20:15:29 +00001506
Tom Goffae2254a2010-11-10 13:01:41 -08001507void
1508ospf6_message_terminate (void)
1509{
1510 if (recvbuf)
1511 {
1512 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1513 recvbuf = NULL;
1514 }
1515
1516 if (sendbuf)
1517 {
1518 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1519 sendbuf = NULL;
1520 }
1521
1522 iobuflen = 0;
1523}
1524
paul718e3742002-12-13 20:15:29 +00001525int
1526ospf6_receive (struct thread *thread)
1527{
paul0c083ee2004-10-10 12:54:58 +00001528 int sockfd;
1529 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001530 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001531 struct in6_addr src, dst;
1532 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001533 struct iovec iovector[2];
1534 struct ospf6_interface *oi;
1535 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001536
1537 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001538 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001539 thread_add_read (master, ospf6_receive, NULL, sockfd);
1540
1541 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001542 memset (&src, 0, sizeof (src));
1543 memset (&dst, 0, sizeof (dst));
1544 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001545 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001546 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001547 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001548 iovector[1].iov_base = NULL;
1549 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001550
1551 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001552 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001553 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001554 {
hasso508e53e2004-05-18 18:57:06 +00001555 zlog_err ("Excess message read");
1556 return 0;
1557 }
paul718e3742002-12-13 20:15:29 +00001558
hasso508e53e2004-05-18 18:57:06 +00001559 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1560 if (oi == NULL || oi->area == NULL)
1561 {
hassoc6487d62004-12-24 06:00:11 +00001562 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001563 return 0;
1564 }
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001565 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1566 {
1567 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1568 zlog_debug ("%s: Ignore message on passive interface %s",
1569 __func__, oi->interface->name);
1570 return 0;
1571 }
hasso508e53e2004-05-18 18:57:06 +00001572
1573 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001574 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1575 return 0;
1576
1577 /* Being here means, that no sizing/alignment issues were detected in
1578 the input packet. This renders the additional checks performed below
1579 and also in the type-specific dispatching functions a dead code,
1580 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001581
1582 /* Log */
1583 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1584 {
1585 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1586 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001587 zlog_debug ("%s received on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001588 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001589 zlog_debug (" src: %s", srcname);
1590 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001591
1592 switch (oh->type)
1593 {
1594 case OSPF6_MESSAGE_TYPE_HELLO:
1595 ospf6_hello_print (oh);
1596 break;
1597 case OSPF6_MESSAGE_TYPE_DBDESC:
1598 ospf6_dbdesc_print (oh);
1599 break;
1600 case OSPF6_MESSAGE_TYPE_LSREQ:
1601 ospf6_lsreq_print (oh);
1602 break;
1603 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1604 ospf6_lsupdate_print (oh);
1605 break;
1606 case OSPF6_MESSAGE_TYPE_LSACK:
1607 ospf6_lsack_print (oh);
1608 break;
1609 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001610 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001611 }
1612 }
1613
hasso508e53e2004-05-18 18:57:06 +00001614 switch (oh->type)
1615 {
1616 case OSPF6_MESSAGE_TYPE_HELLO:
1617 ospf6_hello_recv (&src, &dst, oi, oh);
1618 break;
1619
1620 case OSPF6_MESSAGE_TYPE_DBDESC:
1621 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1622 break;
1623
1624 case OSPF6_MESSAGE_TYPE_LSREQ:
1625 ospf6_lsreq_recv (&src, &dst, oi, oh);
1626 break;
1627
1628 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1629 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1630 break;
1631
1632 case OSPF6_MESSAGE_TYPE_LSACK:
1633 ospf6_lsack_recv (&src, &dst, oi, oh);
1634 break;
1635
1636 default:
Denis Ovsienkofa079662011-10-08 17:22:45 +04001637 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001638 }
1639
1640 return 0;
1641}
1642
Paul Jakma6ac29a52008-08-15 13:45:30 +01001643static void
hasso508e53e2004-05-18 18:57:06 +00001644ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1645 struct ospf6_interface *oi, struct ospf6_header *oh)
1646{
1647 int len;
1648 char srcname[64], dstname[64];
1649 struct iovec iovector[2];
1650
1651 /* initialize */
1652 iovector[0].iov_base = (caddr_t) oh;
1653 iovector[0].iov_len = ntohs (oh->length);
1654 iovector[1].iov_base = NULL;
1655 iovector[1].iov_len = 0;
1656
1657 /* fill OSPF header */
1658 oh->version = OSPFV3_VERSION;
1659 /* message type must be set before */
1660 /* message length must be set before */
1661 oh->router_id = oi->area->ospf6->router_id;
1662 oh->area_id = oi->area->area_id;
1663 /* checksum is calculated by kernel */
1664 oh->instance_id = oi->instance_id;
1665 oh->reserved = 0;
1666
1667 /* Log */
1668 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1669 {
1670 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1671 if (src)
1672 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1673 else
1674 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001675 zlog_debug ("%s send on %s",
Denis Ovsienko5031ed12011-10-14 21:59:58 +04001676 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001677 zlog_debug (" src: %s", srcname);
1678 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001679
1680 switch (oh->type)
1681 {
1682 case OSPF6_MESSAGE_TYPE_HELLO:
1683 ospf6_hello_print (oh);
1684 break;
1685 case OSPF6_MESSAGE_TYPE_DBDESC:
1686 ospf6_dbdesc_print (oh);
1687 break;
1688 case OSPF6_MESSAGE_TYPE_LSREQ:
1689 ospf6_lsreq_print (oh);
1690 break;
1691 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1692 ospf6_lsupdate_print (oh);
1693 break;
1694 case OSPF6_MESSAGE_TYPE_LSACK:
1695 ospf6_lsack_print (oh);
1696 break;
1697 default:
hassoc6487d62004-12-24 06:00:11 +00001698 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001699 assert (0);
1700 break;
1701 }
1702 }
1703
1704 /* send message */
1705 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1706 if (len != ntohs (oh->length))
1707 zlog_err ("Could not send entire message");
1708}
1709
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001710static uint32_t
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001711ospf6_packet_max(struct ospf6_interface *oi)
1712{
Vyacheslav Trushkincba1fab2011-12-22 18:24:19 +04001713 assert (oi->ifmtu > sizeof (struct ip6_hdr));
1714 return oi->ifmtu - (sizeof (struct ip6_hdr));
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001715}
1716
hasso508e53e2004-05-18 18:57:06 +00001717int
1718ospf6_hello_send (struct thread *thread)
1719{
1720 struct ospf6_interface *oi;
1721 struct ospf6_header *oh;
1722 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001723 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001724 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001725 struct ospf6_neighbor *on;
1726
1727 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1728 oi->thread_send_hello = (struct thread *) NULL;
1729
1730 if (oi->state <= OSPF6_INTERFACE_DOWN)
1731 {
1732 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001733 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001734 oi->interface->name);
1735 return 0;
1736 }
1737
1738 /* set next thread */
1739 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1740 oi, oi->hello_interval);
1741
hasso3b4cd3a2004-05-18 19:28:32 +00001742 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001743 oh = (struct ospf6_header *) sendbuf;
1744 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1745
1746 hello->interface_id = htonl (oi->interface->ifindex);
1747 hello->priority = oi->priority;
1748 hello->options[0] = oi->area->options[0];
1749 hello->options[1] = oi->area->options[1];
1750 hello->options[2] = oi->area->options[2];
1751 hello->hello_interval = htons (oi->hello_interval);
1752 hello->dead_interval = htons (oi->dead_interval);
1753 hello->drouter = oi->drouter;
1754 hello->bdrouter = oi->bdrouter;
1755
Paul Jakma6ac29a52008-08-15 13:45:30 +01001756 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001757
paul1eb8ef22005-04-07 07:30:20 +00001758 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001759 {
hasso508e53e2004-05-18 18:57:06 +00001760 if (on->state < OSPF6_NEIGHBOR_INIT)
1761 continue;
1762
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001763 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001764 {
1765 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001766 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001767 break;
1768 }
1769
1770 memcpy (p, &on->router_id, sizeof (u_int32_t));
1771 p += sizeof (u_int32_t);
1772 }
1773
1774 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1775 oh->length = htons (p - sendbuf);
1776
1777 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1778 return 0;
1779}
1780
1781int
1782ospf6_dbdesc_send (struct thread *thread)
1783{
1784 struct ospf6_neighbor *on;
1785 struct ospf6_header *oh;
1786 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001787 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001788 struct ospf6_lsa *lsa;
1789
1790 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1791 on->thread_send_dbdesc = (struct thread *) NULL;
1792
1793 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1794 {
1795 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001796 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1797 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001798 return 0;
1799 }
1800
1801 /* set next thread if master */
1802 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1803 on->thread_send_dbdesc =
1804 thread_add_timer (master, ospf6_dbdesc_send, on,
1805 on->ospf6_if->rxmt_interval);
1806
hasso3b4cd3a2004-05-18 19:28:32 +00001807 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001808 oh = (struct ospf6_header *) sendbuf;
1809 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1810 sizeof (struct ospf6_header));
1811
1812 /* if this is initial one, initialize sequence number for DbDesc */
1813 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1814 {
1815 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001816 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001817 tv.tv_sec = 1;
1818 on->dbdesc_seqnum = tv.tv_sec;
1819 }
1820
1821 dbdesc->options[0] = on->ospf6_if->area->options[0];
1822 dbdesc->options[1] = on->ospf6_if->area->options[1];
1823 dbdesc->options[2] = on->ospf6_if->area->options[2];
1824 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1825 dbdesc->bits = on->dbdesc_bits;
1826 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1827
1828 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001829 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001830 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1831 {
1832 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1833 lsa = ospf6_lsdb_next (lsa))
1834 {
1835 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1836
1837 /* MTU check */
1838 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001839 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001840 {
1841 ospf6_lsa_unlock (lsa);
1842 break;
1843 }
1844 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1845 p += sizeof (struct ospf6_lsa_header);
1846 }
1847 }
1848
1849 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1850 oh->length = htons (p - sendbuf);
1851
1852 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1853 on->ospf6_if, oh);
1854 return 0;
1855}
1856
1857int
1858ospf6_dbdesc_send_newone (struct thread *thread)
1859{
1860 struct ospf6_neighbor *on;
1861 struct ospf6_lsa *lsa;
1862 unsigned int size = 0;
1863
1864 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001865 ospf6_lsdb_remove_all (on->dbdesc_list);
1866
1867 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1868 so that ospf6_send_dbdesc () can send those LSAs */
1869 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1870 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1871 lsa = ospf6_lsdb_next (lsa))
1872 {
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001873 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001874 {
1875 ospf6_lsa_unlock (lsa);
1876 break;
1877 }
1878
hasso508e53e2004-05-18 18:57:06 +00001879 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1880 ospf6_lsdb_remove (lsa, on->summary_list);
1881 size += sizeof (struct ospf6_lsa_header);
1882 }
1883
1884 if (on->summary_list->count == 0)
1885 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1886
1887 /* If slave, More bit check must be done here */
1888 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1889 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1890 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1891 thread_add_event (master, exchange_done, on, 0);
1892
1893 thread_execute (master, ospf6_dbdesc_send, on, 0);
1894 return 0;
1895}
1896
1897int
1898ospf6_lsreq_send (struct thread *thread)
1899{
1900 struct ospf6_neighbor *on;
1901 struct ospf6_header *oh;
1902 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001903 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001904 struct ospf6_lsa *lsa;
1905
1906 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1907 on->thread_send_lsreq = (struct thread *) NULL;
1908
1909 /* LSReq will be sent only in ExStart or Loading */
1910 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1911 on->state != OSPF6_NEIGHBOR_LOADING)
1912 {
1913 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001914 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1915 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001916 return 0;
1917 }
1918
1919 /* schedule loading_done if request list is empty */
1920 if (on->request_list->count == 0)
1921 {
1922 thread_add_event (master, loading_done, on, 0);
1923 return 0;
1924 }
1925
1926 /* set next thread */
1927 on->thread_send_lsreq =
1928 thread_add_timer (master, ospf6_lsreq_send, on,
1929 on->ospf6_if->rxmt_interval);
1930
hasso3b4cd3a2004-05-18 19:28:32 +00001931 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001932 oh = (struct ospf6_header *) sendbuf;
1933
1934 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001935 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001936 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1937 lsa = ospf6_lsdb_next (lsa))
1938 {
1939 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04001940 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001941 {
1942 ospf6_lsa_unlock (lsa);
1943 break;
1944 }
1945
1946 e = (struct ospf6_lsreq_entry *) p;
1947 e->type = lsa->header->type;
1948 e->id = lsa->header->id;
1949 e->adv_router = lsa->header->adv_router;
1950 p += sizeof (struct ospf6_lsreq_entry);
1951 }
1952
1953 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1954 oh->length = htons (p - sendbuf);
1955
1956 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1957 on->ospf6_if, oh);
1958 return 0;
1959}
1960
1961int
1962ospf6_lsupdate_send_neighbor (struct thread *thread)
1963{
1964 struct ospf6_neighbor *on;
1965 struct ospf6_header *oh;
1966 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001967 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001968 int num;
1969 struct ospf6_lsa *lsa;
1970
1971 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1972 on->thread_send_lsupdate = (struct thread *) NULL;
1973
hasso6452df02004-08-15 05:52:07 +00001974 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001975 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001976
hasso508e53e2004-05-18 18:57:06 +00001977 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1978 {
1979 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001980 zlog_debug ("Quit to send (neighbor state %s)",
1981 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001982 return 0;
1983 }
1984
1985 /* if we have nothing to send, return */
1986 if (on->lsupdate_list->count == 0 &&
1987 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001988 {
1989 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001990 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001991 return 0;
1992 }
hasso508e53e2004-05-18 18:57:06 +00001993
hasso3b4cd3a2004-05-18 19:28:32 +00001994 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001995 oh = (struct ospf6_header *) sendbuf;
1996 lsupdate = (struct ospf6_lsupdate *)
1997 ((caddr_t) oh + sizeof (struct ospf6_header));
1998
Paul Jakma6ac29a52008-08-15 13:45:30 +01001999 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002000 num = 0;
2001
2002 /* lsupdate_list lists those LSA which doesn't need to be
2003 retransmitted. remove those from the list */
2004 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2005 lsa = ospf6_lsdb_next (lsa))
2006 {
2007 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002008 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002009 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002010 {
2011 ospf6_lsa_unlock (lsa);
2012 break;
2013 }
2014
hasso508e53e2004-05-18 18:57:06 +00002015 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2016 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2017 p += OSPF6_LSA_SIZE (lsa->header);
2018 num++;
2019
2020 assert (lsa->lock == 2);
2021 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2022 }
2023
2024 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2025 lsa = ospf6_lsdb_next (lsa))
2026 {
2027 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002028 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002029 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002030 {
2031 ospf6_lsa_unlock (lsa);
2032 break;
2033 }
2034
hasso508e53e2004-05-18 18:57:06 +00002035 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2036 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2037 p += OSPF6_LSA_SIZE (lsa->header);
2038 num++;
2039 }
2040
2041 lsupdate->lsa_number = htonl (num);
2042
2043 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2044 oh->length = htons (p - sendbuf);
2045
2046 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2047 on->ospf6_if, oh);
2048
2049 if (on->lsupdate_list->count != 0 ||
2050 on->retrans_list->count != 0)
2051 {
2052 if (on->lsupdate_list->count != 0)
2053 on->thread_send_lsupdate =
2054 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2055 else
2056 on->thread_send_lsupdate =
2057 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2058 on->ospf6_if->rxmt_interval);
2059 }
2060
2061 return 0;
2062}
2063
2064int
2065ospf6_lsupdate_send_interface (struct thread *thread)
2066{
2067 struct ospf6_interface *oi;
2068 struct ospf6_header *oh;
2069 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002070 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002071 int num;
2072 struct ospf6_lsa *lsa;
2073
2074 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2075 oi->thread_send_lsupdate = (struct thread *) NULL;
2076
2077 if (oi->state <= OSPF6_INTERFACE_WAITING)
2078 {
2079 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002080 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2081 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002082 return 0;
2083 }
2084
2085 /* if we have nothing to send, return */
2086 if (oi->lsupdate_list->count == 0)
2087 return 0;
2088
hasso3b4cd3a2004-05-18 19:28:32 +00002089 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002090 oh = (struct ospf6_header *) sendbuf;
2091 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
2092 sizeof (struct ospf6_header));
2093
Paul Jakma6ac29a52008-08-15 13:45:30 +01002094 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002095 num = 0;
2096
2097 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2098 lsa = ospf6_lsdb_next (lsa))
2099 {
2100 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002101 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002102 > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002103 {
2104 ospf6_lsa_unlock (lsa);
2105 break;
2106 }
2107
hasso508e53e2004-05-18 18:57:06 +00002108 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2109 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2110 p += OSPF6_LSA_SIZE (lsa->header);
2111 num++;
2112
2113 assert (lsa->lock == 2);
2114 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2115 }
2116
2117 lsupdate->lsa_number = htonl (num);
2118
2119 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2120 oh->length = htons (p - sendbuf);
2121
2122 if (oi->state == OSPF6_INTERFACE_DR ||
2123 oi->state == OSPF6_INTERFACE_BDR)
2124 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2125 else
2126 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2127
2128 if (oi->lsupdate_list->count > 0)
2129 {
2130 oi->thread_send_lsupdate =
2131 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2132 }
2133
2134 return 0;
2135}
2136
2137int
2138ospf6_lsack_send_neighbor (struct thread *thread)
2139{
2140 struct ospf6_neighbor *on;
2141 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002142 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002143 struct ospf6_lsa *lsa;
2144
2145 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2146 on->thread_send_lsack = (struct thread *) NULL;
2147
2148 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2149 {
2150 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002151 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2152 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002153 return 0;
2154 }
2155
2156 /* if we have nothing to send, return */
2157 if (on->lsack_list->count == 0)
2158 return 0;
2159
hasso3b4cd3a2004-05-18 19:28:32 +00002160 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002161 oh = (struct ospf6_header *) sendbuf;
2162
Paul Jakma6ac29a52008-08-15 13:45:30 +01002163 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002164
2165 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2166 lsa = ospf6_lsdb_next (lsa))
2167 {
2168 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002169 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002170 {
2171 /* if we run out of packet size/space here,
2172 better to try again soon. */
2173 THREAD_OFF (on->thread_send_lsack);
2174 on->thread_send_lsack =
2175 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2176
2177 ospf6_lsa_unlock (lsa);
2178 break;
2179 }
2180
2181 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2182 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2183 p += sizeof (struct ospf6_lsa_header);
2184
2185 assert (lsa->lock == 2);
2186 ospf6_lsdb_remove (lsa, on->lsack_list);
2187 }
2188
2189 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2190 oh->length = htons (p - sendbuf);
2191
2192 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2193 on->ospf6_if, oh);
2194 return 0;
2195}
2196
2197int
2198ospf6_lsack_send_interface (struct thread *thread)
2199{
2200 struct ospf6_interface *oi;
2201 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002202 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002203 struct ospf6_lsa *lsa;
2204
2205 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2206 oi->thread_send_lsack = (struct thread *) NULL;
2207
2208 if (oi->state <= OSPF6_INTERFACE_WAITING)
2209 {
2210 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002211 zlog_debug ("Quit to send LSAck to interface %s state %s",
2212 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002213 return 0;
2214 }
2215
2216 /* if we have nothing to send, return */
2217 if (oi->lsack_list->count == 0)
2218 return 0;
2219
hasso3b4cd3a2004-05-18 19:28:32 +00002220 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002221 oh = (struct ospf6_header *) sendbuf;
2222
Paul Jakma6ac29a52008-08-15 13:45:30 +01002223 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002224
2225 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2226 lsa = ospf6_lsdb_next (lsa))
2227 {
2228 /* MTU check */
Dmitrij Tejblum681b84e2011-07-12 17:53:33 +04002229 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002230 {
2231 /* if we run out of packet size/space here,
2232 better to try again soon. */
2233 THREAD_OFF (oi->thread_send_lsack);
2234 oi->thread_send_lsack =
2235 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2236
2237 ospf6_lsa_unlock (lsa);
2238 break;
2239 }
2240
2241 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2242 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2243 p += sizeof (struct ospf6_lsa_header);
2244
2245 assert (lsa->lock == 2);
2246 ospf6_lsdb_remove (lsa, oi->lsack_list);
2247 }
2248
2249 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2250 oh->length = htons (p - sendbuf);
2251
2252 if (oi->state == OSPF6_INTERFACE_DR ||
2253 oi->state == OSPF6_INTERFACE_BDR)
2254 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2255 else
2256 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2257
2258 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2259 {
2260 oi->thread_send_lsack =
2261 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2262 }
paul718e3742002-12-13 20:15:29 +00002263
2264 return 0;
2265}
2266
2267
hasso508e53e2004-05-18 18:57:06 +00002268/* Commands */
2269DEFUN (debug_ospf6_message,
2270 debug_ospf6_message_cmd,
2271 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2272 DEBUG_STR
2273 OSPF6_STR
2274 "Debug OSPFv3 message\n"
2275 "Debug Unknown message\n"
2276 "Debug Hello message\n"
2277 "Debug Database Description message\n"
2278 "Debug Link State Request message\n"
2279 "Debug Link State Update message\n"
2280 "Debug Link State Acknowledgement message\n"
2281 "Debug All message\n"
2282 )
paul718e3742002-12-13 20:15:29 +00002283{
hasso508e53e2004-05-18 18:57:06 +00002284 unsigned char level = 0;
2285 int type = 0;
paul718e3742002-12-13 20:15:29 +00002286 int i;
2287
hasso508e53e2004-05-18 18:57:06 +00002288 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002289
hasso508e53e2004-05-18 18:57:06 +00002290 /* check type */
2291 if (! strncmp (argv[0], "u", 1))
2292 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2293 else if (! strncmp (argv[0], "h", 1))
2294 type = OSPF6_MESSAGE_TYPE_HELLO;
2295 else if (! strncmp (argv[0], "d", 1))
2296 type = OSPF6_MESSAGE_TYPE_DBDESC;
2297 else if (! strncmp (argv[0], "lsr", 3))
2298 type = OSPF6_MESSAGE_TYPE_LSREQ;
2299 else if (! strncmp (argv[0], "lsu", 3))
2300 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2301 else if (! strncmp (argv[0], "lsa", 3))
2302 type = OSPF6_MESSAGE_TYPE_LSACK;
2303 else if (! strncmp (argv[0], "a", 1))
2304 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002305
hasso508e53e2004-05-18 18:57:06 +00002306 if (argc == 1)
2307 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2308 else if (! strncmp (argv[1], "s", 1))
2309 level = OSPF6_DEBUG_MESSAGE_SEND;
2310 else if (! strncmp (argv[1], "r", 1))
2311 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002312
hasso508e53e2004-05-18 18:57:06 +00002313 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002314 {
hasso508e53e2004-05-18 18:57:06 +00002315 for (i = 0; i < 6; i++)
2316 OSPF6_DEBUG_MESSAGE_ON (i, level);
2317 }
2318 else
2319 OSPF6_DEBUG_MESSAGE_ON (type, level);
2320
2321 return CMD_SUCCESS;
2322}
2323
2324ALIAS (debug_ospf6_message,
2325 debug_ospf6_message_sendrecv_cmd,
2326 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2327 DEBUG_STR
2328 OSPF6_STR
2329 "Debug OSPFv3 message\n"
2330 "Debug Unknown message\n"
2331 "Debug Hello message\n"
2332 "Debug Database Description message\n"
2333 "Debug Link State Request message\n"
2334 "Debug Link State Update message\n"
2335 "Debug Link State Acknowledgement message\n"
2336 "Debug All message\n"
2337 "Debug only sending message\n"
2338 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002339 )
hasso508e53e2004-05-18 18:57:06 +00002340
2341
2342DEFUN (no_debug_ospf6_message,
2343 no_debug_ospf6_message_cmd,
2344 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2345 NO_STR
2346 DEBUG_STR
2347 OSPF6_STR
2348 "Debug OSPFv3 message\n"
2349 "Debug Unknown message\n"
2350 "Debug Hello message\n"
2351 "Debug Database Description message\n"
2352 "Debug Link State Request message\n"
2353 "Debug Link State Update message\n"
2354 "Debug Link State Acknowledgement message\n"
2355 "Debug All message\n"
2356 )
2357{
2358 unsigned char level = 0;
2359 int type = 0;
2360 int i;
2361
2362 assert (argc > 0);
2363
2364 /* check type */
2365 if (! strncmp (argv[0], "u", 1))
2366 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2367 else if (! strncmp (argv[0], "h", 1))
2368 type = OSPF6_MESSAGE_TYPE_HELLO;
2369 else if (! strncmp (argv[0], "d", 1))
2370 type = OSPF6_MESSAGE_TYPE_DBDESC;
2371 else if (! strncmp (argv[0], "lsr", 3))
2372 type = OSPF6_MESSAGE_TYPE_LSREQ;
2373 else if (! strncmp (argv[0], "lsu", 3))
2374 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2375 else if (! strncmp (argv[0], "lsa", 3))
2376 type = OSPF6_MESSAGE_TYPE_LSACK;
2377 else if (! strncmp (argv[0], "a", 1))
2378 type = OSPF6_MESSAGE_TYPE_ALL;
2379
2380 if (argc == 1)
2381 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2382 else if (! strncmp (argv[1], "s", 1))
2383 level = OSPF6_DEBUG_MESSAGE_SEND;
2384 else if (! strncmp (argv[1], "r", 1))
2385 level = OSPF6_DEBUG_MESSAGE_RECV;
2386
2387 if (type == OSPF6_MESSAGE_TYPE_ALL)
2388 {
2389 for (i = 0; i < 6; i++)
2390 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2391 }
2392 else
2393 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2394
2395 return CMD_SUCCESS;
2396}
2397
2398ALIAS (no_debug_ospf6_message,
2399 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002400 "no debug ospf6 message "
2401 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002402 NO_STR
2403 DEBUG_STR
2404 OSPF6_STR
2405 "Debug OSPFv3 message\n"
2406 "Debug Unknown message\n"
2407 "Debug Hello message\n"
2408 "Debug Database Description message\n"
2409 "Debug Link State Request message\n"
2410 "Debug Link State Update message\n"
2411 "Debug Link State Acknowledgement message\n"
2412 "Debug All message\n"
2413 "Debug only sending message\n"
2414 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002415 )
hasso508e53e2004-05-18 18:57:06 +00002416
2417int
2418config_write_ospf6_debug_message (struct vty *vty)
2419{
paul0c083ee2004-10-10 12:54:58 +00002420 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002421 "lsreq", "lsupdate", "lsack"};
2422 unsigned char s = 0, r = 0;
2423 int i;
2424
2425 for (i = 0; i < 6; i++)
2426 {
2427 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2428 s |= 1 << i;
2429 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2430 r |= 1 << i;
2431 }
2432
2433 if (s == 0x3f && r == 0x3f)
2434 {
hasso049207c2004-08-04 20:02:13 +00002435 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002436 return 0;
2437 }
2438
hasso508e53e2004-05-18 18:57:06 +00002439 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002440 {
hasso049207c2004-08-04 20:02:13 +00002441 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002442 return 0;
2443 }
2444 else if (s == 0 && r == 0x3f)
2445 {
hasso049207c2004-08-04 20:02:13 +00002446 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002447 return 0;
paul718e3742002-12-13 20:15:29 +00002448 }
2449
hasso508e53e2004-05-18 18:57:06 +00002450 /* Unknown message is logged by default */
2451 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2452 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002453 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002454 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002455 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002456 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002457 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002458
hasso508e53e2004-05-18 18:57:06 +00002459 for (i = 1; i < 6; i++)
2460 {
2461 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2462 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002463 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002464 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2465 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002466 VNL);
hasso508e53e2004-05-18 18:57:06 +00002467 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2468 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002469 VNL);
hasso508e53e2004-05-18 18:57:06 +00002470 }
paul718e3742002-12-13 20:15:29 +00002471
2472 return 0;
2473}
2474
paul718e3742002-12-13 20:15:29 +00002475void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002476install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002477{
hasso508e53e2004-05-18 18:57:06 +00002478 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2479 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2480 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2481 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2482 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2483 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2484 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2485 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002486}
2487
paul718e3742002-12-13 20:15:29 +00002488