1. 程式人生 > >Linux C 常用網絡卡操作 (收集|整理)

Linux C 常用網絡卡操作 (收集|整理)

實現靜態IP地址,掩碼,閘道器的設定

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <error.h>
#include <net/route.h>

int SetIfAddr(char *ifname, char *Ipaddr, char *mask,char *gateway)
{
    int
fd; int rc; struct ifreq ifr; struct sockaddr_in *sin; struct rtentry rt; fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd < 0) { perror("socket error"); return -1; } memset(&ifr,0,sizeof(ifr)); strcpy(ifr.ifr_name,ifname); sin
= (struct sockaddr_in*)&ifr.ifr_addr; sin->sin_family = AF_INET; //ipaddr if(inet_aton(Ipaddr,&(sin->sin_addr)) < 0) { perror("inet_aton error"); return -2; } if(ioctl(fd,SIOCSIFADDR,&ifr) < 0) { perror("ioctl SIOCSIFADDR error"
); return -3; } //netmask if(inet_aton(mask,&(sin->sin_addr)) < 0) { perror("inet_pton error"); return -4; } if(ioctl(fd, SIOCSIFNETMASK, &ifr) < 0) { perror("ioctl"); return -5; } //gateway memset(&rt, 0, sizeof(struct rtentry)); memset(sin, 0, sizeof(struct sockaddr_in)); sin->sin_family = AF_INET; sin->sin_port = 0; if(inet_aton(gateway, &sin->sin_addr)<0) { printf ( "inet_aton error\n" ); } memcpy ( &rt.rt_gateway, sin, sizeof(struct sockaddr_in)); ((struct sockaddr_in *)&rt.rt_dst)->sin_family=AF_INET; ((struct sockaddr_in *)&rt.rt_genmask)->sin_family=AF_INET; rt.rt_flags = RTF_GATEWAY; if (ioctl(fd, SIOCADDRT, &rt)<0) { zError( "ioctl(SIOCADDRT) error in set_default_route\n"); close(fd); return -1; } close(fd); return rc; }

獲取網絡卡資訊

方法一: 通過ioctl的SIOCGIFCONF

例項1. 檢查特定的網絡卡是否存在

// ppp、wifi是否正常
static int check_ppp_wifi (int wifi_switch) 
{   
    struct ifreq ifr;   
    struct ifconf ifc; 

    char buf[256];      
    int success = 0;    
    int wifi_exist = 0; 
    int ppp_exist = 0;  
    int ret = -1;
    int sock = -1;
    int count = 0; 

    if (wifi_switch == 0)       
        wifi_exist = 1; 
        sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);     
        if (sock == -1) {       
            APP_LogPrintf(ALM_ERROR, "socket error\n");         
            goto out;   
        }   

        ifc.ifc_len = sizeof(buf);      
        ifc.ifc_buf = buf;      
        if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {         
            APP_LogPrintf(ALM_ERROR,"ioctl error\n");       
            goto out;   
        }   

        struct ifreq* it = ifc.ifc_req;     
        const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));          

        for (; it != end; ++it) {       
        strcpy(ifr.ifr_name, it->ifr_name);         
        if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {             
            if (! (ifr.ifr_flags & IFF_LOOPBACK)) { 
                // don't count loopback                 
                if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {                    
                    count ++ ;                      
                    unsigned char * ptr ;                   
                    ptr = (unsigned char  *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0];                   
                    if (strncmp("ppp0", ifr.ifr_name, 4) == 0) {                        
                        ppp_exist = 1;                      
                        if (wifi_exist) {   
                            ret = 0;                            
                            goto out; 
                        }                   
                    } else if (strncmp("uap0", ifr.ifr_name, 4) == 0) {                     
                        wifi_exist = 1;                     
                        if (wifi_exist) {   
                            ret = 0;                            
                            goto out; 
                        }                   
                    }               
                }  
            }       
        } else {            
            APP_LogPrintf(ALM_ERROR,"get mac info error\n");            
            goto out;       
        }   
    }  

out:
    if (-1 != sock)
        close(sock);
    return ret;
}

例項2 列舉系統所有的網絡卡資訊

