ifconfig是linux中用于顯示或配置網絡裝置(網絡接口卡)的指令,英文全稱是network interfaces configuring。
同netstat一樣,ifconfig源碼也位于net-tools中。
源碼位于net-tools工具包中,這是linux網絡的基本工具包,此外還有arp,hostname,route等指令。
項目連結:http://net-tools.sourceforge.net/
下載下傳位址:https://sourceforge.net/projects/net-tools/files/latest/download
下面一起來看下ifconfig的源碼。
直接通過指令make ifconfig就可以編譯ifconfig。
編譯時候出錯需要進行如下修改:
1、在lib/inet_src.c中,108行加入break;
107 default:
108 break;
2、在<b>lib/x25_sr.c </b>
80 memcpy(&rt.address, &sx25.sx25_addr, sizeof(x25_address));
為:
memcpy(&rt.address, &sx25.sx25_addr, sizeof(sx25.sx25_addr));
從main主函數開始,先擷取程式輸入參數,因為支援多如輸入參數例如:ifconfig eth0 192.168.1.2,根據上一個參數以及下一個參數來調用相關的函數。
第一個循環是判斷參數是否為-a,-s,-v,-V,-version,-?,-h,-help,--help,如果是其他例如-x ,那麼就直接報錯後退出。
如果參數沒問題,則往下執行sockets_open函數(最後調用socket函數),打開核心支援的所有協定套接字,
如果沒有參數,則if_print函數列印所有網卡裝置資訊,如果有指定則顯示指定的網口資訊。
擷取下一個參數,是位址族名字(如果不是協定族名字,預設就是ipv4)或者是一個選項(如up)。然後處理剩下的參數。例如是否是-arp,media,port,up,down等。
如果是開關參數,就調用set_flag或clr_flag函數。
如果是功能參數,調用ioctl函數處理。
例如函數ioctl(skfd,
SIOCSIFTXQLEN, &ifr)
其中skfd為本地域套接字,SIOCGIFFLAGS為傳給核心的cmd,ifr接收從核心傳回的資料。SIOCSIFTXQLEN定義在include/uapi/linux/sockios.h檔案中。
#define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */
我們來看下某些函數。
該函數的入參為ifname是個字元串指針,如果為空的話就會調用函數for_all_interfaces來列印系統中所有網卡資訊。
如果不為空,則調用lookup_interface函數擷取接口結構體,接着調用do_if_fetch函數來擷取,最後調用ife_print函數來列印。
來看下位于<b>lib/interface.c</b><b>檔案中的</b>函數for_all_interfaces:
int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
{
struct interface *ife;
if (!int_list && (if_readlist() < 0))
return -1;
for (ife = int_list; ife; ife = ife->next) {
int err = doit(ife, cookie);
if (err)
return err;
}
return 0;
}
其第一參數為會回調函數,第二個會cookie。接口是一個雙向連結清單(見下方結構體源碼),是以全部列印的工作其實就是周遊接口結構體的工作,每次都調用doit回調函數。
其中interface結構體如下,位于<b>include/interface.h</b>檔案中:
struct interface {
struct interface *next, *prev;
char name[IFNAMSIZ]; /* interface name */
short type; /* if type */
short flags; /* various flags */
int metric; /* routing metric */
int mtu; /* MTU value */
int tx_queue_len; /* transmit queue length */
struct ifmap map; /* hardware setup */
struct sockaddr addr; /* IP address */
struct sockaddr dstaddr; /* P-P IP
address */
struct sockaddr broadaddr; /* IP
broadcast address */
struct sockaddr netmask; /* IP
network mask */
struct sockaddr ipxaddr_bb; /* IPX network address
*/
struct sockaddr ipxaddr_sn; /* IPX network address
struct sockaddr ipxaddr_e3; /* IPX network address
struct sockaddr ipxaddr_e2; /* IPX network address
struct sockaddr ddpaddr; /*
Appletalk DDP address */
struct sockaddr ecaddr; /* Econet
int has_ip;
int has_ipx_bb;
int has_ipx_sn;
int has_ipx_e3;
int has_ipx_e2;
int has_ax25;
int has_ddp;
int has_econet;
char hwaddr[32];
/* HW address */
int statistics_valid;
struct user_net_device_stats stats; /* statistics */
int keepalive; /* keepalive value for SLIP */
int outfill; /* outfill value for SLIP */
};
在函數執行過程中會列印/proc/net/dev檔案,其中列出了網絡裝置的其屬性狀态和收發包情況。ifconfig會open這個裝置查找比對資訊。
最後根據ife_short變量,來調用ife_print_short函數或者ife_print_long函數。把interface結構體中的内容列印出來。
當然這個結構體是ifconfig源碼定義的,隻是個容器它需要從核心中去擷取實際的内容,這個會在列印之前由if_fetch函數來實作。
如果願意,可以修改ifconfig代碼,來定制你自己的工具。
例如在源碼中加入如下,其中第一列為行号,不用加入,此處隻為顯示:
419 if (!strcmp(*spp, "testxxx")) {
420 goterr |=
set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING));
421 spp++;
422 continue;
423 }
編譯後,執行如下指令就可以将端口up了。
# ./ifconfig eth0 testxxx
可以讓testxxx起到是up一樣的功效了。
最後祝大家玩得愉快。
最後附上相關的參數:
add<位址>:設定網絡裝置IPv6的ip位址;
del<位址>:删除網絡裝置IPv6的IP位址;
down:關閉指定的網絡裝置;
<hw<網絡裝置類型><硬體位址>:設定網絡裝置的類型與硬體位址;
io_addr<I/O位址>:設定網絡裝置的I/O位址;
irq<IRQ位址>:設定網絡裝置的IRQ;
media<網絡媒介類型>:設定網絡裝置的媒介類型;
mem_start<記憶體位址>:設定網絡裝置在主記憶體所占用的起始位址;
metric<數目>:指定在計算資料包的轉送次數時,所要加上的數目;
mtu<位元組>:設定網絡裝置的MTU;
netmask<子網路遮罩>:設定網絡裝置的子網路遮罩;
tunnel<位址>:建立IPv4與IPv6之間的隧道通信位址;
up:啟動指定的網絡裝置;
-broadcast<位址>:将要送往指定位址的資料包當成廣播資料包來處理;
-pointopoint<位址>:與指定位址的網絡裝置建立直接連線,此模式具有保密功能;
-promisc:關閉或啟動指定網絡裝置的promiscuous模式;
IP位址:指定網絡裝置的IP位址;
網絡裝置:指定網絡裝置的名稱。