1. 程式人生 > >Linux下通過ioctl系統呼叫來獲取和設定網路資訊

Linux下通過ioctl系統呼叫來獲取和設定網路資訊

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/ioctl.h>
  6. #include <net/if.h>
  7. #include <arpa/inet.h>
  8. #include <linux/netlink.h>
  9. #include <linux/rtnetlink.h>
  10. // 獲取IP地址,子網掩碼,MAC地址
  11. int GetLocalNetInfo(  
  12.     constchar* lpszEth,  
  13.     char* szIpAddr,  
  14.     char* szNetmask,  
  15.     char* szMacAddr  
  16. )  
  17. {  
  18.     int ret = 0;  
  19.     struct ifreq req;  
  20.     struct sockaddr_in* host = NULL;  
  21.     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
  22.     if ( -1 == sockfd )  
  23.     {  
  24.         return -1;  
  25.     }  
  26.     bzero(&req, sizeof(struct ifreq));  
  27.     strcpy(req.ifr_name, lpszEth);  
  28.     if ( ioctl(sockfd, SIOCGIFADDR, &req) >= 0 )  
  29.     {  
  30.         host = (struct sockaddr_in*)&req.ifr_addr;  
  31.         strcpy(szIpAddr, inet_ntoa(host->sin_addr));  
  32.     }  
  33.     else
  34.     {  
  35.         ret = -1;  
  36.     }  
  37.     bzero(&req, sizeof(struct ifreq));  
  38.     strcpy(req.ifr_name, lpszEth);  
  39.     if ( ioctl(sockfd, SIOCGIFNETMASK, &req) >= 0 )  
  40.     {  
  41.         host = (struct sockaddr_in*)&req.ifr_addr;  
  42.         strcpy(szNetmask, inet_ntoa(host->sin_addr));  
  43.     }  
  44.     else
  45.     {  
  46.         ret = -1;  
  47.     }  
  48.     bzero(&req, sizeof(struct ifreq));  
  49.     strcpy(req.ifr_name, lpszEth);  
  50.     if ( ioctl(sockfd, SIOCGIFHWADDR, &req) >= 0 )  
  51.     {  
  52.         sprintf(  
  53.             szMacAddr, "%02x:%02x:%02x:%02x:%02x:%02x",  
  54.             (unsigned char)req.ifr_hwaddr.sa_data[0],  
  55.             (unsigned char)req.ifr_hwaddr.sa_data[1],  
  56.             (unsigned char)req.ifr_hwaddr.sa_data[2],  
  57.             (unsigned char)req.ifr_hwaddr.sa_data[3],  
  58.             (unsigned char)req.ifr_hwaddr.sa_data[4],  
  59.             (unsigned char)req.ifr_hwaddr.sa_data[5]  
  60.         );  
  61.     }  
  62.     else
  63.     {  
  64.         ret = -1;  
  65.     }  
  66.     if ( sockfd != -1 )  
  67.     {  
  68.         close(sockfd);  
  69.         sockfd = -1;  
  70.     }  
  71.     return ret;  
  72. }  
  73. // ------------------------------------------------------
  74. #define BUFSIZE 8192
  75. struct route_info  
  76. {  
  77.     char ifName[IF_NAMESIZE];  
  78.     u_int gateWay;  
  79.     u_int srcAddr;  
  80.     u_int dstAddr;  
  81. };  
  82. staticint ReadNlSock(  
  83.     int sockFd,  
  84.     char* bufPtr,  
  85.     int seqNum,  
  86.     int pId  
  87. )  
  88. {  
  89.     struct nlmsghdr* nlHdr = NULL;  
  90.     int readLen = 0, msgLen = 0;  
  91.     while (true)  
  92.     {  
  93.         if ( (readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0 )  
  94.         {  
  95.             return -1;  
  96.         }  
  97.         nlHdr = (struct nlmsghdr *)bufPtr;  
  98.         if ( (NLMSG_OK(nlHdr, (unsigned int)readLen) == 0)  
  99.                 || (nlHdr->nlmsg_type == NLMSG_ERROR) )  
  100.         {  
  101.             return -1;  
  102.         }  
  103.         if ( nlHdr->nlmsg_type == NLMSG_DONE )  
  104.         {  
  105.             break;  
  106.         }  
  107.         else
  108.         {  
  109.             bufPtr += readLen;  
  110.             msgLen += readLen;  
  111.         }  
  112.         if ( (nlHdr->nlmsg_flags & NLM_F_MULTI) == 0 )  
  113.         {  
  114.             break;  
  115.         }  
  116.         if ( (nlHdr->nlmsg_seq != (unsigned int)seqNum)  
  117.                 || (nlHdr->nlmsg_pid != (unsigned int)pId) )  
  118.         {  
  119.             break;  
  120.         }  
  121.     }  
  122.     return msgLen;  
  123. }  
  124. staticint ParseRoutes(  
  125.     struct nlmsghdr* nlHdr,  
  126.     struct route_info* rtInfo,  
  127.     char* default_gateway  
  128. )  
  129. {  
  130.     int rtLen = 0;  
  131.     struct in_addr dst;  
  132.     struct in_addr gate;  
  133.     struct rtmsg* rtMsg = NULL;  
  134.     struct rtattr* rtAttr = NULL;  
  135.     rtMsg = (struct rtmsg*)NLMSG_DATA(nlHdr);  
  136.     if ( (rtMsg->rtm_family != AF_INET)  
  137.             || (rtMsg->rtm_table != RT_TABLE_MAIN) )  
  138.     {  
  139.         return -1;  
  140.     }  
  141.     rtAttr = (struct rtattr*)RTM_RTA(rtMsg);  
  142.     rtLen = RTM_PAYLOAD(nlHdr);  
  143.     for ( ; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen) )  
  144.     {  
  145.         switch (rtAttr->rta_type)  
  146.         {  
  147.         case RTA_OIF:  
  148.             if_indextoname(*(int*)RTA_DATA(rtAttr), rtInfo->ifName);  
  149.             break;  
  150.         case RTA_GATEWAY:  
  151.             rtInfo->gateWay = *(u_int*)RTA_DATA(rtAttr);  
  152.             break;  
  153.         case RTA_PREFSRC:  
  154.             rtInfo->srcAddr = *(u_int*)RTA_DATA(rtAttr);  
  155.             break;  
  156.         case RTA_DST:  
  157.             rtInfo->dstAddr = *(u_int*)RTA_DATA(rtAttr);  
  158.             break;  
  159.         }  
  160.     }  
  161.     dst.s_addr = rtInfo->dstAddr;  
  162.     if (strstr((char*)inet_ntoa(dst), "0.0.0.0"))  
  163.     {  
  164.         gate.s_addr = rtInfo->gateWay;  
  165.         strcpy(default_gateway, (char*)inet_ntoa(gate));  
  166.     }  
  167.     return 0;  
  168. }  
  169. // 獲取預設閘道器
  170. int GetDefaultGateway(  
  171.     constchar* lpszEth,  
  172.     char* szDefaultGateway  
  173. )  
  174. {  
  175.     staticchar szGatewayTemp[32] = {0};  
  176.     staticchar msgBuf[BUFSIZE] = {0};  
  177.     staticstruct route_info ri;  
  178.     int ret = -1;  
  179.     struct nlmsghdr* nlMsg = NULL;  
  180.     struct rtmsg* rtMsg = NULL;  
  181.     struct route_info* rtInfo = &ri;  
  182.     int len = 0, msgSeq = 0;  
  183.     int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);  
  184.     if ( -1 == sock )  
  185.     {  
  186.         goto END;  
  187.     }  
  188.     nlMsg = (struct nlmsghdr*)msgBuf;  
  189.     rtMsg = (struct rtmsg*)NLMSG_DATA(nlMsg);  
  190.     nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));  
  191.     nlMsg->nlmsg_type = RTM_GETROUTE;  
  192.     nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;  
  193.     nlMsg->nlmsg_seq = msgSeq++;  
  194.     nlMsg->nlmsg_pid = getpid();  
  195.     if ( send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0 )  
  196.     {  
  197.         goto END;  
  198.     }  
  199.     if ( (len = ReadNlSock(sock, msgBuf, msgSeq, getpid())) < 0 )  
  200.     {  
  201.         goto END;  
  202.     }  
  203.     if ( rtInfo != NULL )  
  204.     {  
  205.         for ( ; NLMSG_OK(nlMsg, (unsigned int)len); nlMsg = NLMSG_NEXT(nlMsg, len) )  
  206.         {  
  207.             memset(szGatewayTemp, 0, 32);  
  208.             memset(rtInfo, 0, sizeof(struct route_info));  
  209.             if ( 0 == ParseRoutes(nlMsg, rtInfo, szGatewayTemp) )  
  210.             {  
  211.                 if ( strcmp(rtInfo->ifName, lpszEth) == 0  
  212.                         && strcmp(szGatewayTemp, "0.0.0.0") != 0  
  213.                         && strlen(szGatewayTemp) > 0 )  
  214.                 {  
  215.                     strcpy(szDefaultGateway, szGatewayTemp);  
  216.                     ret = 0;  
  217.                 }  
  218.             }  
  219.         }  
  220.     }  
  221. END:  
  222.     if ( sock != -1 )  
  223.     {  
  224.         close(sock);  
  225.         sock = -1;  
  226.     }  
  227.     return ret;  
  228. }  
  229. // ------------------------------------------------------
  230. // 設定IP地址和子網掩碼
  231. int SetLocalNetInfo(  
  232.     constchar* lpszEth,  
  233.     constchar* lpszIpAddr,  
  234.     constchar* lpszNetmask  
  235. )  
  236. {  
  237.     int ret = -1;  
  238.     struct ifreq req;  
  239.     struct sockaddr_in* host = NULL;  
  240.     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
  241.     if ( -1 == sockfd )  
  242.     {  
  243.         goto END;  
  244.     }  
  245.     bzero(&req, sizeof(struct ifreq));  
  246.     strcpy(req.ifr_name, lpszEth);  
  247.     host = (struct sockaddr_in*)&req.ifr_addr;  
  248.     host->sin_family = AF_INET;  
  249.     if ( 1 != inet_pton(AF_INET, lpszIpAddr, &(host->sin_addr)) )  
  250.     {  
  251.         goto END;  
  252.     }  
  253.     if ( ioctl(sockfd, SIOCSIFADDR, &req) < 0 )  
  254.     {  
  255.         goto END;  
  256.     }  
  257.     bzero(&req, sizeof(struct ifreq));  
  258.     strcpy(req.ifr_name, lpszEth);  
  259.     host = (struct sockaddr_in*)&req.ifr_addr;  
  260.     host->sin_family = AF_INET;  
  261.     if ( 1 != inet_pton(AF_INET, lpszNetmask, &(host->sin_addr)) )  
  262.     {  
  263.         goto END;  
  264.     }  
  265.     if ( ioctl(sockfd, SIOCSIFNETMASK, &req) < 0 )  
  266.     {  
  267.         goto END;  
  268.     }  
  269.     ret = 0;  
  270. END:  
  271.     if ( sockfd != -1 )  
  272.     {  
  273.         close(sockfd);  
  274.         sockfd = -1;  
  275.     }  
  276.     return ret;  
  277. }  
  278. // 設定指定網口的mtu值
  279. int SetMTU(constchar* lpszEth, unsigned int mtu)  
  280. {  
  281.     int ret = -1;  
  282.     struct ifreq ifr;  
  283.     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
  284.     if ( -1 == sockfd )  
  285.     {  
  286.         goto END;  
  287.     }  
  288.     strcpy(ifr.ifr_name, lpszEth);  
  289.     ifr.ifr_ifru.ifru_mtu = mtu;  
  290.     if ( ioctl(sockfd, SIOCSIFMTU, &ifr) < 0 )  
  291.     {  
  292.         goto END;  
  293.     }  
  294.     ret = 0;  
  295. END:  
  296.     if ( sockfd != -1 )  
  297.     {  
  298.         close(sockfd);  
  299.         sockfd = -1;  
  300.     }  
  301.     return ret;  
  302. }  
  303. // 關閉指定網口
  304. int SetIfDown(constchar* lpszEth)  
  305. {  
  306.     int ret = -1;  
  307.     struct ifreq ifr;  
  308.     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
  309.     if ( -1 == sockfd )  
  310.     {  
  311.         goto END;  
  312.     }  
  313.     strcpy(ifr.ifr_name, lpszEth);  
  314.     if ( ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0 )  
  315.     {  
  316.         goto END;  
  317.     }  
  318.     ifr.ifr_flags &= ~IFF_UP;  
  319.     if ( ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0 )  
  320.     {  
  321.         goto END;  
  322.     }  
  323.     ret = 0;  
  324. END:  
  325.     if ( sockfd != -1 )  
  326.     {  
  327.         close(sockfd);  
  328.         sockfd = -1;  
  329.     }  
  330.     return ret;  
  331. }  
  332. // 開啟指定網口
  333. int SetIfUp(constchar* lpszEth)  
  334. {  
  335.     int ret = -1;  
  336.     struct ifreq ifr;  
  337.     int sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
  338.     if ( -1 == sockfd )  
  339.     {  
  340.         goto END;  
  341.     }  
  342.     strcpy(ifr.ifr_name, lpszEth);  
  343.     if ( ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0 )  
  344.     {  
  345.         goto END;  
  346.     }  
  347.     ifr.ifr_flags |= IFF_UP;  
  348.     if ( ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0 )  
  349.     {  
  350.         goto END;  
  351.     }  
  352.     ret = 0;  
  353. END:  
  354.     if ( sockfd != -1 )  
  355.     {  
  356.         close(sockfd);  
  357.         sockfd = -1;  
  358.     }  
  359.     return ret;  
  360. }  