#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>

int main()
{
    struct ifreq ifr;
    struct ifconf ifc;
    char buf[2048];
    int success = 0;

    int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sock == -1) {
        printf("socket error\n");
        return -1;
    }

    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
        printf("ioctl error\n");
        return -1;
    }

    struct ifreq* it = ifc.ifc_req;
    const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
    char szMac[64];
    int count = 0;
    for (; it != end; ++it) {
        strcpy(ifr.ifr_name, it->ifr_name);
        if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
            if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // don't count loopback
                if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
                    count ++ ;
                    unsigned char * ptr ;
                    ptr = (unsigned char  *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0];
                    snprintf(szMac,64,"%02X:%02X:%02X:%02X:%02X:%02X",*ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),*(ptr+5));
                    printf("%d,Interface name : %s , Mac address : %s \n",count,ifr.ifr_name,szMac);
                }
            }
        }else{
            printf("get mac info error\n");
            return -1;
        }
    }
}

注意:使用的時候一定要記得關閉socket,不然可能會導致開啟檔案過多,程式崩潰。

方案二:通過getifaddrs()來實現

例項1 檢查特定網絡卡:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <ifaddrs.h>
#include <arpa/inet.h> 


int c_ifaddrs_netlink_status(const char *if_name )
{
    struct ifaddrs *ifa = NULL, *ifList;  

    if (getifaddrs(&ifList) < 0) {
        return -1;
    }

    for (ifa = ifList; ifa != NULL; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr->sa_family == AF_INET) {
            if (strcmp(ifa->ifa_name, if_name) ==0) {
                if (!(ifa->ifa_flags & IFF_UP)) {
                    printf("DEVICE_DOWN\r\n");
                    freeifaddrs(ifList);
                    return 1;
                }

                if (!(ifa->ifa_flags & IFF_RUNNING)) {
                    printf("DEVICE_UNPLUGGED\r\n");
                    freeifaddrs(ifList);
                    return 2;
                }

                printf("DEVICE_LINKED\r\n");
                freeifaddrs(ifList);
                return 3;
            }
        }  
    }  

    printf(stderr, "DEVICE_NONE\r\n");
    freeifaddrs(ifList);
    return 0;
}

int main(int argc, char* argv[])
{
    int i=0;
    if (argc != 2) {
        fprintf(stderr, "usage: %s <ethname>\r\n", argv[0]);
        return -1;
    }

    i = c_ifaddrs_netlink_status(argv[1]);

    fprintf(stderr,"c_ifaddrs_netlink_status if_status = %d\n", i );
    return 0;
}

例項2 列舉系統所有網絡卡資訊:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <time.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <ifaddrs.h>  

int main(int argc, char* argv[]) {  
    struct ifaddrs *ifc, *ifc1;  
    char ip[64] = {};  
    char nm[64] = {};  

    if(0 != getifaddrs(&ifc)) return -1;  
    ifc1 = ifc;  

    printf("iface\tIP address\tNetmask\n");  
    for (; NULL != ifc; ifc = (*ifc).ifa_next) {  
        printf("%s", (*ifc).ifa_name);  
        if (NULL != (*ifc).ifa_addr) {  
            inet_ntop(AF_INET, &(((struct sockaddr_in*)((*ifc).ifa_addr))->sin_addr), ip, 64);  
            printf("\t%s", ip);  
        } else {  
            printf("\t\t");  
        }  
        if (NULL != (*ifc).ifa_netmask) {  
            inet_ntop(AF_INET, &(((struct sockaddr_in*)((*ifc).ifa_netmask))->sin_addr), nm, 64);  
            printf("\t%s", nm);  
        } else {  
            printf("\t\t");  
        }  
        printf("\n");  
    }  

    freeifaddrs(ifc1);  
    return 0;  
} 

其他:

linux程式設計獲取本機IP地址的三種方法:

  1. 通過gethostname()和gethostbyname()
  2. 通過列舉網絡卡,API介面可檢視man netdevice,,, 關注,getifaddrs(&ifAddrStruct);
  3. 開啟一個對外界伺服器的網路連線,通過getsockname()反查自己的IP