• 正文
    • 一、原理
    • 二、函數(shù)實(shí)現(xiàn)
    • 三、測(cè)試
  • 推薦器件
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

Linux下C語(yǔ)言操作網(wǎng)卡的幾個(gè)代碼實(shí)例!特別實(shí)用

2023/10/02
2738
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論
前面寫了一篇關(guān)于網(wǎng)絡(luò)相關(guān)的文章:如何獲取當(dāng)前可用網(wǎng)口。《簡(jiǎn)簡(jiǎn)單單教你如何用C語(yǔ)言列舉當(dāng)前所有網(wǎng)口!》

那么如何使用C語(yǔ)言直接操作網(wǎng)口?比如讀寫IP地址、讀寫MAC地址等。

一、原理

主要通過(guò)系統(tǒng)用socket()、ioctl()、實(shí)現(xiàn)

int?socket(int?domain,?int?type,?int?protocol);
功能:
????創(chuàng)建套接字
參數(shù):
?domain:?
??Name????????????????Purpose??????????????????????????Man?page
??AF_UNIX,?AF_LOCAL???Local?communication??????????????unix(7)
??AF_INET?????????????IPv4?Internet?protocols??????????ip(7)

?type:
??SOCK_STREAM?????Provides?sequenced,?reliable,?two-way,?connection-based
??????????????????????byte??streams.??An?out-of-band?data?transmission?mecha‐
??????????????????????nism?may?be?supported.
??????SOCK_DGRAM??????Supports?datagrams?(connectionless,?unreliable?messages
??????????????????????of?a?fixed?maximum?length).
?protocol:
??通常為0
返回值:
?成功:新的套接字的文件描述符
?失?。哄e(cuò)誤碼,負(fù)值
int?ioctl(int?fd,?unsigned?long?request,?...);
參數(shù):
???fd?:文件描述符
???request:命令
???...?:參數(shù)

其中網(wǎng)絡(luò)用到的request定義頭文件位于:

/usr/include/linux/sockios.h
/*?Linux-specific?socket?ioctls?*/
#define?SIOCINQ??FIONREAD
#define?SIOCOUTQ?TIOCOUTQ????????/*?output?queue?size?(not?sent?+?not?acked)?*/

/*?Routing?table?calls.?*/
#define?SIOCADDRT?0x890B??/*?add?routing?table?entry?*/
#define?SIOCDELRT?0x890C??/*?delete?routing?table?entry?*/
#define?SIOCRTMSG?0x890D??/*?call?to?routing?system?*/

/*?Socket?configuration?controls.?*/
#define?SIOCGIFNAME?0x8910??/*?get?iface?name??*/
#define?SIOCSIFLINK?0x8911??/*?set?iface?channel??*/
#define?SIOCGIFCONF?0x8912??/*?get?iface?list??*/
#define?SIOCGIFFLAGS?0x8913??/*?get?flags???*/
#define?SIOCSIFFLAGS?0x8914??/*?set?flags???*/
#define?SIOCGIFADDR?0x8915??/*?get?PA?address??*/
#define?SIOCSIFADDR?0x8916??/*?set?PA?address??*/
#define?SIOCGIFDSTADDR?0x8917??/*?get?remote?PA?address?*/
#define?SIOCSIFDSTADDR?0x8918??/*?set?remote?PA?address?*/
#define?SIOCGIFBRDADDR?0x8919??/*?get?broadcast?PA?address?*/
#define?SIOCSIFBRDADDR?0x891a??/*?set?broadcast?PA?address?*/
#define?SIOCGIFNETMASK?0x891b??/*?get?network?PA?mask??*/
#define?SIOCSIFNETMASK?0x891c??/*?set?network?PA?mask??*/
#define?SIOCGIFMETRIC?0x891d??/*?get?metric???*/
#define?SIOCSIFMETRIC?0x891e??/*?set?metric???*/
#define?SIOCGIFMEM?0x891f??/*?get?memory?address?(BSD)?*/
#define?SIOCSIFMEM?0x8920??/*?set?memory?address?(BSD)?*/
#define?SIOCGIFMTU?0x8921??/*?get?MTU?size???*/
#define?SIOCSIFMTU?0x8922??/*?set?MTU?size???*/
#define?SIOCSIFNAME?0x8923??/*?set?interface?name?*/
#define?SIOCSIFHWADDR?0x8924??/*?set?hardware?address??*/
#define?SIOCGIFENCAP?0x8925??/*?get/set?encapsulations???????*/
#define?SIOCSIFENCAP?0x8926??
#define?SIOCGIFHWADDR?0x8927??/*?Get?hardware?address??*/
#define?SIOCGIFSLAVE?0x8929??/*?Driver?slaving?support?*/
#define?SIOCSIFSLAVE?0x8930
#define?SIOCADDMULTI?0x8931??/*?Multicast?address?lists?*/
#define?SIOCDELMULTI?0x8932
#define?SIOCGIFINDEX?0x8933??/*?name?->?if_index?mapping?*/
#define?SIOGIFINDEX?SIOCGIFINDEX?/*?misprint?compatibility?:-)?*/
#define?SIOCSIFPFLAGS?0x8934??/*?set/get?extended?flags?set?*/
#define?SIOCGIFPFLAGS?0x8935
#define?SIOCDIFADDR?0x8936??/*?delete?PA?address??*/
#define?SIOCSIFHWBROADCAST?0x8937?/*?set?hardware?broadcast?addr?*/
#define?SIOCGIFCOUNT?0x8938??/*?get?number?of?devices?*/
……

