1/*
2 * Copyright (C) 1999 Yasuhiro Ohara
3 *
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
22#include "ospf6d.h"
23
24int
25is_ospf6_message_dump (u_char type)
26{
27  if (type > OSPF6_MESSAGE_TYPE_LSACK)
28    type = OSPF6_MESSAGE_TYPE_UNKNOWN;
29
30  switch (type)
31    {
32      case OSPF6_MESSAGE_TYPE_UNKNOWN:
33          return 1;
34        break;
35      case OSPF6_MESSAGE_TYPE_HELLO:
36        if (IS_OSPF6_DUMP_HELLO)
37          return 1;
38        break;
39      case OSPF6_MESSAGE_TYPE_DBDESC:
40        if (IS_OSPF6_DUMP_DBDESC)
41          return 1;
42        break;
43      case OSPF6_MESSAGE_TYPE_LSREQ:
44        if (IS_OSPF6_DUMP_LSREQ)
45          return 1;
46        break;
47      case OSPF6_MESSAGE_TYPE_LSUPDATE:
48        if (IS_OSPF6_DUMP_LSUPDATE)
49          return 1;
50        break;
51      case OSPF6_MESSAGE_TYPE_LSACK:
52        if (IS_OSPF6_DUMP_LSACK)
53          return 1;
54        break;
55      default:
56        break;
57    }
58  return 0;
59}
60#define IS_OSPF6_DUMP_MESSAGE(x) (is_ospf6_message_dump(x))
61
62char *ospf6_message_type_string[] =
63{
64  "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck", NULL
65};
66
67void
68ospf6_message_log_lsa_header (struct ospf6_lsa_header *lsa_header)
69{
70  char buf_id[16], buf_router[16], typebuf[32];
71
72  inet_ntop (AF_INET, &lsa_header->advrtr, buf_router, sizeof (buf_router));
73  inet_ntop (AF_INET, &lsa_header->ls_id, buf_id, sizeof (buf_id));
74  zlog_info ("   [%s ID=%s Adv=%s]",
75             ospf6_lsa_type_string (lsa_header->type, typebuf,
76                                    sizeof (typebuf)),
77             buf_id, buf_router);
78  zlog_info ("    Age=%hu SeqNum=%#lx Cksum=%#hx Len=%hu",
79             ntohs (lsa_header->age), (u_long)ntohl (lsa_header->seqnum),
80             ntohs (lsa_header->checksum), ntohs (lsa_header->length));
81}
82
83static void
84ospf6_message_log_unknown (struct iovec *message)
85{
86  zlog_info ("Message:  Unknown");
87}
88
89static void
90ospf6_message_log_hello (struct iovec *message)
91{
92  struct ospf6_header *ospf6_header;
93  u_int16_t length_left;
94  struct ospf6_hello *hello;
95  char dr_str[16], bdr_str[16];
96  char *start, *end, *current;
97
98  /* calculate length */
99  ospf6_header = (struct ospf6_header *) message[0].iov_base;
100  length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
101  length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
102                 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
103
104  hello = (struct ospf6_hello *) message[1].iov_base;
105
106  inet_ntop (AF_INET, &hello->dr, dr_str, sizeof (dr_str));
107  inet_ntop (AF_INET, &hello->bdr, bdr_str, sizeof (bdr_str));
108
109  zlog_info ("    IFID:%ld Priority:%d Option:%s",
110             (u_long)ntohl (hello->interface_id), hello->rtr_pri, "xxx");
111  zlog_info ("    HelloInterval:%hu Deadinterval:%hu",
112             ntohs (hello->hello_interval),
113             ntohs (hello->router_dead_interval));
114  zlog_info ("    DR:%s BDR:%s", dr_str, bdr_str);
115
116  start = (char *) (hello + 1);
117  if (start >= (char *) message[1].iov_base + message[1].iov_len)
118    start = message[2].iov_base;
119  end = (char *) start + (length_left - sizeof (struct ospf6_hello));
120
121  for (current = start; current < end; current += sizeof (u_int32_t))
122    {
123      char neighbor[16];
124      inet_ntop (AF_INET, current, neighbor, sizeof (neighbor));
125      zlog_info ("    Neighbor: %s", neighbor);
126    }
127}
128
129static void
130ospf6_message_log_dbdesc (struct iovec *message)
131{
132  struct ospf6_header *ospf6_header;
133  u_int16_t length_left;
134  struct ospf6_dbdesc *dbdesc;
135  int i;
136  char buffer[16];
137  struct ospf6_lsa_header *lsa_header;
138
139  /* calculate length */
140  ospf6_header = (struct ospf6_header *) message[0].iov_base;
141  length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
142  length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
143                 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
144
145  dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
146  ospf6_options_string (dbdesc->options, buffer, sizeof (buffer));
147
148  zlog_info ("    Option:%s IFMTU:%hu", buffer, ntohs (dbdesc->ifmtu));
149  zlog_info ("    Bits:%s%s%s SeqNum:%#lx",
150             (DD_IS_IBIT_SET (dbdesc->bits) ? "I" : "-"),
151             (DD_IS_MBIT_SET (dbdesc->bits) ? "M" : "-"),
152             (DD_IS_MSBIT_SET (dbdesc->bits) ? "m" : "s"),
153             (u_long)ntohl (dbdesc->seqnum));
154
155  for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
156       (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + message[1].iov_len) &&
157       (char *)(lsa_header + 1) <= (char *)dbdesc + length_left;
158       lsa_header++)
159    ospf6_message_log_lsa_header (lsa_header);
160
161  length_left -= message[1].iov_len;
162  for (i = 2; message[i].iov_base; i++)
163    {
164      for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
165           (char *)(lsa_header + 1) <= (char *) (message[i].iov_base +
166                                                 message[i].iov_len) &&
167           (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left);
168           lsa_header++)
169        ospf6_message_log_lsa_header (lsa_header);
170      length_left -= message[i].iov_len;
171    }
172}
173
174static void
175ospf6_message_log_lsreq (struct iovec *message)
176{
177  struct ospf6_header *ospf6_header;
178  u_int16_t length_left;
179  int i;
180  struct ospf6_lsreq *lsreq;
181  char buf_router[16], buf_id[16], buf_type[16];
182
183  /* calculate length */
184  ospf6_header = (struct ospf6_header *) message[0].iov_base;
185  length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
186  length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
187                 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
188
189  for (i = 1; message[i].iov_base; i++)
190    {
191      for (lsreq = (struct ospf6_lsreq *) message[i].iov_base;
192           (char *)(lsreq + 1) <= (char *) (message[i].iov_base + message[i].iov_len) &&
193           (char *)(lsreq + 1) <= (char *) (message[i].iov_base + length_left);
194           lsreq++)
195        {
196          inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router));
197          inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id));
198          zlog_info ("    [%s ID=%s Adv=%s]",
199                     ospf6_lsa_type_string (lsreq->type, buf_type,
200                                            sizeof (buf_type)),
201                     buf_id, buf_router);
202        }
203      length_left -= message[i].iov_len;
204    }
205}
206
207static void
208ospf6_message_log_lsupdate (struct iovec *message)
209{
210  struct ospf6_header *ospf6_header;
211  u_int16_t length_left;
212  int i, lsanum;
213  struct ospf6_lsupdate *lsupdate;
214  struct ospf6_lsa_header *lsa_header;
215
216  /* calculate length */
217  ospf6_header = (struct ospf6_header *) message[0].iov_base;
218  length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
219  length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
220                 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
221
222  lsupdate = (struct ospf6_lsupdate *) message[1].iov_base;
223  lsanum = ntohl (lsupdate->lsupdate_num);
224
225  zlog_info ("    Number of LSA: #%d", lsanum);
226
227  for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1);
228       (char *)lsa_header < (char *)(message[1].iov_base + message[1].iov_len) &&
229       (char *)lsa_header < (char *)(message[1].iov_base + length_left);
230       lsa_header = OSPF6_LSA_NEXT (lsa_header))
231    ospf6_message_log_lsa_header (lsa_header);
232  length_left -= message[1].iov_len;
233
234  for (i = 2; message[i].iov_base; i++)
235    {
236
237      for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
238           (char *)lsa_header < (char *) (message[i].iov_base + message[i].iov_len) &&
239           (char *)lsa_header < (char *) (message[i].iov_base + length_left);
240           lsa_header = OSPF6_LSA_NEXT (lsa_header))
241        ospf6_message_log_lsa_header (lsa_header);
242      length_left -= message[i].iov_len;
243    }
244}
245
246static void
247ospf6_message_log_lsack (struct iovec *message)
248{
249  struct ospf6_header *ospf6_header;
250  u_int16_t length_left;
251  struct ospf6_lsa_header *lsa_header;
252  int i;
253
254  /* calculate length */
255  ospf6_header = (struct ospf6_header *) message[0].iov_base;
256  length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
257  length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
258                 length_left : iov_totallen (message) - sizeof (struct ospf6_header));
259
260  for (i = 1; message[i].iov_base; i++)
261    {
262      for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
263           (char *)(lsa_header + 1) <= (char *) (message[i].iov_base +
264                                                 message[i].iov_len) &&
265           (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left);
266           lsa_header++)
267        ospf6_message_log_lsa_header (lsa_header);
268      length_left -= message[i].iov_len;
269    }
270}
271
272struct {
273  void (*message_log) (struct iovec *);
274} ospf6_message_log_body [] =
275{
276  {ospf6_message_log_unknown},
277  {ospf6_message_log_hello},
278  {ospf6_message_log_dbdesc},
279  {ospf6_message_log_lsreq},
280  {ospf6_message_log_lsupdate},
281  {ospf6_message_log_lsack},
282};
283
284static void
285ospf6_message_log (struct iovec *message)
286{
287  struct ospf6_header *o6h;
288  char router_id[16], area_id[16];
289  u_char type;
290
291  assert (message[0].iov_len == sizeof (struct ospf6_header));
292  o6h = (struct ospf6_header *) message[0].iov_base;
293
294  inet_ntop (AF_INET, &o6h->router_id, router_id, sizeof (router_id));
295  inet_ntop (AF_INET, &o6h->area_id, area_id, sizeof (area_id));
296
297  zlog_info ("    OSPFv%d Type:%d Len:%hu RouterID:%s",
298             o6h->version, o6h->type, ntohs (o6h->len), router_id);
299  zlog_info ("    AreaID:%s Cksum:%hx InstanceID:%d",
300             area_id, ntohs (o6h->cksum), o6h->instance_id);
301
302  type = (OSPF6_MESSAGE_TYPE_UNKNOWN < o6h->type &&
303          o6h->type <= OSPF6_MESSAGE_TYPE_LSACK ?
304          o6h->type : OSPF6_MESSAGE_TYPE_UNKNOWN);
305  (* ospf6_message_log_body[type].message_log) (&message[0]);
306}
307
308int
309ospf6_opt_is_mismatch (unsigned char opt, char *options1, char *options2)
310{
311  return (OSPF6_OPT_ISSET (options1, opt) ^ OSPF6_OPT_ISSET (options2, opt));
312}
313
314
315void
316ospf6_process_unknown (struct iovec *message,
317                       struct in6_addr *src,
318                       struct in6_addr *dst,
319                       struct ospf6_interface *o6i,
320                       u_int32_t router_id)
321{
322  zlog_warn ("unknown message type, drop");
323}
324
325void
326ospf6_process_hello (struct iovec *message,
327                     struct in6_addr *src,
328                     struct in6_addr *dst,
329                     struct ospf6_interface *o6i,
330                     u_int32_t router_id)
331{
332  struct ospf6_header *ospf6_header;
333  u_int16_t length;
334  struct ospf6_hello *hello;
335  char changes = 0;
336#define CHANGE_RTRPRI (1 << 0)
337#define CHANGE_DR     (1 << 1)
338#define CHANGE_BDR    (1 << 2)
339  int twoway = 0, backupseen = 0, nbchange = 0;
340  u_int32_t *router_id_ptr;
341  int i, seenrtrnum = 0, router_id_space = 0;
342  char strbuf[64];
343  struct ospf6_neighbor *o6n = NULL;
344
345  /* assert interface */
346  assert (o6i);
347
348  /* caluculate length */
349  ospf6_header = (struct ospf6_header *) message[0].iov_base;
350  length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
351  length = (length < message[1].iov_len ? length : message[1].iov_len);
352
353  /* set hello pointer */
354  hello = (struct ospf6_hello *) message[1].iov_base;
355
356  /* find neighbor. if cannot be found, create */
357  o6n = ospf6_neighbor_lookup (router_id, o6i);
358  if (!o6n)
359    {
360      o6n = ospf6_neighbor_create (router_id, o6i);
361      o6n->ifid = ntohl (hello->interface_id);
362      o6n->prevdr = o6n->dr = hello->dr;
363      o6n->prevbdr = o6n->bdr = hello->bdr;
364      o6n->priority = hello->rtr_pri;
365      memcpy (&o6n->hisaddr, src, sizeof (struct in6_addr));
366    }
367
368  /* HelloInterval check */
369  if (ntohs (hello->hello_interval) != o6i->hello_interval)
370    {
371      zlog_warn ("HelloInterval mismatch with %s", o6n->str);
372      return;
373    }
374
375  /* RouterDeadInterval check */
376  if (ntohs (hello->router_dead_interval)
377      != o6i->dead_interval)
378    {
379      zlog_warn ("RouterDeadInterval mismatch with %s", o6n->str);
380      return;
381    }
382
383  /* check options */
384  /* Ebit */
385  if (ospf6_opt_is_mismatch (OSPF6_OPT_E, hello->options, o6i->area->options))
386    {
387      zlog_warn ("Ebit mismatch with %s", o6n->str);
388      return;
389    }
390
391  /* RouterPriority set */
392  if (o6n->priority != hello->rtr_pri)
393    {
394      o6n->priority = hello->rtr_pri;
395      if (IS_OSPF6_DUMP_HELLO)
396        zlog_info ("%s: RouterPriority changed", o6n->str);
397      changes |= CHANGE_RTRPRI;
398    }
399
400  /* DR set */
401  if (o6n->dr != hello->dr)
402    {
403      /* save previous dr, set current */
404      o6n->prevdr = o6n->dr;
405      o6n->dr = hello->dr;
406      inet_ntop (AF_INET, &o6n->dr, strbuf, sizeof (strbuf));
407      if (IS_OSPF6_DUMP_HELLO)
408        zlog_info ("%s declare %s as DR", o6n->str, strbuf);
409      changes |= CHANGE_DR;
410    }
411
412  /* BDR set */
413  if (o6n->bdr != hello->bdr)
414    {
415      /* save previous bdr, set current */
416      o6n->prevbdr = o6n->bdr;
417      o6n->bdr = hello->bdr;
418      inet_ntop (AF_INET, &o6n->bdr, strbuf, sizeof (strbuf));
419      if (IS_OSPF6_DUMP_HELLO)
420        zlog_info ("%s declare %s as BDR", o6n->str, strbuf);
421      changes |= CHANGE_BDR;
422    }
423
424  /* TwoWay check */
425  router_id_space = length - sizeof (struct ospf6_hello);
426  seenrtrnum = router_id_space / sizeof (u_int32_t);
427  router_id_ptr = (u_int32_t *) (hello + 1);
428  for (i = 0; i < seenrtrnum; i++)
429    {
430      if (*router_id_ptr == o6i->area->ospf6->router_id)
431        twoway++;
432      router_id_ptr++;
433    }
434
435  /* execute neighbor events */
436  thread_execute (master, hello_received, o6n, 0);
437  if (twoway)
438    thread_execute (master, twoway_received, o6n, 0);
439  else
440    thread_execute (master, oneway_received, o6n, 0);
441
442  /* BackupSeen check */
443  if (o6i->state == IFS_WAITING)
444    {
445      if (hello->dr == hello->bdr &&
446          hello->dr == o6n->router_id)
447        zlog_warn ("*** DR Election of %s is illegal", o6n->str);
448
449      if (hello->bdr == o6n->router_id)
450        backupseen++;
451      else if (hello->dr == o6n->router_id && hello->bdr == 0)
452        backupseen++;
453    }
454
455  /* NeighborChange check */
456  if (changes & CHANGE_RTRPRI)
457    nbchange++;
458  if (changes & CHANGE_DR)
459    if (o6n->prevdr == o6n->router_id || o6n->dr == o6n->router_id)
460      nbchange++;
461  if (changes & CHANGE_BDR)
462    if (o6n->prevbdr == o6n->router_id || o6n->bdr == o6n->router_id)
463      nbchange++;
464
465  /* schedule interface events */
466  if (backupseen)
467    thread_add_event (master, backup_seen, o6i, 0);
468  if (nbchange)
469    thread_add_event (master, neighbor_change, o6i, 0);
470
471  return;
472}
473
474int
475ospf6_dbdesc_is_master (struct ospf6_neighbor *o6n)
476{
477  char buf[128];
478
479  if (o6n->router_id == ospf6->router_id)
480    {
481      inet_ntop (AF_INET6, &o6n->hisaddr, buf, sizeof (buf));
482      zlog_warn ("Message: Neighbor router-id conflicts: %s: %s",
483                 o6n->str, buf);
484      return -1;
485    }
486  else if (ntohl (o6n->router_id) > ntohl (ospf6->router_id))
487    return 0;
488  return 1;
489}
490
491int
492ospf6_dbdesc_is_duplicate (struct ospf6_dbdesc *received,
493                           struct ospf6_dbdesc *last_received)
494{
495  if (memcmp (received->options, last_received->options, 3) != 0)
496    return 0;
497  if (received->ifmtu != last_received->ifmtu)
498    return 0;
499  if (received->bits != last_received->bits)
500    return 0;
501  if (received->seqnum != last_received->seqnum)
502    return 0;
503  return 1;
504}
505
506void
507ospf6_process_dbdesc_master (struct iovec *message, struct ospf6_neighbor *o6n)
508{
509  struct ospf6_header *ospf6_header;
510  u_int16_t length, lsa_count;
511  struct ospf6_dbdesc *dbdesc;
512  struct ospf6_lsa_header *lsa_header;
513
514  /* caluculate length */
515  ospf6_header = (struct ospf6_header *) message[0].iov_base;
516  length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
517  length = (length < message[1].iov_len ? length : message[1].iov_len);
518
519  /* set database description pointer */
520  dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
521
522  switch (o6n->state)
523    {
524      case NBS_DOWN:
525      case NBS_ATTEMPT:
526      case NBS_TWOWAY:
527        if (IS_OSPF6_DUMP_DBDESC)
528          zlog_info ("DbDesc from %s Ignored: state less than Init",
529                     o6n->str);
530        return;
531
532      case NBS_INIT:
533        thread_execute (master, twoway_received, o6n, 0);
534        if (o6n->state != NBS_EXSTART)
535          {
536            if (IS_OSPF6_DUMP_DBDESC)
537              zlog_info ("DbDesc from %s Ignored: state less than ExStart",
538                         o6n->str);
539            return;
540          }
541        /* else fall through to ExStart */
542      case NBS_EXSTART:
543        if (DDBIT_IS_SLAVE (dbdesc->bits) &&
544            !DDBIT_IS_INITIAL (dbdesc->bits) &&
545            ntohl (dbdesc->seqnum) == o6n->dbdesc_seqnum)
546          {
547            ospf6_neighbor_dbex_init (o6n);
548
549            if (o6n->thread_rxmt_dbdesc)
550              thread_cancel (o6n->thread_rxmt_dbdesc);
551            o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
552
553            thread_add_event (master, negotiation_done, o6n, 0);
554          }
555        else
556          {
557            if (IS_OSPF6_DUMP_DBDESC)
558              zlog_info ("  negotiation failed with %s", o6n->str);
559            return;
560          }
561        break;
562
563      case NBS_EXCHANGE:
564        /* duplicate dbdesc dropped by master */
565        if (!memcmp (dbdesc, &o6n->last_dd,
566                     sizeof (struct ospf6_dbdesc)))
567          {
568            if (IS_OSPF6_DUMP_DBDESC)
569              zlog_info ("  duplicate dbdesc, drop");
570            return;
571          }
572
573        /* check Initialize bit and Master/Slave bit */
574        if (DDBIT_IS_INITIAL (dbdesc->bits))
575          {
576            if (IS_OSPF6_DUMP_DBDESC)
577              zlog_info ("Initialize bit mismatch");
578            thread_add_event (master, seqnumber_mismatch, o6n, 0);
579            return;
580          }
581        if (DDBIT_IS_MASTER (dbdesc->bits))
582          {
583            if (IS_OSPF6_DUMP_DBDESC)
584              zlog_info ("Master/Slave bit mismatch");
585            thread_add_event (master, seqnumber_mismatch, o6n, 0);
586            return;
587          }
588
589        /* dbdesc option check */
590        if (memcmp (dbdesc->options, o6n->last_dd.options,
591                    sizeof (dbdesc->options)))
592          {
593            if (IS_OSPF6_DUMP_DBDESC)
594              zlog_info ("dbdesc option field changed");
595            thread_add_event (master, seqnumber_mismatch, o6n, 0);
596            return;
597          }
598
599        /* dbdesc sequence number check */
600        if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum)
601          {
602            if (IS_OSPF6_DUMP_DBDESC)
603              zlog_warn ("*** dbdesc seqnumber mismatch: %d expected",
604                         o6n->dbdesc_seqnum);
605            thread_add_event (master, seqnumber_mismatch, o6n, 0);
606            return;
607          }
608        break;
609
610      case NBS_LOADING:
611      case NBS_FULL:
612        /* duplicate dbdesc dropped by master */
613        if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd))
614          {
615            if (IS_OSPF6_DUMP_DBDESC)
616              zlog_info ("  duplicate dbdesc, drop");
617            return;
618          }
619        else
620          {
621            if (IS_OSPF6_DUMP_DBDESC)
622              zlog_info ("  not duplicate dbdesc in state %s",
623                         ospf6_neighbor_state_string[o6n->state]);
624            thread_add_event (master, seqnumber_mismatch, o6n, 0);
625            return;
626          }
627        break; /* not reached */
628
629      default:
630        assert (0);
631        break; /* not reached */
632    }
633
634  /* process LSA headers */
635  lsa_count = 0;
636  for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
637       (char *)(lsa_header + 1) <= (char *)dbdesc + length;
638       lsa_header++)
639    {
640      if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0)
641        {
642          thread_add_event (master, seqnumber_mismatch, o6n, 0);
643          return;
644        }
645      lsa_count ++;
646    }
647
648  /* increment dbdesc seqnum */
649  o6n->dbdesc_seqnum++;
650
651  /* cancel transmission/retransmission thread */
652  if (o6n->thread_send_dbdesc)
653    thread_cancel (o6n->thread_send_dbdesc);
654  o6n->thread_send_dbdesc = (struct thread *) NULL;
655  if (o6n->thread_rxmt_dbdesc)
656    thread_cancel (o6n->thread_rxmt_dbdesc);
657  o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
658
659  /* more bit check */
660  if (!DD_IS_MBIT_SET (dbdesc->bits) && !DD_IS_MBIT_SET (o6n->dbdesc_bits))
661    thread_add_event (master, exchange_done, o6n, 0);
662  else
663    o6n->thread_send_dbdesc =
664      thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
665
666  /* save last received dbdesc */
667  memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc));
668
669  /* statistics */
670  o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count;
671
672  return;
673}
674
675void
676ospf6_process_dbdesc_slave (struct iovec *message, struct ospf6_neighbor *o6n)
677{
678  struct ospf6_header *ospf6_header;
679  u_int16_t length, lsa_count;
680  struct ospf6_dbdesc *dbdesc;
681  struct ospf6_lsa_header *lsa_header;
682
683  /* caluculate length */
684  ospf6_header = (struct ospf6_header *) message[0].iov_base;
685  length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
686  length = (length < message[1].iov_len ? length : message[1].iov_len);
687
688  /* set database description pointer */
689  dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
690
691  switch (o6n->state)
692    {
693      case NBS_DOWN:
694      case NBS_ATTEMPT:
695      case NBS_TWOWAY:
696        return;
697      case NBS_INIT:
698        thread_execute (master, twoway_received, o6n, 0);
699        if (o6n->state != NBS_EXSTART)
700          {
701            return;
702          }
703        /* else fall through to ExStart */
704      case NBS_EXSTART:
705        if (DD_IS_IBIT_SET (dbdesc->bits) &&
706            DD_IS_MBIT_SET (dbdesc->bits) &&
707            DD_IS_MSBIT_SET (dbdesc->bits))
708          {
709            /* Master/Slave bit set to slave */
710            DD_MSBIT_CLEAR (o6n->dbdesc_bits);
711            /* Initialize bit clear */
712            DD_IBIT_CLEAR (o6n->dbdesc_bits);
713            /* sequence number set to master's */
714            o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum);
715            ospf6_neighbor_dbex_init (o6n);
716
717            if (o6n->thread_rxmt_dbdesc)
718              thread_cancel (o6n->thread_rxmt_dbdesc);
719            o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
720
721            thread_add_event (master, negotiation_done, o6n, 0);
722          }
723        else
724          {
725            if (IS_OSPF6_DUMP_DBDESC)
726              zlog_info ("negotiation failed");
727            return;
728          }
729        break;
730
731      case NBS_EXCHANGE:
732        /* duplicate dbdesc dropped by master */
733        if (!memcmp (dbdesc, &o6n->last_dd,
734                     sizeof (struct ospf6_dbdesc)))
735          {
736            if (IS_OSPF6_DUMP_DBDESC)
737              zlog_info ("  duplicate dbdesc, retransmit dbdesc");
738
739            if (o6n->thread_rxmt_dbdesc)
740              thread_cancel (o6n->thread_rxmt_dbdesc);
741            o6n->thread_rxmt_dbdesc =
742              thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0);
743
744            return;
745          }
746
747        /* check Initialize bit and Master/Slave bit */
748        if (DDBIT_IS_INITIAL (dbdesc->bits))
749          {
750            if (IS_OSPF6_DUMP_DBDESC)
751              zlog_info ("Initialize bit mismatch");
752            thread_add_event (master, seqnumber_mismatch, o6n, 0);
753            return;
754          }
755        if (DDBIT_IS_SLAVE (dbdesc->bits))
756          {
757            if (IS_OSPF6_DUMP_DBDESC)
758              zlog_info ("Master/Slave bit mismatch");
759            thread_add_event (master, seqnumber_mismatch, o6n, 0);
760            return;
761          }
762
763        /* dbdesc option check */
764        if (memcmp (dbdesc->options, o6n->last_dd.options,
765                    sizeof (dbdesc->options)))
766          {
767            if (IS_OSPF6_DUMP_DBDESC)
768              zlog_info ("dbdesc option field changed");
769            thread_add_event (master, seqnumber_mismatch, o6n, 0);
770            return;
771          }
772
773        /* dbdesc sequence number check */
774        if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum + 1)
775          {
776            if (IS_OSPF6_DUMP_DBDESC)
777              zlog_warn ("*** dbdesc seqnumber mismatch: %d expected",
778                         o6n->dbdesc_seqnum + 1);
779            thread_add_event (master, seqnumber_mismatch, o6n, 0);
780            return;
781          }
782        break;
783
784      case NBS_LOADING:
785      case NBS_FULL:
786        /* duplicate dbdesc cause slave to retransmit */
787        if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd))
788          {
789            if (IS_OSPF6_DUMP_DBDESC)
790              zlog_info ("  duplicate dbdesc, retransmit");
791
792            if (o6n->thread_rxmt_dbdesc)
793              thread_cancel (o6n->thread_rxmt_dbdesc);
794            o6n->thread_rxmt_dbdesc =
795              thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0);
796
797            return;
798          }
799        else
800          {
801            if (IS_OSPF6_DUMP_DBDESC)
802              zlog_info ("  not duplicate dbdesc in state %s",
803                         ospf6_neighbor_state_string[o6n->state]);
804            thread_add_event (master, seqnumber_mismatch, o6n, 0);
805            return;
806          }
807        break; /* not reached */
808
809      default:
810        assert (0);
811        break; /* not reached */
812    }
813
814  /* process LSA headers */
815  lsa_count = 0;
816  for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
817       (char *)(lsa_header + 1) <= (char *)dbdesc + length;
818       lsa_header++)
819    {
820      if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0)
821        {
822          thread_add_event (master, seqnumber_mismatch, o6n, 0);
823          return;
824        }
825      lsa_count ++;
826    }
827
828  /* set dbdesc seqnum to master's */
829  o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum);
830
831  if (o6n->thread_send_dbdesc)
832    thread_cancel (o6n->thread_send_dbdesc);
833  o6n->thread_send_dbdesc =
834    thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
835
836  /* save last received dbdesc */
837  memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc));
838
839  /* statistics */
840  o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count;
841
842  return;
843}
844
845void
846ospf6_process_dbdesc (struct iovec *message,
847                      struct in6_addr *src,
848                      struct in6_addr *dst,
849                      struct ospf6_interface *o6i,
850                      u_int32_t router_id)
851{
852  struct ospf6_header *ospf6_header;
853  u_int16_t length;
854  struct ospf6_neighbor *o6n;
855  struct ospf6_dbdesc *dbdesc;
856  int Im_master = 0;
857
858  /* assert interface */
859  assert (o6i);
860
861  /* caluculate length */
862  ospf6_header = (struct ospf6_header *) message[0].iov_base;
863  length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
864  length = (length < message[1].iov_len ? length : message[1].iov_len);
865
866  /* set database description pointer */
867  dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
868
869  /* find neighbor. if cannot be found, reject this message */
870  o6n = ospf6_neighbor_lookup (router_id, o6i);
871  if (!o6n)
872    {
873      if (IS_OSPF6_DUMP_DBDESC)
874        zlog_info ("neighbor not found, reject");
875      return;
876    }
877
878  if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
879    {
880      if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
881        zlog_info ("From Secondary I/F of the neighbor: ignore");
882      return;
883    }
884
885  /* interface mtu check */
886    /* xxx */
887
888  /* check am I master */
889  Im_master = ospf6_dbdesc_is_master (o6n);
890  if (Im_master < 0)
891    {
892      return; /* can't decide which is master, return */
893    }
894
895  if (Im_master)
896    ospf6_process_dbdesc_master (message, o6n);
897  else
898    ospf6_process_dbdesc_slave (message, o6n);
899
900  return;
901}
902
903void
904ospf6_process_lsreq (struct iovec *message,
905                     struct in6_addr *src,
906                     struct in6_addr *dst,
907                     struct ospf6_interface *o6i,
908                     u_int32_t router_id)
909{
910  struct ospf6_header *ospf6_header;
911  u_int16_t length;
912  struct ospf6_neighbor *o6n;
913  struct ospf6_lsreq *lsreq;
914  struct iovec response[OSPF6_MESSAGE_IOVEC_SIZE];
915  struct ospf6_lsa *lsa;
916  unsigned long lsanum = 0;
917  struct ospf6_lsupdate lsupdate;
918  char buf_id[16], buf_router[16], buf_type[16];
919
920  /* assert interface */
921  assert (o6i);
922
923  /* caluculate length */
924  ospf6_header = (struct ospf6_header *) message[0].iov_base;
925  length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
926  length = (length < message[1].iov_len ? length : message[1].iov_len);
927
928  /* find neighbor. if cannot be found, reject this message */
929  o6n = ospf6_neighbor_lookup (router_id, o6i);
930  if (!o6n)
931    {
932      if (IS_OSPF6_DUMP_LSREQ)
933        zlog_info ("  neighbor not found, reject");
934      return;
935    }
936
937  if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
938    {
939      if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
940        zlog_info ("From Secondary I/F of the neighbor: ignore");
941      return;
942    }
943
944  /* In states other than ExChange, Loading, or Full, the packet
945     should be ignored. */
946  if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING
947      && o6n->state != NBS_FULL)
948    {
949      if (IS_OSPF6_DUMP_LSREQ)
950        zlog_info ("  neighbor state less than Exchange, reject");
951      return;
952    }
953
954  /* Initialize response LSUpdate packet */
955  OSPF6_MESSAGE_CLEAR (response);
956  memset (&lsupdate, 0, sizeof (struct ospf6_lsupdate));
957  OSPF6_MESSAGE_ATTACH (response, &lsupdate, sizeof (struct ospf6_lsupdate));
958
959  /* process each request */
960  lsanum = 0;
961  for (lsreq = (struct ospf6_lsreq *) message[1].iov_base;
962       (char *)(lsreq + 1) <= (char *)(message[1].iov_base + length);
963       lsreq++)
964    {
965      inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router));
966      inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id));
967
968      /* find instance of database copy */
969      lsa = ospf6_lsdb_lookup (lsreq->type, lsreq->id, lsreq->adv_router,
970                               ospf6_lsa_get_scope (lsreq->type, o6i));
971
972      if (!lsa)
973        {
974          if (IS_OSPF6_DUMP_LSREQ)
975            zlog_info ("BadLSReq: %s requests [%s ID=%s Adv=%s] not found",
976                       o6n->str, ospf6_lsa_type_string (lsreq->type, buf_type,
977                                                        sizeof (buf_type)),
978                       buf_id, buf_router);
979          thread_add_event (master, bad_lsreq, o6n, 0);
980          return;
981        }
982
983      /* I/F MTU check */
984      if (sizeof (struct ospf6_header) + sizeof (struct ospf6_lsupdate)
985          + iov_totallen (response) + ntohs (lsa->header->length)
986          > o6i->ifmtu)
987        break;
988
989      OSPF6_MESSAGE_ATTACH (response, lsa->header, ntohs (lsa->header->length));
990      lsanum++;
991    }
992
993  /* send response LSUpdate to this request */
994  if (lsanum)
995    {
996      lsupdate.lsupdate_num = htonl (lsanum);
997
998      ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, response,
999                          &o6n->hisaddr, o6i->if_id);
1000    }
1001
1002  /* statistics */
1003  o6n->lsa_receive[OSPF6_MESSAGE_TYPE_LSREQ]
1004    += length / sizeof (struct ospf6_lsreq);
1005}
1006
1007void
1008ospf6_process_lsupdate (struct iovec *message,
1009                        struct in6_addr *src,
1010                        struct in6_addr *dst,
1011                        struct ospf6_interface *o6i,
1012                        u_int32_t router_id)
1013{
1014  struct ospf6_header *ospf6_header;
1015  u_int16_t length;
1016  struct ospf6_lsupdate *lsupdate;
1017  struct ospf6_neighbor *o6n;
1018  unsigned long lsanum;
1019  struct ospf6_lsa_header *lsa_header;
1020
1021  /* assert interface */
1022  assert (o6i);
1023
1024  /* caluculate length */
1025  ospf6_header = (struct ospf6_header *) message[0].iov_base;
1026  length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
1027  length = (length < message[1].iov_len ? length : message[1].iov_len);
1028
1029  /* find neighbor. if cannot be found, reject this message */
1030  o6n = ospf6_neighbor_lookup (router_id, o6i);
1031  if (! o6n)
1032    {
1033      if (IS_OSPF6_DUMP_LSUPDATE)
1034        zlog_info ("  neighbor not found, reject");
1035      return;
1036    }
1037
1038  if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
1039    {
1040      if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1041        zlog_info ("From Secondary I/F of the neighbor: ignore");
1042      return;
1043    }
1044
1045  /* if neighbor state less than ExChange, reject this message */
1046  if (o6n->state < NBS_EXCHANGE)
1047    {
1048      if (IS_OSPF6_DUMP_LSUPDATE)
1049        zlog_info ("  neighbor state less than Exchange, reject");
1050      return;
1051    }
1052
1053  /* set linkstate update pointer */
1054  lsupdate = (struct ospf6_lsupdate *) message[1].iov_base;
1055
1056  /* save linkstate update info */
1057  lsanum = ntohl (lsupdate->lsupdate_num);
1058
1059  /* statistics */
1060  o6n->ospf6_stat_received_lsa += lsanum;
1061  o6n->ospf6_stat_received_lsupdate++;
1062
1063  /* RFC2328 Section 10.9: When the neighbor responds to these requests
1064     with the proper Link State Update packet(s), the Link state request
1065     list is truncated and a new Link State Request packet is sent. */
1066
1067  /* process LSAs */
1068  for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1);
1069       lsanum && (char *)lsa_header < (char *)lsupdate + length;
1070       lsanum--)
1071    {
1072      ospf6_dbex_receive_lsa (lsa_header, o6n);
1073      lsa_header = OSPF6_LSA_NEXT (lsa_header);
1074    }
1075
1076  /* send new Link State Request packet if this LS Update packet
1077     can be recognized as a response to our previous LS request */
1078  if (! IN6_IS_ADDR_MULTICAST(dst) &&
1079      (o6n->state == NBS_EXCHANGE || o6n->state == NBS_LOADING))
1080    thread_add_event (master, ospf6_send_lsreq, o6n, 0);
1081
1082  return;
1083}
1084
1085void
1086ospf6_process_lsack (struct iovec *message,
1087                     struct in6_addr *src,
1088                     struct in6_addr *dst,
1089                     struct ospf6_interface *o6i,
1090                     u_int32_t router_id)
1091{
1092  struct ospf6_header *ospf6_header;
1093  u_int16_t length;
1094  struct ospf6_neighbor *o6n;
1095  struct ospf6_lsa_header *lsa_header;
1096  struct ospf6_lsa *lsa, *copy, *rem;
1097
1098  /* assert interface */
1099  assert (o6i);
1100
1101  /* caluculate length */
1102  ospf6_header = (struct ospf6_header *) message[0].iov_base;
1103  length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
1104  length = (length < message[1].iov_len ? length : message[1].iov_len);
1105
1106  /* find neighbor. if cannot be found, reject this message */
1107  o6n = ospf6_neighbor_lookup (router_id, o6i);
1108  if (!o6n)
1109    {
1110      if (IS_OSPF6_DUMP_LSACK)
1111        zlog_info ("  neighbor not found, reject");
1112      return;
1113    }
1114
1115  if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
1116    {
1117      if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1118        zlog_info ("From Secondary I/F of the neighbor: ignore");
1119      return;
1120    }
1121
1122  /* if neighbor state less than ExChange, reject this message */
1123  if (o6n->state < NBS_EXCHANGE)
1124    {
1125      if (IS_OSPF6_DUMP_LSACK)
1126        zlog_info ("  neighbor state less than Exchange, reject");
1127      return;
1128    }
1129
1130  /* process each LSA header */
1131  for (lsa_header = (struct ospf6_lsa_header *) message[1].iov_base;
1132       (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + length);
1133       lsa_header++)
1134    {
1135      /* find database copy */
1136      copy = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id,
1137                                lsa_header->advrtr,
1138                                ospf6_lsa_get_scope (lsa_header->type, o6i));
1139
1140      /* if no database copy */
1141      if (!copy)
1142        {
1143          if (IS_OSPF6_DUMP_LSACK)
1144            zlog_info ("no database copy, ignore");
1145          continue;
1146        }
1147
1148      /* if not on his retrans list */
1149      rem = ospf6_lsdb_lookup_lsdb (copy->header->type, copy->header->id,
1150                                    copy->header->adv_router,
1151                                    o6n->retrans_list);
1152      if (rem == NULL)
1153        {
1154          if (IS_OSPF6_DUMP_LSACK)
1155            zlog_info ("not on %s's retranslist, ignore", o6n->str);
1156          continue;
1157        }
1158
1159      /* create temporary LSA from Ack message */
1160      lsa = ospf6_lsa_summary_create ((struct ospf6_lsa_header__ *) lsa_header);
1161
1162      /* if the same instance, remove from retrans list.
1163         else, log and ignore */
1164      if (ospf6_lsa_check_recent (lsa, copy) == 0)
1165        ospf6_neighbor_retrans_remove (rem, o6n);
1166      else
1167        {
1168          /* Log the questionable acknowledgement,
1169             and examine the next one. */
1170          zlog_warn ("LSAck: questionable acknowledge: LSAs differ");
1171        }
1172
1173      /* release temporary LSA from Ack message */
1174      ospf6_lsa_delete (lsa);
1175    }
1176
1177  ospf6_maxage_remover ();
1178  return;
1179}
1180
1181struct {
1182  void (*process) (struct iovec *, struct in6_addr *, struct in6_addr *,
1183                   struct ospf6_interface *, u_int32_t);
1184} ospf6_message_process_type [] =
1185{
1186  {ospf6_process_unknown},
1187  {ospf6_process_hello},
1188  {ospf6_process_dbdesc},
1189  {ospf6_process_lsreq},
1190  {ospf6_process_lsupdate},
1191  {ospf6_process_lsack}
1192};
1193
1194/* process ospf6 protocol header. then, call next process function
1195   for each message type */
1196static void
1197ospf6_message_process (struct iovec *message,
1198                       struct in6_addr *src,
1199                       struct in6_addr *dst,
1200                       struct ospf6_interface *o6i)
1201{
1202  struct ospf6_header *ospf6_header = NULL;
1203  u_char type;
1204  u_int32_t router_id;
1205  char srcname[64];
1206
1207  assert (o6i);
1208  assert (src);
1209  assert (dst);
1210
1211  /* set ospf6_hdr pointer to head of buffer */
1212  ospf6_header = (struct ospf6_header *) message[0].iov_base;
1213
1214  /* version check */
1215  if (ospf6_header->version != OSPF6_VERSION)
1216    {
1217      if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1218        zlog_info ("version mismatch, drop");
1219      return;
1220    }
1221
1222  /* area id check */
1223  if (ospf6_header->area_id != o6i->area->area_id)
1224    {
1225      if (ospf6_header->area_id == 0)
1226        {
1227          if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1228            zlog_info ("virtual link not yet, drop");
1229          return;
1230        }
1231
1232      if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1233        zlog_info ("area id mismatch, drop");
1234      return;
1235    }
1236
1237  /* instance id check */
1238  if (ospf6_header->instance_id != o6i->instance_id)
1239    {
1240      if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
1241        zlog_info ("instance id mismatch, drop");
1242      return;
1243    }
1244
1245  /* router id check */
1246  router_id = ospf6_header->router_id;
1247  if (ospf6_header->router_id == o6i->area->ospf6->router_id)
1248    {
1249      inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
1250      zlog_warn ("*** Router-ID mismatch: from %s on %s",
1251                 srcname, o6i->interface->name);
1252      return;
1253    }
1254
1255  /* message type check */
1256  type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ?
1257          OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type);
1258
1259  /* octet statistics relies on some asumption:
1260       on ethernet, no IPv6 Extention header, etc */
1261#define OSPF6_IP6_HEADER_SIZE   40
1262#define OSPF6_ETHER_HEADER_SIZE 14
1263  o6i->message_stat[type].recv++;
1264  o6i->message_stat[type].recv_octet += ntohs (ospf6_header->len)
1265    + OSPF6_IP6_HEADER_SIZE + OSPF6_ETHER_HEADER_SIZE;
1266
1267  /* futher process */
1268  (*ospf6_message_process_type[type].process) (&message[0], src, dst, o6i, router_id);
1269
1270  return;
1271}
1272
1273int
1274ospf6_receive (struct thread *thread)
1275{
1276  int sockfd;
1277  struct in6_addr src, dst;
1278  unsigned int ifindex;
1279  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1280  struct ospf6_header ospf6_header;
1281  char buffer[OSPF6_MESSAGE_RECEIVE_BUFSIZE];
1282  struct ospf6_interface *o6i;
1283  char srcname[64], dstname[64];
1284  unsigned char type;
1285
1286  /* get socket */
1287  sockfd = THREAD_FD (thread);
1288
1289  /* initialize */
1290  OSPF6_MESSAGE_CLEAR (message);
1291  memset (&ospf6_header, 0, sizeof (struct ospf6_header));
1292
1293  OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header));
1294  OSPF6_MESSAGE_ATTACH (message, buffer, OSPF6_MESSAGE_RECEIVE_BUFSIZE);
1295
1296  /* receive message */
1297  ospf6_recvmsg (&src, &dst, &ifindex, message);
1298
1299  type = (OSPF6_MESSAGE_TYPE_UNKNOWN < ospf6_header.type &&
1300          ospf6_header.type <= OSPF6_MESSAGE_TYPE_LSACK ?
1301          ospf6_header.type : OSPF6_MESSAGE_TYPE_UNKNOWN);
1302  o6i = ospf6_interface_lookup_by_index (ifindex);
1303  if (!o6i || !o6i->area)
1304    {
1305      zlog_warn ("*** received interface ospf6 disabled");
1306      thread_add_read (master, ospf6_receive, NULL, sockfd);
1307      return 0;
1308    }
1309
1310  /* log */
1311  if (IS_OSPF6_DUMP_MESSAGE (type))
1312    {
1313      inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
1314      inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
1315      zlog_info ("Receive %s on %s",
1316                 ospf6_message_type_string[type], o6i->interface->name);
1317      zlog_info ("    %s -> %s", srcname, dstname);
1318      ospf6_message_log (message);
1319    }
1320
1321  /* if not passive, process message */
1322  if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE))
1323    ospf6_message_process (message, &src, &dst, o6i);
1324  else if (IS_OSPF6_DUMP_MESSAGE (type))
1325    zlog_info ("Ignore message on passive interface %s",
1326               o6i->interface->name);
1327
1328  /* add next read thread */
1329  thread_add_read (master, ospf6_receive, NULL, sockfd);
1330
1331  return 0;
1332}
1333
1334
1335/* send section */
1336int
1337ospf6_message_length (struct iovec *message)
1338{
1339  int i, length = 0;
1340  for (i = 0; i < OSPF6_MESSAGE_IOVEC_SIZE; i++)
1341    {
1342      if (message[i].iov_base == NULL && message[i].iov_len == 0)
1343        break;
1344      length += message[i].iov_len;
1345    }
1346  return length;
1347}
1348#define OSPF6_MESSAGE_LENGTH(msg) \
1349(ospf6_message_length (msg))
1350
1351void
1352ospf6_message_send (unsigned char type, struct iovec *msg,
1353                    struct in6_addr *dst, u_int ifindex)
1354{
1355  struct ospf6_interface *o6i;
1356  struct ospf6_header ospf6_header;
1357  char dst_name[64], src_name[64];
1358  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1359  int msg_len;
1360
1361  /* ospf6 interface lookup */
1362  o6i = ospf6_interface_lookup_by_index (ifindex);
1363  assert (o6i);
1364
1365  msg_len = OSPF6_MESSAGE_LENGTH (msg);
1366
1367  /* I/F MTU check */
1368#if 0
1369  if (msg_len + sizeof (struct ospf6_header) >= o6i->interface->mtu)
1370#else
1371  if (msg_len + sizeof (struct ospf6_header) >= o6i->ifmtu)
1372#endif
1373    {
1374      /* If Interface MTU is 0, save the case
1375         since zebra had been failed to get MTU from Kernel */
1376      if (o6i->interface->mtu != 0)
1377        {
1378          zlog_warn ("Message: Send failed on %s: exceeds I/F MTU",
1379                     o6i->interface->name);
1380          zlog_warn ("Message:   while sending %s: Len:%d MTU:%d",
1381                     ospf6_message_type_string[type],
1382                     msg_len + sizeof (struct ospf6_header),
1383                     o6i->ifmtu);
1384          return;
1385        }
1386      else
1387        {
1388          zlog_warn ("Message: I/F MTU check ignored on %s",
1389                     o6i->interface->name);
1390        }
1391    }
1392
1393  /* Initialize */
1394  OSPF6_MESSAGE_CLEAR (message);
1395
1396  /* set OSPF header */
1397  memset (&ospf6_header, 0, sizeof (ospf6_header));
1398  ospf6_header.version = OSPF6_VERSION;
1399  ospf6_header.type = type;
1400  ospf6_header.len = htons (msg_len + sizeof (struct ospf6_header));
1401  ospf6_header.router_id = ospf6->router_id;
1402  ospf6_header.area_id = o6i->area->area_id;
1403  /* checksum is calculated by kernel */
1404  ospf6_header.instance_id = o6i->instance_id;
1405  ospf6_header.reserved = 0;
1406  OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header));
1407
1408  /* Attach rest to message */
1409  OSPF6_MESSAGE_JOIN (message, msg);
1410
1411  /* statistics */
1412  if (type >= OSPF6_MESSAGE_TYPE_MAX)
1413    type = OSPF6_MESSAGE_TYPE_UNKNOWN;
1414  o6i->message_stat[type].send++;
1415  o6i->message_stat[type].send_octet += ntohs (ospf6_header.len);
1416
1417  /* log */
1418  if (IS_OSPF6_DUMP_MESSAGE (type))
1419    {
1420      inet_ntop (AF_INET6, dst, dst_name, sizeof (dst_name));
1421      if (o6i->lladdr)
1422        inet_ntop (AF_INET6, o6i->lladdr, src_name, sizeof (src_name));
1423      else
1424        memcpy (src_name, "Unknown", sizeof (src_name));
1425      zlog_info ("Send %s on %s",
1426                 ospf6_message_type_string[type], o6i->interface->name);
1427      zlog_info ("    %s -> %s", src_name, dst_name);
1428      ospf6_message_log (message);
1429    }
1430
1431  /* send message */
1432  ospf6_sendmsg (o6i->lladdr, dst, &ifindex, message);
1433}
1434
1435
1436int
1437ospf6_send_hello (struct thread *thread)
1438{
1439  listnode n;
1440  struct ospf6_interface *o6i;
1441  struct ospf6_neighbor *o6n;
1442  struct in6_addr dst;
1443  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1444  struct ospf6_hello hello;
1445  char router_buffer[1024]; /* xxx */
1446  u_int router_size;
1447
1448  /* which ospf6 interface to send */
1449  o6i = (struct ospf6_interface *) THREAD_ARG (thread);
1450  o6i->thread_send_hello = (struct thread *) NULL;
1451
1452  /* assure interface is up */
1453  if (o6i->state <= IFS_DOWN)
1454    {
1455      if (IS_OSPF6_DUMP_HELLO)
1456        zlog_warn ("Send HELLO Failed: Interface not enabled: %s",
1457                   o6i->interface->name);
1458      return 0;
1459    }
1460
1461  /* clear message buffer */
1462  OSPF6_MESSAGE_CLEAR (message);
1463
1464  /* set Hello fields */
1465  hello.interface_id = htonl (o6i->if_id);
1466  hello.rtr_pri = o6i->priority;
1467  memcpy (hello.options, o6i->area->options, sizeof (hello.options));
1468  hello.hello_interval = htons (o6i->hello_interval);
1469  hello.router_dead_interval = htons (o6i->dead_interval);
1470  hello.dr = o6i->dr;
1471  hello.bdr = o6i->bdr;
1472  OSPF6_MESSAGE_ATTACH (message, &hello, sizeof (struct ospf6_hello));
1473
1474  /* set neighbor router id */
1475  router_size = 0;
1476  for (n = listhead (o6i->neighbor_list); n; nextnode (n))
1477    {
1478      o6n = (struct ospf6_neighbor *) getdata (n);
1479
1480      if (o6n->state < NBS_INIT)
1481        continue;
1482
1483      if (router_size + sizeof (o6n->router_id) > sizeof (router_buffer))
1484        {
1485          zlog_warn ("Send HELLO: Buffer shortage on %s",
1486                     o6i->interface->name);
1487          break;
1488        }
1489
1490      /* Copy Router-ID to Buffer */
1491      memcpy (router_buffer + router_size, &o6n->router_id,
1492              sizeof (o6n->router_id));
1493      router_size += sizeof (o6n->router_id);
1494    }
1495  OSPF6_MESSAGE_ATTACH (message, router_buffer, router_size);
1496
1497  /* set destionation */
1498  inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
1499
1500  /* send hello */
1501  ospf6_message_send (OSPF6_MESSAGE_TYPE_HELLO, message, &dst,
1502                      o6i->interface->ifindex);
1503
1504  /* set next timer thread */
1505  o6i->thread_send_hello = thread_add_timer (master, ospf6_send_hello,
1506                                             o6i, o6i->hello_interval);
1507
1508  return 0;
1509}
1510
1511void
1512ospf6_dbdesc_seqnum_init (struct ospf6_neighbor *o6n)
1513{
1514  struct timeval tv;
1515
1516  if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
1517    tv.tv_sec = 1;
1518
1519  o6n->dbdesc_seqnum = tv.tv_sec;
1520
1521  if (IS_OSPF6_DUMP_DBDESC)
1522    zlog_info ("set dbdesc seqnum %d for %s", o6n->dbdesc_seqnum, o6n->str);
1523}
1524
1525int
1526ospf6_send_dbdesc_rxmt (struct thread *thread)
1527{
1528  struct ospf6_lsdb_node node;
1529  struct ospf6_neighbor *o6n;
1530  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1531  struct ospf6_lsa *lsa;
1532  struct ospf6_lsa_header *lsa_header;
1533  struct ospf6_dbdesc dbdesc;
1534
1535  o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1536  assert (o6n);
1537
1538  /* clear thread */
1539  o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
1540
1541  /* if state less than ExStart, do nothing */
1542  if (o6n->state < NBS_EXSTART)
1543    return 0;
1544
1545  OSPF6_MESSAGE_CLEAR (message);
1546
1547  /* set dbdesc */
1548  memcpy (dbdesc.options, o6n->ospf6_interface->area->options,
1549          sizeof (dbdesc.options));
1550  dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu);
1551  dbdesc.bits = o6n->dbdesc_bits;
1552  dbdesc.seqnum = htonl (o6n->dbdesc_seqnum);
1553  OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc));
1554
1555  /* if this is not initial, set LSA summary to dbdesc */
1556  if (! DD_IS_IBIT_SET (o6n->dbdesc_bits))
1557    {
1558      for (ospf6_lsdb_head (&node, o6n->dbdesc_list);
1559           ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
1560        {
1561          lsa = node.lsa;
1562
1563          /* xxx, no MTU check: no support for Dynamic MTU change */
1564
1565          /* set age and add InfTransDelay */
1566          ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
1567
1568          /* set LSA summary to send buffer */
1569          lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
1570          OSPF6_MESSAGE_ATTACH (message, lsa_header,
1571                                sizeof (struct ospf6_lsa_header));
1572        }
1573    }
1574
1575  /* send dbdesc */
1576  ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr,
1577                      o6n->ospf6_interface->interface->ifindex);
1578
1579  /* if master, set futher retransmission */
1580  if (DD_IS_MSBIT_SET (o6n->dbdesc_bits))
1581    o6n->thread_rxmt_dbdesc =
1582      thread_add_timer (master, ospf6_send_dbdesc_rxmt,
1583                        o6n, o6n->ospf6_interface->rxmt_interval);
1584
1585  /* statistics */
1586  o6n->ospf6_stat_retrans_dbdesc++;
1587
1588  return 0;
1589}
1590
1591int
1592ospf6_send_dbdesc (struct thread *thread)
1593{
1594  struct ospf6_neighbor *o6n;
1595  struct ospf6_lsa *lsa;
1596  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1597  struct ospf6_dbdesc dbdesc;
1598  struct ospf6_lsdb_node node;
1599
1600  o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1601  assert (o6n);
1602
1603  /* clear thread */
1604  o6n->thread_send_dbdesc = (struct thread *) NULL;
1605  if (o6n->thread_rxmt_dbdesc)
1606    thread_cancel (o6n->thread_rxmt_dbdesc);
1607  o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
1608
1609  /* if state less than ExStart, do nothing */
1610  if (o6n->state < NBS_EXSTART)
1611    return 0;
1612
1613  OSPF6_MESSAGE_CLEAR (message);
1614  OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc));
1615
1616  /* clear previous LSA summary sent */
1617  ospf6_lsdb_remove_all (o6n->dbdesc_list);
1618  assert (o6n->dbdesc_list->count == 0);
1619
1620  /* if this is not initial, set LSA summary to dbdesc */
1621  if (! DD_IS_IBIT_SET (o6n->dbdesc_bits))
1622    {
1623      for (ospf6_lsdb_head (&node, o6n->summary_list);
1624           ! ospf6_lsdb_is_end (&node);
1625           ospf6_lsdb_next (&node))
1626        {
1627          lsa = node.lsa;
1628
1629          /* MTU check */
1630          if (OSPF6_MESSAGE_LENGTH (message)
1631              + sizeof (struct ospf6_lsa_header)
1632              + sizeof (struct ospf6_header)
1633              > o6n->ospf6_interface->ifmtu)
1634            break;
1635
1636          /* debug */
1637          if (IS_OSPF6_DUMP_DBDESC)
1638            zlog_info ("Include DbDesc: %s", lsa->str);
1639
1640          /* attach to dbdesclist */
1641          ospf6_neighbor_dbdesc_add (lsa, o6n);
1642          /* detach from summarylist */
1643          ospf6_neighbor_summary_remove (lsa, o6n);
1644
1645          /* set age and add InfTransDelay */
1646          ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
1647
1648          /* set LSA summary to send buffer */
1649          OSPF6_MESSAGE_ATTACH (message, lsa->header,
1650                                sizeof (struct ospf6_lsa_header));
1651        }
1652
1653      if (o6n->summary_list->count == 0)
1654        {
1655          /* Clear more bit */
1656          DD_MBIT_CLEAR (o6n->dbdesc_bits);
1657
1658          /* slave must schedule ExchangeDone on sending, here */
1659          if (! DD_IS_MSBIT_SET (o6n->dbdesc_bits))
1660            {
1661              if (! DD_IS_MBIT_SET (o6n->dbdesc_bits) &&
1662                  ! DD_IS_MBIT_SET (o6n->last_dd.bits))
1663                thread_add_event (master, exchange_done, o6n, 0);
1664            }
1665        }
1666    }
1667
1668  /* if this is initial, set seqnum */
1669  if (DDBIT_IS_INITIAL (o6n->dbdesc_bits))
1670    ospf6_dbdesc_seqnum_init (o6n);
1671
1672  /* set dbdesc */
1673  memcpy (dbdesc.options, o6n->ospf6_interface->area->options,
1674          sizeof (dbdesc.options));
1675  dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu);
1676  dbdesc.bits = o6n->dbdesc_bits;
1677  dbdesc.seqnum = htonl (o6n->dbdesc_seqnum);
1678
1679  /* send dbdesc */
1680  ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr,
1681                      o6n->ospf6_interface->interface->ifindex);
1682
1683  /* if master, set retransmission */
1684  if (DD_IS_MSBIT_SET (o6n->dbdesc_bits))
1685    o6n->thread_rxmt_dbdesc =
1686      thread_add_timer (master, ospf6_send_dbdesc_rxmt,
1687                          o6n, o6n->ospf6_interface->rxmt_interval);
1688
1689  /* statistics */
1690  o6n->lsa_send[OSPF6_MESSAGE_TYPE_DBDESC] += o6n->dbdesc_list->count;
1691
1692  return 0;
1693}
1694
1695int
1696ospf6_send_lsreq_rxmt (struct thread *thread)
1697{
1698  struct ospf6_neighbor *o6n;
1699
1700  o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1701  assert (o6n);
1702
1703  o6n->thread_rxmt_lsreq = (struct thread *) NULL;
1704  o6n->thread_send_lsreq = thread_add_event (master, ospf6_send_lsreq, o6n, 0);
1705  return 0;
1706}
1707
1708int
1709ospf6_send_lsreq (struct thread *thread)
1710{
1711  struct ospf6_neighbor *o6n;
1712  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1713  struct ospf6_lsreq lsreq[OSPF6_MESSAGE_IOVEC_SIZE];
1714  struct ospf6_lsa *lsa;
1715  struct ospf6_lsdb_node node;
1716  int i;
1717
1718  o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1719  assert (o6n);
1720
1721  /* LSReq will be send only in ExStart or Loading */
1722  if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING)
1723    return 0;
1724
1725  /* clear thread */
1726  o6n->thread_send_lsreq = (struct thread *) NULL;
1727  if (o6n->thread_rxmt_lsreq)
1728    thread_cancel (o6n->thread_rxmt_lsreq);
1729  o6n->thread_rxmt_lsreq = (struct thread *) NULL;
1730
1731  /* schedule loading_done if request list is empty */
1732  if (o6n->request_list->count == 0)
1733    {
1734      thread_add_event (master, loading_done, o6n, 0);
1735      return 0;
1736    }
1737
1738  /* clear message buffer */
1739  OSPF6_MESSAGE_CLEAR (message);
1740
1741  i = 0;
1742  for (ospf6_lsdb_head (&node, o6n->request_list);
1743       ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
1744    {
1745      lsa = node.lsa;
1746
1747      /* Buffer Overflow */
1748      if (i >= OSPF6_MESSAGE_IOVEC_SIZE)
1749        break;
1750
1751      /* I/F MTU check */
1752      if (OSPF6_MESSAGE_LENGTH (message)
1753          + sizeof (struct ospf6_lsreq)
1754          + sizeof (struct ospf6_header)
1755          > o6n->ospf6_interface->ifmtu)
1756        break;
1757
1758      lsreq[i].mbz = 0;
1759      lsreq[i].type = lsa->header->type;
1760      lsreq[i].id = lsa->header->id;
1761      lsreq[i].adv_router = lsa->header->adv_router;
1762
1763      OSPF6_MESSAGE_ATTACH (message, &lsreq[i], sizeof (struct ospf6_lsreq));
1764      i++;
1765    }
1766
1767  ospf6_message_send (OSPF6_MESSAGE_TYPE_LSREQ, message, &o6n->hisaddr,
1768                      o6n->ospf6_interface->interface->ifindex);
1769
1770  /* set retransmit thread */
1771  o6n->thread_rxmt_lsreq =
1772    thread_add_timer (master, ospf6_send_lsreq_rxmt,
1773                      o6n, o6n->ospf6_interface->rxmt_interval);
1774
1775  /* statistics */
1776  o6n->lsa_send[OSPF6_MESSAGE_TYPE_LSREQ] += i;
1777
1778  return 0;
1779}
1780
1781/* Send LSUpdate directly to the neighbor, from his retransmission list */
1782int
1783ospf6_send_lsupdate_rxmt (struct thread *thread)
1784{
1785  struct ospf6_neighbor *o6n;
1786  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1787  struct ospf6_lsupdate lsupdate;
1788  struct ospf6_lsa *lsa;
1789  struct ospf6_lsdb_node node;
1790
1791  o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
1792  assert (o6n);
1793
1794  o6n->send_update = (struct thread *) NULL;
1795
1796  if (o6n->ospf6_interface->state <= IFS_WAITING)
1797    return -1;
1798
1799  /* clear message buffer */
1800  OSPF6_MESSAGE_CLEAR (message);
1801
1802  /* set lsupdate header */
1803  lsupdate.lsupdate_num = 0; /* set gradually */
1804  OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
1805
1806  /* for each LSA listed on retransmission-list */
1807  for (ospf6_lsdb_head (&node, o6n->retrans_list);
1808       ! ospf6_lsdb_is_end (&node);
1809       ospf6_lsdb_next (&node))
1810    {
1811      lsa = node.lsa;
1812
1813      /* I/F MTU check */
1814      if (OSPF6_MESSAGE_LENGTH (message)
1815          + sizeof (struct ospf6_lsupdate)
1816          + sizeof (struct ospf6_header)
1817          + ntohs (lsa->header->length)
1818          > o6n->ospf6_interface->ifmtu)
1819        break;
1820
1821      ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
1822      OSPF6_MESSAGE_ATTACH (message, lsa->header, ntohs (lsa->header->length));
1823      lsupdate.lsupdate_num++;
1824    }
1825
1826  /* check and correct lsupdate */
1827  if (lsupdate.lsupdate_num == 0)
1828    return 0;
1829  lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num);
1830
1831  /* statistics */
1832  o6n->ospf6_stat_retrans_lsupdate++;
1833
1834  ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message,
1835                      &o6n->hisaddr, o6n->ospf6_interface->if_id);
1836
1837  o6n->send_update = thread_add_timer (master, ospf6_send_lsupdate_rxmt, o6n,
1838                                       o6n->ospf6_interface->rxmt_interval);
1839  return 0;
1840}
1841
1842/* Send LSUpdate containing one LSA directly to the neighbor.
1843   This is "implied acknowledgement" */
1844void
1845ospf6_send_lsupdate_direct (struct ospf6_lsa *lsa, struct ospf6_neighbor *o6n)
1846{
1847  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1848  struct ospf6_lsupdate lsupdate;
1849  int lsa_len;
1850
1851  /* clear message buffer */
1852  OSPF6_MESSAGE_CLEAR (message);
1853
1854  /* set lsupdate header */
1855  lsupdate.lsupdate_num = ntohl (1);
1856  OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
1857
1858  /* set one LSA */
1859  lsa_len = ntohs (lsa->lsa_hdr->lsh_len);
1860  ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
1861  OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len);
1862
1863  ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &o6n->hisaddr,
1864                      o6n->ospf6_interface->if_id);
1865}
1866
1867/* Send LSUpdate containing one LSA by multicast.
1868   On non-broadcast link, send it to each neighbor by unicast.
1869   This is ordinary flooding */
1870void
1871ospf6_send_lsupdate_flood (struct ospf6_lsa *lsa, struct ospf6_interface *o6i)
1872{
1873  struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
1874  struct ospf6_lsupdate lsupdate;
1875  struct in6_addr dst;
1876  int lsa_len;
1877
1878  /* clear message buffer */
1879  OSPF6_MESSAGE_CLEAR (message);
1880
1881  /* set lsupdate header */
1882  lsupdate.lsupdate_num = ntohl (1);
1883  OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
1884
1885  /* set one LSA */
1886  lsa_len = ntohs (lsa->lsa_hdr->lsh_len);
1887  ospf6_lsa_age_update_to_send (lsa, o6i->transdelay);
1888  OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len);
1889
1890  if (if_is_broadcast (o6i->interface))
1891    {
1892      /* set destination */
1893      if (o6i->state == IFS_DR || o6i->state == IFS_BDR)
1894        inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
1895      else
1896        inet_pton (AF_INET6, ALLDROUTERS6, &dst);
1897    }
1898  else
1899    {
1900      /* IPv6 relies on link local multicast */
1901      inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
1902    }
1903
1904  ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &dst,
1905                      o6i->if_id);
1906}
1907
1908int
1909ospf6_send_lsack_delayed (struct thread *thread)
1910{
1911  struct ospf6_interface *o6i;
1912  struct iovec message[MAXIOVLIST];
1913  struct ospf6_lsa *lsa;
1914  struct ospf6_lsdb_node node;
1915
1916  o6i = THREAD_ARG (thread);
1917  assert (o6i);
1918
1919  o6i->thread_send_lsack_delayed = (struct thread *) NULL;
1920
1921  if (o6i->state <= IFS_WAITING)
1922    return 0;
1923
1924  if (o6i->ack_list->count == 0)
1925    return 0;
1926
1927  iov_clear (message, MAXIOVLIST);
1928
1929  for (ospf6_lsdb_head (&node, o6i->ack_list);
1930       ! ospf6_lsdb_is_end (&node);
1931       ospf6_lsdb_next (&node))
1932    {
1933      lsa = node.lsa;
1934      if (IS_OVER_MTU (message, o6i->ifmtu, sizeof (struct ospf6_lsa_hdr)))
1935        break;
1936
1937      OSPF6_MESSAGE_ATTACH (message, lsa->header,
1938                            sizeof (struct ospf6_lsa_header));
1939      ospf6_interface_delayed_ack_remove (lsa, o6i);
1940    }
1941
1942  /* statistics */
1943  o6i->ospf6_stat_delayed_lsack++;
1944
1945  switch (o6i->state)
1946    {
1947    case IFS_DR:
1948    case IFS_BDR:
1949      ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message,
1950                          &allspfrouters6.sin6_addr, o6i->if_id);
1951      break;
1952    default:
1953      ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message,
1954                          &alldrouters6.sin6_addr, o6i->if_id);
1955      break;
1956    }
1957
1958  iov_clear (message, MAXIOVLIST);
1959  return 0;
1960}
1961
1962