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#if 0
23
24#include <zebra.h>
25
26#include "log.h"
27#include "prefix.h"
28#include "memory.h"
29#include "linklist.h"
30
31#include "ospf6_prefix.h"
32
33#else /*0*/
34
35#include "ospf6d.h"
36
37#endif /*0*/
38
39struct ospf6_prefix *
40ospf6_prefix_create (u_int8_t options, u_int16_t metric, struct prefix_ipv6 *p)
41{
42  struct prefix_ipv6 prefix;
43  struct ospf6_prefix *o6p;
44  size_t size;
45
46  /* copy prefix and apply mask */
47  prefix_copy ((struct prefix *) &prefix, (struct prefix *) p);
48  apply_mask_ipv6 (&prefix);
49
50  size = OSPF6_PREFIX_SPACE (prefix.prefixlen) + sizeof (struct ospf6_prefix);
51  o6p = (struct ospf6_prefix *) XMALLOC (MTYPE_OSPF6_PREFIX, size);
52  if (! o6p)
53    zlog_warn ("Can't allocate memory for ospf6 prefix: size: %d", size);
54  else
55    memset (o6p, 0, size);
56
57  o6p->prefix_length = prefix.prefixlen;
58  o6p->prefix_options = options;
59  o6p->prefix_metric = htons (metric);
60  memcpy (o6p + 1, &prefix.prefix, OSPF6_PREFIX_SPACE (prefix.prefixlen));
61
62  return o6p;
63}
64
65void
66ospf6_prefix_delete (struct ospf6_prefix *p)
67{
68  XFREE (MTYPE_OSPF6_PREFIX, p);
69}
70
71int
72ospf6_prefix_issame (struct ospf6_prefix *p1, struct ospf6_prefix *p2)
73{
74  if (p1->prefix_length != p2->prefix_length)
75    return 0;
76  if (memcmp (&p1->u, &p2->u, sizeof (p1->u)))
77    return 0;
78  if (memcmp (p1 + 1, p2 + 1, OSPF6_PREFIX_SPACE (p1->prefix_length)))
79    return 0;
80  return 1;
81}
82
83struct ospf6_prefix *
84ospf6_prefix_lookup (list l, struct ospf6_prefix *p1)
85{
86  listnode node;
87  struct ospf6_prefix *p2;
88  for (node = listhead (l); node; nextnode (node))
89    {
90      p2 = (struct ospf6_prefix *) getdata (node);
91      if (ospf6_prefix_issame (p1, p2))
92        return p2;
93    }
94  return NULL;
95}
96
97/* add a copy of given prefix to the list */
98void
99ospf6_prefix_add (list l, struct ospf6_prefix *p)
100{
101  struct ospf6_prefix *add;
102  add = (struct ospf6_prefix *) XMALLOC (MTYPE_OSPF6_PREFIX,
103                                         OSPF6_PREFIX_SIZE (p));
104  if (add == NULL)
105    {
106      zlog_warn ("Can't allocate memory for ospf6 prefix");
107      return;
108    }
109  else
110    memcpy (add, p, OSPF6_PREFIX_SIZE (p));
111
112  if (ospf6_prefix_lookup (l, add))
113    {
114      ospf6_prefix_delete (add);
115      return;
116    }
117  listnode_add (l, add);
118}
119
120void
121ospf6_prefix_remove (list l, struct ospf6_prefix *p)
122{
123  struct ospf6_prefix *rem;
124  rem = ospf6_prefix_lookup (l, p);
125  if (rem)
126    {
127      listnode_delete (l, rem);
128      ospf6_prefix_delete (rem);
129    }
130}
131
132void
133ospf6_prefix_in6_addr (struct ospf6_prefix *o6p, struct in6_addr *in6)
134{
135  memset (in6, 0, sizeof (struct in6_addr));
136  memcpy (in6, o6p + 1, OSPF6_PREFIX_SPACE (o6p->prefix_length));
137  return;
138}
139
140char *
141ospf6_prefix_options_str (u_int8_t opt, char *buf, size_t bufsize)
142{
143  char *p, *mc, *la, *nu;
144
145  p = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_P) ? "P" : "-");
146  mc = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_MC) ? "MC" : "--");
147  la = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_LA) ? "LA" : "--");
148  nu = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_NU) ? "NU" : "--");
149
150  snprintf (buf, bufsize, "%s|%s|%s|%s", p, mc, la, nu);
151  return buf;
152}
153
154char *
155ospf6_prefix_string (struct ospf6_prefix *prefix, char *buf, size_t size)
156{
157  struct in6_addr in6;
158  char s[64];
159
160  memset (&in6, 0, sizeof (in6));
161  memcpy (&in6, prefix + 1, OSPF6_PREFIX_SPACE (prefix->prefix_length));
162  inet_ntop (AF_INET6, &in6, s, sizeof (s));
163
164  snprintf (buf, size, "%s/%d", s, prefix->prefix_length);
165  return buf;
166}
167
168void
169ospf6_prefix_copy (struct ospf6_prefix *dst, struct ospf6_prefix *src,
170                   size_t dstsize)
171{
172  size_t srcsize;
173
174  memset (dst, 0, dstsize);
175
176  srcsize = OSPF6_PREFIX_SIZE (src);
177  if (dstsize < srcsize)
178    memcpy (dst, src, dstsize);
179  else
180    memcpy (dst, src, srcsize);
181
182  return;
183}
184
185void
186ospf6_prefix_apply_mask (struct ospf6_prefix *o6p)
187{
188  u_char *pnt, mask;
189  int index, offset;
190
191  char buf[128];
192  struct in6_addr in6;
193  ospf6_prefix_in6_addr (o6p, &in6);
194  inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
195
196  pnt = (u_char *)(o6p + 1);
197  index = o6p->prefix_length / 8;
198  offset = o6p->prefix_length % 8;
199  mask = 0xff << (8 - offset);
200
201  if (index >= 16)
202    return;
203
204  pnt[index] &= mask;
205  index ++;
206
207  while (index < OSPF6_PREFIX_SPACE (o6p->prefix_length))
208    pnt[index++] = 0;
209
210  ospf6_prefix_in6_addr (o6p, &in6);
211  inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
212}
213
214