blob: f40ad4b02704a902f39f3de736d398a4dd413f35 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
hasso508e53e2004-05-18 18:57:06 +000022#include <zebra.h>
23
hasso3b4cd3a2004-05-18 19:28:32 +000024#include "memory.h"
hasso508e53e2004-05-18 18:57:06 +000025#include "log.h"
26#include "vty.h"
27#include "command.h"
28#include "thread.h"
29#include "linklist.h"
30
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
33#include "ospf6_lsdb.h"
34#include "ospf6_network.h"
35#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000036
hasso508e53e2004-05-18 18:57:06 +000037#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_neighbor.h"
40#include "ospf6_interface.h"
41
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040042/* for structures and macros ospf6_lsa_examin() needs */
43#include "ospf6_abr.h"
44#include "ospf6_asbr.h"
45#include "ospf6_intra.h"
46
hasso508e53e2004-05-18 18:57:06 +000047#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000048#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000049
50unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
paul0c083ee2004-10-10 12:54:58 +000051const char *ospf6_message_type_str[] =
hasso508e53e2004-05-18 18:57:06 +000052 { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
53
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +040054/* Minimum (besides the standard OSPF packet header) lengths for OSPF
55 packets of particular types, offset is the "type" field. */
56const u_int16_t ospf6_packet_minlen[OSPF6_MESSAGE_TYPE_ALL] =
57{
58 0,
59 OSPF6_HELLO_MIN_SIZE,
60 OSPF6_DB_DESC_MIN_SIZE,
61 OSPF6_LS_REQ_MIN_SIZE,
62 OSPF6_LS_UPD_MIN_SIZE,
63 OSPF6_LS_ACK_MIN_SIZE
64};
65
66/* Minimum (besides the standard LSA header) lengths for LSAs of particular
67 types, offset is the "LSA function code" portion of "LSA type" field. */
68const u_int16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] =
69{
70 0,
71 /* 0x2001 */ OSPF6_ROUTER_LSA_MIN_SIZE,
72 /* 0x2002 */ OSPF6_NETWORK_LSA_MIN_SIZE,
73 /* 0x2003 */ OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
74 /* 0x2004 */ OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
75 /* 0x4005 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
76 /* 0x2006 */ 0,
77 /* 0x2007 */ OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
78 /* 0x0008 */ OSPF6_LINK_LSA_MIN_SIZE,
79 /* 0x2009 */ OSPF6_INTRA_PREFIX_LSA_MIN_SIZE
80};
81
hasso508e53e2004-05-18 18:57:06 +000082/* print functions */
83
84static void
85ospf6_header_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000086{
hasso508e53e2004-05-18 18:57:06 +000087 char router_id[16], area_id[16];
88 inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
89 inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
paul718e3742002-12-13 20:15:29 +000090
hassoc6487d62004-12-24 06:00:11 +000091 zlog_debug (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
hasso508e53e2004-05-18 18:57:06 +000092 oh->version, oh->type, ntohs (oh->length), router_id);
hassoc6487d62004-12-24 06:00:11 +000093 zlog_debug (" Area-ID:%s Cksum:%hx Instance-ID:%d",
hasso508e53e2004-05-18 18:57:06 +000094 area_id, ntohs (oh->checksum), oh->instance_id);
paul718e3742002-12-13 20:15:29 +000095}
paul718e3742002-12-13 20:15:29 +000096
97void
hasso508e53e2004-05-18 18:57:06 +000098ospf6_hello_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +000099{
paul718e3742002-12-13 20:15:29 +0000100 struct ospf6_hello *hello;
hasso508e53e2004-05-18 18:57:06 +0000101 char options[16];
102 char drouter[16], bdrouter[16], neighbor[16];
103 char *p;
paul718e3742002-12-13 20:15:29 +0000104
hasso508e53e2004-05-18 18:57:06 +0000105 ospf6_header_print (oh);
106 assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
paul718e3742002-12-13 20:15:29 +0000107
hasso508e53e2004-05-18 18:57:06 +0000108 hello = (struct ospf6_hello *)
109 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000110
hasso508e53e2004-05-18 18:57:06 +0000111 inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
112 inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
113 ospf6_options_printbuf (hello->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000114
hassoc6487d62004-12-24 06:00:11 +0000115 zlog_debug (" I/F-Id:%ld Priority:%d Option:%s",
hasso508e53e2004-05-18 18:57:06 +0000116 (u_long) ntohl (hello->interface_id), hello->priority, options);
hassoc6487d62004-12-24 06:00:11 +0000117 zlog_debug (" HelloInterval:%hu DeadInterval:%hu",
hasso508e53e2004-05-18 18:57:06 +0000118 ntohs (hello->hello_interval), ntohs (hello->dead_interval));
hassoc6487d62004-12-24 06:00:11 +0000119 zlog_debug (" DR:%s BDR:%s", drouter, bdrouter);
paul718e3742002-12-13 20:15:29 +0000120
hasso508e53e2004-05-18 18:57:06 +0000121 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
122 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
123 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000124 {
hasso508e53e2004-05-18 18:57:06 +0000125 inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
hassoc6487d62004-12-24 06:00:11 +0000126 zlog_debug (" Neighbor: %s", neighbor);
paul718e3742002-12-13 20:15:29 +0000127 }
hasso508e53e2004-05-18 18:57:06 +0000128
129 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000130 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000131}
132
hasso508e53e2004-05-18 18:57:06 +0000133void
134ospf6_dbdesc_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000135{
paul718e3742002-12-13 20:15:29 +0000136 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000137 char options[16];
138 char *p;
paul718e3742002-12-13 20:15:29 +0000139
hasso508e53e2004-05-18 18:57:06 +0000140 ospf6_header_print (oh);
141 assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
paul718e3742002-12-13 20:15:29 +0000142
hasso508e53e2004-05-18 18:57:06 +0000143 dbdesc = (struct ospf6_dbdesc *)
144 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000145
hasso508e53e2004-05-18 18:57:06 +0000146 ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
paul718e3742002-12-13 20:15:29 +0000147
hassoc6487d62004-12-24 06:00:11 +0000148 zlog_debug (" MBZ: %#x Option: %s IfMTU: %hu",
hasso508e53e2004-05-18 18:57:06 +0000149 dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
hassoc6487d62004-12-24 06:00:11 +0000150 zlog_debug (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
hasso508e53e2004-05-18 18:57:06 +0000151 dbdesc->reserved2,
152 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
153 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
154 (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
155 (u_long) ntohl (dbdesc->seqnum));
paul718e3742002-12-13 20:15:29 +0000156
hasso508e53e2004-05-18 18:57:06 +0000157 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
158 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
159 p += sizeof (struct ospf6_lsa_header))
160 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
161
162 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000163 zlog_debug ("Trailing garbage exists");
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
186 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000187 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000188}
189
hasso508e53e2004-05-18 18:57:06 +0000190void
191ospf6_lsupdate_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000192{
paul718e3742002-12-13 20:15:29 +0000193 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +0000194 u_long num;
195 char *p;
paul718e3742002-12-13 20:15:29 +0000196
hasso508e53e2004-05-18 18:57:06 +0000197 ospf6_header_print (oh);
198 assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
paul718e3742002-12-13 20:15:29 +0000199
hasso508e53e2004-05-18 18:57:06 +0000200 lsupdate = (struct ospf6_lsupdate *)
201 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000202
hasso508e53e2004-05-18 18:57:06 +0000203 num = ntohl (lsupdate->lsa_number);
hassoc6487d62004-12-24 06:00:11 +0000204 zlog_debug (" Number of LSA: %ld", num);
paul718e3742002-12-13 20:15:29 +0000205
hasso508e53e2004-05-18 18:57:06 +0000206 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
207 p < OSPF6_MESSAGE_END (oh) &&
208 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
209 p += OSPF6_LSA_SIZE (p))
paul718e3742002-12-13 20:15:29 +0000210 {
hasso508e53e2004-05-18 18:57:06 +0000211 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
212 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
213 {
hassoc6487d62004-12-24 06:00:11 +0000214 zlog_debug (" Malformed LSA length, quit printing");
hasso508e53e2004-05-18 18:57:06 +0000215 break;
216 }
217 }
paul718e3742002-12-13 20:15:29 +0000218
hasso508e53e2004-05-18 18:57:06 +0000219 if (p != OSPF6_MESSAGE_END (oh))
220 {
221 char buf[32];
222
223 int num = 0;
224 memset (buf, 0, sizeof (buf));
225
hassoc6487d62004-12-24 06:00:11 +0000226 zlog_debug (" Trailing garbage exists");
hasso508e53e2004-05-18 18:57:06 +0000227 while (p < OSPF6_MESSAGE_END (oh))
228 {
229 snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
230 num++;
231 if (num == 8)
232 {
hassoc6487d62004-12-24 06:00:11 +0000233 zlog_debug (" %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000234 memset (buf, 0, sizeof (buf));
235 num = 0;
236 }
237 }
238 if (num)
hassoc6487d62004-12-24 06:00:11 +0000239 zlog_debug (" %s", buf);
paul718e3742002-12-13 20:15:29 +0000240 }
241}
242
hasso508e53e2004-05-18 18:57:06 +0000243void
244ospf6_lsack_print (struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000245{
hasso508e53e2004-05-18 18:57:06 +0000246 char *p;
paul718e3742002-12-13 20:15:29 +0000247
hasso508e53e2004-05-18 18:57:06 +0000248 ospf6_header_print (oh);
249 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +0000250
hasso508e53e2004-05-18 18:57:06 +0000251 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
252 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
253 p += sizeof (struct ospf6_lsa_header))
254 ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
255
256 if (p != OSPF6_MESSAGE_END (oh))
hassoc6487d62004-12-24 06:00:11 +0000257 zlog_debug ("Trailing garbage exists");
paul718e3742002-12-13 20:15:29 +0000258}
259
Paul Jakma6ac29a52008-08-15 13:45:30 +0100260static void
hasso508e53e2004-05-18 18:57:06 +0000261ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
262 struct ospf6_interface *oi, struct ospf6_header *oh)
263{
264 struct ospf6_hello *hello;
265 struct ospf6_neighbor *on;
266 char *p;
267 int twoway = 0;
268 int neighborchange = 0;
269 int backupseen = 0;
270
hasso508e53e2004-05-18 18:57:06 +0000271 hello = (struct ospf6_hello *)
272 ((caddr_t) oh + sizeof (struct ospf6_header));
273
paul718e3742002-12-13 20:15:29 +0000274 /* HelloInterval check */
hasso508e53e2004-05-18 18:57:06 +0000275 if (ntohs (hello->hello_interval) != oi->hello_interval)
paul718e3742002-12-13 20:15:29 +0000276 {
hasso508e53e2004-05-18 18:57:06 +0000277 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000278 zlog_debug ("HelloInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000279 return;
280 }
281
282 /* RouterDeadInterval check */
hasso508e53e2004-05-18 18:57:06 +0000283 if (ntohs (hello->dead_interval) != oi->dead_interval)
paul718e3742002-12-13 20:15:29 +0000284 {
hasso508e53e2004-05-18 18:57:06 +0000285 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000286 zlog_debug ("RouterDeadInterval mismatch");
paul718e3742002-12-13 20:15:29 +0000287 return;
288 }
289
hasso508e53e2004-05-18 18:57:06 +0000290 /* E-bit check */
291 if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
292 OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
paul718e3742002-12-13 20:15:29 +0000293 {
hasso508e53e2004-05-18 18:57:06 +0000294 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000295 zlog_debug ("E-bit mismatch");
paul718e3742002-12-13 20:15:29 +0000296 return;
297 }
298
hasso508e53e2004-05-18 18:57:06 +0000299 /* Find neighbor, create if not exist */
300 on = ospf6_neighbor_lookup (oh->router_id, oi);
301 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000302 {
hasso508e53e2004-05-18 18:57:06 +0000303 on = ospf6_neighbor_create (oh->router_id, oi);
304 on->prev_drouter = on->drouter = hello->drouter;
305 on->prev_bdrouter = on->bdrouter = hello->bdrouter;
306 on->priority = hello->priority;
paul718e3742002-12-13 20:15:29 +0000307 }
308
hasso7b6ae022005-06-24 08:17:51 +0000309 /* always override neighbor's source address and ifindex */
310 on->ifindex = ntohl (hello->interface_id);
311 memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
312
paul718e3742002-12-13 20:15:29 +0000313 /* TwoWay check */
hasso508e53e2004-05-18 18:57:06 +0000314 for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
315 p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
316 p += sizeof (u_int32_t))
paul718e3742002-12-13 20:15:29 +0000317 {
hasso508e53e2004-05-18 18:57:06 +0000318 u_int32_t *router_id = (u_int32_t *) p;
319
320 if (*router_id == oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000321 twoway++;
paul718e3742002-12-13 20:15:29 +0000322 }
323
hasso508e53e2004-05-18 18:57:06 +0000324 if (p != OSPF6_MESSAGE_END (oh))
325 {
326 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000327 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000328 }
329
330 /* RouterPriority check */
331 if (on->priority != hello->priority)
332 {
333 on->priority = hello->priority;
334 neighborchange++;
335 }
336
337 /* DR check */
338 if (on->drouter != hello->drouter)
339 {
340 on->prev_drouter = on->drouter;
341 on->drouter = hello->drouter;
342 if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
343 neighborchange++;
344 }
345
346 /* BDR check */
347 if (on->bdrouter != hello->bdrouter)
348 {
349 on->prev_bdrouter = on->bdrouter;
350 on->bdrouter = hello->bdrouter;
351 if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
352 neighborchange++;
353 }
paul718e3742002-12-13 20:15:29 +0000354
355 /* BackupSeen check */
hasso508e53e2004-05-18 18:57:06 +0000356 if (oi->state == OSPF6_INTERFACE_WAITING)
paul718e3742002-12-13 20:15:29 +0000357 {
hasso508e53e2004-05-18 18:57:06 +0000358 if (hello->bdrouter == on->router_id)
paul718e3742002-12-13 20:15:29 +0000359 backupseen++;
hasso508e53e2004-05-18 18:57:06 +0000360 else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
paul718e3742002-12-13 20:15:29 +0000361 backupseen++;
362 }
363
hasso508e53e2004-05-18 18:57:06 +0000364 /* Execute neighbor events */
365 thread_execute (master, hello_received, on, 0);
366 if (twoway)
367 thread_execute (master, twoway_received, on, 0);
368 else
369 thread_execute (master, oneway_received, on, 0);
paul718e3742002-12-13 20:15:29 +0000370
hasso508e53e2004-05-18 18:57:06 +0000371 /* Schedule interface events */
paul718e3742002-12-13 20:15:29 +0000372 if (backupseen)
hasso508e53e2004-05-18 18:57:06 +0000373 thread_add_event (master, backup_seen, oi, 0);
374 if (neighborchange)
375 thread_add_event (master, neighbor_change, oi, 0);
paul718e3742002-12-13 20:15:29 +0000376}
377
hasso508e53e2004-05-18 18:57:06 +0000378static void
379ospf6_dbdesc_recv_master (struct ospf6_header *oh,
380 struct ospf6_neighbor *on)
paul718e3742002-12-13 20:15:29 +0000381{
paul718e3742002-12-13 20:15:29 +0000382 struct ospf6_dbdesc *dbdesc;
hasso508e53e2004-05-18 18:57:06 +0000383 char *p;
paul718e3742002-12-13 20:15:29 +0000384
hasso508e53e2004-05-18 18:57:06 +0000385 dbdesc = (struct ospf6_dbdesc *)
386 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +0000387
hasso508e53e2004-05-18 18:57:06 +0000388 if (on->state < OSPF6_NEIGHBOR_INIT)
paul718e3742002-12-13 20:15:29 +0000389 {
hasso508e53e2004-05-18 18:57:06 +0000390 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000391 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000392 return;
393 }
394
hasso508e53e2004-05-18 18:57:06 +0000395 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000396 {
hasso508e53e2004-05-18 18:57:06 +0000397 case OSPF6_NEIGHBOR_TWOWAY:
398 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000399 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000400 return;
401
402 case OSPF6_NEIGHBOR_INIT:
403 thread_execute (master, twoway_received, on, 0);
404 if (on->state != OSPF6_NEIGHBOR_EXSTART)
405 {
406 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000407 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000408 return;
409 }
410 /* else fall through to ExStart */
411
412 case OSPF6_NEIGHBOR_EXSTART:
413 /* if neighbor obeys us as our slave, schedule negotiation_done
414 and process LSA Headers. Otherwise, ignore this message */
415 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
416 ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
417 ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
418 {
419 /* execute NegotiationDone */
420 thread_execute (master, negotiation_done, on, 0);
421
422 /* Record neighbor options */
423 memcpy (on->options, dbdesc->options, sizeof (on->options));
424 }
425 else
426 {
427 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000428 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000429 return;
430 }
431 /* fall through to exchange */
432
433 case OSPF6_NEIGHBOR_EXCHANGE:
434 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
435 {
436 /* Duplicated DatabaseDescription is dropped by master */
437 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000438 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000439 return;
440 }
441
442 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
443 {
444 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000445 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000446 thread_add_event (master, seqnumber_mismatch, on, 0);
447 return;
448 }
449
450 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
451 {
452 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000453 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000454 thread_add_event (master, seqnumber_mismatch, on, 0);
455 return;
456 }
457
458 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
459 {
460 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000461 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000462 thread_add_event (master, seqnumber_mismatch, on, 0);
463 return;
464 }
465
466 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
467 {
468 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000469 zlog_debug ("Sequence number mismatch (%#lx expected)",
hasso508e53e2004-05-18 18:57:06 +0000470 (u_long) on->dbdesc_seqnum);
471 thread_add_event (master, seqnumber_mismatch, on, 0);
472 return;
473 }
474 break;
475
476 case OSPF6_NEIGHBOR_LOADING:
477 case OSPF6_NEIGHBOR_FULL:
478 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
479 {
480 /* Duplicated DatabaseDescription is dropped by master */
481 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000482 zlog_debug ("Duplicated dbdesc discarded by Master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000483 return;
484 }
485
486 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000487 zlog_debug ("Not duplicate dbdesc in state %s",
488 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000489 thread_add_event (master, seqnumber_mismatch, on, 0);
490 return;
491
492 default:
493 assert (0);
494 break;
495 }
496
497 /* Process LSA headers */
498 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
499 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
500 p += sizeof (struct ospf6_lsa_header))
501 {
502 struct ospf6_lsa *his, *mine;
503 struct ospf6_lsdb *lsdb = NULL;
504
505 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000506
507 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000508 zlog_debug ("%s", his->name);
hasso6452df02004-08-15 05:52:07 +0000509
510 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000511 {
hasso6452df02004-08-15 05:52:07 +0000512 case OSPF6_SCOPE_LINKLOCAL:
513 lsdb = on->ospf6_if->lsdb;
514 break;
515 case OSPF6_SCOPE_AREA:
516 lsdb = on->ospf6_if->area->lsdb;
517 break;
518 case OSPF6_SCOPE_AS:
519 lsdb = on->ospf6_if->area->ospf6->lsdb;
520 break;
521 case OSPF6_SCOPE_RESERVED:
522 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000523 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000524 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000525 continue;
526 break;
hasso508e53e2004-05-18 18:57:06 +0000527 }
528
529 if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
hasso6452df02004-08-15 05:52:07 +0000530 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000531 {
532 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000533 zlog_debug ("SeqNumMismatch (E-bit mismatch), discard");
hasso508e53e2004-05-18 18:57:06 +0000534 ospf6_lsa_delete (his);
535 thread_add_event (master, seqnumber_mismatch, on, 0);
536 return;
537 }
538
539 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
540 his->header->adv_router, lsdb);
hasso6452df02004-08-15 05:52:07 +0000541 if (mine == NULL)
hasso508e53e2004-05-18 18:57:06 +0000542 {
hasso6452df02004-08-15 05:52:07 +0000543 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000544 zlog_debug ("Add request (No database copy)");
hasso6452df02004-08-15 05:52:07 +0000545 ospf6_lsdb_add (his, on->request_list);
546 }
547 else if (ospf6_lsa_compare (his, mine) < 0)
548 {
549 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000550 zlog_debug ("Add request (Received MoreRecent)");
hasso508e53e2004-05-18 18:57:06 +0000551 ospf6_lsdb_add (his, on->request_list);
552 }
553 else
hasso6452df02004-08-15 05:52:07 +0000554 {
555 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000556 zlog_debug ("Discard (Existing MoreRecent)");
hasso6452df02004-08-15 05:52:07 +0000557 ospf6_lsa_delete (his);
558 }
hasso508e53e2004-05-18 18:57:06 +0000559 }
560
561 if (p != OSPF6_MESSAGE_END (oh))
562 {
563 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000564 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000565 }
566
567 /* Increment sequence number */
568 on->dbdesc_seqnum ++;
569
570 /* schedule send lsreq */
571 if (on->thread_send_lsreq == NULL)
572 on->thread_send_lsreq =
573 thread_add_event (master, ospf6_lsreq_send, on, 0);
574
575 THREAD_OFF (on->thread_send_dbdesc);
576
577 /* More bit check */
578 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
579 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
580 thread_add_event (master, exchange_done, on, 0);
581 else
582 on->thread_send_dbdesc =
583 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
584
585 /* save last received dbdesc */
586 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
587}
588
589static void
590ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
591 struct ospf6_neighbor *on)
592{
593 struct ospf6_dbdesc *dbdesc;
594 char *p;
595
596 dbdesc = (struct ospf6_dbdesc *)
597 ((caddr_t) oh + sizeof (struct ospf6_header));
598
599 if (on->state < OSPF6_NEIGHBOR_INIT)
600 {
601 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000602 zlog_debug ("Neighbor state less than Init, ignore");
paul718e3742002-12-13 20:15:29 +0000603 return;
604 }
605
hasso508e53e2004-05-18 18:57:06 +0000606 switch (on->state)
paul718e3742002-12-13 20:15:29 +0000607 {
hasso508e53e2004-05-18 18:57:06 +0000608 case OSPF6_NEIGHBOR_TWOWAY:
609 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000610 zlog_debug ("Neighbor state is 2-Way, ignore");
hasso508e53e2004-05-18 18:57:06 +0000611 return;
612
613 case OSPF6_NEIGHBOR_INIT:
614 thread_execute (master, twoway_received, on, 0);
615 if (on->state != OSPF6_NEIGHBOR_EXSTART)
616 {
617 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000618 zlog_debug ("Neighbor state is not ExStart, ignore");
hasso508e53e2004-05-18 18:57:06 +0000619 return;
620 }
621 /* else fall through to ExStart */
622
623 case OSPF6_NEIGHBOR_EXSTART:
624 /* If the neighbor is Master, act as Slave. Schedule negotiation_done
625 and process LSA Headers. Otherwise, ignore this message */
626 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
627 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
628 CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
629 ntohs (oh->length) == sizeof (struct ospf6_header) +
630 sizeof (struct ospf6_dbdesc))
631 {
632 /* set the master/slave bit to slave */
633 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
634
635 /* set the DD sequence number to one specified by master */
636 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
637
638 /* schedule NegotiationDone */
639 thread_execute (master, negotiation_done, on, 0);
640
641 /* Record neighbor options */
642 memcpy (on->options, dbdesc->options, sizeof (on->options));
643 }
644 else
645 {
646 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000647 zlog_debug ("Negotiation failed");
hasso508e53e2004-05-18 18:57:06 +0000648 return;
649 }
650 break;
651
652 case OSPF6_NEIGHBOR_EXCHANGE:
653 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
654 {
655 /* Duplicated DatabaseDescription causes slave to retransmit */
656 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000657 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000658 THREAD_OFF (on->thread_send_dbdesc);
659 on->thread_send_dbdesc =
660 thread_add_event (master, ospf6_dbdesc_send, on, 0);
661 return;
662 }
663
664 if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
665 {
666 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000667 zlog_debug ("Master/Slave bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000668 thread_add_event (master, seqnumber_mismatch, on, 0);
669 return;
670 }
671
672 if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
673 {
674 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000675 zlog_debug ("Initialize bit mismatch");
hasso508e53e2004-05-18 18:57:06 +0000676 thread_add_event (master, seqnumber_mismatch, on, 0);
677 return;
678 }
679
680 if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
681 {
682 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000683 zlog_debug ("Option field mismatch");
hasso508e53e2004-05-18 18:57:06 +0000684 thread_add_event (master, seqnumber_mismatch, on, 0);
685 return;
686 }
687
688 if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
689 {
690 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000691 zlog_debug ("Sequence number mismatch (%#lx expected)",
692 (u_long) on->dbdesc_seqnum + 1);
hasso508e53e2004-05-18 18:57:06 +0000693 thread_add_event (master, seqnumber_mismatch, on, 0);
694 return;
695 }
696 break;
697
698 case OSPF6_NEIGHBOR_LOADING:
699 case OSPF6_NEIGHBOR_FULL:
700 if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
701 {
702 /* Duplicated DatabaseDescription causes slave to retransmit */
703 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000704 zlog_debug ("Duplicated dbdesc causes retransmit");
hasso508e53e2004-05-18 18:57:06 +0000705 THREAD_OFF (on->thread_send_dbdesc);
706 on->thread_send_dbdesc =
707 thread_add_event (master, ospf6_dbdesc_send, on, 0);
708 return;
709 }
710
711 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000712 zlog_debug ("Not duplicate dbdesc in state %s",
713 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +0000714 thread_add_event (master, seqnumber_mismatch, on, 0);
715 return;
716
717 default:
718 assert (0);
719 break;
paul718e3742002-12-13 20:15:29 +0000720 }
721
hasso508e53e2004-05-18 18:57:06 +0000722 /* Process LSA headers */
723 for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
724 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
725 p += sizeof (struct ospf6_lsa_header))
726 {
727 struct ospf6_lsa *his, *mine;
728 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000729
hasso508e53e2004-05-18 18:57:06 +0000730 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
hasso6452df02004-08-15 05:52:07 +0000731
732 switch (OSPF6_LSA_SCOPE (his->header->type))
hasso508e53e2004-05-18 18:57:06 +0000733 {
hasso6452df02004-08-15 05:52:07 +0000734 case OSPF6_SCOPE_LINKLOCAL:
735 lsdb = on->ospf6_if->lsdb;
736 break;
737 case OSPF6_SCOPE_AREA:
738 lsdb = on->ospf6_if->area->lsdb;
739 break;
740 case OSPF6_SCOPE_AS:
741 lsdb = on->ospf6_if->area->ospf6->lsdb;
742 break;
743 case OSPF6_SCOPE_RESERVED:
744 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000745 zlog_debug ("Ignoring LSA of reserved scope");
hasso508e53e2004-05-18 18:57:06 +0000746 ospf6_lsa_delete (his);
hasso6452df02004-08-15 05:52:07 +0000747 continue;
748 break;
hasso508e53e2004-05-18 18:57:06 +0000749 }
750
hasso6452df02004-08-15 05:52:07 +0000751 if (OSPF6_LSA_SCOPE (his->header->type) == OSPF6_SCOPE_AS &&
752 IS_AREA_STUB (on->ospf6_if->area))
hasso508e53e2004-05-18 18:57:06 +0000753 {
754 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000755 zlog_debug ("E-bit mismatch with LSA Headers");
hasso508e53e2004-05-18 18:57:06 +0000756 ospf6_lsa_delete (his);
757 thread_add_event (master, seqnumber_mismatch, on, 0);
758 return;
759 }
760
761 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
762 his->header->adv_router, lsdb);
763 if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
764 {
hasso6452df02004-08-15 05:52:07 +0000765 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000766 zlog_debug ("Add request-list: %s", his->name);
hasso508e53e2004-05-18 18:57:06 +0000767 ospf6_lsdb_add (his, on->request_list);
768 }
769 else
770 ospf6_lsa_delete (his);
771 }
772
773 if (p != OSPF6_MESSAGE_END (oh))
774 {
775 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000776 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +0000777 }
778
779 /* Set sequence number to Master's */
780 on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
781
782 /* schedule send lsreq */
783 if (on->thread_send_lsreq == NULL)
784 on->thread_send_lsreq =
785 thread_add_event (master, ospf6_lsreq_send, on, 0);
786
787 THREAD_OFF (on->thread_send_dbdesc);
788 on->thread_send_dbdesc =
789 thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
790
791 /* save last received dbdesc */
792 memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
paul718e3742002-12-13 20:15:29 +0000793}
794
Paul Jakma6ac29a52008-08-15 13:45:30 +0100795static void
hasso508e53e2004-05-18 18:57:06 +0000796ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
797 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +0000798{
hasso508e53e2004-05-18 18:57:06 +0000799 struct ospf6_neighbor *on;
800 struct ospf6_dbdesc *dbdesc;
801
hasso508e53e2004-05-18 18:57:06 +0000802 on = ospf6_neighbor_lookup (oh->router_id, oi);
803 if (on == NULL)
804 {
805 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000806 zlog_debug ("Neighbor not found, ignore");
hasso508e53e2004-05-18 18:57:06 +0000807 return;
808 }
809
hasso508e53e2004-05-18 18:57:06 +0000810 dbdesc = (struct ospf6_dbdesc *)
811 ((caddr_t) oh + sizeof (struct ospf6_header));
812
813 /* Interface MTU check */
Dmitrij Tejblumd42306d2011-04-22 19:27:54 +0400814 if (!oi->mtu_ignore && ntohs (dbdesc->ifmtu) != oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +0000815 {
816 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000817 zlog_debug ("I/F MTU mismatch");
hasso508e53e2004-05-18 18:57:06 +0000818 return;
819 }
820
821 if (dbdesc->reserved1 || dbdesc->reserved2)
822 {
823 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000824 zlog_debug ("Non-0 reserved field in %s's DbDesc, correct",
825 on->name);
hasso508e53e2004-05-18 18:57:06 +0000826 dbdesc->reserved1 = 0;
827 dbdesc->reserved2 = 0;
828 }
829
830 if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
831 ospf6_dbdesc_recv_master (oh, on);
832 else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
833 ospf6_dbdesc_recv_slave (oh, on);
834 else
835 {
836 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000837 zlog_debug ("Can't decide which is master, ignore");
hasso508e53e2004-05-18 18:57:06 +0000838 }
839}
840
Paul Jakma6ac29a52008-08-15 13:45:30 +0100841static void
hasso508e53e2004-05-18 18:57:06 +0000842ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
843 struct ospf6_interface *oi, struct ospf6_header *oh)
844{
845 struct ospf6_neighbor *on;
846 char *p;
847 struct ospf6_lsreq_entry *e;
hasso508e53e2004-05-18 18:57:06 +0000848 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000849 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000850
hasso508e53e2004-05-18 18:57:06 +0000851 on = ospf6_neighbor_lookup (oh->router_id, oi);
852 if (on == NULL)
paul718e3742002-12-13 20:15:29 +0000853 {
hasso508e53e2004-05-18 18:57:06 +0000854 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000855 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +0000856 return;
857 }
858
hasso508e53e2004-05-18 18:57:06 +0000859 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
860 on->state != OSPF6_NEIGHBOR_LOADING &&
861 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000862 {
hasso508e53e2004-05-18 18:57:06 +0000863 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000864 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +0000865 return;
866 }
867
hasso508e53e2004-05-18 18:57:06 +0000868 /* Process each request */
869 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
870 p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
871 p += sizeof (struct ospf6_lsreq_entry))
paul718e3742002-12-13 20:15:29 +0000872 {
hasso508e53e2004-05-18 18:57:06 +0000873 e = (struct ospf6_lsreq_entry *) p;
hasso6452df02004-08-15 05:52:07 +0000874
875 switch (OSPF6_LSA_SCOPE (e->type))
876 {
877 case OSPF6_SCOPE_LINKLOCAL:
878 lsdb = on->ospf6_if->lsdb;
879 break;
880 case OSPF6_SCOPE_AREA:
881 lsdb = on->ospf6_if->area->lsdb;
882 break;
883 case OSPF6_SCOPE_AS:
884 lsdb = on->ospf6_if->area->ospf6->lsdb;
885 break;
886 default:
887 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000888 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +0000889 continue;
890 break;
891 }
paul718e3742002-12-13 20:15:29 +0000892
hasso508e53e2004-05-18 18:57:06 +0000893 /* Find database copy */
894 lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
895 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000896 {
hasso508e53e2004-05-18 18:57:06 +0000897 char id[16], adv_router[16];
898 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
899 {
900 inet_ntop (AF_INET, &e->id, id, sizeof (id));
901 inet_ntop (AF_INET, &e->adv_router, adv_router,
902 sizeof (adv_router));
hassoc6487d62004-12-24 06:00:11 +0000903 zlog_debug ("Can't find requested [%s Id:%s Adv:%s]",
904 ospf6_lstype_name (e->type), id, adv_router);
hasso508e53e2004-05-18 18:57:06 +0000905 }
906 thread_add_event (master, bad_lsreq, on, 0);
paul718e3742002-12-13 20:15:29 +0000907 return;
908 }
909
hasso508e53e2004-05-18 18:57:06 +0000910 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
paul718e3742002-12-13 20:15:29 +0000911 }
912
hasso508e53e2004-05-18 18:57:06 +0000913 if (p != OSPF6_MESSAGE_END (oh))
paul718e3742002-12-13 20:15:29 +0000914 {
hasso508e53e2004-05-18 18:57:06 +0000915 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +0000916 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +0000917 }
918
hasso508e53e2004-05-18 18:57:06 +0000919 /* schedule send lsupdate */
920 THREAD_OFF (on->thread_send_lsupdate);
921 on->thread_send_lsupdate =
922 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
paul718e3742002-12-13 20:15:29 +0000923}
924
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +0400925/* Verify, that the specified memory area contains exactly N valid IPv6
926 prefixes as specified by RFC5340, A.4.1. */
927static unsigned
928ospf6_prefixes_examin
929(
930 struct ospf6_prefix *current, /* start of buffer */
931 unsigned length,
932 const u_int32_t req_num_pfxs /* always compared with the actual number of prefixes */
933)
934{
935 u_char requested_pfx_bytes;
936 u_int32_t real_num_pfxs = 0;
937
938 while (length)
939 {
940 if (length < OSPF6_PREFIX_MIN_SIZE)
941 {
942 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
943 zlog_debug ("%s: undersized IPv6 prefix header", __func__);
944 return MSG_NG;
945 }
946 /* safe to look deeper */
947 if (current->prefix_length > IPV6_MAX_BITLEN)
948 {
949 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
950 zlog_debug ("%s: invalid PrefixLength (%u bits)", __func__, current->prefix_length);
951 return MSG_NG;
952 }
953 /* covers both fixed- and variable-sized fields */
954 requested_pfx_bytes = OSPF6_PREFIX_MIN_SIZE + OSPF6_PREFIX_SPACE (current->prefix_length);
955 if (requested_pfx_bytes > length)
956 {
957 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
958 zlog_debug ("%s: undersized IPv6 prefix", __func__);
959 return MSG_NG;
960 }
961 /* next prefix */
962 length -= requested_pfx_bytes;
963 current = (struct ospf6_prefix *) ((caddr_t) current + requested_pfx_bytes);
964 real_num_pfxs++;
965 }
966 if (real_num_pfxs != req_num_pfxs)
967 {
968 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
969 zlog_debug ("%s: IPv6 prefix number mismatch (%u required, %u real)",
970 __func__, req_num_pfxs, real_num_pfxs);
971 return MSG_NG;
972 }
973 return MSG_OK;
974}
975
976/* Verify an LSA to have a valid length and dispatch further (where
977 appropriate) to check if the contents, including nested IPv6 prefixes,
978 is properly sized/aligned within the LSA. Note that this function gets
979 LSA type in network byte order, uses in host byte order and passes to
980 ospf6_lstype_name() in network byte order again. */
981static unsigned
982ospf6_lsa_examin (struct ospf6_lsa_header *lsah, const u_int16_t lsalen, const u_char headeronly)
983{
984 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
985 struct ospf6_as_external_lsa *as_external_lsa;
986 struct ospf6_link_lsa *link_lsa;
987 unsigned exp_length;
988 u_int8_t ltindex;
989 u_int16_t lsatype;
990
991 /* In case an additional minimum length constraint is defined for current
992 LSA type, make sure that this constraint is met. */
993 lsatype = ntohs (lsah->type);
994 ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
995 if
996 (
997 ltindex < OSPF6_LSTYPE_SIZE &&
998 ospf6_lsa_minlen[ltindex] &&
999 lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE
1000 )
1001 {
1002 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1003 zlog_debug ("%s: undersized (%u B) LSA", __func__, lsalen);
1004 return MSG_NG;
1005 }
1006 switch (lsatype)
1007 {
1008 case OSPF6_LSTYPE_ROUTER:
1009 /* RFC5340 A.4.3, LSA header + OSPF6_ROUTER_LSA_MIN_SIZE bytes followed
1010 by N>=0 interface descriptions. */
1011 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE) % OSPF6_ROUTER_LSDESC_FIX_SIZE)
1012 {
1013 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1014 zlog_debug ("%s: interface description alignment error", __func__);
1015 return MSG_NG;
1016 }
1017 break;
1018 case OSPF6_LSTYPE_NETWORK:
1019 /* RFC5340 A.4.4, LSA header + OSPF6_NETWORK_LSA_MIN_SIZE bytes
1020 followed by N>=0 attached router descriptions. */
1021 if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_NETWORK_LSA_MIN_SIZE) % OSPF6_NETWORK_LSDESC_FIX_SIZE)
1022 {
1023 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1024 zlog_debug ("%s: router description alignment error", __func__);
1025 return MSG_NG;
1026 }
1027 break;
1028 case OSPF6_LSTYPE_INTER_PREFIX:
1029 /* RFC5340 A.4.5, LSA header + OSPF6_INTER_PREFIX_LSA_MIN_SIZE bytes
1030 followed by 3-4 fields of a single IPv6 prefix. */
1031 if (headeronly)
1032 break;
1033 return ospf6_prefixes_examin
1034 (
1035 (struct ospf6_prefix *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_PREFIX_LSA_MIN_SIZE),
1036 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
1037 1
1038 );
1039 case OSPF6_LSTYPE_INTER_ROUTER:
1040 /* RFC5340 A.4.6, fixed-size LSA. */
1041 if (lsalen > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE)
1042 {
1043 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1044 zlog_debug ("%s: oversized (%u B) LSA", __func__, lsalen);
1045 return MSG_NG;
1046 }
1047 break;
1048 case OSPF6_LSTYPE_AS_EXTERNAL: /* RFC5340 A.4.7, same as A.4.8. */
1049 case OSPF6_LSTYPE_TYPE_7:
1050 /* RFC5340 A.4.8, LSA header + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE bytes
1051 followed by 3-4 fields of IPv6 prefix and 3 conditional LSA fields:
1052 16 bytes of forwarding address, 4 bytes of external route tag,
1053 4 bytes of referenced link state ID. */
1054 if (headeronly)
1055 break;
1056 as_external_lsa = (struct ospf6_as_external_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1057 exp_length = OSPF6_LSA_HEADER_SIZE + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE;
1058 /* To find out if the last optional field (Referenced Link State ID) is
1059 assumed in this LSA, we need to access fixed fields of the IPv6
1060 prefix before ospf6_prefix_examin() confirms its sizing. */
1061 if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen)
1062 {
1063 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1064 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1065 return MSG_NG;
1066 }
1067 /* forwarding address */
1068 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
1069 exp_length += 16;
1070 /* external route tag */
1071 if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
1072 exp_length += 4;
1073 /* referenced link state ID */
1074 if (as_external_lsa->prefix.u._prefix_referenced_lstype)
1075 exp_length += 4;
1076 /* All the fixed-size fields (mandatory and optional) must fit. I.e.,
1077 this check does not include any IPv6 prefix fields. */
1078 if (exp_length > lsalen)
1079 {
1080 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1081 zlog_debug ("%s: undersized (%u B) LSA header", __func__, lsalen);
1082 return MSG_NG;
1083 }
1084 /* The last call completely covers the remainder (IPv6 prefix). */
1085 return ospf6_prefixes_examin
1086 (
1087 (struct ospf6_prefix *) ((caddr_t) as_external_lsa + OSPF6_AS_EXTERNAL_LSA_MIN_SIZE),
1088 lsalen - exp_length,
1089 1
1090 );
1091 case OSPF6_LSTYPE_LINK:
1092 /* RFC5340 A.4.9, LSA header + OSPF6_LINK_LSA_MIN_SIZE bytes followed
1093 by N>=0 IPv6 prefix blocks (with N declared beforehand). */
1094 if (headeronly)
1095 break;
1096 link_lsa = (struct ospf6_link_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1097 return ospf6_prefixes_examin
1098 (
1099 (struct ospf6_prefix *) ((caddr_t) link_lsa + OSPF6_LINK_LSA_MIN_SIZE),
1100 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_LINK_LSA_MIN_SIZE,
1101 ntohl (link_lsa->prefix_num) /* 32 bits */
1102 );
1103 case OSPF6_LSTYPE_INTRA_PREFIX:
1104 /* RFC5340 A.4.10, LSA header + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE bytes
1105 followed by N>=0 IPv6 prefixes (with N declared beforehand). */
1106 if (headeronly)
1107 break;
1108 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1109 return ospf6_prefixes_examin
1110 (
1111 (struct ospf6_prefix *) ((caddr_t) intra_prefix_lsa + OSPF6_INTRA_PREFIX_LSA_MIN_SIZE),
1112 lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
1113 ntohs (intra_prefix_lsa->prefix_num) /* 16 bits */
1114 );
1115 }
1116 /* No additional validation is possible for unknown LSA types, which are
1117 themselves valid in OPSFv3, hence the default decision is to accept. */
1118 return MSG_OK;
1119}
1120
1121/* Verify if the provided input buffer is a valid sequence of LSAs. This
1122 includes verification of LSA blocks length/alignment and dispatching
1123 of deeper-level checks. */
1124static unsigned
1125ospf6_lsaseq_examin
1126(
1127 struct ospf6_lsa_header *lsah, /* start of buffered data */
1128 size_t length,
1129 const u_char headeronly,
1130 /* When declared_num_lsas is not 0, compare it to the real number of LSAs
1131 and treat the difference as an error. */
1132 const u_int32_t declared_num_lsas
1133)
1134{
1135 u_int32_t counted_lsas = 0;
1136
1137 while (length)
1138 {
1139 u_int16_t lsalen;
1140 if (length < OSPF6_LSA_HEADER_SIZE)
1141 {
1142 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1143 zlog_debug ("%s: undersized (%u B) trailing (#%u) LSA header",
1144 __func__, length, counted_lsas);
1145 return MSG_NG;
1146 }
1147 /* save on ntohs() calls here and in the LSA validator */
1148 lsalen = OSPF6_LSA_SIZE (lsah);
1149 if (lsalen < OSPF6_LSA_HEADER_SIZE)
1150 {
1151 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1152 zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
1153 __func__, counted_lsas, lsalen);
1154 return MSG_NG;
1155 }
1156 if (headeronly)
1157 {
1158 /* less checks here and in ospf6_lsa_examin() */
1159 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 1))
1160 {
1161 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1162 zlog_debug ("%s: anomaly in header-only %s LSA #%u", __func__,
1163 ospf6_lstype_name (lsah->type), counted_lsas);
1164 return MSG_NG;
1165 }
1166 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + OSPF6_LSA_HEADER_SIZE);
1167 length -= OSPF6_LSA_HEADER_SIZE;
1168 }
1169 else
1170 {
1171 /* make sure the input buffer is deep enough before further checks */
1172 if (lsalen > length)
1173 {
1174 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1175 zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %u B",
1176 __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length);
1177 return MSG_NG;
1178 }
1179 if (MSG_OK != ospf6_lsa_examin (lsah, lsalen, 0))
1180 {
1181 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1182 zlog_debug ("%s: anomaly in %s LSA #%u", __func__,
1183 ospf6_lstype_name (lsah->type), counted_lsas);
1184 return MSG_NG;
1185 }
1186 lsah = (struct ospf6_lsa_header *) ((caddr_t) lsah + lsalen);
1187 length -= lsalen;
1188 }
1189 counted_lsas++;
1190 }
1191
1192 if (declared_num_lsas && counted_lsas != declared_num_lsas)
1193 {
1194 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1195 zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
1196 __func__, declared_num_lsas, counted_lsas);
1197 return MSG_NG;
1198 }
1199 return MSG_OK;
1200}
1201
1202/* Verify a complete OSPF packet for proper sizing/alignment. */
1203static unsigned
1204ospf6_packet_examin (struct ospf6_header *oh, const unsigned bytesonwire)
1205{
1206 struct ospf6_lsupdate *lsupd;
1207 unsigned test;
1208
1209 /* length, 1st approximation */
1210 if (bytesonwire < OSPF6_HEADER_SIZE)
1211 {
1212 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1213 zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
1214 return MSG_NG;
1215 }
1216 /* Now it is safe to access header fields. */
1217 if (bytesonwire != ntohs (oh->length))
1218 {
1219 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1220 zlog_debug ("%s: packet length error (%u real, %u declared)",
1221 __func__, bytesonwire, ntohs (oh->length));
1222 return MSG_NG;
1223 }
1224 /* version check */
1225 if (oh->version != OSPFV3_VERSION)
1226 {
1227 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1228 zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
1229 return MSG_NG;
1230 }
1231 /* length, 2nd approximation */
1232 if
1233 (
1234 oh->type < OSPF6_MESSAGE_TYPE_ALL &&
1235 ospf6_packet_minlen[oh->type] &&
1236 bytesonwire < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]
1237 )
1238 {
1239 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1240 zlog_debug ("%s: undersized (%u B) %s packet", __func__,
1241 bytesonwire, ospf6_message_type_str[oh->type]);
1242 return MSG_NG;
1243 }
1244 /* type-specific deeper validation */
1245 switch (oh->type)
1246 {
1247 case OSPF6_MESSAGE_TYPE_HELLO:
1248 /* RFC5340 A.3.2, packet header + OSPF6_HELLO_MIN_SIZE bytes followed
1249 by N>=0 router-IDs. */
1250 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE) % 4)
1251 return MSG_OK;
1252 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1253 zlog_debug ("%s: alignment error in %s packet",
1254 __func__, ospf6_message_type_str[oh->type]);
1255 return MSG_NG;
1256 case OSPF6_MESSAGE_TYPE_DBDESC:
1257 /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed
1258 by N>=0 header-only LSAs. */
1259 test = ospf6_lsaseq_examin
1260 (
1261 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_DB_DESC_MIN_SIZE),
1262 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_DB_DESC_MIN_SIZE,
1263 1,
1264 0
1265 );
1266 break;
1267 case OSPF6_MESSAGE_TYPE_LSREQ:
1268 /* RFC5340 A.3.4, packet header + N>=0 LS description blocks. */
1269 if (0 == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE) % OSPF6_LSREQ_LSDESC_FIX_SIZE)
1270 return MSG_OK;
1271 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1272 zlog_debug ("%s: alignment error in %s packet",
1273 __func__, ospf6_message_type_str[oh->type]);
1274 return MSG_NG;
1275 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1276 /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed
1277 by N>=0 full LSAs (with N declared beforehand). */
1278 lsupd = (struct ospf6_lsupdate *) ((caddr_t) oh + OSPF6_HEADER_SIZE);
1279 test = ospf6_lsaseq_examin
1280 (
1281 (struct ospf6_lsa_header *) ((caddr_t) lsupd + OSPF6_LS_UPD_MIN_SIZE),
1282 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_UPD_MIN_SIZE,
1283 0,
1284 ntohl (lsupd->lsa_number) /* 32 bits */
1285 );
1286 break;
1287 case OSPF6_MESSAGE_TYPE_LSACK:
1288 /* RFC5340 A.3.6, packet header + N>=0 header-only LSAs. */
1289 test = ospf6_lsaseq_examin
1290 (
1291 (struct ospf6_lsa_header *) ((caddr_t) oh + OSPF6_HEADER_SIZE + OSPF6_LS_ACK_MIN_SIZE),
1292 bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_ACK_MIN_SIZE,
1293 1,
1294 0
1295 );
1296 break;
1297 default:
1298 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1299 zlog_debug ("%s: invalid (%u) message type", __func__, oh->type);
1300 return MSG_NG;
1301 }
1302 if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1303 zlog_debug ("%s: anomaly in %s packet", __func__, ospf6_message_type_str[oh->type]);
1304 return test;
1305}
1306
1307/* Verify particular fields of otherwise correct received OSPF packet to
1308 meet the requirements of RFC. */
1309static int
1310ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, const unsigned bytesonwire)
1311{
1312 char buf[2][INET_ADDRSTRLEN];
1313
1314 if (MSG_OK != ospf6_packet_examin (oh, bytesonwire))
1315 return MSG_NG;
1316
1317 /* Area-ID check */
1318 if (oh->area_id != oi->area->area_id)
1319 {
1320 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1321 {
1322 if (oh->area_id == BACKBONE_AREA_ID)
1323 zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
1324 else
1325 zlog_debug
1326 (
1327 "%s: Area-ID mismatch (my %s, rcvd %s)", __func__,
1328 inet_ntop (AF_INET, &oi->area->area_id, buf[0], INET_ADDRSTRLEN),
1329 inet_ntop (AF_INET, &oh->area_id, buf[1], INET_ADDRSTRLEN)
1330 );
1331 }
1332 return MSG_NG;
1333 }
1334
1335 /* Instance-ID check */
1336 if (oh->instance_id != oi->instance_id)
1337 {
1338 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1339 zlog_debug ("%s: Instance-ID mismatch (my %u, rcvd %u)", __func__, oi->instance_id, oh->instance_id);
1340 return MSG_NG;
1341 }
1342
1343 /* Router-ID check */
1344 if (oh->router_id == oi->area->ospf6->router_id)
1345 {
1346 zlog_warn ("%s: Duplicate Router-ID (%s)", __func__, inet_ntop (AF_INET, &oh->router_id, buf[0], INET_ADDRSTRLEN));
1347 return MSG_NG;
1348 }
1349 return MSG_OK;
1350}
1351
Paul Jakma6ac29a52008-08-15 13:45:30 +01001352static void
hasso508e53e2004-05-18 18:57:06 +00001353ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
1354 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001355{
hasso508e53e2004-05-18 18:57:06 +00001356 struct ospf6_neighbor *on;
paul718e3742002-12-13 20:15:29 +00001357 struct ospf6_lsupdate *lsupdate;
hasso508e53e2004-05-18 18:57:06 +00001358 unsigned long num;
1359 char *p;
paul718e3742002-12-13 20:15:29 +00001360
hasso508e53e2004-05-18 18:57:06 +00001361 on = ospf6_neighbor_lookup (oh->router_id, oi);
1362 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001363 {
hasso508e53e2004-05-18 18:57:06 +00001364 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001365 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001366 return;
1367 }
1368
hasso508e53e2004-05-18 18:57:06 +00001369 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1370 on->state != OSPF6_NEIGHBOR_LOADING &&
1371 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001372 {
hasso508e53e2004-05-18 18:57:06 +00001373 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001374 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001375 return;
1376 }
1377
hasso508e53e2004-05-18 18:57:06 +00001378 lsupdate = (struct ospf6_lsupdate *)
1379 ((caddr_t) oh + sizeof (struct ospf6_header));
paul718e3742002-12-13 20:15:29 +00001380
hasso508e53e2004-05-18 18:57:06 +00001381 num = ntohl (lsupdate->lsa_number);
paul718e3742002-12-13 20:15:29 +00001382
hasso508e53e2004-05-18 18:57:06 +00001383 /* Process LSAs */
1384 for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
1385 p < OSPF6_MESSAGE_END (oh) &&
1386 p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
1387 p += OSPF6_LSA_SIZE (p))
1388 {
1389 if (num == 0)
1390 break;
1391 if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
1392 {
1393 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001394 zlog_debug ("Malformed LSA length, quit processing");
hasso508e53e2004-05-18 18:57:06 +00001395 break;
1396 }
1397
hasso6452df02004-08-15 05:52:07 +00001398 ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p);
hasso508e53e2004-05-18 18:57:06 +00001399 num--;
1400 }
1401
1402 if (num != 0)
1403 {
1404 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001405 zlog_debug ("Malformed LSA number or LSA length");
hasso508e53e2004-05-18 18:57:06 +00001406 }
1407 if (p != OSPF6_MESSAGE_END (oh))
1408 {
1409 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001410 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001411 }
paul718e3742002-12-13 20:15:29 +00001412
1413 /* RFC2328 Section 10.9: When the neighbor responds to these requests
1414 with the proper Link State Update packet(s), the Link state request
1415 list is truncated and a new Link State Request packet is sent. */
paul718e3742002-12-13 20:15:29 +00001416 /* send new Link State Request packet if this LS Update packet
hasso508e53e2004-05-18 18:57:06 +00001417 can be recognized as a response to our previous LS Request */
1418 if (! IN6_IS_ADDR_MULTICAST (dst) &&
1419 (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
1420 on->state == OSPF6_NEIGHBOR_LOADING))
1421 {
1422 THREAD_OFF (on->thread_send_lsreq);
1423 on->thread_send_lsreq =
1424 thread_add_event (master, ospf6_lsreq_send, on, 0);
1425 }
paul718e3742002-12-13 20:15:29 +00001426}
1427
Paul Jakma6ac29a52008-08-15 13:45:30 +01001428static void
hasso508e53e2004-05-18 18:57:06 +00001429ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
1430 struct ospf6_interface *oi, struct ospf6_header *oh)
paul718e3742002-12-13 20:15:29 +00001431{
hasso508e53e2004-05-18 18:57:06 +00001432 struct ospf6_neighbor *on;
1433 char *p;
1434 struct ospf6_lsa *his, *mine;
1435 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +00001436
hasso508e53e2004-05-18 18:57:06 +00001437 assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
paul718e3742002-12-13 20:15:29 +00001438
hasso508e53e2004-05-18 18:57:06 +00001439 on = ospf6_neighbor_lookup (oh->router_id, oi);
1440 if (on == NULL)
paul718e3742002-12-13 20:15:29 +00001441 {
hasso508e53e2004-05-18 18:57:06 +00001442 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001443 zlog_debug ("Neighbor not found, ignore");
paul718e3742002-12-13 20:15:29 +00001444 return;
1445 }
1446
hasso508e53e2004-05-18 18:57:06 +00001447 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1448 on->state != OSPF6_NEIGHBOR_LOADING &&
1449 on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +00001450 {
hasso508e53e2004-05-18 18:57:06 +00001451 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001452 zlog_debug ("Neighbor state less than Exchange, ignore");
paul718e3742002-12-13 20:15:29 +00001453 return;
1454 }
1455
hasso508e53e2004-05-18 18:57:06 +00001456 for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
1457 p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
1458 p += sizeof (struct ospf6_lsa_header))
paul718e3742002-12-13 20:15:29 +00001459 {
hasso508e53e2004-05-18 18:57:06 +00001460 his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
paul718e3742002-12-13 20:15:29 +00001461
hasso6452df02004-08-15 05:52:07 +00001462 switch (OSPF6_LSA_SCOPE (his->header->type))
1463 {
1464 case OSPF6_SCOPE_LINKLOCAL:
1465 lsdb = on->ospf6_if->lsdb;
1466 break;
1467 case OSPF6_SCOPE_AREA:
1468 lsdb = on->ospf6_if->area->lsdb;
1469 break;
1470 case OSPF6_SCOPE_AS:
1471 lsdb = on->ospf6_if->area->ospf6->lsdb;
1472 break;
1473 case OSPF6_SCOPE_RESERVED:
1474 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001475 zlog_debug ("Ignoring LSA of reserved scope");
hasso6452df02004-08-15 05:52:07 +00001476 ospf6_lsa_delete (his);
1477 continue;
1478 break;
1479 }
1480
1481 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001482 zlog_debug ("%s acknowledged by %s", his->name, on->name);
hasso508e53e2004-05-18 18:57:06 +00001483
1484 /* Find database copy */
1485 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1486 his->header->adv_router, lsdb);
1487 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001488 {
hasso508e53e2004-05-18 18:57:06 +00001489 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001490 zlog_debug ("No database copy");
hasso508e53e2004-05-18 18:57:06 +00001491 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001492 continue;
1493 }
1494
hasso508e53e2004-05-18 18:57:06 +00001495 /* Check if the LSA is on his retrans-list */
1496 mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
1497 his->header->adv_router, on->retrans_list);
1498 if (mine == NULL)
paul718e3742002-12-13 20:15:29 +00001499 {
hasso508e53e2004-05-18 18:57:06 +00001500 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001501 zlog_debug ("Not on %s's retrans-list", on->name);
hasso508e53e2004-05-18 18:57:06 +00001502 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001503 continue;
1504 }
1505
hasso508e53e2004-05-18 18:57:06 +00001506 if (ospf6_lsa_compare (his, mine) != 0)
paul718e3742002-12-13 20:15:29 +00001507 {
hasso508e53e2004-05-18 18:57:06 +00001508 /* Log this questionable acknowledgement,
paul718e3742002-12-13 20:15:29 +00001509 and examine the next one. */
hasso508e53e2004-05-18 18:57:06 +00001510 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001511 zlog_debug ("Questionable acknowledgement");
hasso508e53e2004-05-18 18:57:06 +00001512 ospf6_lsa_delete (his);
1513 continue;
paul718e3742002-12-13 20:15:29 +00001514 }
1515
hasso6452df02004-08-15 05:52:07 +00001516 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001517 zlog_debug ("Acknowledged, remove from %s's retrans-list",
1518 on->name);
hasso508e53e2004-05-18 18:57:06 +00001519
Paul Jakma932bf192006-05-15 10:42:24 +00001520 ospf6_decrement_retrans_count (mine);
hasso508e53e2004-05-18 18:57:06 +00001521 if (OSPF6_LSA_IS_MAXAGE (mine))
1522 ospf6_maxage_remove (on->ospf6_if->area->ospf6);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001523 ospf6_lsdb_remove (mine, on->retrans_list);
hasso508e53e2004-05-18 18:57:06 +00001524 ospf6_lsa_delete (his);
paul718e3742002-12-13 20:15:29 +00001525 }
1526
hasso508e53e2004-05-18 18:57:06 +00001527 if (p != OSPF6_MESSAGE_END (oh))
1528 {
1529 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
hassoc6487d62004-12-24 06:00:11 +00001530 zlog_debug ("Trailing garbage ignored");
hasso508e53e2004-05-18 18:57:06 +00001531 }
paul718e3742002-12-13 20:15:29 +00001532}
1533
Paul Jakma6ac29a52008-08-15 13:45:30 +01001534static u_char *recvbuf = NULL;
1535static u_char *sendbuf = NULL;
1536static unsigned int iobuflen = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001537
1538int
paul0c083ee2004-10-10 12:54:58 +00001539ospf6_iobuf_size (unsigned int size)
hasso3b4cd3a2004-05-18 19:28:32 +00001540{
Paul Jakma6ac29a52008-08-15 13:45:30 +01001541 u_char *recvnew, *sendnew;
hasso3b4cd3a2004-05-18 19:28:32 +00001542
1543 if (size <= iobuflen)
1544 return iobuflen;
1545
1546 recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1547 sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size);
1548 if (recvnew == NULL || sendnew == NULL)
1549 {
hassob596c712004-07-09 18:33:43 +00001550 if (recvnew)
1551 XFREE (MTYPE_OSPF6_MESSAGE, recvnew);
1552 if (sendnew)
1553 XFREE (MTYPE_OSPF6_MESSAGE, sendnew);
hassoc6487d62004-12-24 06:00:11 +00001554 zlog_debug ("Could not allocate I/O buffer of size %d.", size);
hasso3b4cd3a2004-05-18 19:28:32 +00001555 return iobuflen;
1556 }
1557
1558 if (recvbuf)
1559 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1560 if (sendbuf)
1561 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1562 recvbuf = recvnew;
1563 sendbuf = sendnew;
1564 iobuflen = size;
1565
1566 return iobuflen;
1567}
paul718e3742002-12-13 20:15:29 +00001568
Tom Goffae2254a2010-11-10 13:01:41 -08001569void
1570ospf6_message_terminate (void)
1571{
1572 if (recvbuf)
1573 {
1574 XFREE (MTYPE_OSPF6_MESSAGE, recvbuf);
1575 recvbuf = NULL;
1576 }
1577
1578 if (sendbuf)
1579 {
1580 XFREE (MTYPE_OSPF6_MESSAGE, sendbuf);
1581 sendbuf = NULL;
1582 }
1583
1584 iobuflen = 0;
1585}
1586
paul718e3742002-12-13 20:15:29 +00001587int
1588ospf6_receive (struct thread *thread)
1589{
paul0c083ee2004-10-10 12:54:58 +00001590 int sockfd;
1591 unsigned int len;
hasso508e53e2004-05-18 18:57:06 +00001592 char srcname[64], dstname[64];
paul718e3742002-12-13 20:15:29 +00001593 struct in6_addr src, dst;
1594 unsigned int ifindex;
hasso508e53e2004-05-18 18:57:06 +00001595 struct iovec iovector[2];
1596 struct ospf6_interface *oi;
1597 struct ospf6_header *oh;
paul718e3742002-12-13 20:15:29 +00001598
1599 /* add next read thread */
hasso508e53e2004-05-18 18:57:06 +00001600 sockfd = THREAD_FD (thread);
paul718e3742002-12-13 20:15:29 +00001601 thread_add_read (master, ospf6_receive, NULL, sockfd);
1602
1603 /* initialize */
Paul Jakmacf1ce252006-05-15 10:46:07 +00001604 memset (&src, 0, sizeof (src));
1605 memset (&dst, 0, sizeof (dst));
1606 ifindex = 0;
hasso3b4cd3a2004-05-18 19:28:32 +00001607 memset (recvbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001608 iovector[0].iov_base = recvbuf;
hasso3b4cd3a2004-05-18 19:28:32 +00001609 iovector[0].iov_len = iobuflen;
hasso508e53e2004-05-18 18:57:06 +00001610 iovector[1].iov_base = NULL;
1611 iovector[1].iov_len = 0;
paul718e3742002-12-13 20:15:29 +00001612
1613 /* receive message */
hasso508e53e2004-05-18 18:57:06 +00001614 len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
hasso3b4cd3a2004-05-18 19:28:32 +00001615 if (len > iobuflen)
paul718e3742002-12-13 20:15:29 +00001616 {
hasso508e53e2004-05-18 18:57:06 +00001617 zlog_err ("Excess message read");
1618 return 0;
1619 }
paul718e3742002-12-13 20:15:29 +00001620
hasso508e53e2004-05-18 18:57:06 +00001621 oi = ospf6_interface_lookup_by_ifindex (ifindex);
1622 if (oi == NULL || oi->area == NULL)
1623 {
hassoc6487d62004-12-24 06:00:11 +00001624 zlog_debug ("Message received on disabled interface");
hasso508e53e2004-05-18 18:57:06 +00001625 return 0;
1626 }
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001627 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
1628 {
1629 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
1630 zlog_debug ("%s: Ignore message on passive interface %s",
1631 __func__, oi->interface->name);
1632 return 0;
1633 }
hasso508e53e2004-05-18 18:57:06 +00001634
1635 oh = (struct ospf6_header *) recvbuf;
Denis Ovsienkoabc7ef42011-09-26 13:18:51 +04001636 if (ospf6_rxpacket_examin (oi, oh, len) != MSG_OK)
1637 return 0;
1638
1639 /* Being here means, that no sizing/alignment issues were detected in
1640 the input packet. This renders the additional checks performed below
1641 and also in the type-specific dispatching functions a dead code,
1642 which can be dismissed in a cleanup-focused review round later. */
hasso508e53e2004-05-18 18:57:06 +00001643
1644 /* Log */
1645 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
1646 {
1647 inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1648 inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
hassoc6487d62004-12-24 06:00:11 +00001649 zlog_debug ("%s received 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 if (len != ntohs (oh->length))
hassoc6487d62004-12-24 06:00:11 +00001654 zlog_debug ("Message length does not match actually received: %d", len);
hasso508e53e2004-05-18 18:57:06 +00001655
1656 switch (oh->type)
1657 {
1658 case OSPF6_MESSAGE_TYPE_HELLO:
1659 ospf6_hello_print (oh);
1660 break;
1661 case OSPF6_MESSAGE_TYPE_DBDESC:
1662 ospf6_dbdesc_print (oh);
1663 break;
1664 case OSPF6_MESSAGE_TYPE_LSREQ:
1665 ospf6_lsreq_print (oh);
1666 break;
1667 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1668 ospf6_lsupdate_print (oh);
1669 break;
1670 case OSPF6_MESSAGE_TYPE_LSACK:
1671 ospf6_lsack_print (oh);
1672 break;
1673 default:
hassoc6487d62004-12-24 06:00:11 +00001674 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001675 break;
1676 }
1677 }
1678
hasso508e53e2004-05-18 18:57:06 +00001679 switch (oh->type)
1680 {
1681 case OSPF6_MESSAGE_TYPE_HELLO:
1682 ospf6_hello_recv (&src, &dst, oi, oh);
1683 break;
1684
1685 case OSPF6_MESSAGE_TYPE_DBDESC:
1686 ospf6_dbdesc_recv (&src, &dst, oi, oh);
1687 break;
1688
1689 case OSPF6_MESSAGE_TYPE_LSREQ:
1690 ospf6_lsreq_recv (&src, &dst, oi, oh);
1691 break;
1692
1693 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1694 ospf6_lsupdate_recv (&src, &dst, oi, oh);
1695 break;
1696
1697 case OSPF6_MESSAGE_TYPE_LSACK:
1698 ospf6_lsack_recv (&src, &dst, oi, oh);
1699 break;
1700
1701 default:
1702 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hassoc6487d62004-12-24 06:00:11 +00001703 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001704 break;
1705 }
1706
1707 return 0;
1708}
1709
Paul Jakma6ac29a52008-08-15 13:45:30 +01001710static void
hasso508e53e2004-05-18 18:57:06 +00001711ospf6_send (struct in6_addr *src, struct in6_addr *dst,
1712 struct ospf6_interface *oi, struct ospf6_header *oh)
1713{
1714 int len;
1715 char srcname[64], dstname[64];
1716 struct iovec iovector[2];
1717
1718 /* initialize */
1719 iovector[0].iov_base = (caddr_t) oh;
1720 iovector[0].iov_len = ntohs (oh->length);
1721 iovector[1].iov_base = NULL;
1722 iovector[1].iov_len = 0;
1723
1724 /* fill OSPF header */
1725 oh->version = OSPFV3_VERSION;
1726 /* message type must be set before */
1727 /* message length must be set before */
1728 oh->router_id = oi->area->ospf6->router_id;
1729 oh->area_id = oi->area->area_id;
1730 /* checksum is calculated by kernel */
1731 oh->instance_id = oi->instance_id;
1732 oh->reserved = 0;
1733
1734 /* Log */
1735 if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
1736 {
1737 inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
1738 if (src)
1739 inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1740 else
1741 memset (srcname, 0, sizeof (srcname));
hassoc6487d62004-12-24 06:00:11 +00001742 zlog_debug ("%s send on %s",
hasso508e53e2004-05-18 18:57:06 +00001743 OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
hassoc6487d62004-12-24 06:00:11 +00001744 zlog_debug (" src: %s", srcname);
1745 zlog_debug (" dst: %s", dstname);
hasso508e53e2004-05-18 18:57:06 +00001746
1747 switch (oh->type)
1748 {
1749 case OSPF6_MESSAGE_TYPE_HELLO:
1750 ospf6_hello_print (oh);
1751 break;
1752 case OSPF6_MESSAGE_TYPE_DBDESC:
1753 ospf6_dbdesc_print (oh);
1754 break;
1755 case OSPF6_MESSAGE_TYPE_LSREQ:
1756 ospf6_lsreq_print (oh);
1757 break;
1758 case OSPF6_MESSAGE_TYPE_LSUPDATE:
1759 ospf6_lsupdate_print (oh);
1760 break;
1761 case OSPF6_MESSAGE_TYPE_LSACK:
1762 ospf6_lsack_print (oh);
1763 break;
1764 default:
hassoc6487d62004-12-24 06:00:11 +00001765 zlog_debug ("Unknown message");
hasso508e53e2004-05-18 18:57:06 +00001766 assert (0);
1767 break;
1768 }
1769 }
1770
1771 /* send message */
1772 len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
1773 if (len != ntohs (oh->length))
1774 zlog_err ("Could not send entire message");
1775}
1776
1777int
1778ospf6_hello_send (struct thread *thread)
1779{
1780 struct ospf6_interface *oi;
1781 struct ospf6_header *oh;
1782 struct ospf6_hello *hello;
paul0c083ee2004-10-10 12:54:58 +00001783 u_char *p;
paul1eb8ef22005-04-07 07:30:20 +00001784 struct listnode *node, *nnode;
hasso508e53e2004-05-18 18:57:06 +00001785 struct ospf6_neighbor *on;
1786
1787 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1788 oi->thread_send_hello = (struct thread *) NULL;
1789
1790 if (oi->state <= OSPF6_INTERFACE_DOWN)
1791 {
1792 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001793 zlog_debug ("Unable to send Hello on down interface %s",
hasso508e53e2004-05-18 18:57:06 +00001794 oi->interface->name);
1795 return 0;
1796 }
1797
1798 /* set next thread */
1799 oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
1800 oi, oi->hello_interval);
1801
hasso3b4cd3a2004-05-18 19:28:32 +00001802 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001803 oh = (struct ospf6_header *) sendbuf;
1804 hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
1805
1806 hello->interface_id = htonl (oi->interface->ifindex);
1807 hello->priority = oi->priority;
1808 hello->options[0] = oi->area->options[0];
1809 hello->options[1] = oi->area->options[1];
1810 hello->options[2] = oi->area->options[2];
1811 hello->hello_interval = htons (oi->hello_interval);
1812 hello->dead_interval = htons (oi->dead_interval);
1813 hello->drouter = oi->drouter;
1814 hello->bdrouter = oi->bdrouter;
1815
Paul Jakma6ac29a52008-08-15 13:45:30 +01001816 p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello));
hasso508e53e2004-05-18 18:57:06 +00001817
paul1eb8ef22005-04-07 07:30:20 +00001818 for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
hasso508e53e2004-05-18 18:57:06 +00001819 {
hasso508e53e2004-05-18 18:57:06 +00001820 if (on->state < OSPF6_NEIGHBOR_INIT)
1821 continue;
1822
1823 if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
1824 {
1825 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
hassoc6487d62004-12-24 06:00:11 +00001826 zlog_debug ("sending Hello message: exceeds I/F MTU");
hasso508e53e2004-05-18 18:57:06 +00001827 break;
1828 }
1829
1830 memcpy (p, &on->router_id, sizeof (u_int32_t));
1831 p += sizeof (u_int32_t);
1832 }
1833
1834 oh->type = OSPF6_MESSAGE_TYPE_HELLO;
1835 oh->length = htons (p - sendbuf);
1836
1837 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
1838 return 0;
1839}
1840
1841int
1842ospf6_dbdesc_send (struct thread *thread)
1843{
1844 struct ospf6_neighbor *on;
1845 struct ospf6_header *oh;
1846 struct ospf6_dbdesc *dbdesc;
paul0c083ee2004-10-10 12:54:58 +00001847 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001848 struct ospf6_lsa *lsa;
1849
1850 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1851 on->thread_send_dbdesc = (struct thread *) NULL;
1852
1853 if (on->state < OSPF6_NEIGHBOR_EXSTART)
1854 {
1855 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
hassoc6487d62004-12-24 06:00:11 +00001856 zlog_debug ("Quit to send DbDesc to neighbor %s state %s",
1857 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001858 return 0;
1859 }
1860
1861 /* set next thread if master */
1862 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
1863 on->thread_send_dbdesc =
1864 thread_add_timer (master, ospf6_dbdesc_send, on,
1865 on->ospf6_if->rxmt_interval);
1866
hasso3b4cd3a2004-05-18 19:28:32 +00001867 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001868 oh = (struct ospf6_header *) sendbuf;
1869 dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
1870 sizeof (struct ospf6_header));
1871
1872 /* if this is initial one, initialize sequence number for DbDesc */
1873 if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1874 {
1875 struct timeval tv;
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001876 if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
hasso508e53e2004-05-18 18:57:06 +00001877 tv.tv_sec = 1;
1878 on->dbdesc_seqnum = tv.tv_sec;
1879 }
1880
1881 dbdesc->options[0] = on->ospf6_if->area->options[0];
1882 dbdesc->options[1] = on->ospf6_if->area->options[1];
1883 dbdesc->options[2] = on->ospf6_if->area->options[2];
1884 dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
1885 dbdesc->bits = on->dbdesc_bits;
1886 dbdesc->seqnum = htonl (on->dbdesc_seqnum);
1887
1888 /* if this is not initial one, set LSA headers in dbdesc */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001889 p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
hasso508e53e2004-05-18 18:57:06 +00001890 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
1891 {
1892 for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
1893 lsa = ospf6_lsdb_next (lsa))
1894 {
1895 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
1896
1897 /* MTU check */
1898 if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
1899 on->ospf6_if->ifmtu)
1900 {
1901 ospf6_lsa_unlock (lsa);
1902 break;
1903 }
1904 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
1905 p += sizeof (struct ospf6_lsa_header);
1906 }
1907 }
1908
1909 oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
1910 oh->length = htons (p - sendbuf);
1911
1912 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
1913 on->ospf6_if, oh);
1914 return 0;
1915}
1916
1917int
1918ospf6_dbdesc_send_newone (struct thread *thread)
1919{
1920 struct ospf6_neighbor *on;
1921 struct ospf6_lsa *lsa;
1922 unsigned int size = 0;
1923
1924 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
hasso508e53e2004-05-18 18:57:06 +00001925 ospf6_lsdb_remove_all (on->dbdesc_list);
1926
1927 /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
1928 so that ospf6_send_dbdesc () can send those LSAs */
1929 size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
1930 for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
1931 lsa = ospf6_lsdb_next (lsa))
1932 {
1933 if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
1934 {
1935 ospf6_lsa_unlock (lsa);
1936 break;
1937 }
1938
hasso508e53e2004-05-18 18:57:06 +00001939 ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
1940 ospf6_lsdb_remove (lsa, on->summary_list);
1941 size += sizeof (struct ospf6_lsa_header);
1942 }
1943
1944 if (on->summary_list->count == 0)
1945 UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
1946
1947 /* If slave, More bit check must be done here */
1948 if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
1949 ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
1950 ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
1951 thread_add_event (master, exchange_done, on, 0);
1952
1953 thread_execute (master, ospf6_dbdesc_send, on, 0);
1954 return 0;
1955}
1956
1957int
1958ospf6_lsreq_send (struct thread *thread)
1959{
1960 struct ospf6_neighbor *on;
1961 struct ospf6_header *oh;
1962 struct ospf6_lsreq_entry *e;
paul0c083ee2004-10-10 12:54:58 +00001963 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00001964 struct ospf6_lsa *lsa;
1965
1966 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
1967 on->thread_send_lsreq = (struct thread *) NULL;
1968
1969 /* LSReq will be sent only in ExStart or Loading */
1970 if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
1971 on->state != OSPF6_NEIGHBOR_LOADING)
1972 {
1973 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
hassoc6487d62004-12-24 06:00:11 +00001974 zlog_debug ("Quit to send LSReq to neighbor %s state %s",
1975 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00001976 return 0;
1977 }
1978
1979 /* schedule loading_done if request list is empty */
1980 if (on->request_list->count == 0)
1981 {
1982 thread_add_event (master, loading_done, on, 0);
1983 return 0;
1984 }
1985
1986 /* set next thread */
1987 on->thread_send_lsreq =
1988 thread_add_timer (master, ospf6_lsreq_send, on,
1989 on->ospf6_if->rxmt_interval);
1990
hasso3b4cd3a2004-05-18 19:28:32 +00001991 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00001992 oh = (struct ospf6_header *) sendbuf;
1993
1994 /* set Request entries in lsreq */
Paul Jakma6ac29a52008-08-15 13:45:30 +01001995 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00001996 for (lsa = ospf6_lsdb_head (on->request_list); lsa;
1997 lsa = ospf6_lsdb_next (lsa))
1998 {
1999 /* MTU check */
2000 if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
2001 {
2002 ospf6_lsa_unlock (lsa);
2003 break;
2004 }
2005
2006 e = (struct ospf6_lsreq_entry *) p;
2007 e->type = lsa->header->type;
2008 e->id = lsa->header->id;
2009 e->adv_router = lsa->header->adv_router;
2010 p += sizeof (struct ospf6_lsreq_entry);
2011 }
2012
2013 oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
2014 oh->length = htons (p - sendbuf);
2015
2016 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2017 on->ospf6_if, oh);
2018 return 0;
2019}
2020
2021int
2022ospf6_lsupdate_send_neighbor (struct thread *thread)
2023{
2024 struct ospf6_neighbor *on;
2025 struct ospf6_header *oh;
2026 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002027 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002028 int num;
2029 struct ospf6_lsa *lsa;
2030
2031 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2032 on->thread_send_lsupdate = (struct thread *) NULL;
2033
hasso6452df02004-08-15 05:52:07 +00002034 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002035 zlog_debug ("LSUpdate to neighbor %s", on->name);
hasso6452df02004-08-15 05:52:07 +00002036
hasso508e53e2004-05-18 18:57:06 +00002037 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2038 {
2039 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002040 zlog_debug ("Quit to send (neighbor state %s)",
2041 ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002042 return 0;
2043 }
2044
2045 /* if we have nothing to send, return */
2046 if (on->lsupdate_list->count == 0 &&
2047 on->retrans_list->count == 0)
hasso6452df02004-08-15 05:52:07 +00002048 {
2049 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002050 zlog_debug ("Quit to send (nothing to send)");
hasso6452df02004-08-15 05:52:07 +00002051 return 0;
2052 }
hasso508e53e2004-05-18 18:57:06 +00002053
hasso3b4cd3a2004-05-18 19:28:32 +00002054 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002055 oh = (struct ospf6_header *) sendbuf;
2056 lsupdate = (struct ospf6_lsupdate *)
2057 ((caddr_t) oh + sizeof (struct ospf6_header));
2058
Paul Jakma6ac29a52008-08-15 13:45:30 +01002059 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002060 num = 0;
2061
2062 /* lsupdate_list lists those LSA which doesn't need to be
2063 retransmitted. remove those from the list */
2064 for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
2065 lsa = ospf6_lsdb_next (lsa))
2066 {
2067 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002068 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
2069 > on->ospf6_if->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00002070 {
2071 ospf6_lsa_unlock (lsa);
2072 break;
2073 }
2074
hasso508e53e2004-05-18 18:57:06 +00002075 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2076 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2077 p += OSPF6_LSA_SIZE (lsa->header);
2078 num++;
2079
2080 assert (lsa->lock == 2);
2081 ospf6_lsdb_remove (lsa, on->lsupdate_list);
2082 }
2083
2084 for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
2085 lsa = ospf6_lsdb_next (lsa))
2086 {
2087 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002088 if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
2089 > on->ospf6_if->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00002090 {
2091 ospf6_lsa_unlock (lsa);
2092 break;
2093 }
2094
hasso508e53e2004-05-18 18:57:06 +00002095 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2096 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2097 p += OSPF6_LSA_SIZE (lsa->header);
2098 num++;
2099 }
2100
2101 lsupdate->lsa_number = htonl (num);
2102
2103 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2104 oh->length = htons (p - sendbuf);
2105
2106 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2107 on->ospf6_if, oh);
2108
2109 if (on->lsupdate_list->count != 0 ||
2110 on->retrans_list->count != 0)
2111 {
2112 if (on->lsupdate_list->count != 0)
2113 on->thread_send_lsupdate =
2114 thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
2115 else
2116 on->thread_send_lsupdate =
2117 thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
2118 on->ospf6_if->rxmt_interval);
2119 }
2120
2121 return 0;
2122}
2123
2124int
2125ospf6_lsupdate_send_interface (struct thread *thread)
2126{
2127 struct ospf6_interface *oi;
2128 struct ospf6_header *oh;
2129 struct ospf6_lsupdate *lsupdate;
paul0c083ee2004-10-10 12:54:58 +00002130 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002131 int num;
2132 struct ospf6_lsa *lsa;
2133
2134 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2135 oi->thread_send_lsupdate = (struct thread *) NULL;
2136
2137 if (oi->state <= OSPF6_INTERFACE_WAITING)
2138 {
2139 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
hassoc6487d62004-12-24 06:00:11 +00002140 zlog_debug ("Quit to send LSUpdate to interface %s state %s",
2141 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002142 return 0;
2143 }
2144
2145 /* if we have nothing to send, return */
2146 if (oi->lsupdate_list->count == 0)
2147 return 0;
2148
hasso3b4cd3a2004-05-18 19:28:32 +00002149 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002150 oh = (struct ospf6_header *) sendbuf;
2151 lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
2152 sizeof (struct ospf6_header));
2153
Paul Jakma6ac29a52008-08-15 13:45:30 +01002154 p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
hasso508e53e2004-05-18 18:57:06 +00002155 num = 0;
2156
2157 for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
2158 lsa = ospf6_lsdb_next (lsa))
2159 {
2160 /* MTU check */
paul0c083ee2004-10-10 12:54:58 +00002161 if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
2162 > oi->ifmtu)
hasso508e53e2004-05-18 18:57:06 +00002163 {
2164 ospf6_lsa_unlock (lsa);
2165 break;
2166 }
2167
hasso508e53e2004-05-18 18:57:06 +00002168 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2169 memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
2170 p += OSPF6_LSA_SIZE (lsa->header);
2171 num++;
2172
2173 assert (lsa->lock == 2);
2174 ospf6_lsdb_remove (lsa, oi->lsupdate_list);
2175 }
2176
2177 lsupdate->lsa_number = htonl (num);
2178
2179 oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2180 oh->length = htons (p - sendbuf);
2181
2182 if (oi->state == OSPF6_INTERFACE_DR ||
2183 oi->state == OSPF6_INTERFACE_BDR)
2184 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2185 else
2186 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2187
2188 if (oi->lsupdate_list->count > 0)
2189 {
2190 oi->thread_send_lsupdate =
2191 thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
2192 }
2193
2194 return 0;
2195}
2196
2197int
2198ospf6_lsack_send_neighbor (struct thread *thread)
2199{
2200 struct ospf6_neighbor *on;
2201 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002202 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002203 struct ospf6_lsa *lsa;
2204
2205 on = (struct ospf6_neighbor *) THREAD_ARG (thread);
2206 on->thread_send_lsack = (struct thread *) NULL;
2207
2208 if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
2209 {
2210 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002211 zlog_debug ("Quit to send LSAck to neighbor %s state %s",
2212 on->name, ospf6_neighbor_state_str[on->state]);
hasso508e53e2004-05-18 18:57:06 +00002213 return 0;
2214 }
2215
2216 /* if we have nothing to send, return */
2217 if (on->lsack_list->count == 0)
2218 return 0;
2219
hasso3b4cd3a2004-05-18 19:28:32 +00002220 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002221 oh = (struct ospf6_header *) sendbuf;
2222
Paul Jakma6ac29a52008-08-15 13:45:30 +01002223 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002224
2225 for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
2226 lsa = ospf6_lsdb_next (lsa))
2227 {
2228 /* MTU check */
2229 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
2230 {
2231 /* if we run out of packet size/space here,
2232 better to try again soon. */
2233 THREAD_OFF (on->thread_send_lsack);
2234 on->thread_send_lsack =
2235 thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
2236
2237 ospf6_lsa_unlock (lsa);
2238 break;
2239 }
2240
2241 ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
2242 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2243 p += sizeof (struct ospf6_lsa_header);
2244
2245 assert (lsa->lock == 2);
2246 ospf6_lsdb_remove (lsa, on->lsack_list);
2247 }
2248
2249 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2250 oh->length = htons (p - sendbuf);
2251
2252 ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
2253 on->ospf6_if, oh);
2254 return 0;
2255}
2256
2257int
2258ospf6_lsack_send_interface (struct thread *thread)
2259{
2260 struct ospf6_interface *oi;
2261 struct ospf6_header *oh;
paul0c083ee2004-10-10 12:54:58 +00002262 u_char *p;
hasso508e53e2004-05-18 18:57:06 +00002263 struct ospf6_lsa *lsa;
2264
2265 oi = (struct ospf6_interface *) THREAD_ARG (thread);
2266 oi->thread_send_lsack = (struct thread *) NULL;
2267
2268 if (oi->state <= OSPF6_INTERFACE_WAITING)
2269 {
2270 if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
hassoc6487d62004-12-24 06:00:11 +00002271 zlog_debug ("Quit to send LSAck to interface %s state %s",
2272 oi->interface->name, ospf6_interface_state_str[oi->state]);
hasso508e53e2004-05-18 18:57:06 +00002273 return 0;
2274 }
2275
2276 /* if we have nothing to send, return */
2277 if (oi->lsack_list->count == 0)
2278 return 0;
2279
hasso3b4cd3a2004-05-18 19:28:32 +00002280 memset (sendbuf, 0, iobuflen);
hasso508e53e2004-05-18 18:57:06 +00002281 oh = (struct ospf6_header *) sendbuf;
2282
Paul Jakma6ac29a52008-08-15 13:45:30 +01002283 p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
hasso508e53e2004-05-18 18:57:06 +00002284
2285 for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
2286 lsa = ospf6_lsdb_next (lsa))
2287 {
2288 /* MTU check */
2289 if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
2290 {
2291 /* if we run out of packet size/space here,
2292 better to try again soon. */
2293 THREAD_OFF (oi->thread_send_lsack);
2294 oi->thread_send_lsack =
2295 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2296
2297 ospf6_lsa_unlock (lsa);
2298 break;
2299 }
2300
2301 ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
2302 memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
2303 p += sizeof (struct ospf6_lsa_header);
2304
2305 assert (lsa->lock == 2);
2306 ospf6_lsdb_remove (lsa, oi->lsack_list);
2307 }
2308
2309 oh->type = OSPF6_MESSAGE_TYPE_LSACK;
2310 oh->length = htons (p - sendbuf);
2311
2312 if (oi->state == OSPF6_INTERFACE_DR ||
2313 oi->state == OSPF6_INTERFACE_BDR)
2314 ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
2315 else
2316 ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
2317
2318 if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
2319 {
2320 oi->thread_send_lsack =
2321 thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
2322 }
paul718e3742002-12-13 20:15:29 +00002323
2324 return 0;
2325}
2326
2327
hasso508e53e2004-05-18 18:57:06 +00002328/* Commands */
2329DEFUN (debug_ospf6_message,
2330 debug_ospf6_message_cmd,
2331 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2332 DEBUG_STR
2333 OSPF6_STR
2334 "Debug OSPFv3 message\n"
2335 "Debug Unknown message\n"
2336 "Debug Hello message\n"
2337 "Debug Database Description message\n"
2338 "Debug Link State Request message\n"
2339 "Debug Link State Update message\n"
2340 "Debug Link State Acknowledgement message\n"
2341 "Debug All message\n"
2342 )
paul718e3742002-12-13 20:15:29 +00002343{
hasso508e53e2004-05-18 18:57:06 +00002344 unsigned char level = 0;
2345 int type = 0;
paul718e3742002-12-13 20:15:29 +00002346 int i;
2347
hasso508e53e2004-05-18 18:57:06 +00002348 assert (argc > 0);
paul718e3742002-12-13 20:15:29 +00002349
hasso508e53e2004-05-18 18:57:06 +00002350 /* check type */
2351 if (! strncmp (argv[0], "u", 1))
2352 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2353 else if (! strncmp (argv[0], "h", 1))
2354 type = OSPF6_MESSAGE_TYPE_HELLO;
2355 else if (! strncmp (argv[0], "d", 1))
2356 type = OSPF6_MESSAGE_TYPE_DBDESC;
2357 else if (! strncmp (argv[0], "lsr", 3))
2358 type = OSPF6_MESSAGE_TYPE_LSREQ;
2359 else if (! strncmp (argv[0], "lsu", 3))
2360 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2361 else if (! strncmp (argv[0], "lsa", 3))
2362 type = OSPF6_MESSAGE_TYPE_LSACK;
2363 else if (! strncmp (argv[0], "a", 1))
2364 type = OSPF6_MESSAGE_TYPE_ALL;
paul718e3742002-12-13 20:15:29 +00002365
hasso508e53e2004-05-18 18:57:06 +00002366 if (argc == 1)
2367 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2368 else if (! strncmp (argv[1], "s", 1))
2369 level = OSPF6_DEBUG_MESSAGE_SEND;
2370 else if (! strncmp (argv[1], "r", 1))
2371 level = OSPF6_DEBUG_MESSAGE_RECV;
paul718e3742002-12-13 20:15:29 +00002372
hasso508e53e2004-05-18 18:57:06 +00002373 if (type == OSPF6_MESSAGE_TYPE_ALL)
paul718e3742002-12-13 20:15:29 +00002374 {
hasso508e53e2004-05-18 18:57:06 +00002375 for (i = 0; i < 6; i++)
2376 OSPF6_DEBUG_MESSAGE_ON (i, level);
2377 }
2378 else
2379 OSPF6_DEBUG_MESSAGE_ON (type, level);
2380
2381 return CMD_SUCCESS;
2382}
2383
2384ALIAS (debug_ospf6_message,
2385 debug_ospf6_message_sendrecv_cmd,
2386 "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
2387 DEBUG_STR
2388 OSPF6_STR
2389 "Debug OSPFv3 message\n"
2390 "Debug Unknown message\n"
2391 "Debug Hello message\n"
2392 "Debug Database Description message\n"
2393 "Debug Link State Request message\n"
2394 "Debug Link State Update message\n"
2395 "Debug Link State Acknowledgement message\n"
2396 "Debug All message\n"
2397 "Debug only sending message\n"
2398 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002399 )
hasso508e53e2004-05-18 18:57:06 +00002400
2401
2402DEFUN (no_debug_ospf6_message,
2403 no_debug_ospf6_message_cmd,
2404 "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
2405 NO_STR
2406 DEBUG_STR
2407 OSPF6_STR
2408 "Debug OSPFv3 message\n"
2409 "Debug Unknown message\n"
2410 "Debug Hello message\n"
2411 "Debug Database Description message\n"
2412 "Debug Link State Request message\n"
2413 "Debug Link State Update message\n"
2414 "Debug Link State Acknowledgement message\n"
2415 "Debug All message\n"
2416 )
2417{
2418 unsigned char level = 0;
2419 int type = 0;
2420 int i;
2421
2422 assert (argc > 0);
2423
2424 /* check type */
2425 if (! strncmp (argv[0], "u", 1))
2426 type = OSPF6_MESSAGE_TYPE_UNKNOWN;
2427 else if (! strncmp (argv[0], "h", 1))
2428 type = OSPF6_MESSAGE_TYPE_HELLO;
2429 else if (! strncmp (argv[0], "d", 1))
2430 type = OSPF6_MESSAGE_TYPE_DBDESC;
2431 else if (! strncmp (argv[0], "lsr", 3))
2432 type = OSPF6_MESSAGE_TYPE_LSREQ;
2433 else if (! strncmp (argv[0], "lsu", 3))
2434 type = OSPF6_MESSAGE_TYPE_LSUPDATE;
2435 else if (! strncmp (argv[0], "lsa", 3))
2436 type = OSPF6_MESSAGE_TYPE_LSACK;
2437 else if (! strncmp (argv[0], "a", 1))
2438 type = OSPF6_MESSAGE_TYPE_ALL;
2439
2440 if (argc == 1)
2441 level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
2442 else if (! strncmp (argv[1], "s", 1))
2443 level = OSPF6_DEBUG_MESSAGE_SEND;
2444 else if (! strncmp (argv[1], "r", 1))
2445 level = OSPF6_DEBUG_MESSAGE_RECV;
2446
2447 if (type == OSPF6_MESSAGE_TYPE_ALL)
2448 {
2449 for (i = 0; i < 6; i++)
2450 OSPF6_DEBUG_MESSAGE_OFF (i, level);
2451 }
2452 else
2453 OSPF6_DEBUG_MESSAGE_OFF (type, level);
2454
2455 return CMD_SUCCESS;
2456}
2457
2458ALIAS (no_debug_ospf6_message,
2459 no_debug_ospf6_message_sendrecv_cmd,
hasso049207c2004-08-04 20:02:13 +00002460 "no debug ospf6 message "
2461 "(unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
hasso508e53e2004-05-18 18:57:06 +00002462 NO_STR
2463 DEBUG_STR
2464 OSPF6_STR
2465 "Debug OSPFv3 message\n"
2466 "Debug Unknown message\n"
2467 "Debug Hello message\n"
2468 "Debug Database Description message\n"
2469 "Debug Link State Request message\n"
2470 "Debug Link State Update message\n"
2471 "Debug Link State Acknowledgement message\n"
2472 "Debug All message\n"
2473 "Debug only sending message\n"
2474 "Debug only receiving message\n"
Paul Jakma6ac29a52008-08-15 13:45:30 +01002475 )
hasso508e53e2004-05-18 18:57:06 +00002476
2477int
2478config_write_ospf6_debug_message (struct vty *vty)
2479{
paul0c083ee2004-10-10 12:54:58 +00002480 const char *type_str[] = {"unknown", "hello", "dbdesc",
hasso508e53e2004-05-18 18:57:06 +00002481 "lsreq", "lsupdate", "lsack"};
2482 unsigned char s = 0, r = 0;
2483 int i;
2484
2485 for (i = 0; i < 6; i++)
2486 {
2487 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2488 s |= 1 << i;
2489 if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2490 r |= 1 << i;
2491 }
2492
2493 if (s == 0x3f && r == 0x3f)
2494 {
hasso049207c2004-08-04 20:02:13 +00002495 vty_out (vty, "debug ospf6 message all%s", VNL);
paul718e3742002-12-13 20:15:29 +00002496 return 0;
2497 }
2498
hasso508e53e2004-05-18 18:57:06 +00002499 if (s == 0x3f && r == 0)
paul718e3742002-12-13 20:15:29 +00002500 {
hasso049207c2004-08-04 20:02:13 +00002501 vty_out (vty, "debug ospf6 message all send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002502 return 0;
2503 }
2504 else if (s == 0 && r == 0x3f)
2505 {
hasso049207c2004-08-04 20:02:13 +00002506 vty_out (vty, "debug ospf6 message all recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002507 return 0;
paul718e3742002-12-13 20:15:29 +00002508 }
2509
hasso508e53e2004-05-18 18:57:06 +00002510 /* Unknown message is logged by default */
2511 if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
2512 ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002513 vty_out (vty, "no debug ospf6 message unknown%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002514 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
hasso049207c2004-08-04 20:02:13 +00002515 vty_out (vty, "no debug ospf6 message unknown send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00002516 else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
hasso049207c2004-08-04 20:02:13 +00002517 vty_out (vty, "no debug ospf6 message unknown recv%s", VNL);
paul718e3742002-12-13 20:15:29 +00002518
hasso508e53e2004-05-18 18:57:06 +00002519 for (i = 1; i < 6; i++)
2520 {
2521 if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
2522 IS_OSPF6_DEBUG_MESSAGE (i, RECV))
hasso049207c2004-08-04 20:02:13 +00002523 vty_out (vty, "debug ospf6 message %s%s", type_str[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00002524 else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
2525 vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002526 VNL);
hasso508e53e2004-05-18 18:57:06 +00002527 else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
2528 vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
hasso049207c2004-08-04 20:02:13 +00002529 VNL);
hasso508e53e2004-05-18 18:57:06 +00002530 }
paul718e3742002-12-13 20:15:29 +00002531
2532 return 0;
2533}
2534
paul718e3742002-12-13 20:15:29 +00002535void
Paul Jakma6ac29a52008-08-15 13:45:30 +01002536install_element_ospf6_debug_message (void)
paul718e3742002-12-13 20:15:29 +00002537{
hasso508e53e2004-05-18 18:57:06 +00002538 install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
2539 install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
2540 install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
2541 install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
2542 install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
2543 install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
2544 install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
2545 install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
paul718e3742002-12-13 20:15:29 +00002546}
2547
paul718e3742002-12-13 20:15:29 +00002548