2

What would be the C code to translate an IPv6 address representing the prefix mask into an integer.

For example, this IPv6 address prefix mask: FFFF:FFFF:FFFF:FFFF:0000:0000:0000:0000

would be converted to 64

Thanks

Need to change this from sockaddr_in6 into a int

Samuel
  • 175
  • 4
  • 11
  • possible duplicate of [IPv6 parsing in C](http://stackoverflow.com/questions/2962664/ipv6-parsing-in-c) – Mahmoud Al-Qudsi May 24 '12 at 21:49
  • 2
    What are you asking? Are you asking for "the number of bits set within an IPV6 address? Because FFFF:FFFF:FFFF:FFFF is not 64 in any numberic system, it just happens be be a 64-bit number that has all 64-bits set. So do you want the width of the integer? Or just the number of bits set. Or do you want to conver that to a real integer such as (2^64)-1. – selbie May 24 '12 at 21:52
  • 1
    More like the equivalent for IPv4: 255.255.255.0 will be /24 so here, 64 bits set to 1 making a /64 bit netmask out of the 128-bit IPv6 address. Thanks! – Samuel May 24 '12 at 21:58
  • 1
    No, not a duplicate of IPV6 parsing in C. This is for networking purpose where you want to represent the subnet mask of the network using an integer rather than in address format. In IPv4, we would use 255.255.255.0 for representing a /24 network or 255.255.255.248 for a /29 network – Samuel May 24 '12 at 22:06
  • Just like IPv4: use `inet_pton` to pack the string into a number, then start counting bits. – ikegami May 24 '12 at 23:34
  • Sorry, this already a number. I have it in a sockaddr_in6 – Samuel May 25 '12 at 02:41
  • Need to change this sockaddr_in6 into a int – Samuel May 25 '12 at 02:57
  • @selbie Im sorry about that, I share my account with some other people (friends, family) and I'm not a frequent user of stackoverflow, so some of the questions on my account go on ignored. thanks for pointing this out. – Samuel May 25 '12 at 13:01

2 Answers2

3

The best way to find the number of bits is to never forget them. Since IPv6 requires that bitmasks be specified by the Address/Bits method, record Bits and keep it around.

If you do not, then this is a bit counting problem. Since the bits must be all at the beginning I would try to approach it by checking Word-Size bits at a time. The Word-Size is probably 32 or 64. When it no longer equals -1UL then check half-word size, quarter-word size and 1 byte. Use a 256 item lookup table for the last byte.

There is probably some terribly cool bit twiddling method to do this very quickly. You'll have to look that up on your own.

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
3

My approach is related to Zan's, but copes with the fact that a struct in6_addr, which is contained in a struct sockaddr_in6, is essentially an array of 16 chars.

So you should iterate over the bytes until you find a value != 0xFF.

int bits = 0;
struct in6_addr * addr = &((struct sockaddr_in6 *)ai_addr)->sin6_addr;
for (i=0; i<16; i++) {
    if (addr->s6_addr[i] == '\xFF') {
        bits += 8;
    } else {
        case (addr->s6_addr[i]) {
            '\xFE': bits += 7; break;
            '\xFC': bits += 6; break;
            '\xF8': bits += 5; break;
            '\xF0': bits += 4; break;
            '\xE0': bits += 3; break;
            '\xC0': bits += 2; break;
            '\x80': bits += 1; break;
            '\x00': bits += 0; break;
            default: complain();
        }
        break;
    }
}

But, as Zan writes, better keep the number you already have an generate the mask if you need it, not the other way.

But, @SamuelChampagne, really: you should really accept working answers! One day, people will refuse to help you at all.

glglgl
  • 89,107
  • 13
  • 149
  • 217