⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prefix.c

📁 zebra测试源代码用于 SOCKET 通信
💻 C
字号:
/* * Prefix related functions. * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING.  If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA.   */#include <zebra.h>#include "prefix.h"#include "vty.h"#include "sockunion.h"#include "memory.h"#include "log.h"/* Maskbit. */static u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,			         0xf8, 0xfc, 0xfe, 0xff};/* Number of bits in prefix type. */#ifndef PNBBY#define PNBBY 8#endif /* PNBBY */#define MASKBIT(offset)  ((0xff << (PNBBY - (offset))) & 0xff)/* Address Famiy Identifier to Address Family converter. */intafi2family (int afi){  if (afi == AFI_IP)    return AF_INET;#ifdef HAVE_IPV6  else if (afi == AFI_IP6)    return AF_INET6;#endif /* HAVE_IPV6 */  return 0;}intfamily2afi (int family){  if (family == AF_INET)    return AFI_IP;#ifdef HAVE_IPV6  else if (family == AF_INET6)    return AFI_IP6;#endif /* HAVE_IPV6 */  return 0;}/* If n includes p prefix then return 1 else return 0. */intprefix_match (struct prefix *n, struct prefix *p){  int offset;  int shift;  /* Set both prefix's head pointer. */  u_char *np = (u_char *)&n->u.prefix;  u_char *pp = (u_char *)&p->u.prefix;  /* If n's prefix is longer than p's one return 0. */  if (n->prefixlen > p->prefixlen)    return 0;  offset = n->prefixlen / PNBBY;  shift =  n->prefixlen % PNBBY;  if (shift)    if (maskbit[shift] & (np[offset] ^ pp[offset]))      return 0;    while (offset--)    if (np[offset] != pp[offset])      return 0;  return 1;}/* Copy prefix from src to dest. */voidprefix_copy (struct prefix *dest, struct prefix *src){  dest->family = src->family;  dest->prefixlen = src->prefixlen;  if (src->family == AF_INET)    dest->u.prefix4 = src->u.prefix4;#ifdef HAVE_IPV6  else if (src->family == AF_INET6)    dest->u.prefix6 = src->u.prefix6;#endif /* HAVE_IPV6 */  else if (src->family == AF_UNSPEC)    {      dest->u.lp.id = src->u.lp.id;      dest->u.lp.adv_router = src->u.lp.adv_router;    }  else    {      zlog (NULL, LOG_INFO, "prefix_copy(): Unknown address family %d",	      src->family);      assert (0);    }}/* If both prefix structure is same then return 1 else return 0. */intprefix_same (struct prefix *p1, struct prefix *p2){  if (p1->family == p2->family && p1->prefixlen == p2->prefixlen)    {      if (p1->family == AF_INET)	if (IPV4_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))	  return 1;#ifdef HAVE_IPV6      if (p1->family == AF_INET6 )	if (IPV6_ADDR_SAME (&p1->u.prefix, &p2->u.prefix))	  return 1;#endif /* HAVE_IPV6 */    }  return 0;}/* When both prefix structure is not same, but will be same after   applying mask, return 0. otherwise, return 1 */intprefix_cmp (struct prefix *p1, struct prefix *p2){  int offset;  int shift;  /* Set both prefix's head pointer. */  u_char *pp1 = (u_char *)&p1->u.prefix;  u_char *pp2 = (u_char *)&p2->u.prefix;  if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)    return 1;  offset = p1->prefixlen / 8;  shift = p1->prefixlen % 8;  if (shift)    if (maskbit[shift] & (pp1[offset] ^ pp2[offset]))      return 1;  while (offset--)    if (pp1[offset] != pp2[offset])      return 1;  return 0;}/* Return prefix family type string. */char *prefix_family_str (struct prefix *p){  if (p->family == AF_INET)    return "inet";#ifdef HAVE_IPV6  if (p->family == AF_INET6)    return "inet6";#endif /* HAVE_IPV6 */  return "unspec";}/* Allocate new prefix_ipv4 structure. */struct prefix_ipv4 *prefix_ipv4_new (){  struct prefix_ipv4 *p;  p = XCALLOC (MTYPE_PREFIX_IPV4, sizeof *p);  p->family = AF_INET;  return p;}/* Free prefix_ipv4 structure. */voidprefix_ipv4_free (struct prefix_ipv4 *p){  XFREE (MTYPE_PREFIX_IPV4, p);}/* When string format is invalid return 0. */intstr2prefix_ipv4 (char *str, struct prefix_ipv4 *p){  int ret;  int plen;  char *pnt;  char *cp;  /* Find slash inside string. */  pnt = strchr (str, '/');  /* String doesn't contail slash. */  if (pnt == NULL)     {      /* Convert string to prefix. */      ret = inet_aton (str, &p->prefix);      if (ret == 0)	return 0;      /* If address doesn't contain slash we assume it host address. */      p->family = AF_INET;      p->prefixlen = IPV4_MAX_BITLEN;      return ret;    }  else    {      cp = XMALLOC (MTYPE_TMP, (pnt - str) + 1);      strncpy (cp, str, pnt - str);      *(cp + (pnt - str)) = '\0';      ret = inet_aton (cp, &p->prefix);      XFREE (MTYPE_TMP, cp);      /* Get prefix length. */      plen = (u_char) atoi (++pnt);      if (plen > 32)	return 0;      p->family = AF_INET;      p->prefixlen = plen;    }  return ret;}/* Convert masklen into IP address's netmask. */voidmasklen2ip (int masklen, struct in_addr *netmask){  u_char *pnt;  int bit;  int offset;  memset (netmask, 0, sizeof (struct in_addr));  pnt = (unsigned char *) netmask;  offset = masklen / 8;  bit = masklen % 8;    while (offset--)    *pnt++ = 0xff;  if (bit)    *pnt = maskbit[bit];}/* Convert IP address's netmask into integer. We assume netmask is   sequential one. Argument netmask should be network byte order. */u_charip_masklen (struct in_addr netmask){  u_char len;  u_char *pnt;  u_char *end;  u_char val;  len = 0;  pnt = (u_char *) &netmask;  end = pnt + 4;  while ((*pnt == 0xff) && pnt < end)    {      len+= 8;      pnt++;    }   if (pnt < end)    {      val = *pnt;      while (val)	{	  len++;	  val <<= 1;	}    }  return len;}/* Apply mask to IPv4 prefix. */voidapply_mask_ipv4 (struct prefix_ipv4 *p){  u_char *pnt;  int index;  int offset;  index = p->prefixlen / 8;  if (index < 4)    {      pnt = (u_char *) &p->prefix;      offset = p->prefixlen % 8;      pnt[index] &= maskbit[offset];      index++;      while (index < 4)	pnt[index++] = 0;    }}/* If prefix is 0.0.0.0/0 then return 1 else return 0. */intprefix_ipv4_any (struct prefix_ipv4 *p){  return (p->prefix.s_addr == 0 && p->prefixlen == 0);}#ifdef HAVE_IPV6/* Allocate a new ip version 6 route */struct prefix_ipv6 *prefix_ipv6_new (){  struct prefix_ipv6 *p;  p = XCALLOC (MTYPE_PREFIX_IPV6, sizeof (struct prefix_ipv6));  p->family = AF_INET6;  return p;}/* Free prefix for IPv6. */voidprefix_ipv6_free (struct prefix_ipv6 *p){  XFREE (MTYPE_PREFIX_IPV6, p);}/* If given string is valid return pin6 else return NULL */intstr2prefix_ipv6 (char *str, struct prefix_ipv6 *p){  char *pnt;  char *cp;  int ret;  pnt = strchr (str, '/');  /* If string doesn't contain `/' treat it as host route. */  if (pnt == NULL)     {      ret = inet_pton (AF_INET6, str, &p->prefix);      if (ret != 1)	return 0;      p->prefixlen = IPV6_MAX_BITLEN;    }  else     {      int plen;      cp = XMALLOC (0, (pnt - str) + 1);      strncpy (cp, str, pnt - str);      *(cp + (pnt - str)) = '\0';      ret = inet_pton (AF_INET6, cp, &p->prefix);      free (cp);      if (ret != 1)	return 0;      plen = (u_char) atoi (++pnt);      if (plen > 128)	return 0;      p->prefixlen = plen;    }  p->family = AF_INET6;  return ret;}/* Convert struct in6_addr netmask into integer. */intip6_masklen (struct in6_addr netmask){  int len = 0;  unsigned char val;  unsigned char *pnt;    pnt = (unsigned char *) & netmask;  while ((*pnt == 0xff) && len < 128)     {      len += 8;      pnt++;    }     if (len < 128)     {      val = *pnt;      while (val) 	{	  len++;	  val <<= 1;	}    }  return len;}voidmasklen2ip6 (int masklen, struct in6_addr *netmask){  unsigned char *pnt;  int bit;  int offset;  memset (netmask, 0, sizeof (struct in6_addr));  pnt = (unsigned char *) netmask;  offset = masklen / 8;  bit = masklen % 8;  while (offset--)    *pnt++ = 0xff;  if (bit)    *pnt = maskbit[bit];}voidapply_mask_ipv6 (struct prefix_ipv6 *p){  u_char *pnt;  int index;  int offset;  index = p->prefixlen / 8;  if (index < 16)    {      pnt = (u_char *) &p->prefix;      offset = p->prefixlen % 8;      pnt[index] &= maskbit[offset];      index++;      while (index < 16)	pnt[index++] = 0;    }}voidstr2in6_addr (char *str, struct in6_addr *addr){  int i;  unsigned int x;  /* %x must point to unsinged int */  for (i = 0; i < 16; i++)    {      sscanf (str + (i * 2), "%02x", &x);      addr->s6_addr[i] = x & 0xff;    }}#endif /* HAVE_IPV6 */voidapply_mask (struct prefix *p){  switch (p->family)    {      case AF_INET:        apply_mask_ipv4 ((struct prefix_ipv4 *)p);        break;#ifdef HAVE_IPV6      case AF_INET6:        apply_mask_ipv6 ((struct prefix_ipv6 *)p);        break;#endif /* HAVE_IPV6 */      default:        break;    }  return;}/* Utility function of convert between struct prefix <=> union sockunion */struct prefix *sockunion2prefix (union sockunion *dest,		  union sockunion *mask){  if (dest->sa.sa_family == AF_INET)    {      struct prefix_ipv4 *p;      p = prefix_ipv4_new ();      p->family = AF_INET;      p->prefix = dest->sin.sin_addr;      p->prefixlen = ip_masklen (mask->sin.sin_addr);      return (struct prefix *) p;    }#ifdef HAVE_IPV6  if (dest->sa.sa_family == AF_INET6)    {      struct prefix_ipv6 *p;      p = prefix_ipv6_new ();      p->family = AF_INET6;      p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);      memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));      return (struct prefix *) p;    }#endif /* HAVE_IPV6 */  return NULL;}/* Utility function of convert between struct prefix <=> union sockunion */struct prefix *sockunion2hostprefix (union sockunion *su){  if (su->sa.sa_family == AF_INET)    {      struct prefix_ipv4 *p;      p = prefix_ipv4_new ();      p->family = AF_INET;      p->prefix = su->sin.sin_addr;      p->prefixlen = IPV4_MAX_BITLEN;      return (struct prefix *) p;    }#ifdef HAVE_IPV6  if (su->sa.sa_family == AF_INET6)    {      struct prefix_ipv6 *p;      p = prefix_ipv6_new ();      p->family = AF_INET6;      p->prefixlen = IPV6_MAX_BITLEN;      memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr));      return (struct prefix *) p;    }#endif /* HAVE_IPV6 */  return NULL;}intprefix_blen (struct prefix *p){  switch (p->family)     {    case AF_INET:      return IPV4_MAX_BYTELEN;      break;#ifdef HAVE_IPV6    case AF_INET6:      return IPV6_MAX_BYTELEN;      break;#endif /* HAVE_IPV6 */    }  return 0;}/* Generic function for conversion string to struct prefix. */intstr2prefix (char *str, struct prefix *p){  int ret;  /* First we try to convert string to struct prefix_ipv4. */  ret = str2prefix_ipv4 (str, (struct prefix_ipv4 *) p);  if (ret)    return ret;#ifdef HAVE_IPV6  /* Next we try to convert string to struct prefix_ipv6. */  ret = str2prefix_ipv6 (str, (struct prefix_ipv6 *) p);  if (ret)    return ret;#endif /* HAVE_IPV6 */  return 0;}intprefix2str (struct prefix *p, char *str, int size){  char buf[BUFSIZ];  inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ);  snprintf (str, size, "%s/%d", buf, p->prefixlen);  return 0;}struct prefix *prefix_new (){  struct prefix *p;  p = XCALLOC (MTYPE_PREFIX, sizeof *p);  return p;}/* Free prefix structure. */voidprefix_free (struct prefix *p){  XFREE (MTYPE_PREFIX, p);}/* Utility function.  Check the string only contains digit   character. */intall_digit (char *str){  for (; *str != '\0'; str++)    if (!isdigit ((int) *str))      return 0;  return 1;}/* Utility function to convert ipv4 prefixes to Classful prefixes */void apply_classful_mask_ipv4 (struct prefix_ipv4 *p){  u_int32_t destination;    destination = ntohl (p->prefix.s_addr);    if (p->prefixlen == 32);  /* do nothing for host routes */  else if (IN_CLASSC (destination))     {      p->prefixlen=24;      apply_mask_ipv4(p);    }  else if (IN_CLASSB(destination))     {      p->prefixlen=16;      apply_mask_ipv4(p);    }  else     {      p->prefixlen=8;      apply_mask_ipv4(p);    }}/* Utility function to convert ipv4 netmask to prefixes    ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"   ex.) "1.0.0.0" NULL => "1.0.0.0/8"                   */intnetmask_str2prefix_str (char *net_str, char *mask_str, char *prefix_str){  struct in_addr network;  struct in_addr mask;  u_char prefixlen;  u_int32_t destination;  int ret;  ret = inet_aton (net_str, &network);  if (! ret)    return 0;  if (mask_str)    {      ret = inet_aton (mask_str, &mask);      if (! ret)        return 0;      prefixlen = ip_masklen (mask);    }  else     {      destination = ntohl (network.s_addr);      if (network.s_addr == 0)	prefixlen = 0;      else if (IN_CLASSC (destination))	prefixlen = 24;      else if (IN_CLASSB (destination))	prefixlen = 16;      else if (IN_CLASSA (destination))	prefixlen = 8;      else	return 0;    }  sprintf (prefix_str, "%s/%d", net_str, prefixlen);  return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -