取本机所有的 IP

代码修改自 qmail 的 ipme.c , 要点是对于 struct ifreq 里定义了 ifr_addr.sa_len 的系统(比如 FreeBSD),是和 Linux 不太一样的。
在 CentOS 3 和 FreeBSD 4.7 上测试通过

  1. /* ipme.c from qmail */
  2. #include "sys/types.h"
  3. #include "sys/ioctl.h"
  4. #include "sys/socket.h"
  5. #include "netinet/in.h"
  6. #include "net/if.h"
  7.  
  8. int main(int argc, char *argv[])
  9. {
  10.     struct ifconf ifc;
  11.     int sockfd;
  12.     char buf[20000];
  13.     char *ptr;
  14.  
  15.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  16.         return -1;
  17.     }
  18.  
  19.     ifc.ifc_buf = buf;
  20.     ifc.ifc_len = sizeof(buf);
  21.     if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
  22.         return -1;
  23.     }
  24.  
  25.     ptr = buf;
  26.     while (ptr < buf + ifc.ifc_len) {
  27.         struct ifreq *ifr;
  28.         struct sockaddr_in *sin;
  29.         int len;
  30.  
  31.         ifr = (struct ifreq *)ptr;
  32. #ifdef __FreeBSD__
  33.         len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
  34.  
  35.         if (ifr->ifr_addr.sa_family == AF_INET) {
  36.             printf("%s", ifr->ifr_name);
  37.             sin = (struct sockaddr_in *)&ifr->ifr_addr;
  38.             printf("\t%s", inet_ntoa(sin->sin_addr));
  39.             if (ioctl(sockfd, SIOCGIFFLAGS, ifr) == 0) {
  40.                 if (ifr->ifr_flags & IFF_UP) {
  41.                     printf("\tUP\n");
  42.                 } else {
  43.                     printf("\tDOWN\n");
  44.                 }
  45.             }
  46.         }
  47.  
  48.         // 这段代码来自 qmail 的 ipme.c, 在 FreeBSD 上实测中没有出现过 len 小的情况
  49.         if (len < sizeof(struct ifreq))
  50. #else
  51.         if (ioctl(sockfd, SIOCGIFFLAGS, ifr) == 0) {
  52.             if (ifr->ifr_flags & IFF_UP) {
  53.                 if (ioctl(sockfd, SIOCGIFADDR, ifr) == 0) {
  54.                     if (ifr->ifr_addr.sa_family == AF_INET) {
  55.                         sin = (struct sockaddr_in *)&ifr->ifr_addr;
  56.                         printf("%s\t%s\n", ifr->ifr_name, inet_ntoa(sin->sin_addr));
  57.                     }
  58.                 }
  59.             }
  60.         }
  61. #endif
  62.         len = sizeof(struct ifreq);
  63.         ptr += len;
  64.     }
  65. }
Topic: 技术

评论

/* ADD #include */

在我的debian上测试通过,博主能否再写一个获取本机外部IP?

脚本也行啊!

什么叫本机外部IP ?

debian 上装一个facter
hmy@luna:~$facter |grep -i ipadd
ipaddress => 192.168.2.10
ipaddress_eth0 => 192.168.2.10
ipaddress_eth0:0 => 10.0.1.10
ipaddress_eth1 => 192.168.0.103

ipaddress_vmnet1 => 10.0.35.1

收藏学习了,学习!

如:
我的本机内部IP:192.168.1.2

我的外部IP:221.221.0.11

上面的代码能得到192.168.1.2,但我想得到221.221.0.11

我现在的方法是wget一个IP的网站,然后cron给我的gmail,这样我在家或外地也可以ssh到公司的机器上,因为IP是动态的!

这种方法就是只能取到本地配置的,可以用 ifconfig 看到的 IP 啊.