小記:前端時間因為需要在Linux下獲取和設定網路資訊,所以就簡單的學習了一下,寫出了以上的幾個工具函式。最開始是用了一種比較土的方式,就是通過system函式執行命令,然後命令是通過呼叫ifconfig這個程式來到達設定網路資訊的目的,但是感覺很彆扭,還是應該使用相應的API比較好,但是又沒有找到Linux有對應的API,上網查也似乎沒能找到什麼比較好的現成函式,所以最後只好自己寫了。

相關推薦

Linux通過ioctl系統呼叫獲取設定網路資訊

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/ioctl.h>#includ

LinuxSignal訊號系統呼叫

前面兩節已經介紹了有關訊號的大部分知 識。這一節我們來了解一下這些系統呼叫。其中,系統呼叫signal是程序用來設定某個訊號的處理方法,系統呼叫kill是用來發送訊號給指定程序的。這 兩個呼叫可以形成訊號的基本操作。後兩個呼叫pause和alarm是通過訊號實現的程序暫停和

(轉)Linux通過rsync與inotify(異步文件系統事件監控機制)實現文件實時同步

-a 推送 root started init.d log tool mysql同步 .tar.gz Linux下通過rsync與inotify(異步文件系統事件監控機制)實現文件實時同步原文:http://www.summerspacestation.com/linux%

