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