2014年5月5日 星期一

union

因為IPv6的address一共有128bit,
若要處理的話,
目前long int也只有4 bytes(32bit),
double只有8bytes(64bit)
沒有一個變數可以儲存到128bit,
這個時候就要用到union

直接寫下

/* IPv6 address */
struct in6_addr {
  union {
    uint8_t  u6_addr8[16];
    uint16_t u6_addr16[8];
    uint32_t u6_addr32[4];
  } in6_u;
#define s6_addr   in6_u.u6_addr8
#define s6_addr16  in6_u.u6_addr16
#define s6_addr32  in6_u.u6_addr32
};

這個宣告方式,可以讓128bit,
各別的使用8bit在運算。

下面是我寫的一個sub function,
也因為有了這個,
要運算IPv6才會變的比較簡單。

/*
 * Filter the IPv6 by prefix to Network ID or Interface ID
 *
 * @param IPv6_Addr_Src     the source for filtering
 * @param IPv6_Addr_Dst     the result of the filtering process
 * @param PrefixLen         the prefix of the network
 * @param MaskType          if the value is NetworkPrefix, network prefix would be reserved
 *                          if the value is InterfaceIdentifier, the interface identifier would be reserved
 */
static void
MaskIPv6 (
  struct in6_addr   IPv6_Addr_Src,
  struct in6_addr   *IPv6_Addr_Dst,
  int               PrefixLen,
  enum MaskType     Direction
  )
{
  char            *AddrPtr, *IndexAddrPtr;
  int             FullByteNumber, BitNumber;
  char            Mask;
  int             Index;
  int             CurrentPosition;

  //
  // The bytes of network id part
  //
  FullByteNumber = PrefixLen / 8;
  //
  // The bits of network id part
  //
  BitNumber = PrefixLen % 8;

  //
  // filter the bytes of Network ID part
  //
  for (CurrentPosition = 0; CurrentPosition < FullByteNumber; CurrentPosition++) {
    if (Direction == NetworkPrefix) {
      IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0xFF;
    } else {
      IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0x00;
    }
  }

  //
  // filter the bits of Network ID part and the bits of Interface ID part
  //
  Mask = 0;
  if (BitNumber != 0) {
    for (Index = 0; Index < BitNumber; Index++) {
      Mask = (Mask << 1) | 1;
    }

    for (Index = 0; Index < 8 - BitNumber; Index++) {
      Mask = Mask << 1;
    }

    if (Direction == InterfaceIdentifier) {
      Mask = ~Mask;
    }

    IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & Mask;

    CurrentPosition++;
  }

  //
  // filter the bytes of Interface ID part
  //
  for (; CurrentPosition < 16; CurrentPosition++) {
    if (Direction == NetworkPrefix) {
      IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0x00;
    } else {
      IPv6_Addr_Src.s6_addr[CurrentPosition] = IPv6_Addr_Src.s6_addr[CurrentPosition] & 0xFF;
    }
  }

  //
  // Copy the modified IPv6_Addr_Src context for return
  //
  memcpy (IPv6_Addr_Dst, &IPv6_Addr_Src, sizeof (IPv6_Addr_Src));

}

1 則留言:

阿踢博士 提到...

HI, Beej 現在有中文版囉 ^_^
http://beej-zhtw.netdpi.net/