Linux下通過ioctl系統呼叫來獲取和設定網路資訊
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <net/if.h>
- #include <arpa/inet.h>
- #include <linux/netlink.h>
- #include <linux/rtnetlink.h>
- // 獲取IP地址,子網掩碼,MAC地址
- int GetLocalNetInfo(
- constchar* lpszEth,
- char* szIpAddr,
- char* szNetmask,
- char* szMacAddr
- )
- {
- int ret = 0;
- struct ifreq req;
- struct sockaddr_in* host = NULL;
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if ( -1 == sockfd )
- {
- return -1;
- }
- bzero(&req, sizeof(struct ifreq));
- strcpy(req.ifr_name, lpszEth);
- if ( ioctl(sockfd, SIOCGIFADDR, &req) >= 0 )
- {
- host = (struct sockaddr_in*)&req.ifr_addr;
- strcpy(szIpAddr, inet_ntoa(host->sin_addr));
- }
- else
- {
- ret = -1;
- }
- bzero(&req, sizeof(struct ifreq));
- strcpy(req.ifr_name, lpszEth);
- if ( ioctl(sockfd, SIOCGIFNETMASK, &req) >= 0 )
- {
- host = (struct sockaddr_in*)&req.ifr_addr;
- strcpy(szNetmask, inet_ntoa(host->sin_addr));
- }
- else
- {
- ret = -1;
- }
- bzero(&req, sizeof(struct ifreq));
- strcpy(req.ifr_name, lpszEth);
- if ( ioctl(sockfd, SIOCGIFHWADDR, &req) >= 0 )
- {
- sprintf(
- szMacAddr, "%02x:%02x:%02x:%02x:%02x:%02x",
- (unsigned char)req.ifr_hwaddr.sa_data[0],
- (unsigned char)req.ifr_hwaddr.sa_data[1],
- (unsigned char)req.ifr_hwaddr.sa_data[2],
- (unsigned char)req.ifr_hwaddr.sa_data[3],
- (unsigned char)req.ifr_hwaddr.sa_data[4],
- (unsigned char)req.ifr_hwaddr.sa_data[5]
- );
- }
- else
- {
- ret = -1;
- }
- if ( sockfd != -1 )
- {
- close(sockfd);
- sockfd = -1;
- }
- return ret;
- }
- // ------------------------------------------------------
- #define BUFSIZE 8192
- struct route_info
- {
- char ifName[IF_NAMESIZE];
- u_int gateWay;
- u_int srcAddr;
- u_int dstAddr;
- };
- staticint ReadNlSock(
- int sockFd,
- char* bufPtr,
- int seqNum,
- int pId
- )
- {
- struct nlmsghdr* nlHdr = NULL;
- int readLen = 0, msgLen = 0;
- while (true)
- {
- if ( (readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0 )
- {
- return -1;
- }
- nlHdr = (struct nlmsghdr *)bufPtr;
- if ( (NLMSG_OK(nlHdr, (unsigned int)readLen) == 0)
- || (nlHdr->nlmsg_type == NLMSG_ERROR) )
- {
- return -1;
- }
- if ( nlHdr->nlmsg_type == NLMSG_DONE )
- {
- break;
- }
- else
- {
- bufPtr += readLen;
- msgLen += readLen;
- }
- if ( (nlHdr->nlmsg_flags & NLM_F_MULTI) == 0 )
- {
- break;
- }
- if ( (nlHdr->nlmsg_seq != (unsigned int)seqNum)
- || (nlHdr->nlmsg_pid != (unsigned int)pId) )
- {
- break;
- }
- }
- return msgLen;
- }
- staticint ParseRoutes(
- struct nlmsghdr* nlHdr,
- struct route_info* rtInfo,
- char* default_gateway
- )
- {
- int rtLen = 0;
- struct in_addr dst;
- struct in_addr gate;
- struct rtmsg* rtMsg = NULL;
- struct rtattr* rtAttr = NULL;
- rtMsg = (struct rtmsg*)NLMSG_DATA(nlHdr);
- if ( (rtMsg->rtm_family != AF_INET)
- || (rtMsg->rtm_table != RT_TABLE_MAIN) )
- {
- return -1;
- }
- rtAttr = (struct rtattr*)RTM_RTA(rtMsg);
- rtLen = RTM_PAYLOAD(nlHdr);
- for ( ; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen) )
- {
- switch (rtAttr->rta_type)
- {
- case RTA_OIF:
- if_indextoname(*(int*)RTA_DATA(rtAttr), rtInfo->ifName);
- break;
- case RTA_GATEWAY:
- rtInfo->gateWay = *(u_int*)RTA_DATA(rtAttr);
- break;
- case RTA_PREFSRC:
- rtInfo->srcAddr = *(u_int*)RTA_DATA(rtAttr);
- break;
- case RTA_DST:
- rtInfo->dstAddr = *(u_int*)RTA_DATA(rtAttr);
- break;
- }
- }
- dst.s_addr = rtInfo->dstAddr;
- if (strstr((char*)inet_ntoa(dst), "0.0.0.0"))
- {
- gate.s_addr = rtInfo->gateWay;
- strcpy(default_gateway, (char*)inet_ntoa(gate));
- }
- return 0;
- }
- // 獲取預設閘道器
- int GetDefaultGateway(
- constchar* lpszEth,
- char* szDefaultGateway
- )
- {
- staticchar szGatewayTemp[32] = {0};
- staticchar msgBuf[BUFSIZE] = {0};
- staticstruct route_info ri;
- int ret = -1;
- struct nlmsghdr* nlMsg = NULL;
- struct rtmsg* rtMsg = NULL;
- struct route_info* rtInfo = &ri;
- int len = 0, msgSeq = 0;
- int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
- if ( -1 == sock )
- {
- goto END;
- }
- nlMsg = (struct nlmsghdr*)msgBuf;
- rtMsg = (struct rtmsg*)NLMSG_DATA(nlMsg);
- nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- nlMsg->nlmsg_type = RTM_GETROUTE;
- nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
- nlMsg->nlmsg_seq = msgSeq++;
- nlMsg->nlmsg_pid = getpid();
- if ( send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0 )
- {
- goto END;
- }
- if ( (len = ReadNlSock(sock, msgBuf, msgSeq, getpid())) < 0 )
- {
- goto END;
- }
- if ( rtInfo != NULL )
- {
- for ( ; NLMSG_OK(nlMsg, (unsigned int)len); nlMsg = NLMSG_NEXT(nlMsg, len) )
- {
- memset(szGatewayTemp, 0, 32);
- memset(rtInfo, 0, sizeof(struct route_info));
- if ( 0 == ParseRoutes(nlMsg, rtInfo, szGatewayTemp) )
- {
- if ( strcmp(rtInfo->ifName, lpszEth) == 0
- && strcmp(szGatewayTemp, "0.0.0.0") != 0
- && strlen(szGatewayTemp) > 0 )
- {
- strcpy(szDefaultGateway, szGatewayTemp);
- ret = 0;
- }
- }
- }
- }
- END:
- if ( sock != -1 )
- {
- close(sock);
- sock = -1;
- }
- return ret;
- }
- // ------------------------------------------------------
- // 設定IP地址和子網掩碼
- int SetLocalNetInfo(
- constchar* lpszEth,
- constchar* lpszIpAddr,
- constchar* lpszNetmask
- )
- {
- int ret = -1;
- struct ifreq req;
- struct sockaddr_in* host = NULL;
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if ( -1 == sockfd )
- {
- goto END;
- }
- bzero(&req, sizeof(struct ifreq));
- strcpy(req.ifr_name, lpszEth);
- host = (struct sockaddr_in*)&req.ifr_addr;
- host->sin_family = AF_INET;
- if ( 1 != inet_pton(AF_INET, lpszIpAddr, &(host->sin_addr)) )
- {
- goto END;
- }
- if ( ioctl(sockfd, SIOCSIFADDR, &req) < 0 )
- {
- goto END;
- }
- bzero(&req, sizeof(struct ifreq));
- strcpy(req.ifr_name, lpszEth);
- host = (struct sockaddr_in*)&req.ifr_addr;
- host->sin_family = AF_INET;
- if ( 1 != inet_pton(AF_INET, lpszNetmask, &(host->sin_addr)) )
- {
- goto END;
- }
- if ( ioctl(sockfd, SIOCSIFNETMASK, &req) < 0 )
- {
- goto END;
- }
- ret = 0;
- END:
- if ( sockfd != -1 )
- {
- close(sockfd);
- sockfd = -1;
- }
- return ret;
- }
- // 設定指定網口的mtu值
- int SetMTU(constchar* lpszEth, unsigned int mtu)
- {
- int ret = -1;
- struct ifreq ifr;
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if ( -1 == sockfd )
- {
- goto END;
- }
- strcpy(ifr.ifr_name, lpszEth);
- ifr.ifr_ifru.ifru_mtu = mtu;
- if ( ioctl(sockfd, SIOCSIFMTU, &ifr) < 0 )
- {
- goto END;
- }
- ret = 0;
- END:
- if ( sockfd != -1 )
- {
- close(sockfd);
- sockfd = -1;
- }
- return ret;
- }
- // 關閉指定網口
- int SetIfDown(constchar* lpszEth)
- {
- int ret = -1;
- struct ifreq ifr;
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if ( -1 == sockfd )
- {
- goto END;
- }
- strcpy(ifr.ifr_name, lpszEth);
- if ( ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0 )
- {
- goto END;
- }
- ifr.ifr_flags &= ~IFF_UP;
- if ( ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0 )
- {
- goto END;
- }
- ret = 0;
- END:
- if ( sockfd != -1 )
- {
- close(sockfd);
- sockfd = -1;
- }
- return ret;
- }
- // 開啟指定網口
- int SetIfUp(constchar* lpszEth)
- {
- int ret = -1;
- struct ifreq ifr;
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if ( -1 == sockfd )
- {
- goto END;
- }
- strcpy(ifr.ifr_name, lpszEth);
- if ( ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0 )
- {
- goto END;
- }
- ifr.ifr_flags |= IFF_UP;
- if ( ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0 )
- {
- goto END;
- }
- ret = 0;
- END:
- if ( sockfd != -1 )
- {
- close(sockfd);
- sockfd = -1;
- }
- return ret;
- }
小記:前端時間因為需要在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
Linux下Signal訊號系統呼叫
前面兩節已經介紹了有關訊號的大部分知 識。這一節我們來了解一下這些系統呼叫。其中,系統呼叫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