**************************************** **************************************** **************************************** ***
Author: EasyWave time: 2013.01.19
Category: Linux application instance source code Declaration: reprinted, please keep the link
NOTE: If any error occurs, please correct it. These are my Learning Log articles ......
**************************************** **************************************** **************************************** ***
During this period, I learned about the USB tonet driver and used IOCTL to set the MAC address and check the connection status of the NIC. Therefore, I learned about network programming from the network. generally, the interaction between Linux network programs and the kernel is achieved through ioctl. ioctl interacts with the network protocol stack to obtain information about network interfaces, the ing property of the NIC device and the network interface configuration. you can also view, modify, and delete ARP high-speed cache information. Therefore, let's take a look at the specific implementation of the ioctl function.
Function Format:
# Include <sys/ioctl. h>
Int ioctl (int d, int request ,...);
Category |
Request |
Description |
Data Type |
Set Connect Port |
SIOCATMARK SIOCSPGRP SIOCGPGRP |
Whether it is in the out-of-band mark Set the process ID or process group ID of the Set Interface Obtain the process ID or group ID of the Set interface. |
Int Int Int |
Text Parts |
FIONBIN FIOASYNC FIONREAD FIOSETOWN FIOGETOWN |
Set/clear non-blocking I/O flag Set/clear signal-driven asynchronous I/O flag Obtain the number of bytes in the receiving cache. Set the process ID or group ID of the file. Obtain the process ID or group ID of the file. |
Int Int Int Int Int |
Connect Port |
SIOCGIFCONF SIOCSIFADDR SIOCGIFADDR SIOCSIFFLAGS SIOCGIFFLAGS SIOCSIFDSTADDR SIOCGIFDSTADDR SIOCGIFBRDADDR SIOCSIFBRDADDR SIOCGIFNETMASK SIOCSIFNETMASK SIOCGIFMETRIC SIOCSIFMETRIC SIOCGIFMTU SIOCxxx |
Retrieve the list of all interfaces Set the interface address Obtain the interface address Set interface flag Get interface flag Set point-to-point address Get point-to-point address Get broadcast address Set broadcast address Obtain Subnet Mask Set Subnet Mask Obtain the measure of an interface Set the measure of the interface Obtain the MTU Interface (A lot more depends on the implementation of the system) |
Struct ifconf Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq Struct ifreq |
ARP |
SIOCSARP SIOCGARP SIOCDARP |
Create/modify ARP table items Obtain ARP table items Delete ARP table items |
Struct arpreq Struct arpreq Struct arpreq |
Road By |
SIOCADDRT SIOCDELRT |
Add path Delete path |
Struct rtentry Struct rtentry |
| |
|
|
|
Related Data Structure:
1): Network Interface request structure ifreq
Struct ifreq {# define IFHWADDRLEN 6 // six-byte hardware address, that is, MAC union {char ifrn_name [IFNAMESIZ]; // network interface name} ifr_ifrn; union {struct sockaddr ifru_addr; // local IP address struct sockaddr ifru_dstaddr; // target IP address struct sockaddr ifru_broadaddr; // broadcast IP address struct sockaddr ifru_netmask; // local subnet mask address struct sockaddr ifru_hwaddr; // local MAC address short ifru_flags; // Network Interface flag int ifru_ivalue; // different request meanings have different struct ifmap ifru_map; // NIC address ing int ifru_mtu; // maximum transmission unit char ifru_slave [IFNAMSIZ]; // placeholder char ifru_newname [IFNAMSIZE]; // new name void _ user * ifru_data; // user data struct if_settings ifru_settings; // device Protocol Settings} ifr_ifru;} # define ifr_name ifr_ifrn.ifrn_name; // interface name # define ifr_hwaddr restart; // MAC # define ifr_addr restart; // local IP # define ifr_dstaddr restart; // target IP # define ifr_broadaddr ifr_ifru.broadaddr; // broadcast IP # define ifr_netmask mask; // subnet mask # define ifr_flags mask; // flag # define ifr_metric ifr_ifru.ifru_ivalue; // interface degree # define ifr_mtu degree; // maximum transmission unit # define ifr_map ifr_ifru.ifru_map; // device address ing # define ifr_slave degree; // sub-device # define ifr_data ifr_ifru.ifru_data; // interface use # define ifr_ifrindex setting; // network interface number # define ifr_qlen serial; // transmission unit length # define ifr_newname setting; // new name # define ifr_seeting ifr_ifru.ifru_settings; // device Protocol Settings
2): ifmap
Struct ifmap {// The ing attribute unsigned long mem_start of the NIC device; // The start address unsigned long mem_end; // The end address unsigned short base_addr; // The base address unsigned char irq; // interrupt number unsigned char dma; // DMA unsigned char port; // port}
3): network configuration interface ifconf
Struct ifconf {// the network configuration struct is a buffer zone int ifc_len; // the size of the buffer zone ifr_buf union {char _ user * ifcu_buf; // display the dashboard pointer struct ifreq _ user * ifcu_req; // point to ifreq pointer} ifc_ifcu;}; # define ifc_buf ifc_ifcu.ifcu_buf; // The buffer address # define ifc_req accept; // ifc_req address
4): ARP high-speed cache operation arpreq
Struct arpreq {struct sockaddr arp_pa; // Protocol address struct sockaddr arp_ha; // hardware address int arp_flags; // mark struct sockaddr arp_netmask; // The subnet mask of the Protocol address char arp_dev [16]; // query the name of the network interface}
ARP high-speed cache operations, including IP address and hardware address ing tables. commands for operating ARP high-speed cache: SIOCDARP, SIOCGARP, and SIOCSARP are respectively used to delete a record of ARP high-speed cache, obtain a record of ARP high-speed cache and modify a record of ARP high-speed cache
Related example [the following is an excerpt from the Network: it has been verified on the machine]:
# Include <sys/types. h> # include <stdio. h> # include <stdlib. h> # include <unistd. h> # include <sys/ioctl. h> # include <sys/socket. h> # include <netdb. h> # include <string. h> # include <fcntl. h> # include <net/if. h> int main (int argc, char * argv []) {int s, sv6; int err; s = socket (AF_INET, SOCK_DGRAM, 0); if (s <0) {perror ("socket error"); return-1;} struct ifreq ifr; ifr. ifr_ifindex = 2; // obtain the name of the 2nd Network Interfaces Err = ioctl (s, SIOCGIFNAME, & ifr); if (err) {perror ("index error");} else {printf ("the % dst interface is: % s \ n ", ifr. ifr_ifindex, ifr. ifr_name);} memcpy (ifr. ifr_name, "eth0", 5); err = ioctl (s, SIOCGIFFLAGS, & ifr); if (! Err) {printf ("SIOCGIFFLAGS: % d \ n", ifr. ifr_flags);} err = ioctl (s, SIOCGIFMTU, & ifr); if (! Err) {printf ("SIOCGIFMTU: % d \ n", ifr. ifr_mtu);} err = ioctl (s, SIOCGIFHWADDR, & ifr); if (! Err) {unsigned char * hw = ifr. ifr_hwaddr.sa_data; printf ("SIOCGIFHWADDR: % 02x: % 02x: % 02x: % 02x: % 02x: % 02x \ n", hw [0], hw [1], hw [2], hw [3], hw [4], hw [5]);} err = ioctl (s, SIOCGIFMAP, & ifr); if (! Err) {printf ("SIOCGIFMAP, mem_start: % d, mem_end: % d, base_addr: % d, ifr_map: % d, dma: % d, port: % d \ n ", ifr. ifr_map.mem_start, ifr. ifr_map.mem_end, ifr. ifr_map.base_addr, ifr. ifr_map.irq, ifr. ifr_map.dma, ifr. ifr_map.port);} err = ioctl (s, SIOCGIFINDEX, & ifr); if (! Err) {printf ("SIOCGIFINDEX: % d \ n", ifr. ifr_ifindex);} err = ioctl (s, SIOCGIFTXQLEN, & ifr); if (! Err) {printf ("SIOCGIFTXQLEN: % d \ n", ifr. ifr_qlen);} struct sockaddr_in * sin = (struct sockaddr_in *) & ifr. ifr_addr; // stores the binary IP char ip Address [16]; // character array, which stores the string memset (ip, 0, 16); err = ioctl (s, SIOCGIFADDR, & ifr); if (! Err) {inet_ntop (AF_INET, & sin-> sin_addr.s_addr, ip, 16); // Save the converted string to the ip array. The second parameter is the binary IP pointer to be converted, the third parameter is the buffer where the IP address is converted. The last parameter is the buffer length printf ("SIOCGIFADDR: % s \ n", ip);} err = ioctl (s, SIOCGIFDSTADDR, & ifr); if (! Err) {inet_ntop (AF_INET, & sin-> sin_addr.s_addr, ip, 16); printf ("SIOCGIFDSTADDR: % s \ n", ip);} err = ioctl (s, SIOCGIFNETMASK, & ifr); if (! Err) {inet_ntop (AF_INET, & sin-> sin_addr.s_addr, ip, 16); printf ("SIOCGIFNETMASK: % s \ n", ip);} memset (& ifr, 0, sizeof (ifr); memcpy (ifr. ifr_name, "eth0", 5); ioctl (s, SIOCGIFBRDADDR, & ifr); struct sockaddr_in * broadcast = (struct sockaddr_in *) & ifr. ifr_broadaddr; inet_ntop (AF_INET, & broadcast-> sin_addr.s_addr, ip, 16); // inet_ntop converts a binary IP address to a decimal string printf ("broadcast ip: % s \ n ", ip); close (s );}
Example 2: [after the code is modified, it has been verified on the machine] Set and obtain the MAC address
#include <stdio.h>#include <string.h>#include <errno.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <net/if.h>typedef unsigned char u8#define LOGD(...) do {printf(__VA_ARGS__); printf("\n");} while(0)int set_mac(u8* addr, int len);int get_mac(u8* addr, int len);int main(int argc, char*argv[]){ int ret = 0; u8 addr[6] = {0x00, 0x00, 0x00, 0x61, 0x20, 0x58}; ret = set_mac(addr, 6); if (ret < 0) { LOGD("set_mac() error"); return 0; } LOGD("set_mac() done"); ret = get_mac(addr, 6); if (ret < 0) { LOGD("get_mac() error"); return 0; } LOGD("get_mac() done"); char buf[32] = {0}; snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); LOGD("%s", buf); return 0;}int set_mac(u8* addr, int len){ int s; int ret; struct ifreq ifr; if (len < 6) { LOGD("set_mac(), invalid length"); return -1; } s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { LOGD("socket() error: %s", strerror(errno)); return -1; } strcpy(ifr.ifr_ifrn.ifrn_name, "eth0"); ifr.ifr_ifru.ifru_hwaddr.sa_family = 1; memcpy(ifr.ifr_ifru.ifru_hwaddr.sa_data, addr, 6); ret = ioctl(s, SIOCSIFHWADDR, &ifr); if (ret != 0) { LOGD("ioctl(SIOCSIFHWADDR) error: %d(%s)", errno, strerror(errno)); return -1; } return 0;}int get_mac(u8* addr, int len){ int s; int ret; struct ifreq ifr; if (len < 6) { LOGD("get_mac(), invalid length"); return -1; } s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { LOGD("socket() error: %s", strerror(errno)); return -1; } strcpy(ifr.ifr_ifrn.ifrn_name, "eth0"); ret = ioctl(s, SIOCGIFHWADDR, &ifr); if (ret != 0) { LOGD("ioctl(SIOCSIFHWADDR) error: %s", strerror(errno)); return -1; } memcpy(addr, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6); return 0;}
Instance 3: Nic connection status [verified on the computer after modification]
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <errno.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/socket.h>#include <linux/if.h>typedef unsigned short u16;typedef unsigned int u32;typedef unsigned char u8;typedef unsigned long longu64#include <linux/sockios.h>#include <linux/ethtool.h>int get_netlink_status(const char *if_name);int main(int argc, char* argv[]){ if(argc != 2) { fprintf(stderr, "usage: %s <ethname>.\n", argv[0]); return -1; } if(getuid() != 0) { fprintf(stderr, "Netlink Status Check Need Root User.\n"); return 1; } printf("Net link status: %s.\n", get_netlink_status(argv[1])==1?"up":"down"); return 0;}// if_name like "ra0", "eth0". Notice: call this function// return value:// -1 -- error , details can check errno// 1 -- interface link up// 0 -- interface link down.int get_netlink_status(const char *if_name){ int skfd; struct ifreq ifr; struct ethtool_value edata; edata.cmd = ETHTOOL_GLINK; edata.data = 0; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1); ifr.ifr_data = (char *) &edata; if (( skfd = socket( AF_INET, SOCK_DGRAM, 0 )) == 0) return -1; if(ioctl( skfd, SIOCETHTOOL, &ifr ) == -1) { close(skfd); return -1; } close(skfd); return edata.data;}
Refer to the network programming code written by the predecessors on the network. After you verify and debug the code by yourself, you will be posted on the blog. Thank you for sharing your knowledge on the network ....