其中ioctl的參數(shù)需要借助結(jié)構(gòu)體struct ifreq
定義頭文件:

/usr/include/linux/if.h
#if?__UAPI_DEF_IF_IFREQ
struct?ifreq?{
#define?IFHWADDRLEN?6
?union
?{
??char?ifrn_name[IFNAMSIZ];??/*?if?name,?e.g.?"en0"?*/
?}?ifr_ifrn;
?
?union?{
??struct?sockaddr?ifru_addr;
??struct?sockaddr?ifru_dstaddr;
??struct?sockaddr?ifru_broadaddr;
??struct?sockaddr?ifru_netmask;
??struct??sockaddr?ifru_hwaddr;
??short?ifru_flags;
??int?ifru_ivalue;
??int?ifru_mtu;
??struct??ifmap?ifru_map;
??char?ifru_slave[IFNAMSIZ];?/*?Just?fits?the?size?*/
??char?ifru_newname[IFNAMSIZ];
??void?*?ifru_data;
??struct?if_settings?ifru_settings;
?}?ifr_ifru;
};
#endif?/*?__UAPI_DEF_IF_IFREQ?*/

#define?ifr_name?ifr_ifrn.ifrn_name?/*?interface?name??*/
#define?ifr_hwaddr?ifr_ifru.ifru_hwaddr?/*?MAC?address???*/
#define?ifr_addr?ifr_ifru.ifru_addr?/*?address??*/
#define?ifr_dstaddr?ifr_ifru.ifru_dstaddr?/*?other?end?of?p-p?lnk?*/
#define?ifr_broadaddr?ifr_ifru.ifru_broadaddr?/*?broadcast?address?*/
#define?ifr_netmask?ifr_ifru.ifru_netmask?/*?interface?net?mask?*/
#define?ifr_flags?ifr_ifru.ifru_flags?/*?flags??*/
#define?ifr_metric?ifr_ifru.ifru_ivalue?/*?metric??*/
#define?ifr_mtu??ifr_ifru.ifru_mtu?/*?mtu???*/
#define?ifr_map??ifr_ifru.ifru_map?/*?device?map??*/
#define?ifr_slave?ifr_ifru.ifru_slave?/*?slave?device??*/
#define?ifr_data?ifr_ifru.ifru_data?/*?for?use?by?interface?*/
#define?ifr_ifindex?ifr_ifru.ifru_ivalue?/*?interface?index?*/
#define?ifr_bandwidth?ifr_ifru.ifru_ivalue????/*?link?bandwidth?*/
#define?ifr_qlen?ifr_ifru.ifru_ivalue?/*?Queue?length??*/
#define?ifr_newname?ifr_ifru.ifru_newname?/*?New?name??*/
#define?ifr_settings?ifr_ifru.ifru_settings?/*?Device/proto?settings*/

二、函數(shù)實(shí)現(xiàn)

下面將實(shí)現(xiàn)不同功能的函數(shù)一一列舉。

1. 獲取本機(jī)網(wǎng)卡IP

