有时候设备网卡上有多个IPv6,其中只有一个是可用的,另外一个是内网地址,无法使用,如果程序需要绑定一个V6地址的时候,需要获取网卡上的V6地址,并且要求是可用的。

通过ifconfig可用看到,eth0网卡上有2个IP地址,其中只有第一个V6地址的ScopeGlobal

eth0      Link encap:Ethernet  HWaddr 52:54:00:1D:79:D1
inet addr:192.168.121.120 Bcast:192.168.121.255 Mask:255.255.255.0
inet6 addr: 2001:250:250:250:250:250:250:222/64 Scope:Global
inet6 addr: fe80::5054:ff:fe1d:79d1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:5999959 errors:0 dropped:0 overruns:0 frame:0
TX packets:104610 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:317521212 (302.8 MiB) TX bytes:8564391 (8.1 MiB)

那么如何用C获取IPv6地址,并且过滤其中Scope为Global的地址:

#define _GNU_SOURCE    # required for NI_NUMERICHOST
#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <netdb.h> int main ()
{
struct ifaddrs *ifap, *ifa;
struct sockaddr_in6 *sa;
struct sockaddr_in *sa4;
char addr[INET6_ADDRSTRLEN];
char addr4[INET_ADDRSTRLEN]; getifaddrs (&ifap);
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr) {
continue;
}
if (ifa->ifa_addr->sa_family==AF_INET6) {
sa = (struct sockaddr_in6 *) ifa->ifa_addr;
getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), addr,
sizeof(addr), NULL, 0, NI_NUMERICHOST);
printf("Interface: %5s\tAddress: %s, scope: ", ifa->ifa_name, addr); // struct sockaddr_in6 sa;
if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) {
printf ("link-local ");
}
if (IN6_IS_ADDR_SITELOCAL(&sa->sin6_addr)) {
printf ("site-local ");
}
if (IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr)) {
printf ("v4mapped ");
}
if (IN6_IS_ADDR_V4COMPAT(&sa->sin6_addr)) {
printf ("v4compat ");
}
if (IN6_IS_ADDR_LOOPBACK(&sa->sin6_addr)) {
printf ("host ");
}
if (IN6_IS_ADDR_UNSPECIFIED(&sa->sin6_addr)) {
printf ("unspecified ");
}
if (IN6_IS_ADDR_MC_GLOBAL(&sa->sin6_addr)){
printf ("global ");
}
printf("\n");
} else if(ifa->ifa_addr->sa_family == AF_INET){
sa4 = (struct sockaddr_in *)ifa->ifa_addr;
getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), addr4,
sizeof(addr4), NULL, 0, NI_NUMERICHOST);
/*inet_ntop(AF_INET, sa4, addr4, INET_ADDRSTRLEN);*/
printf("Interface: %5s\tAddress: %s\n", ifa->ifa_name, addr4);
}
} freeifaddrs(ifap);
return 0;
}

编译下:

gcc -o ipa ipa.c

运行输出:

# ./ipa
Interface: lo Address: 127.0.0.1
Interface: eth0 Address: 192.168.121.120
Interface: eth1 Address: 10.24.0.114
Interface: lo Address: ::1, scope: host
Interface: eth0 Address: 2001:250:250:250:250:250:250:222, scope:
Interface: eth0 Address: fe80::5054:ff:fe1d:79d1%eth0, scope: link-local
Interface: eth1 Address: fe80::5054:ff:fedb:bdd7%eth1, scope: link-local

啊,可见IN6_IS_ADDR_MC_GLOBAL无法判断global的地址,我们只能用排除法了,将IN6_IS_ADDR_MC_GLOBAL判断修改为如下代码:

      // if (IN6_IS_ADDR_MC_GLOBAL(&sa->sin6_addr)){
// printf ("global ");
// }
if (!(IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) && !(IN6_IS_ADDR_SITELOCAL(&sa->sin6_addr)) &&
!(IN6_IS_ADDR_V4MAPPED(&sa->sin6_addr)) && !(IN6_IS_ADDR_LOOPBACK(&sa->sin6_addr)) &&
!(IN6_IS_ADDR_UNSPECIFIED(&sa->sin6_addr))
) {
printf ("global ");
}

重新编译输出:

# ./ipa
Interface: lo Address: 127.0.0.1
Interface: eth0 Address: 192.168.121.120
Interface: eth1 Address: 10.24.0.114
Interface: lo Address: ::1, scope: host
Interface: eth0 Address: 2001:250:250:250:250:250:250:222, scope: global
Interface: eth0 Address: fe80::5054:ff:fe1d:79d1%eth0, scope: link-local
Interface: eth1 Address: fe80::5054:ff:fedb:bdd7%eth1, scope: link-local