記錄linux通過對limits的設置優化系統性能

pgrep 目前 接下來 total 滿足 執行 獲取 linux下 第一個 系統中子進程繼承父進程的系統限制。只有以root用戶運行的進程能任意修改限制。其它進程不能增加硬限制值。這樣在一個session中登錄進程設置的硬限制值影響該session中的所有進程。 當要優化

linux如何通過ioctl呼叫驅動的

ioctl作用:應用層的ioctl函式傳入的cmd和arg引數會直接傳入驅動層的ioctl介面,在對應驅動檔案裡會對相應的命令進行操作 對於傳遞的ioctl命令有一定的規範,具體可以參考:/include/asm/ioctl.h,/Documentation/ioctl-number.txt 這

Linux通過rdesktop遠端登陸Windows系統圖文詳解

rdesktop是一種客戶端程式,可以通過它在Linux系統下遠端訪問Windows桌面,而且支援多種版本,諸如NT 4 Terminal Server, 2000, XP, 2003, 2003 R2, Vista, 2008, 7, and 2008 R2等。(自動掛載以及YUM倉庫的建立詳細步驟如下)

Linux環境伺服器利用組播獲取客戶端IP

單播是兩個主機之間端對端通訊(比如TCP、UDP通訊),而廣播用於一個主機對整個區域網中所有主機的通訊。單播和廣播是兩個極端,要麼對一個主機通訊,要麼對區域網內所有主機通訊。然而在實際情況下,比如要獲取區域網內獲取執行特殊任務主機IP,單播顯然不適用,因為單播必須首先要知道通

