Re: [問題] 如何用C語言,取得本機的gateway和DNS資訊…

看板Linux作者時間17年前 (2008/07/20 02:01), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串2/3 (看更多)
※ 引述《closedpath.bbs@ptt.cc (closed)》之銘言: > 我google只找得到使用socket取得ip和mask, > 但是找不到取得gateway,和DNS, > 不知道socket是否可以取得gateway和DNS, > 要如何取得呢? > 謝謝!! dns 部份自己開 /etc/resolv.conf 內的 nameserver 開頭項目解析 就可以了。 default gateway 比較麻煩,因為 routing table 內有一堆成員,像是 inet or inet6 甚至其他項目等。另外每筆 routing 資訊都不一樣,該 項目可能是 static routing 這類,所以需要解析 destination 的 ip 為 0.0.0.0 項目的 gateway 項目才是所需要的資訊。 #include <stdio.h> #include <string.h> #include <unistd.h> #include <net/if.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <arpa/inet.h> #include <net/if_arp.h> #include <asm/types.h> #include <netinet/ether.h> #include <sys/ioctl.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <stdlib.h> #define BUFSIZE 8192 struct route_info{ u_int dstAddr; u_int srcAddr; u_int gateWay; char ifName[IF_NAMESIZE]; }; int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId) { struct nlmsghdr *nlHdr; int readLen = 0, msgLen = 0; do { readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0); nlHdr = (struct nlmsghdr *)bufPtr; if(nlHdr->nlmsg_type == NLMSG_DONE) break; bufPtr += readLen; msgLen += readLen; if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) break; } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId)); return msgLen; } void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo,char *gateway) { struct rtmsg *rtMsg; struct rtattr *rtAttr; int rtLen; char tempBuf[100]; struct in_addr dst; struct in_addr gate; rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr); if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) return; 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; sprintf(gateway, (char *)inet_ntoa(gate)); } return; } int get_gateway(char *gateway) { struct nlmsghdr *nlMsg; struct rtmsg *rtMsg; struct route_info *rtInfo; char msgBuf[BUFSIZE]; int sock, len, msgSeq = 0; if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { perror("Socket Creation: "); return -1; } memset(msgBuf, 0, BUFSIZE); 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){ printf("Write To Socket Failed...\n"); return -1; } if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) { printf("Read From Socket Failed...\n"); return -1; } rtInfo = (struct route_info *)malloc(sizeof(struct route_info)); for(;NLMSG_OK(nlMsg,len);nlMsg = NLMSG_NEXT(nlMsg,len)){ memset(rtInfo, 0, sizeof(struct route_info)); parseRoutes(nlMsg, rtInfo,gateway); } free(rtInfo); close(sock); return 0; } int main() { char buf[100]; get_gateway(buf); printf("%s\n",buf); } 這段 code 主要來自於該 blog, 給你參考。 http://blog.niwota.com/a/1193200.htm 我有把一些 code 去掉精簡就是。 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 現代人普遍的現象: 「小學而大遺」、「捨本而逐末」 「以偏而概全」、「因噎而廢食」 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ※ Origin: SayYA 資訊站 <bbs.sayya.org> ◆ From: kendlee.sayya.org
文章代碼(AID): #18WYlZ00 (Linux)
文章代碼(AID): #18WYlZ00 (Linux)