在Linux上(如Ubuntu或CentOS), 获取某个Network Interface比如eth0的IP地址等信息,我们可以使用ifconfig或者ip addr show命令。

  1. $ ifconfig eth0
  2. eth0 Link encap:Ethernet HWaddr :::ba:8d:be
  3. inet addr:192.168.1.102 Bcast:192.168.1.255 Mask:255.255.255.0
  4. inet6 addr: fe80:::64ff:feba:8dbe/ Scope:Link
  5. UP BROADCAST RUNNING MULTICAST MTU: Metric:
  6. RX packets: errors: dropped: overruns: frame:
  7. TX packets: errors: dropped: overruns: carrier:
  8. collisions: txqueuelen:
  9. RX bytes: (29.1 MB) TX bytes: (4.0 MB)
  10. Interrupt:
  11.  
  12. $ ip addr show eth0
  13. : eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu qdisc mq state UP group default qlen
  14. link/ether :::ba:8d:be brd ff:ff:ff:ff:ff:ff
  15. inet 192.168.1.102/ brd 192.168.1.255 scope global eth0
  16. valid_lft forever preferred_lft forever
  17. inet6 fe80:::64ff:feba:8dbe/ scope link
  18. valid_lft forever preferred_lft forever

那么用C语言编程怎么实现呢? 先用strace工具观察一下ifconfig eth0的运行内幕。

  1. $ strace ifconfig eth0
  2. execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 71 vars */]) = 0
  3. brk(0) = 0x9565000
  4. access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
  5. mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76fe000
  6. access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
  7. open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
  8. fstat64(3, {st_mode=S_IFREG|0644, st_size=114965, ...}) = 0
  9. mmap2(NULL, 114965, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76e1000
  10. close(3) = 0
  11. access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
  12. open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
  13. read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0P\234\1\0004\0\0\0"..., 512) = 512
  14. fstat64(3, {st_mode=S_IFREG|0755, st_size=1763068, ...}) = 0
  15. mmap2(NULL, 1772156, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7530000
  16. mmap2(0xb76db000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1aa000) = 0xb76db000
  17. mmap2(0xb76de000, 10876, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb76de000
  18. close(3) = 0
  19. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb752f000
  20. set_thread_area({entry_number:-1 -> 6, base_addr:0xb752f940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
  21. mprotect(0xb76db000, 8192, PROT_READ) = 0
  22. mprotect(0x8058000, 4096, PROT_READ) = 0
  23. mprotect(0xb7724000, 4096, PROT_READ) = 0
  24. munmap(0xb76e1000, 114965) = 0
  25. brk(0) = 0x9565000
  26. brk(0x9586000) = 0x9586000
  27. open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
  28. fstat64(3, {st_mode=S_IFREG|0644, st_size=8752496, ...}) = 0
  29. mmap2(NULL, 2097152, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb732f000
  30. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0x855000) = 0xb76fd000
  31. close(3) = 0
  32. uname({sys="Linux", node="idorax", ...}) = 0
  33. access("/proc/net", R_OK) = 0
  34. access("/proc/net/unix", R_OK) = 0
  35. socket(PF_LOCAL, SOCK_DGRAM, 0) = 3
  36. socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
  37. access("/proc/net/if_inet6", R_OK) = 0
  38. socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 5
  39. access("/proc/net/ax25", R_OK) = -1 ENOENT (No such file or directory)
  40. access("/proc/net/nr", R_OK) = -1 ENOENT (No such file or directory)
  41. access("/proc/net/rose", R_OK) = -1 ENOENT (No such file or directory)
  42. access("/proc/net/ipx", R_OK) = -1 ENOENT (No such file or directory)
  43. access("/proc/net/appletalk", R_OK) = -1 ENOENT (No such file or directory)
  44. access("/proc/sys/net/econet", R_OK) = -1 ENOENT (No such file or directory)
  45. access("/proc/sys/net/ash", R_OK) = -1 ENOENT (No such file or directory)
  46. access("/proc/net/x25", R_OK) = -1 ENOENT (No such file or directory)
  47. open("/proc/net/dev", O_RDONLY) = 6
  48. fstat64(6, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
  49. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76fc000
  50. read(6, "Inter-| Receive "..., 1024) = 447
  51. close(6) = 0
  52. munmap(0xb76fc000, 4096) = 0
  53. ioctl(5, SIOCGIFFLAGS, {ifr_name="eth0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
  54. ioctl(5, SIOCGIFHWADDR, {ifr_name="eth0", ifr_hwaddr=00:25:64:ba:8d:be}) = 0
  55. ioctl(5, SIOCGIFMETRIC, {ifr_name="eth0", ifr_metric=0}) = 0
  56. ioctl(5, SIOCGIFMTU, {ifr_name="eth0", ifr_mtu=1500}) = 0
  57. ioctl(5, SIOCGIFMAP, {ifr_name="eth0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=16, dma=0, port=0}}) = 0
  58. ioctl(5, SIOCGIFMAP, {ifr_name="eth0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=16, dma=0, port=0}}) = 0
  59. ioctl(5, SIOCGIFTXQLEN, {ifr_name="eth0", ifr_qlen=1000}) = 0
  60. open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 6
  61. fstat64(6, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0
  62. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76fc000
  63. read(6, "# Locale name alias data base.\n#"..., 4096) = 2570
  64. read(6, "", 4096) = 0
  65. close(6) = 0
  66. munmap(0xb76fc000, 4096) = 0
  67. open("/usr/share/locale/en_US/LC_MESSAGES/net-tools.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
  68. open("/usr/share/locale/en/LC_MESSAGES/net-tools.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
  69. open("/usr/share/locale-langpack/en_US/LC_MESSAGES/net-tools.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
  70. open("/usr/share/locale-langpack/en/LC_MESSAGES/net-tools.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
  71. ioctl(4, SIOCGIFADDR, {ifr_name="eth0", ifr_addr={AF_INET, inet_addr("192.168.1.102")}}) = 0
  72. ioctl(4, SIOCGIFDSTADDR, {ifr_name="eth0", ifr_dstaddr={AF_INET, inet_addr("192.168.1.102")}}) = 0
  73. ioctl(4, SIOCGIFBRDADDR, {ifr_name="eth0", ifr_broadaddr={AF_INET, inet_addr("192.168.1.255")}}) = 0
  74. ioctl(4, SIOCGIFNETMASK, {ifr_name="eth0", ifr_netmask={AF_INET, inet_addr("255.255.255.0")}}) = 0
  75. fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 6), ...}) = 0
  76. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76fc000
  77. write(1, "eth0 Link encap:Ethernet H"..., 58eth0 Link encap:Ethernet HWaddr 00:25:64:ba:8d:be
  78. ) = 58
  79. write(1, " inet addr:192.168.1.10"..., 75 inet addr:192.168.1.102 Bcast:192.168.1.255 Mask:255.255.255.0
  80. ) = 75
  81. open("/proc/net/if_inet6", O_RDONLY) = 6
  82. fstat64(6, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
  83. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76fb000
  84. read(6, "00000000000000000000000000000001"..., 1024) = 108
  85. read(6, "", 1024) = 0
  86. write(1, " inet6 addr: fe80::225:"..., 61 inet6 addr: fe80::225:64ff:feba:8dbe/64 Scope:Link
  87. ) = 61
  88. read(6, "", 1024) = 0
  89. close(6) = 0
  90. munmap(0xb76fb000, 4096) = 0
  91. write(1, " UP BROADCAST RUNNING M"..., 61 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
  92. ) = 61
  93. write(1, " RX packets:31318 error"..., 65 RX packets:31318 errors:0 dropped:0 overruns:0 frame:0
  94. ) = 65
  95. write(1, " TX packets:29503 error"..., 67 TX packets:29503 errors:0 dropped:0 overruns:0 carrier:0
  96. ) = 67
  97. write(1, " collisions:0 txqueuele"..., 40 collisions:0 txqueuelen:1000
  98. ) = 40
  99. write(1, " RX bytes:29127563 (29."..., 65 RX bytes:29127563 (29.1 MB) TX bytes:4104503 (4.1 MB)
  100. ) = 65
  101. write(1, " Interrupt:16 \n", 24 Interrupt:16
  102. ) = 24
  103. write(1, "\n", 1
  104. ) = 1
  105. close(5) = 0
  106. exit_group(0) = ?
  107. +++ exited with 0 +++

注意上面的socket()和ioctl(), 我们不难发现如下关键调用,

  1. socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
  2. ioctl(4, SIOCGIFADDR, {ifr_name="eth0", ifr_addr={AF_INET, inet_addr("192.168.1.102")}}) = 0
  3. ioctl(4, SIOCGIFNETMASK, {ifr_name="eth0", ifr_netmask={AF_INET, inet_addr("255.255.255.0")}}) = 0

好了,现在可以上C代码了,(foo_get.c)

  1. /**
  2. * get IPv4 address and subnet mask of a network interface
  3. */
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <sys/socket.h>
  8. #include <sys/ioctl.h>
  9. #include <net/if.h>
  10. #include <arpa/inet.h>
  11.  
  12. int
  13. main(int argc, char *argv[])
  14. {
  15. int rc = ;
  16. struct sockaddr_in *addr = NULL;
  17.  
  18. if (argc != ) {
  19. fprintf(stderr, "Usage: %s <ifname>\n", argv[]);
  20. return -;
  21. }
  22.  
  23. char *ifname = argv[];
  24.  
  25. struct ifreq ifr;
  26. memset(&ifr, , sizeof(struct ifreq));
  27.  
  28. /* 0. create a socket */
  29. int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
  30. if (fd == -)
  31. return -;
  32.  
  33. /* 1. set type of address to retrieve : IPv4 */
  34. ifr.ifr_addr.sa_family = AF_INET;
  35.  
  36. /* 2. copy interface name to ifreq structure */
  37. strncpy(ifr.ifr_name, ifname, IFNAMSIZ - );
  38.  
  39. /* 3. get the IP address */
  40. if ((rc = ioctl(fd, SIOCGIFADDR, &ifr)) != )
  41. goto done;
  42.  
  43. char ipv4[] = { };
  44. addr = (struct sockaddr_in *)&ifr.ifr_addr;
  45. strncpy(ipv4, inet_ntoa(addr->sin_addr), sizeof(ipv4));
  46.  
  47. /* 4. get the mask */
  48. if ((rc = ioctl(fd, SIOCGIFNETMASK, &ifr)) != )
  49. goto done;
  50.  
  51. char mask[] = { };
  52. addr = (struct sockaddr_in *)&ifr.ifr_addr;
  53. strncpy(mask, inet_ntoa(addr->sin_addr), sizeof(mask));
  54.  
  55. /* 5. display */
  56. printf("IFNAME:IPv4:MASK\n");
  57. printf("%s:%s:%s\n", ifname, ipv4, mask);
  58.  
  59. /* 6. close the socket */
  60. done:
  61. close(fd);
  62.  
  63. return rc;
  64. }

编译并测试,

  1. $ gcc -g -Wall -std=gnu99 -o foo_get foo_get.c
  2.  
  3. $ ./foo_get eth0
  4. IFNAME:IPv4:MASK
  5. eth0:192.168.1.102:255.255.255.0
  6.  
  7. $ ./foo_get lo
  8. IFNAME:IPv4:MASK
  9. lo:127.0.0.1:255.0.0.0

参考资料:

  • NETDEVICE(7)
  • INET(3)
  • https://stackoverflow.com/questions/6652384/how-to-set-the-ip-address-from-c-in-linux

在Linux上使用C语言编程获取IPv4地址及子网掩码的更多相关文章

  1. linux 操作系统下c语言编程入门

    2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门--时间概念 5)Linux程序设计入门--信号处理 6)Linux程序设计入门--消息管理  ...

  2. [转] linux操作系统下c语言编程入门--基础知识

    点击阅读原文 这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将会学到以下内容: 1. 源程序编译        2. Makefile的编写        3. 程序库 ...

  3. linux下的c语言编程学习笔记

    视频参看csdn学院王阳和下面的linux环境下c语言编程基础相当的经典,其中王阳的视频讲的很好,相当的经典 编译hellogcc.c需要依赖/home目录下的头文件 为了避免同一个文件被includ ...

  4. Linux下的C语言编程

    一.在Linux下的C语言编程所需工具(下面所列举的都是我编程所用的工具) 1.文本编辑器 Vim 2.编译链接工具 gcc 3.调试器 gdb 4.项目管理工具 make和makefile 二.VI ...

  5. Linux下的C Socket编程 -- 获取对方IP地址

    Linux下的C Socket编程(二) 获取域名对应的IP地址 经过上面的讨论,如果我们想要连接到远程的服务器,我们需要知道对方的IP地址,系统函数gethostbyname便能够实现这个目的.它能 ...

  6. windows下C语言编程获取磁盘(分区)使用情况

    windows下编程获取磁盘(分区)使用情况 windows下编程获取磁盘(分区)使用情况 GetLogicalDriveStrings函数 使用示例 获取需要的缓冲区长度示例 获取所有驱动器号示例 ...

  7. 实验四 Linux系统搭建C语言编程环境

    项目 内容 这个作业属于那个课程 <班级课程的主页链接> 这个作业的要求在哪里 <作业要求链接地址> 学号-姓名 17043220-万文文 作业学习目标 1).Linux系统下 ...

  8. Centos7(Linux)网络配置,自动获取ip地址

    Centos7.0 Vmware 网络桥接配置,利用DHCP自动获取ip地址 首先要将Vmware10.0.3设置为桥接模式. CentOS 7.0默认安装好之后是没有自动开启网络连接的! cd  / ...

  9. Hadoop 上使用C 语言编程【转】

    转自:https://www.linuxidc.com/Linux/2012-04/58991.htm 今天尝试用C语言在Hadoop上编写统计单词的程序,具体过程如下: 一.编写map和reduce ...

随机推荐

  1. [转发]RTH试用手记之“外场应用”

    年初,罗德与施瓦茨公司(Rohde & Schwarz)推出了第一款的手持示波器,从指标上看,该示波器打破了传统手持器功能简单.指标水平低.结构粗糙的印象,取而代之达到了主流台式数字示波器的性 ...

  2. makefile文件。批处理文件。

    makefile文件: NAME=XXX             #要编译的文件名 OBJS=$(NAME).obj              #指定输出的目标文件名 ML_FLAG=/C  /COF ...

  3. C#集合总结

    1.为什么引入集合? 因为数组长度是固定的,为了建立一个动态的"数组",所以引入了集合. 2.为什么引入ArrayList 非泛型集合? ArrayList可以填补数组的不足,进行 ...

  4. java invoke(转摘)

      JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为java语言的反射机制 ...

  5. Message Loop 原理及应用

    此文已由作者王荣涛授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Message loop,即消息循环,在不同系统或者机制下叫法也不尽相同,有被叫做event loop,也有 ...

  6. 2018-2019-2 20165219《网络对抗技术》Exp4 恶意代码分析

    基础问题回答 实验目的 监控系统的运行状态,看有没有可疑的程序在运行 分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysinternals,systracer套 ...

  7. 小A的旅行(绿豆蛙的归宿)【期望DP】

    Description 给出一个有向无环的连通图,起点为1,终点为N,每条边都有一个长度.小A从起点出发,走向终点.到达每一个顶点时,如果有K条离开该点的道路,小A可以选择任意一条道路离开该点,并且走 ...

  8. [CSS3] 二级下拉导航

    <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8& ...

  9. [Objective-C语言教程]数据封装(27)

    所有Objective-C程序都由以下两个基本要素组成 - 程序语句(代码) - 这是执行操作的程序的一部分,它们被称为方法(函数). 程序数据 - 数据是受程序功能影响的程序信息. 封装是一种面向对 ...

  10. 关闭tomcat端口号

    一. CentOS 关闭tomcat端口号 1. 首先保证liunx下 ps -ef | grep java 2. 会显示如下信息 我使用的是IDEA打包的war包.tomcat是自带的 3. 查看未 ...