Linux使用ioctl獲取硬體資訊------案例一

    #include <stdio.h>     #include <stdlib.h>     #include <sys/types.h>     #include <sys/stat.h>     #include

Linux利用ioctl函式獲取網絡卡資訊

linux下的ioctl函式原型如下: #include <sys/ioctl.h> int ioctl(int handle, int cmd, [int *argc, int argv]) 函式成功返回0,失敗返回-1. 其相關命令介面如下:

Linux通過shell獲取網絡卡的ip地址mac地址

ip=`ifconfig eth0 | grep "inet addr" | awk -F: '{print $2}' | awk '{print $1}'` mac=`ifconfig | grep HWaddr | awk -F" " '{print $5}'` 轉自:http://blog.csdn.

Linux通過修改fstab自動掛載Windows 分割槽

我電腦裝的是Windows和Linux雙系統,以前在Linux下,要開啟Windows系統的C盤或D盤的時候,總是要輸入密碼,很麻煩,而且麻煩了很長時間. 後來有一天浩哥看到了,說可以在Linux開機時自動掛載Windows分割槽的,修改/etc/fstab這個檔案,可以採

Linux核心分析——扒開系統呼叫的三層皮(

張瑜 《Linux核心分析》MOOC課程 http://mooc.study.163.com/course/USTC-1000029000 一、實驗內容 1. 通過核心的方式使用系統呼叫 上週是從使用者態來看系統呼叫,這周是從核心方面來看這個問題

linux使用ioctl() 獲取本機mac地址、ip地址等等

       在linux下,我們知道可以通過ifconfig獲取mac地址和ip地址等相關資訊,但是如果要使用gcc程式實現的話,我們就需要使用到系統所提供的一個函式ioctl(),iotec函式是對裝置的i/o通道進行管理的函式。由於這個函式用途比較多,如果要學習可以參

Linux系統呼叫__get_thread獲取TLS失敗導致應用程式奔潰

背景 Android模擬器執行在PC端,Android應用執行在模擬器內部,當PC機在BIOS中沒有開啟虛擬化技術(vt-x: intel的硬體虛擬化技術; AMD-V: AMD CPU的硬體虛擬化技術)的時候,在模擬器內部執行ARM庫的遊戲,出現崩潰或者執行

【Python】在Linux通過psutil庫獲取指定的pid的處理

在Linux下通過psutil獲取指定pid的處理方法: 程式碼: import psutil def processinfo(processName): pids = psutil.pi

Linux使用ioctl獲取本地介面IP

最近在ubuntu上寫FTP伺服器時封裝了getlocalIP來獲取本機IP,函式內部使用gethostname()獲取主機名,使用gethostbyname()來獲取主機IP列表,但是用該函式獲取的ip繫結socket去使用connect方法時會失敗,errno程式碼為2

C#編寫運行在Linux環境的采用Mediainfo獲取多媒體文件信息的代碼

compress chap lee sin cef mas photo loss repl 原文:C#編寫運行在Linux環境下的采用Mediainfo來獲取多媒體文件信息的代碼項目開始設計的是運行在windows下,所以一開始采用的是windows服務模式來獲取多媒體文件

Linux通過find命令進行rm文件刪除的小技巧

ase test sysconfig ger sdn tun 執行過程 fun alt 我們常常會通過find命令進行批量操作。如:批量刪除舊文件、批量改動、基於時間的文件統計、基於文件大小的文件統計等。在這些操作其中,因為rm刪除操作會導致文件夾結構變化,

linux通過yum倉庫安裝mysql

linux mysql 倉庫 環境:Centos6.5查看centos版本:[[email protected]/* */ ~]# cat /etc/redhat-release CentOS release 6.5 (Final)1.查看是否安裝了mysql[[email 

Linux通過vconfig配置vlan

strong str 都是 指定 ssa 註冊 chkconfig init add 初衷: 我在centos上面搭建了一個dhcp server,由於client發來的dhcp request是加了tag的,為了使dhcp server能夠正常response分給clie