arm linux ifconfig 什么都,[Linux] 嵌入式系統不可或缺的工具 – busybox 分析 ifconfig command...

24e1cff8c1d93c23bdeacb8da713bbe6.png

玩過嵌入式系統的使用者,一定都會知道 Busybox,它提供一些小型 Linux command,方便在 console 端使用,以及一些 C 語言或者是 shell script 裡面,大家都知道 ifconfig 這指令,為了從 Kernel 2.6.15 轉換到 2.6.34.7 版本,原本的 Busybox 版本只有 1.0.1,現在已經到 1.18.1,轉換過程改了 Kernel netfilter 部份,以及 user space 部份 iptables extension。ifconfig 是 Busybox 其中一個指令用來查看目前有多少網路介面(network interface),來看看他是如何得到這些 interface 資訊,包含介面名稱、type、IP Adress、IP network mask、HW address 等….。

要讀取 interface 相關資訊可以透過兩種方式,一種是讀取 (IPv6 是 /proc/net/if_inet6),另一種透過 Socket 連接SOCK_DGRAM,最後用 iotcl 方式讀取 interface 相關資料,busybox 會先偵測檔案 /proc/net/dev 是否存在,如果 Kernel 有支援,就會讀取此檔案,如果不存在,則利用 socket 讀取資料。

if_readlist_proc 函式裡面:

fh = fopen_or_warn(_PATH_PROCNET_DEV, "r");

if (!fh) {

return if_readconf();

}

看一下 /proc/net/dev 內容

Inter-| Receive | Transmit

face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed

lo: 104 1 0 0 0 0 0 0 104 1 0 0 0 0 0 0

eth0:21798505 51360 0 0 0 0 0 0 7693686 46844 0 0 0 0 0 0

首先濾掉前兩行不需要的資料,在利用 get_name 函式抓取 lo 跟 eth0 interface

fgets(buf, sizeof buf, fh);/* eat line */

fgets(buf, sizeof buf, fh);

procnetdev_vsn = procnetdev_version(buf);

err = 0;

while (fgets(buf, sizeof buf, fh)) {

char *s, name[128];

s = get_name(name, buf);

ife = add_interface(name);

get_dev_fields(s, ife, procnetdev_vsn);

ife->statistics_valid = 1;

if (target && !strcmp(target, name))

break;

}

get_name 直接濾掉每行冒號 : 後面的資料,並且將其加入 interface structure 雙向 link list

static char *get_name(char *name, char *p)

{

/* Extract from nul-terminated p where p matches

* : after leading whitespace.

* If match is not made, set name empty and return unchanged p

*/

char *nameend;

char *namestart = skip_whitespace(p);

nameend = namestart;

while (*nameend && *nameend != ':' && !isspace(*nameend))

nameend++;

if (*nameend == ':') {

if ((nameend - namestart) < IFNAMSIZ) {

memcpy(name, namestart, nameend - namestart);

name[nameend - namestart] = '\0';

p = nameend;

} else {

/* Interface name too large */

name[0] = '\0';

}

} else {

/* trailing ':' not found - return empty */

name[0] = '\0';

}

return p + 1;

}[/code]

add_interface 將 network interface 加入 link list

[code lang="C"]static struct interface *add_interface(char *name)

{

struct interface *ife, **nextp, *new;

for (ife = int_last; ife; ife = ife->prev) {

int n = /*n*/strcmp(ife->name, name);

if (n == 0)

return ife;

if (n < 0)

break;

}

new = xzalloc(sizeof(*new));

strncpy_IFNAMSIZ(new->name, name);

nextp = ife ? &ife->next : &int_list;

new->prev = ife;

new->next = *nextp;

if (new->next)

new->next->prev = new;

else

int_last = new;

*nextp = new;

return new;

}

最後將 /proc/net/dev 剩餘資訊利用 get_dev_fields 讀取 sscanf

static void get_dev_fields(char *bp, struct interface *ife, int procnetdev_vsn)

{

memset(&ife->stats, 0, sizeof(struct user_net_device_stats));

sscanf(bp, ss_fmt[procnetdev_vsn],

&ife->stats.rx_bytes, /* missing for 0 */

&ife->stats.rx_packets,

&ife->stats.rx_errors,

&ife->stats.rx_dropped,

&ife->stats.rx_fifo_errors,

&ife->stats.rx_frame_errors,

&ife->stats.rx_compressed, /* missing for <= 1 */

&ife->stats.rx_multicast, /* missing for <= 1 */

&ife->stats.tx_bytes, /* missing for 0 */

&ife->stats.tx_packets,

&ife->stats.tx_errors,

&ife->stats.tx_dropped,

&ife->stats.tx_fifo_errors,

&ife->stats.collisions,

&ife->stats.tx_carrier_errors,

&ife->stats.tx_compressed /* missing for <= 1 */

);

if (procnetdev_vsn <= 1) {

if (procnetdev_vsn == 0) {

ife->stats.rx_bytes = 0;

ife->stats.tx_bytes = 0;

}

ife->stats.rx_multicast = 0;

ife->stats.rx_compressed = 0;

ife->stats.tx_compressed = 0;

}

}

另外要得到 IP Address 資訊,就必須用 if_fetch 函式,透過 ioctl 進行讀取

/* Fetch the interface configuration from the kernel. */

static int if_fetch(struct interface *ife)

{

struct ifreq ifr;

char *ifname = ife->name;

int skfd;

skfd = xsocket(AF_INET, SOCK_DGRAM, 0);

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) {

close(skfd);

return -1;

}

ife->flags = ifr.ifr_flags;

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

memset(ife->hwaddr, 0, 32);

if (ioctl(skfd, SIOCGIFHWADDR, &ifr) >= 0)

memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);

ife->type = ifr.ifr_hwaddr.sa_family;

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

ife->metric = 0;

if (ioctl(skfd, SIOCGIFMETRIC, &ifr) >= 0)

ife->metric = ifr.ifr_metric;

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

ife->mtu = 0;

if (ioctl(skfd, SIOCGIFMTU, &ifr) >= 0)

ife->mtu = ifr.ifr_mtu;

memset(&ife->map, 0, sizeof(struct ifmap));

#ifdef SIOCGIFMAP

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

if (ioctl(skfd, SIOCGIFMAP, &ifr) == 0)

ife->map = ifr.ifr_map;

#endif

#ifdef HAVE_TXQUEUELEN

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

ife->tx_queue_len = -1;/* unknown value */

if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) >= 0)

ife->tx_queue_len = ifr.ifr_qlen;

#else

ife->tx_queue_len = -1;/* unknown value */

#endif

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

ifr.ifr_addr.sa_family = AF_INET;

memset(&ife->addr, 0, sizeof(struct sockaddr));

if (ioctl(skfd, SIOCGIFADDR, &ifr) == 0) {

ife->has_ip = 1;

ife->addr = ifr.ifr_addr;

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

memset(&ife->dstaddr, 0, sizeof(struct sockaddr));

if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) >= 0)

ife->dstaddr = ifr.ifr_dstaddr;

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

memset(&ife->broadaddr, 0, sizeof(struct sockaddr));

if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) >= 0)

ife->broadaddr = ifr.ifr_broadaddr;

strncpy_IFNAMSIZ(ifr.ifr_name, ifname);

memset(&ife->netmask, 0, sizeof(struct sockaddr));

if (ioctl(skfd, SIOCGIFNETMASK, &ifr) >= 0)

ife->netmask = ifr.ifr_netmask;

}

close(skfd);

return 0;

}

以上就是執行 ifconfig command 的流程,如果有任何問題可以直接留言 ^^

Related

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值