2014年5月21日 星期三

Linux C - gcc 預先定義的巨集

在Linux下使用gcc編譯,
有幾個內建的變數可以非常好用,
在Debug的時候,
占非常重要的角色。

1. __BASE_FILE__
完整的原始檔案路徑

2. __cplusplus
表示該檔案由 g++ 所編譯,當成 C++ 的檔案

3. __DATE__
編譯的日期

4. __TIME__
編譯的時間

5. __FILE__
原始檔名

6. __LINE__
所在行數

7. __VERSION__
gcc 版本

8. __func__
替代 __FUNCTION__,__FUNCTION__ 已被 GNU 不推薦使用

參考資料:
LinuxC – gcc 預先定義的巨集

2014年5月9日 星期五

如何開啟windows 7的telnet與tftp

為了把image燒到測試的板子上面,
必需要用到tftp這一個指令。

而在windows 7預設是把telnet與tftp關掉。

如何把這兩個功能打開呢?

開啟控制台→程式集→開啟或關閉Windows功能



選擇「Telnet用戶端」與「TFTP用戶端」的選擇,
再按確定。



這樣就可以使用telnet與tftp了。

參考資料:
Win7 開啟 telnet and tftp

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));

}