1. 程式人生 > >linux下獲取本機IPv6地址、字首、閘道器

linux下獲取本機IPv6地址、字首、閘道器

獲取本機IPv6資訊命令:cat /proc/net/if_inet6

[email protected]:/home/user1/# cat /proc/net/if_inet6 
fe80000000000000922b34fffe4e70f4 02 40 20 80     eth0
20010f80075400000000000000000050 02 40 00 80     eth0
00000000000000000000000000000001 01 80 10 80       lo

 

獲取本機IPv6閘道器命令:ip -6 route show dev eth0

 

[email protected]:/home/user1/# ip -6 route show dev eth0
2001:f80:754::/64  proto kernel  metric 256 
fe80::/64  proto kernel  metric 256 
default via 2001:f80:754::1  proto static  metric 1 

 

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <errno.h>
#include <paths.h>
#include <sys/syscall.h>
#include <sys/resource.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <sys/ioctl.h>
#include <sys/types.h>    
#include <sys/socket.h>      
#include <net/route.h> 

#define PROCNET_ROUTE_PATH	"/proc/net/route"
#define PROCNET_IFINET6_PATH	"/proc/net/if_inet6"
#define SCOPE_LINK_STR		"fe80"


int net_get_ipv6_ifaddr(char type, const char *ifname, char *addr, int length, char *prefix, int length2)
{
	int ret = 0;
	FILE *fp;
	char addr6[46] = {0}, dev_name[20] = {0};
	char addr6p[8][5];
	int length_of_prefix, scope_value, if_flags, if_index;
	struct sockaddr_in6 sap = {0};
	
	if (!ifname || !addr || length <= 0 || !prefix || length2 <= 0)
		return -1;

	fp = fopen(PROCNET_IFINET6_PATH, "r");
	if (!fp) return -1;

	lockf(fileno(fp), F_LOCK, 0);	
	
	while (fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
		addr6p[0], addr6p[1], addr6p[2], addr6p[3],
		addr6p[4], addr6p[5], addr6p[6], addr6p[7],
		 &if_index, &length_of_prefix, &scope_value, &if_flags, dev_name) != EOF) {
		if (!strcmp(dev_name, ifname)) {
			sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
				addr6p[0], addr6p[1], addr6p[2], addr6p[3],
				addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
			if (strncmp(addr6p[0], SCOPE_LINK_STR, strlen(SCOPE_LINK_STR)) == 0) {
				//fe80 Scope:Link
				if (type == 1) {
					inet_pton(AF_INET6, addr6, &sap.sin6_addr);
					inet_ntop(AF_INET6, &sap.sin6_addr, addr, length);
					snprintf(prefix, length2, "%d", length_of_prefix);
					lockf(fileno(fp), F_ULOCK, 0);
					fclose(fp);
					return 0;
				}
			} else {
				//2001 Scope:Global
				if (type == 0) {
					inet_pton(AF_INET6, addr6, &sap.sin6_addr);
					inet_ntop(AF_INET6, &sap.sin6_addr, addr, length);
					snprintf(prefix, length2, "%d", length_of_prefix);
					lockf(fileno(fp), F_ULOCK, 0);
					fclose(fp);
					return 0;
				}
			}
		}
	}
	lockf(fileno(fp), F_ULOCK, 0);	
	fclose(fp);
	return -1;
}

int net_get_ipv6_gateway(char type, const char *ifname, char *gateway, int length)
{
	FILE *fp;
	char buffer[80] = {'\0'};
	char path[128] = {'\0'};
	char flag = 0;
	char *dfstr = "default via ";
	char *p, *q;
	
	if (!ifname || !gateway || length <= 0)
		return -1;

	//snprintf(path, sizeof(path), "/bin/ip -6 route show dev %s", ifname);
	snprintf(path, sizeof(path), "ip -6 route show dev %s", ifname);//hi3798 have not /bin/ip
	fp = popen(path, "r");
	if (!fp) return -1;

	lockf(fileno(fp), F_LOCK, 0);
	while (fgets(buffer, sizeof(buffer), fp)) {
		if (!strncmp(buffer, dfstr, strlen(dfstr))) {
			p = (char *)&buffer[strlen(dfstr)];
			if (p) {
				q = strchr(p, ' ');
				if (q) {
					if (type == 1) {
						if (strncmp(p, SCOPE_LINK_STR, strlen(SCOPE_LINK_STR)) == 0) {
							snprintf(gateway, (int)(q - p + 1), "%s", p);
							lockf(fileno(fp), F_ULOCK, 0);
							pclose(fp);
							return 0;
						}
					} else {
						snprintf(gateway, (int)(q - p + 1), "%s", p);
						lockf(fileno(fp), F_ULOCK, 0);
						pclose(fp);
						return 0;
					}
				}
			}
		}
	}

	lockf(fileno(fp), F_ULOCK, 0);
	pclose(fp);
	return -1;
}

int net_is_validipv6(const char *hostname)
{
	struct sockaddr_in6 addr;
	
	if (!hostname) return -1;
	if (strchr(hostname, '.')) return -1;//暫時排除::ffff:204.152.189.116
	if (inet_pton(AF_INET6, hostname, &addr.sin6_addr) != 1) return -1;
    	
	return 0;
}

 

 

int net_ipv4_trans_ipv6(const char *source, char *dest, int length)
{
	if (!source || !dest || length <= 0)
		return -1;
	
	if (strncmp(source, "::ffff:", strlen("::ffff:")) == 0 && strchr(source, '.')) {
		char ipv4[32] = {0};
		snprintf(ipv4, sizeof(ipv4), "%s", source+strlen("::ffff:"));
		
		struct in_addr s4 = {0};
		if (inet_pton(AF_INET, ipv4, (void*)&s4) != 1)
			return -1;
		
		char s6[4] = {0};
		s6[0] = s4.s_addr&0xff;
		s6[1] = s4.s_addr>>8&0xff;
		s6[2] = s4.s_addr>>16&0xff;
		s6[3] = s4.s_addr>>24&0xff;
		snprintf(dest, length, "::ffff:%x%.2x:%x%.2x", s6[0]&0xff, s6[1]&0xff, s6[2]&0xff, s6[3]&0xff);
		return 0;
	}
	
	
	return -1;
}



int main(int argc, char *argv[])
{
	int ret = 0;
	char ipv6[64] = {0};
	
	ret = net_ipv4_trans_ipv6(argv[1], ipv6, sizeof(ipv6));
	printf("ret = %d ipv6 = %s\n", ret, ipv6);
	
	return ret;
}