int?getLocalIp(const?char?*eth,?char?*ip)?{
????struct?ifreq?ifr;
????struct?sockaddr_in?sin;
????int?fd;
????bzero(&ifr,?sizeof(ifr));
????if?((fd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)?{
????????return?-1;
????}
????strcpy(ifr.ifr_name,?eth);
????if?(ioctl(fd,?SIOCGIFADDR,?&ifr)?<?0)?{
????????close(fd);
????????return?-1;
????}
????memcpy(&sin,?&ifr.ifr_addr,?sizeof(sin));
????snprintf(ip,?IP_SIZE,?"%s",?inet_ntoa(sin.sin_addr));
????close(fd);
????return?0;
}

2. 設(shè)置本網(wǎng)卡IP地址

int?setIpAddrManual(const?char?*eth,?char?*ipstr)?{
????int?fd;
????struct?sockaddr_in?sin;
????struct?ifreq?ifr;
????bzero(&ifr,?sizeof(ifr));
????if?((fd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)
????{
????????return?-1;
????}
????strcpy(ifr.ifr_name,?eth);

?sin.sin_addr.s_addr?=?inet_addr(ipstr);
?
?sin.sin_family?=?AF_INET;
????memcpy(&ifr.ifr_addr,?&sin,?sizeof(sin));
?
????if?(ioctl(fd,?SIOCSIFADDR,?&ifr)?<?0)
????{
?????perror("");
????????close(fd);
????????return?-1;
????}
????close(fd);
????return?0;
}?

3. 獲取本機(jī)網(wǎng)卡Mac地址

int?getLocalMac(const?char?*eth,?char?*mac)?{


????int?fd;
????struct?ifreq?ifr;
????bzero(&ifr,?sizeof(ifr));
????if?((fd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)
????{
????????return?-1;
????}
????strcpy(ifr.ifr_name,?eth);
????if?(ioctl(fd,?SIOCGIFHWADDR,?&ifr)?<?0)
????{
????????close(fd);
????????return?-1;
????}
???snprintf(mac,18,?"%02x:%02x:%02x:%02x:%02x:%02x",
?????????(unsigned?char)?ifr.ifr_hwaddr.sa_data[0],
?????????(unsigned?char)?ifr.ifr_hwaddr.sa_data[1],
?????????(unsigned?char)?ifr.ifr_hwaddr.sa_data[2],
?????????(unsigned?char)?ifr.ifr_hwaddr.sa_data[3],
?????????(unsigned?char)?ifr.ifr_hwaddr.sa_data[4],
?????????(unsigned?char)?ifr.ifr_hwaddr.sa_data[5]);
????close(fd);
????return?0;

}?

4. 設(shè)置網(wǎng)卡mac地址

/*
support?format?[00:11:22:33:44:55]
*/
#define?MAC_ARRAY(mac_array)??(unsigned?int?*)&mac_array[0],(unsigned?int?*)&mac_array[1],(unsigned?int?*)&mac_array[2],(unsigned?int?*)&mac_array[3],(unsigned?int?*)&mac_array[4],(unsigned?int?*)&mac_array[5]?
int?setLocalMac(const?char?*eth,?char?*mac)?{
????int?fd;
????struct?ifreq?ifr;
?unsigned?char?mac_array[6]?=?{0};
?
????bzero(&ifr,?sizeof(ifr));
????if?((fd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)
????{
????????return?-1;
????}
????strcpy(ifr.ifr_name,?eth);
?ifr.ifr_hwaddr.sa_family?=?AF_LOCAL;
?
?sscanf(mac,"%02x:%02x:%02x:%02x:%02x:%02x",
??MAC_ARRAY(mac_array));

?memcpy(ifr.ifr_hwaddr.sa_data,mac_array,6);

????if?(ioctl(fd,?SIOCSIFHWADDR,?&ifr)?<?0)
????{
?????perror("SIOCSIFHWADDR:");
????????close(fd);
????????return?-1;
????}

????close(fd);
????return?0;
}?

注意:

    網(wǎng)卡地址的第一字節(jié)必須是偶數(shù)sa_family ?值必須為:AF_LOCAL

5. 獲取網(wǎng)卡mtu

int?getMtu(const?char?*eth,?char?*mtu)?{
????int?fd;
????struct?ifreq?ifr;
????bzero(&ifr,?sizeof(ifr));
????if?((fd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)
????{
????????return?-1;
????}
????strcpy(ifr.ifr_name,?eth);
????if?(ioctl(fd,?SIOCGIFMTU,?&ifr)?<?0)
????{
????????close(fd);
????????return?-1;
????}?
????snprintf(mtu,64,?"%d",?(unsigned?char)?ifr.ifr_mtu);
????close(fd);
????return?0;
}?

6. 獲取廣播地址

int?getBroadAddr(const?char?*eth,?char?*ip)?{
????int?fd;
????struct?sockaddr_in?sin;
????struct?ifreq?ifr;
????bzero(&ifr,?sizeof(ifr));
????if?((fd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)
????{
????????return?-1;
????}
????strcpy(ifr.ifr_name,?eth);
????if?(ioctl(fd,?SIOCGIFBRDADDR,?&ifr)?<?0)
????{
?????perror("");
????????close(fd);
????????return?-1;
????}
????memcpy(&sin,?&ifr.ifr_broadaddr,?sizeof(sin));
????snprintf(ip,?IP_SIZE,?"%s",?inet_ntoa(sin.sin_addr));

????close(fd);
????return?0;
}?

7. 獲取掩碼

int?getNetMask(const?char?*eth,?char?*mask)?{
????int?fd;
????struct?sockaddr_in?sin;
????struct?ifreq?ifr;
????bzero(&ifr,?sizeof(ifr));
????if?((fd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)
????{
????????return?-1;
????}
????strcpy(ifr.ifr_name,?eth);
????if?(ioctl(fd,?SIOCGIFNETMASK,?&ifr)?<?0)
????{
?????perror("");
????????close(fd);
????????return?-1;
????}
????memcpy(&sin,?&ifr.ifr_netmask,?sizeof(sin));
????snprintf(mask,?IP_SIZE,?"%s",?inet_ntoa(sin.sin_addr));

????close(fd);
????return?0;
}

8. 獲取網(wǎng)卡flag

int?getFlags(const?char?*eth,?char?*fg)?{
????int?fd;
????struct?sockaddr_in?sin;
????struct?ifreq?ifr;
????bzero(&ifr,?sizeof(ifr));
????if?((fd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)
????{
????????return?-1;
????}
????strcpy(ifr.ifr_name,?eth);
????if?(ioctl(fd,?SIOCGIFFLAGS,?&ifr)?<?0)
????{
?????perror("");
????????close(fd);
????????return?-1;
????}
?snprintf(fg,?IP_SIZE,?"%x",?ifr.ifr_flags);

????close(fd);
????return?0;
}?

三、測(cè)試

1. 測(cè)試程序

int?main(int?argc,?char?**argv)
{
?int?fg=0;
?char?mac[32]={};
?char?ip[IP_SIZE]={0};
?char?buf[64];


?getBroadAddr(ethname,ip);
?printf("broad?ip:t%sn",ip);

?getNetMask(ethname,ip);
?printf("mask:t%sn",ip);
?
?setIpAddrManual(ethname,?"1.1.1.1");
?getLocalIp(ethname,ip);
?printf("ip:t%sn",ip);
?
?setLocalMac(ethname,"00:11:22:33:44:55");
?getLocalMac(ethname,mac);
?printf("mac:t%sn",mac);

?getMtu(ethname,buf);
?printf("mtu:t%sn",buf);?

?return?1;
}

2. 執(zhí)行結(jié)果

執(zhí)行后結(jié)果:

peng@ubuntu:~/work/test/ip$?ifconfig?
eth0??????Link?encap:Ethernet??HWaddr?00:11:22:33:44:55??
??????????inet?addr:1.1.1.1??Bcast:1.255.255.255??Mask:255.0.0.0
??????????inet6?addr:?fe80::d9d4:d42b:a04a:9d40/64?Scope:Link
??????????UP?BROADCAST?RUNNING?MULTICAST??MTU:1500??Metric:1
??????????RX?packets:188577?errors:0?dropped:0?overruns:0?frame:0
??????????TX?packets:208116?errors:0?dropped:0?overruns:0?carrier:0
??????????collisions:0?txqueuelen:1000?
??????????RX?bytes:53762370?(53.7?MB)??TX?bytes:172094089?(172.0?MB)

完整代碼,公眾號(hào)【一口Linux?】后臺(tái)回復(fù):eth

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
NC7S14M5X 1 onsemi TinyLogic HS Inverter with Schmitt Trigger Input, 3000-REEL

ECAD模型

下載ECAD模型
$0.28 查看
PVG612S-TPBF 1 International Rectifier Transistor Output SSR, 1-Channel, 4000V Isolation, LEAD FREE, SURFACE MOUNT, DIP-6
$7.68 查看
74HC245D 1 Nexperia Bus Transceiver

ECAD模型

下載ECAD模型
$1.25 查看

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

公眾號(hào)『一口Linux』號(hào)主彭老師,擁有15年嵌入式開發(fā)經(jīng)驗(yàn)和培訓(xùn)經(jīng)驗(yàn)。曾任職ZTE,某研究所,華清遠(yuǎn)見教學(xué)總監(jiān)。擁有多篇網(wǎng)絡(luò)協(xié)議相關(guān)專利和軟件著作。精通計(jì)算機(jī)網(wǎng)絡(luò)、Linux系統(tǒng)編程、ARM、Linux驅(qū)動(dòng)、龍芯、物聯(lián)網(wǎng)。原創(chuàng)內(nèi)容基本從實(shí)際項(xiàng)目出發(fā),保持原理+實(shí)踐風(fēng)格,適合Linux驅(qū)動(dòng)新手入門和技術(shù)進(jìn)階。