1/*
2 * Prefix related functions.
3 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING.  If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "prefix.h"
26#include "vty.h"
27#include "sockunion.h"
28#include "memory.h"
29#include "log.h"
30
31/* Maskbit. */
32static u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
33			         0xf8, 0xfc, 0xfe, 0xff};
34
35/* Number of bits in prefix type. */
36#ifndef PNBBY
37#define PNBBY 8
38#endif /* PNBBY */
39
40#define MASKBIT(offset)  ((0xff << (PNBBY - (offset))) & 0xff)
41
42#ifdef FOX_SUPPORT
43/* Address Famiy Identifier to Address Family converter. */
44int
45afi2family (int afi)
46{
47  if (afi == AFI_IP)
48    return AF_INET;
49#ifdef HAVE_IPV6
50  else if (afi == AFI_IP6)
51    return AF_INET6;
52#endif /* HAVE_IPV6 */
53  return 0;
54}
55
56int
57family2afi (int family)
58{
59  if (family == AF_INET)
60    return AFI_IP;
61#ifdef HAVE_IPV6
62  else if (family == AF_INET6)
63    return AFI_IP6;
64#endif /* HAVE_IPV6 */
65  return 0;
66}
67#endif /* FOX_SUPPORT */
68
69/* If n includes p prefix then return 1 else return 0. */
70int
71prefix_match (struct prefix *n, struct prefix *p)
72{
73  int offset;
74  int shift;
75
76  /* Set both prefix's head pointer. */
77  u_char *np = (u_char *)&n->u.prefix;
78  u_char *pp = (u_char *)&p->u.prefix;
79
80  /* If n's prefix is longer than p's one return 0. */
81  if (n->prefixlen > p->prefixlen)
82    return 0;
83
84  offset = n->prefixlen / PNBBY;
85  shift =  n->prefixlen % PNBBY;
86
87  if (shift)
88    if (maskbit[shift] & (np[offset] ^ pp[offset]))
89      return 0;
90
91  while (offset--)
92    if (np[offset] != pp[offset])
93      return 0;
94  return 1;
95}
96
97/* Copy prefix from src to dest. */
98void
99prefix_copy (struct prefix *dest, struct prefix *src)
100{
101  dest->family = src->family;
102  dest->prefixlen = src->prefixlen;
103
104  if (src->family == AF_INET)
105    dest->u.prefix4 = src->u.prefix4;
106#ifdef HAVE_IPV6
107  else if (src->family == AF_INET6)
108    dest->u.prefix6 = src->u.prefix6;
109#endif /* HAVE_IPV6 */
110  else if (src->family == AF_UNSPEC)
111    {
112      dest->u.lp.id = src->u.lp.id;
113      dest->u.lp.adv_router = src->u.lp.adv_router;
114    }
115  else
116    {
117#ifdef FOX_RIP_DEBUG
118      zlog (NULL, LOG_INFO, "prefix_copy(): Unknown address family %d",
119	      src->family);
120#endif /* FOX_RIP_DEBUG */
121      assert (0);
122    }
123}
124
125/* If both prefix structure is same then return 1 else return 0. */
126int
127prefix_same (struct prefix *p1, struct prefix *p2)
128{
129  if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)
130    {
131      if (p1->family == AF_INET)
132	if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
133	  return 1;
134#ifdef HAVE_IPV6
135      if (p1->family == AF_INET6 )
136	if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))
137	  return 1;
138#endif /* HAVE_IPV6 */
139    }
140  return 0;
141}
142#ifdef FOX_SUPPORT
143/* When both prefix structure is not same, but will be same after
144   applying mask, return 0. otherwise, return 1 */
145int
146prefix_cmp (struct prefix *p1, struct prefix *p2)
147{
148  int offset;
149  int shift;
150
151  /* Set both prefix's head pointer. */
152  u_char *pp1 = (u_char *)&p1->u.prefix;
153  u_char *pp2 = (u_char *)&p2->u.prefix;
154
155  if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
156    return 1;
157
158  offset = p1->prefixlen / 8;
159  shift = p1->prefixlen % 8;
160
161  if (shift)
162    if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))
163      return 1;
164
165  while (offset--)
166    if (pp1[offset] != pp2[offset])
167      return 1;
168
169  return 0;
170}
171#endif
172
173#if defined(FOX_CMD_SUPPORT) || defined(FOX_RIP_DEBUG)
174/* Return prefix family type string. */
175char *
176prefix_family_str (struct prefix *p)
177{
178  if (p->family == AF_INET)
179    return "inet";
180#ifdef HAVE_IPV6
181  if (p->family == AF_INET6)
182    return "inet6";
183#endif /* HAVE_IPV6 */
184  return "unspec";
185}
186#endif /* FOX_SUPPORT */
187
188/* Allocate new prefix_ipv4 structure. */
189struct prefix_ipv4 *
190prefix_ipv4_new ()
191{
192  struct prefix_ipv4 *p;
193
194  p = XCALLOC (MTYPE_PREFIX_IPV4, sizeof *p);
195  p->family = AF_INET;
196  return p;
197}
198
199/* Free prefix_ipv4 structure. */
200void
201prefix_ipv4_free (struct prefix_ipv4 *p)
202{
203  XFREE (MTYPE_PREFIX_IPV4, p);
204}
205
206/* When string format is invalid return 0. */
207int
208str2prefix_ipv4 (char *str, struct prefix_ipv4 *p)
209{
210  int ret;
211  int plen;
212  char *pnt;
213  char *cp;
214
215  /* Find slash inside string. */
216  pnt = strchr (str, '/');
217
218  /* String doesn't contail slash. */
219  if (pnt == NULL)
220    {
221      /* Convert string to prefix. */
222      ret = inet_aton (str, &p->prefix);
223      if (ret == 0)
224	return 0;
225
226      /* If address doesn't contain slash we assume it host address. */
227      p->family = AF_INET;
228      p->prefixlen = IPV4_MAX_BITLEN;
229
230      return ret;
231    }
232  else
233    {
234      cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);
235      strncpy (cp, str, pnt - str);
236      *(cp + (pnt - str)) = '\0';
237      ret = inet_aton (cp, &p->prefix);
238      XFREE (MTYPE_TMP, cp);
239
240      /* Get prefix length. */
241      plen = (u_char) atoi (++pnt);
242      if (plen > 32)
243	return 0;
244
245      p->family = AF_INET;
246      p->prefixlen = plen;
247    }
248
249  return ret;
250}
251
252/* Convert masklen into IP address's netmask. */
253void
254masklen2ip (int masklen, struct in_addr *netmask)
255{
256  u_char *pnt;
257  int bit;
258  int offset;
259
260  memset (netmask, 0, sizeof (struct in_addr));
261  pnt = (unsigned char *) netmask;
262
263  offset = masklen / 8;
264  bit = masklen % 8;
265
266  while (offset--)
267    *pnt++ = 0xff;
268
269  if (bit)
270    *pnt = maskbit[bit];
271}
272
273/* Convert IP address's netmask into integer. We assume netmask is
274   sequential one. Argument netmask should be network byte order. */
275u_char
276ip_masklen (struct in_addr netmask)
277{
278  u_char len;
279  u_char *pnt;
280  u_char *end;
281  u_char val;
282
283  len = 0;
284  pnt = (u_char *) &netmask;
285  end = pnt + 4;
286
287  while ((*pnt == 0xff) && pnt < end)
288    {
289      len+= 8;
290      pnt++;
291    }
292
293  if (pnt < end)
294    {
295      val = *pnt;
296      while (val)
297	{
298	  len++;
299	  val <<= 1;
300	}
301    }
302  return len;
303}
304
305/* Apply mask to IPv4 prefix. */
306void
307apply_mask_ipv4 (struct prefix_ipv4 *p)
308{
309  u_char *pnt;
310  int index;
311  int offset;
312
313  index = p->prefixlen / 8;
314
315  if (index < 4)
316    {
317      pnt = (u_char *) &p->prefix;
318      offset = p->prefixlen % 8;
319
320      pnt[index] &= maskbit[offset];
321      index++;
322
323      while (index < 4)
324	pnt[index++] = 0;
325    }
326}
327
328/* If prefix is 0.0.0.0/0 then return 1 else return 0. */
329int
330prefix_ipv4_any (struct prefix_ipv4 *p)
331{
332  return (p->prefix.s_addr == 0 && p->prefixlen == 0);
333}
334
335#ifdef HAVE_IPV6
336
337/* Allocate a new ip version 6 route */
338struct prefix_ipv6 *
339prefix_ipv6_new ()
340{
341  struct prefix_ipv6 *p;
342
343  p = XCALLOC (MTYPE_PREFIX_IPV6, sizeof (struct prefix_ipv6));
344  p->family = AF_INET6;
345  return p;
346}
347
348/* Free prefix for IPv6. */
349void
350prefix_ipv6_free (struct prefix_ipv6 *p)
351{
352  XFREE (MTYPE_PREFIX_IPV6, p);
353}
354
355/* If given string is valid return pin6 else return NULL */
356int
357str2prefix_ipv6 (char *str, struct prefix_ipv6 *p)
358{
359  char *pnt;
360  char *cp;
361  int ret;
362
363  pnt = strchr (str, '/');
364
365  /* If string doesn't contain `/' treat it as host route. */
366  if (pnt == NULL)
367    {
368      ret = inet_pton (AF_INET6, str, &p->prefix);
369      if (ret != 1)
370	return 0;
371      p->prefixlen = IPV6_MAX_BITLEN;
372    }
373  else
374    {
375      int plen;
376
377      cp = XMALLOC (0, (pnt - str) + 1);
378      strncpy (cp, str, pnt - str);
379      *(cp + (pnt - str)) = '\0';
380      ret = inet_pton (AF_INET6, cp, &p->prefix);
381      free (cp);
382      if (ret != 1)
383	return 0;
384      plen = (u_char) atoi (++pnt);
385      if (plen > 128)
386	return 0;
387      p->prefixlen = plen;
388    }
389  p->family = AF_INET6;
390
391  return ret;
392}
393
394/* Convert struct in6_addr netmask into integer. */
395int
396ip6_masklen (struct in6_addr netmask)
397{
398  int len = 0;
399  unsigned char val;
400  unsigned char *pnt;
401
402  pnt = (unsigned char *) & netmask;
403
404  while ((*pnt == 0xff) && len < 128)
405    {
406      len += 8;
407      pnt++;
408    }
409
410  if (len < 128)
411    {
412      val = *pnt;
413      while (val)
414	{
415	  len++;
416	  val <<= 1;
417	}
418    }
419  return len;
420}
421
422void
423masklen2ip6 (int masklen, struct in6_addr *netmask)
424{
425  unsigned char *pnt;
426  int bit;
427  int offset;
428
429  memset (netmask, 0, sizeof (struct in6_addr));
430  pnt = (unsigned char *) netmask;
431
432  offset = masklen / 8;
433  bit = masklen % 8;
434
435  while (offset--)
436    *pnt++ = 0xff;
437
438  if (bit)
439    *pnt = maskbit[bit];
440}
441
442void
443apply_mask_ipv6 (struct prefix_ipv6 *p)
444{
445  u_char *pnt;
446  int index;
447  int offset;
448
449  index = p->prefixlen / 8;
450
451  if (index < 16)
452    {
453      pnt = (u_char *) &p->prefix;
454      offset = p->prefixlen % 8;
455
456      pnt[index] &= maskbit[offset];
457      index++;
458
459      while (index < 16)
460	pnt[index++] = 0;
461    }
462}
463
464void
465str2in6_addr (char *str, struct in6_addr *addr)
466{
467  int i;
468  unsigned int x;
469
470  /* %x must point to unsinged int */
471  for (i = 0; i < 16; i++)
472    {
473      sscanf (str + (i * 2), "%02x", &x);
474      addr->s6_addr[i] = x & 0xff;
475    }
476}
477#endif /* HAVE_IPV6 */
478
479void
480apply_mask (struct prefix *p)
481{
482  switch (p->family)
483    {
484      case AF_INET:
485        apply_mask_ipv4 ((struct prefix_ipv4 *)p);
486        break;
487#ifdef HAVE_IPV6
488      case AF_INET6:
489        apply_mask_ipv6 ((struct prefix_ipv6 *)p);
490        break;
491#endif /* HAVE_IPV6 */
492      default:
493        break;
494    }
495  return;
496}
497
498#ifdef FOX_SUPPORT
499
500/* Utility function of convert between struct prefix <=> union sockunion */
501struct prefix *
502sockunion2prefix (union sockunion *dest,
503		  union sockunion *mask)
504{
505  if (dest->sa.sa_family == AF_INET)
506    {
507      struct prefix_ipv4 *p;
508
509      p = prefix_ipv4_new ();
510      p->family = AF_INET;
511      p->prefix = dest->sin.sin_addr;
512      p->prefixlen = ip_masklen (mask->sin.sin_addr);
513      return (struct prefix *) p;
514    }
515#ifdef HAVE_IPV6
516  if (dest->sa.sa_family == AF_INET6)
517    {
518      struct prefix_ipv6 *p;
519
520      p = prefix_ipv6_new ();
521      p->family = AF_INET6;
522      p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
523      memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
524      return (struct prefix *) p;
525    }
526#endif /* HAVE_IPV6 */
527  return NULL;
528}
529
530/* Utility function of convert between struct prefix <=> union sockunion */
531struct prefix *
532sockunion2hostprefix (union sockunion *su)
533{
534  if (su->sa.sa_family == AF_INET)
535    {
536      struct prefix_ipv4 *p;
537
538      p = prefix_ipv4_new ();
539      p->family = AF_INET;
540      p->prefix = su->sin.sin_addr;
541      p->prefixlen = IPV4_MAX_BITLEN;
542      return (struct prefix *) p;
543    }
544#ifdef HAVE_IPV6
545  if (su->sa.sa_family == AF_INET6)
546    {
547      struct prefix_ipv6 *p;
548
549      p = prefix_ipv6_new ();
550      p->family = AF_INET6;
551      p->prefixlen = IPV6_MAX_BITLEN;
552      memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));
553      return (struct prefix *) p;
554    }
555#endif /* HAVE_IPV6 */
556  return NULL;
557}
558#endif /* FOX_SUPPORT */
559
560int
561prefix_blen (struct prefix *p)
562{
563  switch (p->family)
564    {
565    case AF_INET:
566      return IPV4_MAX_BYTELEN;
567      break;
568#ifdef HAVE_IPV6
569    case AF_INET6:
570      return IPV6_MAX_BYTELEN;
571      break;
572#endif /* HAVE_IPV6 */
573    }
574  return 0;
575}
576
577#ifdef FOX_SUPPORT
578/* Generic function for conversion string to struct prefix. */
579int
580str2prefix (char *str, struct prefix *p)
581{
582  int ret;
583
584  /* First we try to convert string to struct prefix_ipv4. */
585  ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);
586  if (ret)
587    return ret;
588
589#ifdef HAVE_IPV6
590  /* Next we try to convert string to struct prefix_ipv6. */
591  ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);
592  if (ret)
593    return ret;
594#endif /* HAVE_IPV6 */
595
596  return 0;
597}
598
599int
600prefix2str (struct prefix *p, char *str, int size)
601{
602  char buf[BUFSIZ];
603
604  inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);
605  snprintf (str, size, "%s/%d", buf, p->prefixlen);
606  return 0;
607}
608#endif /* FOX_SUPPORT */
609
610struct prefix *
611prefix_new ()
612{
613  struct prefix *p;
614
615  p = XCALLOC (MTYPE_PREFIX, sizeof *p);
616  return p;
617}
618
619/* Free prefix structure. */
620void
621prefix_free (struct prefix *p)
622{
623  XFREE (MTYPE_PREFIX, p);
624}
625
626#ifdef FOX_SUPPORT
627/* Utility function.  Check the string only contains digit
628   character. */
629int
630all_digit (char *str)
631{
632  for (; *str != '\0'; str++)
633    if (!isdigit ((int) *str))
634      return 0;
635  return 1;
636}
637#endif /* FOX_SUPPORT */
638
639/* Utility function to convert ipv4 prefixes to Classful prefixes */
640void apply_classful_mask_ipv4 (struct prefix_ipv4 *p)
641{
642
643  u_int32_t destination;
644
645  destination = ntohl (p->prefix.s_addr);
646
647  if (p->prefixlen == 32);
648  /* do nothing for host routes */
649  else if (IN_CLASSC (destination))
650    {
651      p->prefixlen=24;
652      apply_mask_ipv4(p);
653    }
654  else if (IN_CLASSB(destination))
655    {
656      p->prefixlen=16;
657      apply_mask_ipv4(p);
658    }
659  else
660    {
661      p->prefixlen=8;
662      apply_mask_ipv4(p);
663    }
664}
665#ifdef FOX_SUPPORT
666/* Utility function to convert ipv4 netmask to prefixes
667   ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
668   ex.) "1.0.0.0" NULL => "1.0.0.0/8"                   */
669int
670netmask_str2prefix_str (char *net_str, char *mask_str, char *prefix_str)
671{
672  struct in_addr network;
673  struct in_addr mask;
674  u_char prefixlen;
675  u_int32_t destination;
676  int ret;
677
678  ret = inet_aton (net_str, &network);
679  if (! ret)
680    return 0;
681
682  if (mask_str)
683    {
684      ret = inet_aton (mask_str, &mask);
685      if (! ret)
686        return 0;
687
688      prefixlen = ip_masklen (mask);
689    }
690  else
691    {
692      destination = ntohl (network.s_addr);
693
694      if (network.s_addr == 0)
695	prefixlen = 0;
696      else if (IN_CLASSC (destination))
697	prefixlen = 24;
698      else if (IN_CLASSB (destination))
699	prefixlen = 16;
700      else if (IN_CLASSA (destination))
701	prefixlen = 8;
702      else
703	return 0;
704    }
705
706  sprintf (prefix_str, "%s/%d", net_str, prefixlen);
707
708  return 1;
709}
710
711#endif /* FOX_SUPPORT */
712