那么如何使用直接操作?
本文引用地址:比如读写IP地址、读写MAC地址等。
一、原理
主要通过系统用socket()、ioctl()、实现
int socket(int domain, int type, int protocol); 功能: 创建套接字 参数: 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 返回值: 成功:新的套接字的文件描述符 失败:错误码,负值
int ioctl(int fd, unsigned long request, ...); 参数: fd :文件描述符 request:命令 ... :参数
其中网络用到的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的参数需要借助结构体struct ifreq, 定义头文件:
/usr/include/linux/if.h
#if __UAPI_DEF_IF_IFREQstruct 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*/
二、函数实现
下面将实现不同功能的函数一一列举。
0. 列出所有可用
int list_all_port(){ struct ifconf ifconf; struct ifreq *ifr; int m, n, s, fd; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { return -11; } s = sizeof(struct ifreq)*5; for (;;) { ifr = malloc(s); ifconf.ifc_len = s; ifconf.ifc_req = ifr; if (ioctl(fd, SIOCGIFCONF, &ifconf) < 0) { perror("SIOCGIFCONF:"); free(ifr); close(fd); return 1; } if (ifconf.ifc_len != s) break; free(ifr); s *= 2; } close(fd); m = ifconf.ifc_len/sizeof(struct ifreq); for (n = 0; n < m; n++) { printf("port:t%sn",ifconf.ifc_req[n].ifr_name); } free(ifr); }
1. 获取指定网卡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. 设置本网卡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. 获取本机网卡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. 设置网卡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; }
注意:
网卡地址的第一字节必须是偶数
sa_family 值必须为:AF_LOCAL
5. 获取网卡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. 获取网卡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; }
三、测试
1. 测试程序
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. 执行结果
执行后结果:
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)
文章来源于:电子产品世界 原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。
相关文章
GCC中的内嵌汇编语言(2023-06-27)
GCC中的内嵌汇编语言;一.声明
虽然Linux的核心代码大部分是用C语言编写的,但是不可避免的其中还是有一部分是用汇编语言写成的。有些汇编语言代码是直接写在汇编源程序中的,特别是Linux的启动代码......
单片机编程好学吗?单片机初学者怎样看懂代码?(2023-01-05)
在屏幕前显示冷冰冰一些字符。
而单片机则有趣的多,你只要会C语言入门语句,再加一点单片机寄存器配置就能点亮电路板上的一个灯。
这个时候你会更有成就感,感觉你学的东西可以很快看到成果,很快......
单片机的程序结束后都干嘛去了?(2022-12-08)
干什么是由所使用的C语言编译器决定的。
一、问题提出
今天在单片机led模块定义函数中看到一个有趣的问题。提问者在进行基本的C51编程实验,编写了一个简单的C51程序如下:
程序执行完之后,可以......
S3C2440中的GPIO(2024-07-17)
令行,首先进入bin文件所在的目录,然后执行oflash led_on.bin,下载到开发板中即可执行。
5.C语言点亮GPF4
我们编写如下C语言代码控制LED,
int main......
5.4.2 按键扫描(单片机最简洁的键盘扫描程序详解)(2023-01-31)
较少情况可以一起处理
按键较多推荐分开处理,程序层次分明
二、完整的C语言代码
#define SYS_CLK 12000000L//设置定时器、串口频率参数
#define KEY_POWER 0x01......
基于ESP32构建的音频播放器(2022-12-05)
转到编辑 》 复制为 》 C以复制 C 语言格式的代码。
然后将此代码粘贴到 Arduino IDE 中。
代码说明
非接触式ESP32 音频播放器的完整代码在页面末尾给出。在这里,我们将解释代码......
PMSM矢量控制坐标变换之Clark变换(2024-08-09)
的变换;Park变换是两相静止坐标系α-β到两相旋转坐标系d、q之间的变换;Anti-Park变换是Park的逆变换。
本篇文章将讲述Clark变换,从公式推导到仿真实现,最后到C语言代码......
如何得当使用C语言的特殊的用法(2024-06-20)
如何得当使用C语言的特殊的用法;C语言有很多特殊的用法,如果这些特殊用法使用得当,会是你的代码变得更加有健壮,更加容易维护。
比如我们在使用STM32库的断言(assert),你会......
STM32CUBE概述及相关技术手册的寻找方法(2024-08-20)
分是指图形化配置工具软件STM32CubeMX,它可以让STM32开发者通过图形化界面进行有关管脚、时钟等基本配置并最终生成初始化C语言代码。整个操作非常简单,往往只需动动鼠标或个别数据填写即可完成。
另外一部分就是指基于STM32各系......
我将GuiLite移植到了STM32F4开发板上(2023-09-18)
我将GuiLite移植到了STM32F4开发板上;摘要:最近在做Github找到一个有趣的开源Gui框架:GuiLite,按照说明移植了GuiLite到STM32F4OLED屏幕上,分析......