blob: 8179fc14ea30e6de6f26c373c8e5d10a8c9d91db [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 Ovsienko552563a2011-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 Tejblum82a963a2011-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 Ovsienkoed721562011-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 Ovsienko552563a2011-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 Ovsienko484af2c2011-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 Ovsienko484af2c2011-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 Ovsienko484af2c2011-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 Ovsienko484af2c2011-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 Ovsienko484af2c2011-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 Ovsienko484af2c2011-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 Ovsienko484af2c2011-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 Ovsienko484af2c2011-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 Tejblumab1be8a2011-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 Ovsienko484af2c2011-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 Ovsienko552563a2011-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))
1107 zlog_debug ("%s: undersized (%u B) trailing (#%u) LSA header",
1108 __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))
1139 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %u B",
1140 __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 Ovsienkoed721562011-10-14 21:59:58 +04001205 bytesonwire, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienko552563a2011-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 Ovsienkoed721562011-10-14 21:59:58 +04001218 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienko552563a2011-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 Ovsienkoed721562011-10-14 21:59:58 +04001237 __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienko552563a2011-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 Ovsienkoed721562011-10-14 21:59:58 +04001267 zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type));
Denis Ovsienko552563a2011-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 Ovsienko484af2c2011-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 Ovsienko484af2c2011-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
1507int
1508ospf6_receive (struct thread *thread)
1509{
paul0c083ee2004-10-10 12:54:58 +00001510 int sockfd;
1511 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001512 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001513 struct in6_addr src, dst;
1514 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001515 struct iovec iovector[2];
1516 struct ospf6_interface *oi;
1517 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001518
1519 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001520 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001521 thread_add_read (master, ospf6_receive, NULL, sockfd);
1522
1523 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001524 memset (&src, 0, sizeof (src));
1525 memset (&dst, 0, sizeof (dst));
1526 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001527 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001528 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001529 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001530 iovector[1].iov_base = NULL;
1531 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001532
1533 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001534 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001535 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001536 {
hasso508e53e2004-05-18 18:57:06 +00001537 zlog_err ("Excess message read");
1538 return 0;
1539 }
paul718e3742002-12-13 20:15:29 +00001540
hasso508e53e2004-05-18 18:57:06 +00001541 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1542 if (oi == NULL || oi->area == NULL)
1543 {
hassoc6487d62004-12-24 06:00:11 +00001544 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001545 return 0;
1546 }
Denis Ovsienko552563a2011-09-26 13:18:51 +04001547 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1548 {
1549 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1550 zlog_debug ("%s: Ignore message on passive interface %s",
1551 __func__, oi->interface->name);
1552 return 0;
1553 }
hasso508e53e2004-05-18 18:57:06 +00001554
1555 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienko552563a2011-09-26 13:18:51 +04001556 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1557 return 0;
1558
1559 /* Being here means, that no sizing/alignment issues were detected in
1560 the input packet. This renders the additional checks performed below
1561 and also in the type-specific dispatching functions a dead code,
1562 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001563
1564 /* Log */
1565 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1566 {
1567 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1568 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001569 zlog_debug ("%s received on %s",
Denis Ovsienkoed721562011-10-14 21:59:58 +04001570 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001571 zlog_debug (" src: %s", srcname);
1572 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001573
1574 switch (oh->type)
1575 {
1576 case OSPF6_MESSAGE_TYPE_HELLO:
1577 ospf6_hello_print (oh);
1578 break;
1579 case OSPF6_MESSAGE_TYPE_DBDESC:
1580 ospf6_dbdesc_print (oh);
1581 break;
1582 case OSPF6_MESSAGE_TYPE_LSREQ:
1583 ospf6_lsreq_print (oh);
1584 break;
1585 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1586 ospf6_lsupdate_print (oh);
1587 break;
1588 case OSPF6_MESSAGE_TYPE_LSACK:
1589 ospf6_lsack_print (oh);
1590 break;
1591 default:
Denis Ovsienko484af2c2011-10-08 17:22:45 +04001592 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001593 }
1594 }
1595
hasso508e53e2004-05-18 18:57:06 +00001596 switch (oh->type)
1597 {
1598 case OSPF6_MESSAGE_TYPE_HELLO:
1599 ospf6_hello_recv (&src, &dst, oi, oh);
1600 break;
1601
1602 case OSPF6_MESSAGE_TYPE_DBDESC:
1603 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1604 break;
1605
1606 case OSPF6_MESSAGE_TYPE_LSREQ:
1607 ospf6_lsreq_recv (&src, &dst, oi, oh);
1608 break;
1609
1610 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1611 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1612 break;
1613
1614 case OSPF6_MESSAGE_TYPE_LSACK:
1615 ospf6_lsack_recv (&src, &dst, oi, oh);
1616 break;
1617
1618 default:
Denis Ovsienko484af2c2011-10-08 17:22:45 +04001619 assert (0);
hasso508e53e2004-05-18 18:57:06 +00001620 }
1621
1622 return 0;
1623}
1624
Paul Jakma6ac29a52008-08-15 13:45:30 +01001625static void
hasso508e53e2004-05-18 18:57:06 +00001626ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1627 struct ospf6_interface *oi, struct ospf6_header *oh)
1628{
1629 int len;
1630 char srcname[64], dstname[64];
1631 struct iovec iovector[2];
1632
1633 /* initialize */
1634 iovector[0].iov_base = (caddr_t) oh;
1635 iovector[0].iov_len = ntohs (oh->length);
1636 iovector[1].iov_base = NULL;
1637 iovector[1].iov_len = 0;
1638
1639 /* fill OSPF header */
1640 oh->version = OSPFV3_VERSION;
1641 /* message type must be set before */
1642 /* message length must be set before */
1643 oh->router_id = oi->area->ospf6->router_id;
1644 oh->area_id = oi->area->area_id;
1645 /* checksum is calculated by kernel */
1646 oh->instance_id = oi->instance_id;
1647 oh->reserved = 0;
1648
1649 /* Log */
1650 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1651 {
1652 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1653 if (src)
1654 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1655 else
1656 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001657 zlog_debug ("%s send on %s",
Denis Ovsienkoed721562011-10-14 21:59:58 +04001658 LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001659 zlog_debug (" src: %s", srcname);
1660 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001661
1662 switch (oh->type)
1663 {
1664 case OSPF6_MESSAGE_TYPE_HELLO:
1665 ospf6_hello_print (oh);
1666 break;
1667 case OSPF6_MESSAGE_TYPE_DBDESC:
1668 ospf6_dbdesc_print (oh);
1669 break;
1670 case OSPF6_MESSAGE_TYPE_LSREQ:
1671 ospf6_lsreq_print (oh);
1672 break;
1673 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1674 ospf6_lsupdate_print (oh);
1675 break;
1676 case OSPF6_MESSAGE_TYPE_LSACK:
1677 ospf6_lsack_print (oh);
1678 break;
1679 default:
hassoc6487d62004-12-24 06:00:11 +00001680 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001681 assert (0);
1682 break;
1683 }
1684 }
1685
1686 /* send message */
1687 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1688 if (len != ntohs (oh->length))
1689 zlog_err ("Could not send entire message");
1690}
1691
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001692static int
1693ospf6_packet_max(struct ospf6_interface *oi)
1694{
1695 return oi->ifmtu - sizeof(struct ip6_hdr);
1696}
1697
hasso508e53e2004-05-18 18:57:06 +00001698int
1699ospf6_hello_send (struct thread *thread)
1700{
1701 struct ospf6_interface *oi;
1702 struct ospf6_header *oh;
1703 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001704 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001705 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001706 struct ospf6_neighbor *on;
1707
1708 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1709 oi->thread_send_hello = (struct thread *) NULL;
1710
1711 if (oi->state <= OSPF6_INTERFACE_DOWN)
1712 {
1713 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001714 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001715 oi->interface->name);
1716 return 0;
1717 }
1718
1719 /* set next thread */
1720 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1721 oi, oi->hello_interval);
1722
hasso3b4cd3a2004-05-18 19:28:32 +00001723 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001724 oh = (struct ospf6_header *) sendbuf;
1725 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1726
1727 hello->interface_id = htonl (oi->interface->ifindex);
1728 hello->priority = oi->priority;
1729 hello->options[0] = oi->area->options[0];
1730 hello->options[1] = oi->area->options[1];
1731 hello->options[2] = oi->area->options[2];
1732 hello->hello_interval = htons (oi->hello_interval);
1733 hello->dead_interval = htons (oi->dead_interval);
1734 hello->drouter = oi->drouter;
1735 hello->bdrouter = oi->bdrouter;
1736
Paul Jakma6ac29a52008-08-15 13:45:30 +01001737 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001738
paul1eb8ef22005-04-07 07:30:20 +00001739 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001740 {
hasso508e53e2004-05-18 18:57:06 +00001741 if (on->state < OSPF6_NEIGHBOR_INIT)
1742 continue;
1743
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001744 if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00001745 {
1746 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001747 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001748 break;
1749 }
1750
1751 memcpy (p, &on->router_id, sizeof (u_int32_t));
1752 p += sizeof (u_int32_t);
1753 }
1754
1755 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1756 oh->length = htons (p - sendbuf);
1757
1758 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1759 return 0;
1760}
1761
1762int
1763ospf6_dbdesc_send (struct thread *thread)
1764{
1765 struct ospf6_neighbor *on;
1766 struct ospf6_header *oh;
1767 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001768 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001769 struct ospf6_lsa *lsa;
1770
1771 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1772 on->thread_send_dbdesc = (struct thread *) NULL;
1773
1774 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1775 {
1776 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001777 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1778 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001779 return 0;
1780 }
1781
1782 /* set next thread if master */
1783 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1784 on->thread_send_dbdesc =
1785 thread_add_timer (master, ospf6_dbdesc_send, on,
1786 on->ospf6_if->rxmt_interval);
1787
hasso3b4cd3a2004-05-18 19:28:32 +00001788 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001789 oh = (struct ospf6_header *) sendbuf;
1790 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1791 sizeof (struct ospf6_header));
1792
1793 /* if this is initial one, initialize sequence number for DbDesc */
1794 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1795 {
1796 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001797 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001798 tv.tv_sec = 1;
1799 on->dbdesc_seqnum = tv.tv_sec;
1800 }
1801
1802 dbdesc->options[0] = on->ospf6_if->area->options[0];
1803 dbdesc->options[1] = on->ospf6_if->area->options[1];
1804 dbdesc->options[2] = on->ospf6_if->area->options[2];
1805 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1806 dbdesc->bits = on->dbdesc_bits;
1807 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1808
1809 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001810 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001811 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1812 {
1813 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1814 lsa = ospf6_lsdb_next (lsa))
1815 {
1816 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1817
1818 /* MTU check */
1819 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001820 ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001821 {
1822 ospf6_lsa_unlock (lsa);
1823 break;
1824 }
1825 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1826 p += sizeof (struct ospf6_lsa_header);
1827 }
1828 }
1829
1830 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1831 oh->length = htons (p - sendbuf);
1832
1833 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1834 on->ospf6_if, oh);
1835 return 0;
1836}
1837
1838int
1839ospf6_dbdesc_send_newone (struct thread *thread)
1840{
1841 struct ospf6_neighbor *on;
1842 struct ospf6_lsa *lsa;
1843 unsigned int size = 0;
1844
1845 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001846 ospf6_lsdb_remove_all (on->dbdesc_list);
1847
1848 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1849 so that ospf6_send_dbdesc () can send those LSAs */
1850 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1851 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1852 lsa = ospf6_lsdb_next (lsa))
1853 {
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001854 if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001855 {
1856 ospf6_lsa_unlock (lsa);
1857 break;
1858 }
1859
hasso508e53e2004-05-18 18:57:06 +00001860 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1861 ospf6_lsdb_remove (lsa, on->summary_list);
1862 size += sizeof (struct ospf6_lsa_header);
1863 }
1864
1865 if (on->summary_list->count == 0)
1866 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1867
1868 /* If slave, More bit check must be done here */
1869 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1870 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1871 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1872 thread_add_event (master, exchange_done, on, 0);
1873
1874 thread_execute (master, ospf6_dbdesc_send, on, 0);
1875 return 0;
1876}
1877
1878int
1879ospf6_lsreq_send (struct thread *thread)
1880{
1881 struct ospf6_neighbor *on;
1882 struct ospf6_header *oh;
1883 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001884 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001885 struct ospf6_lsa *lsa;
1886
1887 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1888 on->thread_send_lsreq = (struct thread *) NULL;
1889
1890 /* LSReq will be sent only in ExStart or Loading */
1891 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1892 on->state != OSPF6_NEIGHBOR_LOADING)
1893 {
1894 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001895 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1896 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001897 return 0;
1898 }
1899
1900 /* schedule loading_done if request list is empty */
1901 if (on->request_list->count == 0)
1902 {
1903 thread_add_event (master, loading_done, on, 0);
1904 return 0;
1905 }
1906
1907 /* set next thread */
1908 on->thread_send_lsreq =
1909 thread_add_timer (master, ospf6_lsreq_send, on,
1910 on->ospf6_if->rxmt_interval);
1911
hasso3b4cd3a2004-05-18 19:28:32 +00001912 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001913 oh = (struct ospf6_header *) sendbuf;
1914
1915 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001916 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001917 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1918 lsa = ospf6_lsdb_next (lsa))
1919 {
1920 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001921 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001922 {
1923 ospf6_lsa_unlock (lsa);
1924 break;
1925 }
1926
1927 e = (struct ospf6_lsreq_entry *) p;
1928 e->type = lsa->header->type;
1929 e->id = lsa->header->id;
1930 e->adv_router = lsa->header->adv_router;
1931 p += sizeof (struct ospf6_lsreq_entry);
1932 }
1933
1934 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
1935 oh->length = htons (p - sendbuf);
1936
1937 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1938 on->ospf6_if, oh);
1939 return 0;
1940}
1941
1942int
1943ospf6_lsupdate_send_neighbor (struct thread *thread)
1944{
1945 struct ospf6_neighbor *on;
1946 struct ospf6_header *oh;
1947 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00001948 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001949 int num;
1950 struct ospf6_lsa *lsa;
1951
1952 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1953 on->thread_send_lsupdate = (struct thread *) NULL;
1954
hasso6452df02004-08-15 05:52:07 +00001955 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001956 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00001957
hasso508e53e2004-05-18 18:57:06 +00001958 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
1959 {
1960 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001961 zlog_debug ("Quit to send (neighbor state %s)",
1962 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001963 return 0;
1964 }
1965
1966 /* if we have nothing to send, return */
1967 if (on->lsupdate_list->count == 0 &&
1968 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00001969 {
1970 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00001971 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00001972 return 0;
1973 }
hasso508e53e2004-05-18 18:57:06 +00001974
hasso3b4cd3a2004-05-18 19:28:32 +00001975 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001976 oh = (struct ospf6_header *) sendbuf;
1977 lsupdate = (struct ospf6_lsupdate *)
1978 ((caddr_t) oh + sizeof (struct ospf6_header));
1979
Paul Jakma6ac29a52008-08-15 13:45:30 +01001980 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00001981 num = 0;
1982
1983 /* lsupdate_list lists those LSA which doesn't need to be
1984 retransmitted. remove those from the list */
1985 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
1986 lsa = ospf6_lsdb_next (lsa))
1987 {
1988 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00001989 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04001990 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00001991 {
1992 ospf6_lsa_unlock (lsa);
1993 break;
1994 }
1995
hasso508e53e2004-05-18 18:57:06 +00001996 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1997 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
1998 p += OSPF6_LSA_SIZE (lsa->header);
1999 num++;
2000
2001 assert (lsa->lock == 2);
2002 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2003 }
2004
2005 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2006 lsa = ospf6_lsdb_next (lsa))
2007 {
2008 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002009 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002010 > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002011 {
2012 ospf6_lsa_unlock (lsa);
2013 break;
2014 }
2015
hasso508e53e2004-05-18 18:57:06 +00002016 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2017 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2018 p += OSPF6_LSA_SIZE (lsa->header);
2019 num++;
2020 }
2021
2022 lsupdate->lsa_number = htonl (num);
2023
2024 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2025 oh->length = htons (p - sendbuf);
2026
2027 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2028 on->ospf6_if, oh);
2029
2030 if (on->lsupdate_list->count != 0 ||
2031 on->retrans_list->count != 0)
2032 {
2033 if (on->lsupdate_list->count != 0)
2034 on->thread_send_lsupdate =
2035 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2036 else
2037 on->thread_send_lsupdate =
2038 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2039 on->ospf6_if->rxmt_interval);
2040 }
2041
2042 return 0;
2043}
2044
2045int
2046ospf6_lsupdate_send_interface (struct thread *thread)
2047{
2048 struct ospf6_interface *oi;
2049 struct ospf6_header *oh;
2050 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002051 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002052 int num;
2053 struct ospf6_lsa *lsa;
2054
2055 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2056 oi->thread_send_lsupdate = (struct thread *) NULL;
2057
2058 if (oi->state <= OSPF6_INTERFACE_WAITING)
2059 {
2060 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002061 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2062 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002063 return 0;
2064 }
2065
2066 /* if we have nothing to send, return */
2067 if (oi->lsupdate_list->count == 0)
2068 return 0;
2069
hasso3b4cd3a2004-05-18 19:28:32 +00002070 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002071 oh = (struct ospf6_header *) sendbuf;
2072 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
2073 sizeof (struct ospf6_header));
2074
Paul Jakma6ac29a52008-08-15 13:45:30 +01002075 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002076 num = 0;
2077
2078 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2079 lsa = ospf6_lsdb_next (lsa))
2080 {
2081 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002082 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002083 > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002084 {
2085 ospf6_lsa_unlock (lsa);
2086 break;
2087 }
2088
hasso508e53e2004-05-18 18:57:06 +00002089 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2090 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2091 p += OSPF6_LSA_SIZE (lsa->header);
2092 num++;
2093
2094 assert (lsa->lock == 2);
2095 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2096 }
2097
2098 lsupdate->lsa_number = htonl (num);
2099
2100 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2101 oh->length = htons (p - sendbuf);
2102
2103 if (oi->state == OSPF6_INTERFACE_DR ||
2104 oi->state == OSPF6_INTERFACE_BDR)
2105 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2106 else
2107 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2108
2109 if (oi->lsupdate_list->count > 0)
2110 {
2111 oi->thread_send_lsupdate =
2112 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2113 }
2114
2115 return 0;
2116}
2117
2118int
2119ospf6_lsack_send_neighbor (struct thread *thread)
2120{
2121 struct ospf6_neighbor *on;
2122 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002123 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002124 struct ospf6_lsa *lsa;
2125
2126 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2127 on->thread_send_lsack = (struct thread *) NULL;
2128
2129 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2130 {
2131 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002132 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2133 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002134 return 0;
2135 }
2136
2137 /* if we have nothing to send, return */
2138 if (on->lsack_list->count == 0)
2139 return 0;
2140
hasso3b4cd3a2004-05-18 19:28:32 +00002141 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002142 oh = (struct ospf6_header *) sendbuf;
2143
Paul Jakma6ac29a52008-08-15 13:45:30 +01002144 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002145
2146 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2147 lsa = ospf6_lsdb_next (lsa))
2148 {
2149 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002150 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
hasso508e53e2004-05-18 18:57:06 +00002151 {
2152 /* if we run out of packet size/space here,
2153 better to try again soon. */
2154 THREAD_OFF (on->thread_send_lsack);
2155 on->thread_send_lsack =
2156 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2157
2158 ospf6_lsa_unlock (lsa);
2159 break;
2160 }
2161
2162 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2163 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2164 p += sizeof (struct ospf6_lsa_header);
2165
2166 assert (lsa->lock == 2);
2167 ospf6_lsdb_remove (lsa, on->lsack_list);
2168 }
2169
2170 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2171 oh->length = htons (p - sendbuf);
2172
2173 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2174 on->ospf6_if, oh);
2175 return 0;
2176}
2177
2178int
2179ospf6_lsack_send_interface (struct thread *thread)
2180{
2181 struct ospf6_interface *oi;
2182 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002183 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002184 struct ospf6_lsa *lsa;
2185
2186 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2187 oi->thread_send_lsack = (struct thread *) NULL;
2188
2189 if (oi->state <= OSPF6_INTERFACE_WAITING)
2190 {
2191 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002192 zlog_debug ("Quit to send LSAck to interface %s state %s",
2193 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002194 return 0;
2195 }
2196
2197 /* if we have nothing to send, return */
2198 if (oi->lsack_list->count == 0)
2199 return 0;
2200
hasso3b4cd3a2004-05-18 19:28:32 +00002201 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002202 oh = (struct ospf6_header *) sendbuf;
2203
Paul Jakma6ac29a52008-08-15 13:45:30 +01002204 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002205
2206 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2207 lsa = ospf6_lsdb_next (lsa))
2208 {
2209 /* MTU check */
Dmitrij Tejblum82a963a2011-07-12 17:53:33 +04002210 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
hasso508e53e2004-05-18 18:57:06 +00002211 {
2212 /* if we run out of packet size/space here,
2213 better to try again soon. */
2214 THREAD_OFF (oi->thread_send_lsack);
2215 oi->thread_send_lsack =
2216 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2217
2218 ospf6_lsa_unlock (lsa);
2219 break;
2220 }
2221
2222 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2223 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2224 p += sizeof (struct ospf6_lsa_header);
2225
2226 assert (lsa->lock == 2);
2227 ospf6_lsdb_remove (lsa, oi->lsack_list);
2228 }
2229
2230 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2231 oh->length = htons (p - sendbuf);
2232
2233 if (oi->state == OSPF6_INTERFACE_DR ||
2234 oi->state == OSPF6_INTERFACE_BDR)
2235 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2236 else
2237 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2238
2239 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2240 {
2241 oi->thread_send_lsack =
2242 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2243 }
paul718e3742002-12-13 20:15:29 +00002244
2245 return 0;
2246}
2247
2248
hasso508e53e2004-05-18 18:57:06 +00002249/* Commands */
2250DEFUN (debug_ospf6_message,
2251 debug_ospf6_message_cmd,
2252 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2253 DEBUG_STR
2254 OSPF6_STR
2255 "Debug OSPFv3 message\n"
2256 "Debug Unknown message\n"
2257 "Debug Hello message\n"
2258 "Debug Database Description message\n"
2259 "Debug Link State Request message\n"
2260 "Debug Link State Update message\n"
2261 "Debug Link State Acknowledgement message\n"
2262 "Debug All message\n"
2263 )
paul718e3742002-12-13 20:15:29 +00002264{
hasso508e53e2004-05-18 18:57:06 +00002265 unsigned char level = 0;
2266 int type = 0;
paul718e3742002-12-13 20:15:29 +00002267 int i;
2268
hasso508e53e2004-05-18 18:57:06 +00002269 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002270
hasso508e53e2004-05-18 18:57:06 +00002271 /* check type */
2272 if (! strncmp (argv[0], "u", 1))
2273 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2274 else if (! strncmp (argv[0], "h", 1))
2275 type = OSPF6_MESSAGE_TYPE_HELLO;
2276 else if (! strncmp (argv[0], "d", 1))
2277 type = OSPF6_MESSAGE_TYPE_DBDESC;
2278 else if (! strncmp (argv[0], "lsr", 3))
2279 type = OSPF6_MESSAGE_TYPE_LSREQ;
2280 else if (! strncmp (argv[0], "lsu", 3))
2281 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2282 else if (! strncmp (argv[0], "lsa", 3))
2283 type = OSPF6_MESSAGE_TYPE_LSACK;
2284 else if (! strncmp (argv[0], "a", 1))
2285 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002286
hasso508e53e2004-05-18 18:57:06 +00002287 if (argc == 1)
2288 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2289 else if (! strncmp (argv[1], "s", 1))
2290 level = OSPF6_DEBUG_MESSAGE_SEND;
2291 else if (! strncmp (argv[1], "r", 1))
2292 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002293
hasso508e53e2004-05-18 18:57:06 +00002294 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002295 {
hasso508e53e2004-05-18 18:57:06 +00002296 for (i = 0; i < 6; i++)
2297 OSPF6_DEBUG_MESSAGE_ON (i, level);
2298 }
2299 else
2300 OSPF6_DEBUG_MESSAGE_ON (type, level);
2301
2302 return CMD_SUCCESS;
2303}
2304
2305ALIAS (debug_ospf6_message,
2306 debug_ospf6_message_sendrecv_cmd,
2307 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2308 DEBUG_STR
2309 OSPF6_STR
2310 "Debug OSPFv3 message\n"
2311 "Debug Unknown message\n"
2312 "Debug Hello message\n"
2313 "Debug Database Description message\n"
2314 "Debug Link State Request message\n"
2315 "Debug Link State Update message\n"
2316 "Debug Link State Acknowledgement message\n"
2317 "Debug All message\n"
2318 "Debug only sending message\n"
2319 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002320 )
hasso508e53e2004-05-18 18:57:06 +00002321
2322
2323DEFUN (no_debug_ospf6_message,
2324 no_debug_ospf6_message_cmd,
2325 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2326 NO_STR
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 )
2338{
2339 unsigned char level = 0;
2340 int type = 0;
2341 int i;
2342
2343 assert (argc > 0);
2344
2345 /* check type */
2346 if (! strncmp (argv[0], "u", 1))
2347 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2348 else if (! strncmp (argv[0], "h", 1))
2349 type = OSPF6_MESSAGE_TYPE_HELLO;
2350 else if (! strncmp (argv[0], "d", 1))
2351 type = OSPF6_MESSAGE_TYPE_DBDESC;
2352 else if (! strncmp (argv[0], "lsr", 3))
2353 type = OSPF6_MESSAGE_TYPE_LSREQ;
2354 else if (! strncmp (argv[0], "lsu", 3))
2355 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2356 else if (! strncmp (argv[0], "lsa", 3))
2357 type = OSPF6_MESSAGE_TYPE_LSACK;
2358 else if (! strncmp (argv[0], "a", 1))
2359 type = OSPF6_MESSAGE_TYPE_ALL;
2360
2361 if (argc == 1)
2362 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2363 else if (! strncmp (argv[1], "s", 1))
2364 level = OSPF6_DEBUG_MESSAGE_SEND;
2365 else if (! strncmp (argv[1], "r", 1))
2366 level = OSPF6_DEBUG_MESSAGE_RECV;
2367
2368 if (type == OSPF6_MESSAGE_TYPE_ALL)
2369 {
2370 for (i = 0; i < 6; i++)
2371 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2372 }
2373 else
2374 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2375
2376 return CMD_SUCCESS;
2377}
2378
2379ALIAS (no_debug_ospf6_message,
2380 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002381 "no debug ospf6 message "
2382 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002383 NO_STR
2384 DEBUG_STR
2385 OSPF6_STR
2386 "Debug OSPFv3 message\n"
2387 "Debug Unknown message\n"
2388 "Debug Hello message\n"
2389 "Debug Database Description message\n"
2390 "Debug Link State Request message\n"
2391 "Debug Link State Update message\n"
2392 "Debug Link State Acknowledgement message\n"
2393 "Debug All message\n"
2394 "Debug only sending message\n"
2395 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002396 )
hasso508e53e2004-05-18 18:57:06 +00002397
2398int
2399config_write_ospf6_debug_message (struct vty *vty)
2400{
paul0c083ee2004-10-10 12:54:58 +00002401 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002402 "lsreq", "lsupdate", "lsack"};
2403 unsigned char s = 0, r = 0;
2404 int i;
2405
2406 for (i = 0; i < 6; i++)
2407 {
2408 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2409 s |= 1 << i;
2410 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2411 r |= 1 << i;
2412 }
2413
2414 if (s == 0x3f && r == 0x3f)
2415 {
hasso049207c2004-08-04 20:02:13 +00002416 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002417 return 0;
2418 }
2419
hasso508e53e2004-05-18 18:57:06 +00002420 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002421 {
hasso049207c2004-08-04 20:02:13 +00002422 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002423 return 0;
2424 }
2425 else if (s == 0 && r == 0x3f)
2426 {
hasso049207c2004-08-04 20:02:13 +00002427 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002428 return 0;
paul718e3742002-12-13 20:15:29 +00002429 }
2430
hasso508e53e2004-05-18 18:57:06 +00002431 /* Unknown message is logged by default */
2432 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2433 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002434 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002435 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002436 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002437 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002438 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002439
hasso508e53e2004-05-18 18:57:06 +00002440 for (i = 1; i < 6; i++)
2441 {
2442 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2443 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002444 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002445 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2446 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002447 VNL);
hasso508e53e2004-05-18 18:57:06 +00002448 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2449 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002450 VNL);
hasso508e53e2004-05-18 18:57:06 +00002451 }
paul718e3742002-12-13 20:15:29 +00002452
2453 return 0;
2454}
2455
paul718e3742002-12-13 20:15:29 +00002456void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002457install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002458{
hasso508e53e2004-05-18 18:57:06 +00002459 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2460 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2461 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2462 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2463 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2464 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2465 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2466 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002467}
2468
paul718e3742002-12-13 20:15:29 +00002469