[Help] IPv6 Link-local scope id

This is a discussion on [Help] IPv6 Link-local scope id within the Networking/Device Communication forums, part of the General Programming Boards category; In Ipv6, when send to a link-local address, the scope-id must be set in sockaddr_in6 struct. It is the index ...

  1. #1
    Registered User
    Join Date
    Jul 2006
    Posts
    6

    [Help] IPv6 Link-local scope id

    In Ipv6, when send to a link-local address, the scope-id must be set in sockaddr_in6 struct. It is the index of the interface that is used to communicate with the link-local address.

    For example, on my machine, the interface index used is 4. I have to set

    addrV6.sin6_scope_id = 4;

    Only then can I sendto(). If I leave it unspecified as 0, I got error.

    My question is, how to retrieve this interface index? I don't think I should set it 4, or any other fixed number, since the index could be totally different on another machine. I googled quite a bit online, and didn't find anything too useful. Any ideas? Thanks!

  2. #2
    Registered User
    Join Date
    Jul 2006
    Posts
    6
    I now found if I first use a recvfrom() to receive a packet from the link-local address, the sin6_scope_id is filled in the "out" parameter "addrfrom".

    But any other ways?

  3. #3
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Are you doing an explicit bind before you call sendto? If you are, I would suggest removing the bind call and allowing sendto to do an implicit bind.

    I came up with some code which lists the local addresses and scope ids. However, this does not tell you which one to use. I guess you could try each in turn. You can determine if an address is link-local by checking its prefix which is FE80::/64 for link-local addresses.
    Code:
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdio.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    int main(void)
    {
    	BYTE                 buf1[65535] = { 0 };
    	BYTE                 buf2[65535] = { 0 };
    	DWORD                cbBuf1      = sizeof(buf1);
    	DWORD                cbBuf2      = sizeof(buf2);
    	SOCKET_ADDRESS_LIST* pList       = (SOCKET_ADDRESS_LIST*) buf2;
    	int                  i           = 0;
    	WSADATA              wd          = { 0 };
    	SOCKET               sock        = 0;
    	BOOL                 fLinkLocal  = FALSE;
    	BYTE                 prefix[8]   = { 0xFE, 0x80 }; // Link-local prefix FE80::/64
    
    	WSAStartup(MAKEWORD(2,0), &wd);
    
    	sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
    	WSAIoctl(sock, SIO_ADDRESS_LIST_QUERY, NULL, 0, buf1, sizeof(buf1), &cbBuf1, NULL, NULL);
    	WSAIoctl(sock, SIO_ADDRESS_LIST_SORT, buf1, cbBuf1, buf2, sizeof(buf2), &cbBuf2, NULL, NULL);
    
    	for (i = 0; i < pList->iAddressCount;i++)
    	{
    		char ip[500];
    		SOCKADDR_IN6* pAddr = (SOCKADDR_IN6*) pList->Address[i].lpSockaddr;
    
    		getnameinfo((const struct sockaddr*) pAddr, sizeof(SOCKADDR_IN6), ip, sizeof(ip), NULL, 0, NI_NUMERICHOST);
    
    		fLinkLocal = (memcmp(pAddr->sin6_addr.u.Byte, prefix, sizeof(prefix)) == 0);
    
    		printf("Address: %s -- Scope ID: %lu -- Link Local: %d\n", ip, pAddr->sin6_scope_id, fLinkLocal);
    	}
    
    	getchar();
    	closesocket(sock);
    	WSACleanup();
    	return 0;
    }
    Last edited by anonytmouse; 08-05-2006 at 01:26 AM.

  4. #4
    Registered User
    Join Date
    Jul 2006
    Posts
    6
    I didn't use bind() before sendto(). But why would using implicit bind() help?

    And by the approach you suggested, I still can't guarantee that the interface that has a link-local address is the correct interface to use, because chances are there are more than one interface that have a link-local address. In this sense, maybe the only way to make sure is to have a recvfrom() to decide on which interface is used for the link?

  5. #5
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> I didn't use bind() before sendto(). But why would using implicit bind() help? <<

    I thought that using an implicit bind might work because the function could select a correct source address based on the destination address.

    >> And by the approach you suggested, I still can't guarantee that the interface that has a link-local address is the correct interface to use, because chances are there are more than one interface that have a link-local address. <<

    I think the core problem is that a given link-local address may be valid on multiple interfaces. Therefore, a link-local address without a scope-id is ambiguous. There may be no way to automatically determine which interface to use.

    I think a user advanced enough to get a IPv6 hex address is probably also advanced enough to obtain the scope-id or at least choose which interface to use from a list.

    The other option is to just try all the interfaces and see which one returns a valid response. However, this raises security issues, may be slow and may ultimately connect to the wrong computer.

    In short, I don't think there is a "solution" to this problem. The scope-id must be considered as part of the address, not something that can be determined from a given address.

    >> In this sense, maybe the only way to make sure is to have a recvfrom() to decide on which interface is used for the link? <<

    I'm not sure why this is working. Do you have a sendto on the other side? If not, where are the packets coming from? recvfrom requires a bound socket. Which source address are you binding to and how do you determine this address?

  6. #6
    Registered User
    Join Date
    Jul 2006
    Posts
    6
    >I'm not sure why this is working. Do you have a sendto on the other side? If not, where are the packets coming from? recvfrom requires a bound socket. Which source address are you binding to and how do you determine this address?
    anonytmouse is offline

    Yes, the process is: node B sends multicast UDPs to ff02::1; node A got the multicast UDP, retrieves the local-link address of B and then communicate with B.

    In such a senario, I think it's feasible to get the scope-id (the actual interface index that is used) after A got the multicast UDP from B.

    Thanks a lot for helping me to clear things out.

  7. #7
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> Yes, the process is: node B sends multicast UDPs to ff02::1; node A got the multicast UDP, retrieves the local-link address of B and then communicate with B. <<

    As I understand it, ff02::1 is the multicast address for all link-local nodes. So this is essentially the more efficient version of "try all the interfaces and see which one returns a valid response".

    This seems to be a pretty good solution, assuming that multiple clients and/or servers on a network either don't exist, or are handled as part of your discovery protocol.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  2. what's wrong...
    By dreamkk in forum C Programming
    Replies: 9
    Last Post: 10-09-2003, 07:12 AM
  3. destructor with a link list
    By Bones in forum C++ Programming
    Replies: 1
    Last Post: 09-24-2003, 01:01 PM
  4. Undefined Structure in Link List
    By _Cl0wn_ in forum C Programming
    Replies: 1
    Last Post: 03-22-2003, 05:57 PM
  5. .lib vs .h vs .dll
    By Shadow12345 in forum C++ Programming
    Replies: 13
    Last Post: 01-01-2003, 05:29 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21