Linux下通过ioctl系统调用来获取和设置网络信息

发布时间:2016-12-8 14:13:24 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"Linux下通过ioctl系统调用来获取和设置网络信息",主要涉及到Linux下通过ioctl系统调用来获取和设置网络信息方面的内容,对于Linux下通过ioctl系统调用来获取和设置网络信息感兴趣的同学可以参考一下。

Linux下通过ioctl系统调用来获取和设置网络信息  http://blog.csdn.net/leng_que/article/details/7200690 #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(      const char* 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;  };    static int 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;  }    static int 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(      const char* lpszEth,      char* szDefaultGateway  )  {      static char szGatewayTemp[32] = {0};      static char msgBuf[BUFSIZE] = {0};      static struct 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(      const char* lpszEth,      const char* lpszIpAddr,      const char* 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(const char* 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(const char* 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(const char* 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,上网查也似乎没能找到什么比较好的现成函数,所以最后只好自己写了。

上一篇:LeetCode 73: Set Matrix Zeroes
下一篇:JSP语法简表

相关文章

相关评论