/**
* Function: To print the IPv6 addresses assinged to a given
* interface by reading /proc/net/if_inet6. This file has
* data in the following format;
*
3ffe040007a0ba0a0000000000000001 06 40 00 80     eth2
3ffe040007a0ba080000000000000001 05 40 00 80     eth1
00000000000000000000000000000001 01 80 10 80       lo
3ffe040007a0ba000000000000000003 04 40 00 80     eth0
fe80000000000000020476fffe11e0ef 06 40 20 80     eth2
fe80000000000000023005fffe0f7fc4 04 40 20 80     eth0
fe80000000000000020a5efffe52a9b0 05 40 20 80     eth1
*
*
* Compile this program with;
*  gcc -o get-ipv6-addr get-ipv6-addr.c
*
* Author: Asanga Udugama (adu@comnets.uni-bremen.de)
* Date: 07-oct-2006
* License: GPL
*/
#include <stdio.h>
#include <string.h>
 
void print_address(char *buf);
void print_usage(char *argv[]);

int main(int argc, char *argv[])
{
	FILE *fp;
	char buf[256];
	unsigned int fl = 0;
	int found, x;

	if(argc != 2) {
		printf("No interface name given\n");
		print_usage(argv);
		exit(1);
	}

	if((fp = fopen("/proc/net/if_inet6", "r")) == (FILE *) 0) {
		printf("Cannot open /proc/net/if_inet6\n");
		print_usage(argv);
		exit(1);
	}
			
	found = 0;
	while(fgets(buf, 256, fp) != NULL) {

		// is it the given interface name ?
		if(strstr(buf, argv[1]) == (char *) 0) {
			continue;
		}
		
		// get the interface type flag
		if(sscanf(buf, "%*s %*02x %*02x %02x", &fl) != 1) {
			continue;
		}
		
		// if the first nible of flag is 0x00; then 
		// it is global IPv6 address  
		if((fl & 0xF0) == 0x00) {
			printf("Global Address: ");
			print_address(buf);
			printf("\n");
			found = 1;
		
		// if the first nible of flag is 0x20; then 
		// it is link local IPv6 address  
		} else if((fl & 0xF0) == 0x20) {
			printf("Link-local Address: ");
			print_address(buf);
			printf("\n");
			found = 1;
		
		// if the first nible of flag is 0x10; then 
		// it is loopback IPv6 address  
		} else if((fl & 0xF0) == 0x10) {
			printf("Loopback Address: ");
			print_address(buf);
			printf("\n");
			found = 1;
		}
	}

	if(!found) {
		printf("No IPv6 addresses found for the given interface \n");
		exit(1);
	}
	
}

void print_address(char *buf)
{
	printf("%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c:%c%c%c%c", 
				buf[0], buf[1], buf[2], buf[3],
				buf[4], buf[5], buf[6], buf[7],
				buf[8], buf[9], buf[10], buf[11],
				buf[12], buf[13], buf[14], buf[15],
				buf[16], buf[17], buf[18], buf[19],
				buf[20], buf[21], buf[22], buf[23],
				buf[24], buf[25], buf[26], buf[27],
				buf[28], buf[29], buf[30], buf[31]);
}

void print_usage(char *argv[])
{
	printf("Usage:\n");
	printf("   %s ifc-name\n", argv[0]);
	printf("   ifc-name = interface name (e.g. eth0, tun0, etc)\n");
}
