It will bind fine to global IPv6 addresses, but not to link-local IPv6 addresses. I don't have time to track it down now, so opening bug so issue is not totally forgotten. Code in question looks like this: int createSctp6Socket(const char* ipv6_addr_string, uint16 ip_port, const char* dev_to_bind_to) { return createConnected6Socket(ipv6_addr_string, ip_port, dev_to_bind_to, IPPROTO_SCTP); } int createConnected6Socket(const char* ipv6_addr_string, uint16 ip_port, const char* dev_to_bind_to, int proto_type) { int aiErr; int s = -1; struct addrinfo *aiHead; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICSERV; hints.ai_family = PF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = proto_type; char service[40]; sprintf(service, "%d", (int)(ip_port)); const char* node = ipv6_addr_string; if (( aiErr = getaddrinfo(node, service, &hints, &aiHead)) != 0) { VLOG_ERR(VLOG << "ERROR: trying to get addrinfo for ipv6 on port: " << dev_to_bind_to << " error: " << gai_strerror(aiErr) << " node: " << node << " service: " << service << endl); return -1; } if (aiHead) { // Got one..not sure why we'd get multiple..will ignore for now. s = lfsocket(aiHead->ai_family, aiHead->ai_socktype, aiHead->ai_protocol); if (s < 0) { cerr << "ERROR: connected IPv6 socket: " << LFSTRERROR << endl; VLOG << "ERROR: connected IPv6 socket: " << LFSTRERROR << endl; return s; } close_exec(s); reuseaddr_socket(s); if (dev_to_bind_to) { // Bind to specific device. #if ! (defined(__WIN32__) || defined(__sun__)) if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, dev_to_bind_to, DEV_NAME_LEN + 1)) { VLOG_ERR(VLOG << "ERROR: tcp-connect, setsockopt (BINDTODEVICE): " << LFSTRERROR << " Not fatal in most cases..continuing...\n"); } #endif }//if // Windows doesn't support this it seems. #ifdef IPV6_V6ONLY int v6_only = 1; if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &v6_only, sizeof(v6_only))) { VLOG_ERR(VLOG << "ERROR: setsockopt(IPV6_V6ONLY): " << LFSTRERROR << endl); } #endif int r = bind(s, aiHead->ai_addr, aiHead->ai_addrlen); if (r < 0) { VLOG_ERR(VLOG << "ERROR: connected IPv6 bind: " << LFSTRERROR << " IP: " << ipv6_addr_string << " ip_ort: " << ip_port << " ai-addr: " << toString((struct sockaddr_in6*)(aiHead->ai_addr)) << " ai-addr-len: " << aiHead->ai_addrlen << " ai-socktype: " << (int)(aiHead->ai_socktype) << " ai-protocol: " << (int)(aiHead->ai_protocol) << endl); closesocket(s); return r; } else { VLOG_INF(VLOG << "Successfully bound connected socket IP6: " << toString((struct sockaddr_in6*)(aiHead->ai_addr)) << " port: " << ip_port << endl); } nonblock(s, "create tcp6 socket"); }//if we found one freeaddrinfo( aiHead ); return s; }
the reason is that : sctp_do_bind invoke sctp_inet6_bind_verify(),which have the following limit: ... if (type & IPV6_ADDR_LINKLOCAL) { struct net *net; if (!addr->v6.sin6_scope_id) <=== the limit return 0; net = sock_net(&opt->inet.sk); rcu_read_lock(); dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id); if (!dev || !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0)) { rcu_read_unlock(); return 0; } rcu_read_unlock(); } else if (type == IPV6_ADDR_MAPPED) { ... so it's not a bug , you can workaround it like: 1.add a line: aiHead->ai_addr.sin6_scope_id=3 (3 is the dev's ifindex , you need to know it). or, 2.getting your sockaddr to bind from getifaddrs(), which will fill out the scope id for you. note: sin6_scope_id is net_device's ifindex when sockaddr is link local addr in ipv6.
@lucien I was wondering if you could point to the easiest way to test this bug. I am a novice and this is my first try at fixing a bug. Thanks, Aarti (In reply to lucien from comment #1) > the reason is that : sctp_do_bind invoke sctp_inet6_bind_verify(),which have > the following limit: > ... > if (type & IPV6_ADDR_LINKLOCAL) { > struct net *net; > if (!addr->v6.sin6_scope_id) <=== the limit > return 0; > net = sock_net(&opt->inet.sk); > rcu_read_lock(); > dev = dev_get_by_index_rcu(net, > addr->v6.sin6_scope_id); > if (!dev || > !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, > 0)) { > rcu_read_unlock(); > return 0; > } > rcu_read_unlock(); > } else if (type == IPV6_ADDR_MAPPED) { > ... > > so it's not a bug , you can workaround it like: > 1.add a line: aiHead->ai_addr.sin6_scope_id=3 (3 is the dev's ifindex , you > need to know it). > > or, > 2.getting your sockaddr to bind from getifaddrs(), which will fill out the > scope id for you. > > note: sin6_scope_id is net_device's ifindex when sockaddr is link local addr > in ipv6.