Hello,
ipv6(7) says in the ERROR paragraph that binding to a link-local v6
address without specifying a valid interface index in sin6_scope_id
returns the error ENODEV. This is a bit misleading because specifying 0
or a valid but wrong interface index returns EINVAL or EADDRNOTAVAIL
respectively.
Here is an easy test program
------------------------------->8-------------------------------
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
int main(int argc, char *const argv[])
{
uint32_t scope_id = 0;
char *addr;
in_port_t port = 12345;
int c;
struct sockaddr_in6 sa;
int s, ret;
while ((c = getopt(argc, argv, "i:p:")) != -1) {
switch (c) {
case 'i':
scope_id = atoi(optarg);
break;
case 'p':
port = atoi(optarg);
break;
default:
fprintf(stderr, "Usage: %s [-i scope_id] [-p port] addr\n", argv[0]);
return EXIT_FAILURE;
}
}
if (optind >= argc) {
fprintf(stderr, "Usage: %s [-i scope_id] [-p port] addr\n", argv[0]);
return EXIT_FAILURE;
}
sa.sin6_family = AF_INET6;
inet_pton(AF_INET6, argv[optind], &sa.sin6_addr);
sa.sin6_port = htons(port);
sa.sin6_scope_id = scope_id;
s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (s < 0) {
fprintf(stderr, "Failed to create socket, errno=%d\n", errno);
return EXIT_FAILURE;
}
ret = bind(s, (void *)&sa, sizeof(sa));
if (ret < 0) {
fprintf(stderr, "Failed to bind socket, errno=%d\n", errno);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
------------------------------->8-------------------------------
And with this I get:
$ ./testprog -i 42 -p 12342 fe80::f2de:f1ff:fe44:529d
Failed to bind socket, errno=19
$ ./testprog -i 3 -p 12342 fe80::f2de:f1ff:fe44:529d
$ ./testprog -i 2 -p 12342 fe80::f2de:f1ff:fe44:529d
Failed to bind socket, errno=99
$ ./testprog -i 0 -p 12342 fe80::f2de:f1ff:fe44:529d
Failed to bind socket, errno=22
while interface 3 has the address passed as last parameter.
Best regards
Uwe