2015年8月23日 星期日

CIDR (Classless Interdomain Routing) 與 netmask

host id, network, netmask, 搞亂我了。在電腦手動設定 ip 時, 除了 ip 還會填入 netmask, 這些資訊和 host id, network, netmask 是如何建立起來的?

你還停留在 class A, B, C 這個以 classful 分類的觀念嗎?

man inet_ntoa
Classful network addresses are now obsolete

已經告訴我們, 這已經不用了, 所以還是費點心思來把 Classless Inter-Domain Routing (CIDR) 搞懂。

cidr.cpp
 1 #include <stdio.h>
 2 #include <stdint.h>
 3 
 4 #include <sys/socket.h>
 5 #include <netinet/in.h>
 6 #include <arpa/inet.h>
 7 
 8 int main(int argc, char *argv[])
 9 {
10   struct in_addr ip, mask, network_ip;
11 
12 #if 0
13   inet_aton("192.168.6.60", &ip);
14   inet_aton("255.255.255.252", &mask);
15 #endif
16 
17 #if 0
18   inet_aton("192.168.6.60", &ip);
19   inet_aton("255.255.255.0", &mask);
20 #endif
21 
22 #if 1
23   inet_aton("192.168.6.70", &ip);
24   inet_aton("255.255.255.192", &mask);
25 #endif
26 
27   printf("ip (%x): %s\n", ntohl(ip.s_addr), inet_ntoa(ip));
28   printf("mask (%x): %s\n", ntohl(mask.s_addr), inet_ntoa(mask));
29 
30   uint32_t host = 0xffffffff ^ ntohl(mask.s_addr); // mask is network order, host is host order
31 
32 
33   uint32_t network = ntohl(ip.s_addr & mask.s_addr); // host order
34   printf("host: %d\n", host);
35 
36   network_ip.s_addr = htonl(network);
37   printf("network: %x\n", network);
38   printf("network_ip: %s\n", inet_ntoa(network_ip));
39 
40   uint32_t host_begin = network+1;
41   uint32_t host_end = host-1;
42 
43   uint32_t valid_ip_val_begin = network | host_begin;
44   uint32_t valid_ip_val_end = network | host_end;
45 
46   struct in_addr valid_ip_begin, valid_ip_end;
47   valid_ip_begin.s_addr = htonl(valid_ip_val_begin);
48   valid_ip_end.s_addr = htonl(valid_ip_val_end);
49 
50   printf("valid_ip_begin: %s\n", inet_ntoa(valid_ip_begin));
51   printf("valid_ip_end: %s\n", inet_ntoa(valid_ip_end));
52   printf("valid_ip_end_val: %x\n", valid_ip_val_end);
53 
54   return 0;
55 }

怎麼從輸入的 ip, netmask 得到這些資訊呢?

ip: 192.168.6.60
netmask: 255.255.255.252

以上述為例, ip 是不能亂輸入的, 如果 netmask 是這樣, 那合法的 ip 只有 192.168.6.61, 192.168.6.62。

先找出 host (使用 xor 運算) 和 network (使用 and 運算)

host = 0xffffffff ^ 192.168.6.60 = 3
cidr network = 192.168.6.60 &  255.255.255.252 =  192.168.6.60

host 的 3 是兩個 bit 的意思。

若 netmask 改為 255.255.255.0 則會得到
0xffffffff ^ 255.255.255.0 = 0xff
表示 host 有 8 個 bits。

兩個 bit 全 0 或是全 1 不能使用, 所以只剩下 01, 10 可用, 也就是 1,2。
在 or 上 network 就是
192.168.6.61
192.168.6.62
所以合法的 ip 只能設定這兩個。

再舉一個例子:
ip: 192.168.6.70                                                
mask: 255.255.255.192  

host: 0xffffffff ^ 255.255.255.192 = 3f => 6 個 bits
network: 192.168.6.70 (0xc0a80646) &  255.255.255.192 (0xffffffc0) = 192.168.6.64 (0x0xC0A80640)

host 在 6 bits 之間: 000001 ~ 111110 => 1 ~ 126
再和 network or 起來就是合法 ip : 192.168.6.65 ~ 192.168.6.126

我在 windows xp 裡頭的 ip 設定測試過, 結果是一樣的。計算過程要以 host order 計算, 免得出錯。拿出你的計算機吧!

ref:
第二章、基礎網路概念

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。