Linux C 获取本机IPV4和IPV6地址列表的更多相关文章

  1. Linux中获取本机的最新IPv6地址_更新ddns的脚本

    Linux中获取本机的最新IPv6地址_更新ddns的脚本 转载注明来源: 本文链接 来自osnosn的博客,写于 2019-11-07. 运营商提供ipv6地址. 路由器后有台linux机器,通过e ...

  2. ubuntu(Linux) c++ 获取本机IPv4和ipv6、查询本机IPv4,IPv6

    1.关于 演示环境: Linux xxxxxxx 5.4.0-47-generic #51-Ubuntu SMP Fri Sep 4 19:50:52 UTC 2020 x86_64 x86_64 x ...

  3. linux编程获取本机网络相关参数

    getifaddrs()和struct ifaddrs的使用,获取本机IP 博客分类: Linux C编程   ifaddrs结构体定义如下: struct ifaddrs { struct ifad ...

  4. Linux 获取本机IP、MAC地址用法大全

    getifaddrs()和struct ifaddrs的使用,获取本机IP ifaddrs结构体定义如下: struct ifaddrs { struct ifaddrs *ifa_next; /* ...

  5. Linux下获取本机IP地址的代码

    Linux下获取本机IP地址的代码,返回值即为互联网标准点分格式的字符串. #define ETH_NAME "eth0" //获得本机IP地址 char* GetLocalAdd ...

  6. 获取本机IP、mac地址、计算机名

    python获取本机IP.mac地址.计算机名 在python中获取ip地址和在php中有很大不同,我们先来看一下python 获得本机MAC地址: >>> import uuid ...

  7. js获取本机的网络IP地址

    JavaScript是一门脚本语言,是不能操作文件,读取本地信息的,所以想要获取IP,还需要借助后端技术.方法如下: //获取本机的网络ip地址 function jsonpCallback(res) ...

  8. c#中如何获取本机用户名、MAC地址、IP地址、硬盘ID、CPU序列号、系统名称、物理内存

    我们在利用C#开发桌面程序(Winform)程序的时候, 经常需要获取一些跟系统相关的信息, 以下这些代码获取能有些用处. c#中如何获取本机用户名.MAC地址.IP地址.硬盘ID.CPU序列号.系统 ...

  9. (转)协议森林04 地址耗尽危机 (IPv4与IPv6地址)

    协议森林04 地址耗尽危机 (IPv4与IPv6地址) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! IP地址是IP协议的重要组 ...

  10. [Linux]Linux下开启snmp支持IPV4和IPV6

    SNMP简介 简单网络管理协议(SNMP),由一组网络管理的标准组成,包含一个应用层协议(application layer protocol).数据库模型(database schema)和一组资源 ...

随机推荐

  1. element-ui中el-table多层数组渲染问题

    tableData: [ { name: '国家出资人', list: [ { name: '2011', value: '0' }, { name: '2012', value: '0' }, { ...

  2. Java中ArrayList的常见用法

    Java 中的 ArrayList 是一个非常常用的动态数组,它属于 Java 集合框架的一部分.与普通数组不同,ArrayList 可以在需要时动态调整其大小.以下是 ArrayList 的一些详细 ...

  3. 【BUUCTF】BabySQli

    [BUUCTF]BabySQli 题目来源 收录于:BUUCTF GXYCTF2019 题目描述 纯粹的SQL注入题 随意传入 name=abc&pw=a 返回 wrong user 尝试传入 ...

  4. “未能加载工具箱项xxx,将从工具箱中将其删除”提示出现原因及解决方案

    https://www.thinbug.com/q/27289366 https://social.msdn.microsoft.com/Forums/vstudio/en-US/77e10b58-4 ...

  5. 『Python底层原理』--Python字符串的秘密

    在现代编程中,字符串是不可或缺的数据类型. 无论是处理用户输入.文件读写还是网络通信,字符串都扮演着核心角色. 然而,字符串的处理并非简单地将字符拼接在一起,它涉及到字符集.编码以及编程语言的底层实现 ...

  6. Windows 提权-RunAs

    本文通过 Google 翻译 RunAs – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注释补充. 导航 0 前言 ...

  7. 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义

    引言 ❝ 小编是一名10年+的.NET Coder,期间也写过Java.Python,从中深刻的认识到了软件开发与语言的无关性.现在小编已经脱离了一线开发岗位,在带领团队的过程中,发现了很多的问题,究 ...

  8. PostgreSQL psql 常用快捷命令

    psql 常用快捷命令 \l 显示所有数据库 \c 切换当前数据库,相当于 mysql 的 use 命令 \d 显示数据库中有哪些表 \d tb_name 显示表 tb_name 的定义 \d+ 显示 ...

  9. CentOS 版本选择:DVD、Everything、LiveCD、Minimal、NetInstall

    CentOS 7.X,主要是下载的时候有很多版本供选择,如何选择? DVD版:这个是常用版本,就是普通安装版了,推荐大家安装.里面包含大量的常用软件,大部分情况下安装时无需再在线下载,体积为4G.Ev ...

  10. centos7下扩展根分区(图文详解)

    df -h    查看当前系统磁盘使用状况 fdisk -l    可以看见,我新添加了一块硬盘,大小为10G,新磁盘/dev/sdb fdisk /dev/sdb    对新的磁盘进行分区 在交互模 ...