Linux下C语言获取IPv6地址和前缀
1 在Linux系统中需要编程获取某个接口的IPv4地址比较常见, 可以使用ioctl函数等方法, 但是要获取IPv6地址, 以前的一些方法就不一定适合,
从网上查找了很多方法, 有两种我试过都可以得到相应的IPv6地址,
此处直接以一段代码做示例展示如何获取指定接口的(IPv6)本地链路地址(注意, 前提是你的Linux支持IPv6, 目前流行的大多数Linux系统早已支持IPv6). 2 #include <stdio.h> 3 #include <string.h> 4 #include <error.h> 5 #include <stdlib.h> 6 7 #define DEBUG 8 //#define UNSUPPORT_IFADDRS 9 10 /* struct in6_addr */ 11 #include <netinet/in.h> 12 /* getifaddrs, freeifaddrs */ 13 #include <sys/types.h> 14 #ifndef UNSUPPORT_IFADDRS 15 #include <ifaddrs.h> 16 #endif 17 /* inet_ntop, inet_pton */ 18 #include <arpa/inet.h> 19 20 #if defined(DEBUG) 21 #define DG(a, b...) printf("[%s][%s][%d]"a, __FILE__, __func__, __LINE__, ##b) 22 #else 23 #define DG(a, b...) 24 #endif 25 26 #define ER(a, b...) printf("[%s][%s][%d]"a, __FILE__, __func__, __LINE__, ##b) 27 28 #ifndef UNSUPPORT_IFADDRS 29 /** 30 * Whlie head file is not existed in you include directory, just define 31 * macro UNSUPPORT_IFADDRS to disable this function. 32 * Because of function getifaddrs() and freeifaddrs() are declared in this head file, 33 * the function can't pass compiling process if lack in your system. 34 */ 35 int get_linklocal_ipv6addr(struct in6_addr *addr6, char *iface) 36 { 37 struct ifaddrs *ifa, *p; 38 int family; 39 char address[200]; 40 41 if (!addr6 || !iface) { 42 ER("addr6 and iface can't be NULL!\n"); 43 return -1; 44 } 45 46 if (getifaddrs(&ifa)) { 47 ER(""); 48 perror("getifaddrs error"); 49 return -1; 50 } 51 52 for (p = ifa; p != NULL; p = p->ifa_next) { 53 DG("ifa_name = %s, family = 0x%X(%s)\n", p->ifa_name, family, 54 (family == AF_PACKET) ? "AF_PACKET" : 55 (family == AF_INET) ? "AF_INET" : 56 (family == AF_INET6) ? "AF_INET6" : ""); 57 58 family = p->ifa_addr->sa_family; 59 /* Just check IPv6 address */ 60 if (family != AF_INET6) 61 continue; 62 63 *addr6 = ((struct sockaddr_in6 *)(p->ifa_addr))->sin6_addr; 64 /* Just get IPv6 linklocal address of the interface */ 65 if (!strcmp(iface, p->ifa_name) && IN6_IS_ADDR_LINKLOCAL(addr6)) { 66 if (inet_ntop(AF_INET6, addr6, address, sizeof(address))) { 67 DG("find out %s's linklocal IPv6 address: %s\n", iface, address); 68 } 69 break; 70 } 71 } 72 73 freeifaddrs(ifa); 74 return 0; 75 } 76 #else 77 /** 78 * If head file is not existed in your system, you could get information of IPv6 address 79 * in file /proc/net/if_inet6. 80 * 81 * Contents of file "/proc/net/if_inet6" like as below: 82 * 00000000000000000000000000000001 01 80 10 80 lo 83 * fe8000000000000032469afffe08aa0f 08 40 20 80 ath0 84 * fe8000000000000032469afffe08aa0f 07 40 20 80 wifi0 85 * fe8000000000000032469afffe08aa0f 05 40 20 80 eth1 86 * fe8000000000000032469afffe08aa0f 03 40 20 80 br0 87 * fe8000000000000032469afffe08aa10 04 40 20 80 eth0 88 * 89 * +------------------------------+ ++ ++ ++ ++ +---+ 90 * | | | | | | 91 * 1 2 3 4 5 6 92 * 93 * There are 6 row items parameters: 94 * 1 => IPv6 address without ':' 95 * 2 => Interface index 96 * 3 => Length of prefix 97 * 4 => Scope value (see kernel source "include/net/ipv6.h" and "net/ipv6/addrconf.c") 98 * 5 => Interface flags (see kernel source "include/linux/rtnetlink.h" and "net/ipv6/addrconf.c" "linux/include/if_addr.h") 99 * 6 => Device name 100 * 101 * Note that all values of row 1~5 are hexadecimal string 102 */ 103 104 105 int get_linklocal_ipv6addr(struct in6_addr *addr6, char *iface) 106 { 107 #define IF_INET6 "/proc/net/if_inet6" 108 char str[128], address[64]; 109 char *addr, *index, *prefix, *scope, *flags, *name; 110 char *delim = " \t\n", *p, *q; 111 FILE *fp; 112 int count; 113 114 if (!addr6 || !iface) { 115 ER("addr6 and iface can't be NULL!\n"); 116 return -1; 117 } 118 119 if (NULL == (fp = fopen(IF_INET6, "r"))) { 120 ER(""); 121 perror("fopen error"); 122 return -1; 123 } 124 125 #define IPV6_ADDR_LINKLOCAL 0x0020U 126 while (fgets(str, sizeof(str), fp)) { 127 DG("str:%s", str); 128 addr = strtok(str, delim); 129 index = strtok(NULL, delim); 130 prefix = strtok(NULL, delim); 131 scope = strtok(NULL, delim); 132 flags = strtok(NULL, delim); 133 name = strtok(NULL, delim); 134 DG("addr:%s, index:0x%s, prefix:0x%s, scope:0x%s, flags:0x%s, name:%s\n", 135 addr, index, prefix, scope, flags, name); 136 137 if (strcmp(name, iface)) 138 continue; 139 140 /* Just get IPv6 linklocal address */ 141 if (IPV6_ADDR_LINKLOCAL != (unsigned int)strtoul(scope, NULL, 16)) 142 continue; 143 144 memset(address, 0x00, sizeof(address)); 145 p = addr; 146 q = address; 147 count = 0; 148 while (*p != '') { 149 if (count == 4) { 150 *q++ = ':'; 151 count = 0; 152 } 153 *q++ = *p++; 154 count++; 155 } 156 DG("find out %s's linklocal IPv6 address: %s\n", iface, address); 157 158 inet_pton(AF_INET6, address, addr6); 159 break; 160 } 161 #undef IPV6_ADDR_LINKLOCAL 162 163 fclose(fp); 164 return 0; 165 } 166 #endif 167 168 int main (int argc, char *argv[]) 169 { 170 struct in6_addr addr6; 171 char *ifname = "eth0"; 172 char address[64]; 173 174 if (get_linklocal_ipv6addr(&addr6, ifname)) { 175 printf("\nGet IPv6 linklocal address of %s failed :(\n", ifname); 176 return -1; 177 } 178 if (inet_ntop(AF_INET6, &addr6, address, sizeof(address))) 179 printf("\nIPv6 linklocal address of %s is %s :)\n", ifname, address); 180 181 return 0; 182 } 183 184 185 186 注意: 187 188 关于Interface flags 189 190 /* ifa_flags */ 191 #define IFA_F_SECONDARY 0x01 192 #define IFA_F_TEMPORARY IFA_F_SECONDARY 193 194 #define IFA_F_NODAD 0x02 195 #define IFA_F_OPTIMISTIC 0x04 196 #define IFA_F_HOMEADDRESS 0x10 197 #define IFA_F_DEPRECATED 0x20 198 #define IFA_F_TENTATIVE 0x40 199 #define IFA_F_PERMANENT 0x80 200 201 一般请情况下flag的值应为0x80,如果为其他值应该怀疑interface在init的时候是否有起来 202 203 bug record: 204 205 flag=0xc0, init 不对,导致这个interface sendmsg 出错(22) 206 207 208 209 转自:http://yangxy84.blog.163.com/blog/static/708443020119171265179/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律