pyspaに来ています
Linuxでは一つのネットワークインターフェイスに複数のIPアドレスを紐付ける方法として、
- エイリアスを使う方法 (バージョン2.0からサポート)
- ip(8)コマンドのaddr addサブコマンドを使う方法 (バージョン2.2からサポート)
があるのに、残念なことに前者しか今日まで知らなかったのでそれを書く。
この違いは、
- ioctl(2)によるインターフェイスの操作
- netlink(7)によるインターフェイスの操作
というところにも表れているので、それぞれの方法でeth0のIPアドレスを取得する方法を調べてみた。
ioctlを使う方法:
非常に単純。この方法だと紐づいているIPアドレスを1つしか取得できないことがわかる。
netlinkソケットを使う方法:
なんでこんな複雑なんだろうって思う。ドキュメントがないので結局カーネルのソース読んだし。
途中で調べた事も書いておく。
Linuxにおけるネットワークデバイスとアドレスの表現
ネットワークデバイスはnet_device構造体(linux/netdevice.h) で表現されている。
struct net_device {
char name[IFNAMSIZ];
struct hlist_node name_hlist;
char *ifalias;
unsigned long mem_end;
unsigned long mem_start;
unsigned long base_addr;
unsigned int irq;
unsigned long state;
struct list_head dev_list;
struct list_head napi_list;
struct list_head unreg_list;
netdev_features_t features;
netdev_features_t hw_features;
netdev_features_t wanted_features;
netdev_features_t vlan_features;
...
struct in_device __rcu *ip_ptr;
struct inet6_dev __rcu *ip6_ptr;
...
};
IPv4インターフェイスの情報はip_ptrが参照するin_device構造体(linux/inetdevice.h)に、IPv6インターフェイスの情報はip6_ptrが参照するinet6_dev構造体(include/net/if_inet6.h)に定義されている。
struct in_device:
struct in_device {
struct net_device *dev;
atomic_t refcnt;
int dead;
struct in_ifaddr *ifa_list; /* IP ifaddr chain */
struct ip_mc_list __rcu *mc_list; /* IP multicast filter chain */
int mc_count; /* Number of installed mcasts */
spinlock_t mc_tomb_lock;
struct ip_mc_list *mc_tomb;
unsigned long mr_v1_seen;
unsigned long mr_v2_seen;
unsigned long mr_maxdelay;
unsigned char mr_qrv;
unsigned char mr_gq_running;
unsigned char mr_ifc_count;
struct timer_list mr_gq_timer; /* general query timer */
struct timer_list mr_ifc_timer; /* interface change timer */
struct neigh_parms *arp_parms;
struct ipv4_devconf cnf;
struct rcu_head rcu_head;
};
struct inet6_dev:
struct inet6_dev {
struct net_device *dev;
struct list_head addr_list;
struct ifmcaddr6 *mc_list;
struct ifmcaddr6 *mc_tomb;
spinlock_t mc_lock;
unsigned char mc_qrv;
unsigned char mc_gq_running;
unsigned char mc_ifc_count;
unsigned long mc_v1_seen;
unsigned long mc_maxdelay;
struct timer_list mc_gq_timer; /* general query timer */
struct timer_list mc_ifc_timer; /* interface change timer */
struct ifacaddr6 *ac_list;
rwlock_t lock;
atomic_t refcnt;
__u32 if_flags;
int dead;
...
struct neigh_parms *nd_parms;
struct inet6_dev *next;
struct ipv6_devconf cnf;
struct ipv6_devstat stats;
unsigned long tstamp; /* ipv6InterfaceTable update timestamp */
struct rcu_head rcu;
};
in_device構造体に紐づいているIPアドレスのリストはifa_listで、inet6_dev構造体に紐づいているIPアドレスのリストはaddr_listで表現されている。