X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=socket.c;h=48a5d4b57d89d23c463e8ee8817d8e7e11cb5562;hb=3bbfb70938c6b08b72a8958e5a6499a9280a7d8f;hp=a77f6315564c3be800e63b3fc95305ae58ab800f;hpb=4ba1a4b0b4488e5058af67b789187735b529075e;p=catta diff --git a/socket.c b/socket.c index a77f631..48a5d4b 100644 --- a/socket.c +++ b/socket.c @@ -26,12 +26,96 @@ static void mdns_mcast_group_ipv4(struct sockaddr_in *ret_sa) { inet_pton(AF_INET, "224.0.0.251", &ret_sa->sin_addr); } +static void mdns_mcast_group_ipv6(struct sockaddr_in6 *ret_sa) { + + g_assert(ret_sa); + + memset(ret_sa, 0, sizeof(struct sockaddr_in6)); + + ret_sa->sin6_family = AF_INET6; + ret_sa->sin6_port = htons(MDNS_PORT); + inet_pton(AF_INET6, "ff02::fb", &ret_sa->sin6_addr); +} + +int flx_mdns_mcast_join_ipv4 (int index, int fd) +{ + struct ip_mreqn mreq; + struct sockaddr_in sa; + + mdns_mcast_group_ipv4 (&sa); + + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr = sa.sin_addr; + mreq.imr_ifindex = index; + + if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + g_warning("IP_ADD_MEMBERSHIP failed: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +int flx_mdns_mcast_join_ipv6 (int index, int fd) +{ + struct ipv6_mreq mreq6; + struct sockaddr_in6 sa6; + + mdns_mcast_group_ipv6 (&sa6); + + memset(&mreq6, 0, sizeof(mreq6)); + mreq6.ipv6mr_multiaddr = sa6.sin6_addr; + mreq6.ipv6mr_interface = index; + + if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { + g_warning("IPV6_ADD_MEMBERSHIP failed: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +int flx_mdns_mcast_leave_ipv4 (int index, int fd) +{ + struct ip_mreqn mreq; + struct sockaddr_in sa; + + mdns_mcast_group_ipv4 (&sa); + + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr = sa.sin_addr; + mreq.imr_ifindex = index; + + if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + g_warning("IP_DROP_MEMBERSHIP failed: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + +int flx_mdns_mcast_leave_ipv6 (int index, int fd) +{ + struct ipv6_mreq mreq6; + struct sockaddr_in6 sa6; + + mdns_mcast_group_ipv6 (&sa6); + + memset(&mreq6, 0, sizeof(mreq6)); + mreq6.ipv6mr_multiaddr = sa6.sin6_addr; + mreq6.ipv6mr_interface = index; + + if (setsockopt(fd, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { + g_warning("IPV6_DROP_MEMBERSHIP failed: %s\n", strerror(errno)); + return -1; + } + + return 0; +} + gint flx_open_socket_ipv4(void) { - struct ip_mreqn mreq; struct sockaddr_in sa, local; int fd = -1, ttl, yes; - - mdns_mcast_group_ipv4(&sa); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { g_warning("socket() failed: %s\n", strerror(errno)); @@ -39,13 +123,13 @@ gint flx_open_socket_ipv4(void) { } ttl = 255; - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) { + if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) { g_warning("IP_MULTICAST_TTL failed: %s\n", strerror(errno)); goto fail; } ttl = 255; - if (setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) { + if (setsockopt(fd, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) { g_warning("IP_TTL failed: %s\n", strerror(errno)); goto fail; } @@ -56,6 +140,13 @@ gint flx_open_socket_ipv4(void) { goto fail; } + yes = 1; + if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { + g_warning("IP_MULTICAST_LOOP failed: %s\n", strerror(errno)); + goto fail; + } + + memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = htons(MDNS_PORT); @@ -65,24 +156,14 @@ gint flx_open_socket_ipv4(void) { goto fail; } - memset(&mreq, 0, sizeof(mreq)); - mreq.imr_multiaddr = sa.sin_addr; - mreq.imr_address.s_addr = htonl(INADDR_ANY); - mreq.imr_ifindex = 0; - - if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { - g_warning("IP_ADD_MEMBERSHIP failed: %s\n", strerror(errno)); - goto fail; - } - yes = 1; - if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) { + if (setsockopt(fd, SOL_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) { g_warning("IP_RECVTTL failed: %s\n", strerror(errno)); goto fail; } yes = 1; - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) { + if (setsockopt(fd, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) { g_warning("IP_PKTINFO failed: %s\n", strerror(errno)); goto fail; } @@ -106,19 +187,7 @@ fail: return -1; } -static void mdns_mcast_group_ipv6(struct sockaddr_in6 *ret_sa) { - g_assert(ret_sa); - - memset(ret_sa, 0, sizeof(struct sockaddr_in6)); - - ret_sa->sin6_family = AF_INET6; - ret_sa->sin6_port = htons(MDNS_PORT); - inet_pton(AF_INET6, "ff02::fb", &ret_sa->sin6_addr); -} - - gint flx_open_socket_ipv6(void) { - struct ipv6_mreq mreq; struct sockaddr_in6 sa, local; int fd = -1, ttl, yes; @@ -130,13 +199,13 @@ gint flx_open_socket_ipv6(void) { } ttl = 255; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0) { + if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0) { g_warning("IPV6_MULTICAST_HOPS failed: %s\n", strerror(errno)); goto fail; } ttl = 255; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0) { + if (setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0) { g_warning("IPV6_UNICAST_HOPS failed: %s\n", strerror(errno)); goto fail; } @@ -147,6 +216,18 @@ gint flx_open_socket_ipv6(void) { goto fail; } + yes = 1; + if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) < 0) { + g_warning("IPV6_V6ONLY failed: %s\n", strerror(errno)); + goto fail; + } + + yes = 1; + if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { + g_warning("IPV6_MULTICAST_LOOP failed: %s\n", strerror(errno)); + goto fail; + } + memset(&local, 0, sizeof(local)); local.sin6_family = AF_INET6; local.sin6_port = htons(MDNS_PORT); @@ -156,23 +237,14 @@ gint flx_open_socket_ipv6(void) { goto fail; } - memset(&mreq, 0, sizeof(mreq)); - mreq.ipv6mr_multiaddr = sa.sin6_addr; - mreq.ipv6mr_interface = 0; - - if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { - g_warning("IPV6_ADD_MEMBERSHIP failed: %s\n", strerror(errno)); - goto fail; - } - yes = 1; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) { + if (setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) { g_warning("IPV6_HOPLIMIT failed: %s\n", strerror(errno)); goto fail; } yes = 1; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &yes, sizeof(yes)) < 0) { + if (setsockopt(fd, SOL_IPV6, IPV6_PKTINFO, &yes, sizeof(yes)) < 0) { g_warning("IPV6_PKTINFO failed: %s\n", strerror(errno)); goto fail; } @@ -233,7 +305,7 @@ gint flx_send_dns_packet_ipv4(gint fd, gint interface, flxDnsPacket *p) { mdns_mcast_group_ipv4(&sa); memset(&io, 0, sizeof(io)); - io.iov_base = p->data; + io.iov_base = FLX_DNS_PACKET_DATA(p); io.iov_len = p->size; memset(cmsg_data, 0, sizeof(cmsg_data)); @@ -273,7 +345,7 @@ gint flx_send_dns_packet_ipv6(gint fd, gint interface, flxDnsPacket *p) { mdns_mcast_group_ipv6(&sa); memset(&io, 0, sizeof(io)); - io.iov_base = p->data; + io.iov_base = FLX_DNS_PACKET_DATA(p); io.iov_len = p->size; memset(cmsg_data, 0, sizeof(cmsg_data)); @@ -311,10 +383,10 @@ flxDnsPacket* flx_recv_dns_packet_ipv4(gint fd, struct sockaddr_in *ret_sa, gint g_assert(ret_iface); g_assert(ret_ttl); - p = flx_dns_packet_new(); + p = flx_dns_packet_new(0); - io.iov_base = p->data; - io.iov_len = sizeof(p->data); + io.iov_base = FLX_DNS_PACKET_DATA(p); + io.iov_len = p->max_size; memset(&msg, 0, sizeof(msg)); msg.msg_name = ret_sa; @@ -344,7 +416,8 @@ flxDnsPacket* flx_recv_dns_packet_ipv4(gint fd, struct sockaddr_in *ret_sa, gint } } - g_assert(found_iface && found_ttl); + g_assert(found_iface); + g_assert(found_ttl); return p; @@ -356,7 +429,7 @@ fail: } flxDnsPacket* flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6 *ret_sa, gint *ret_iface, guint8* ret_ttl) { - flxDnsPacket *p= NULL; + flxDnsPacket *p = NULL; struct msghdr msg; struct iovec io; uint8_t aux[64]; @@ -369,10 +442,10 @@ flxDnsPacket* flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6 *ret_sa, gin g_assert(ret_iface); g_assert(ret_ttl); - p = flx_dns_packet_new(); + p = flx_dns_packet_new(0); - io.iov_base = p->data; - io.iov_len = sizeof(p->data); + io.iov_base = FLX_DNS_PACKET_DATA(p); + io.iov_len = p->max_size; memset(&msg, 0, sizeof(msg)); msg.msg_name = ret_sa; @@ -389,20 +462,21 @@ flxDnsPacket* flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6 *ret_sa, gin p->size = (size_t) l; *ret_ttl = 0; - - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg,cmsg)) { - if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IPV6_HOPLIMIT) { + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) { *ret_ttl = *(uint8_t *) CMSG_DATA(cmsg); found_ttl = TRUE; } - if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IPV6_PKTINFO) { - *ret_iface = ((struct in_pktinfo*) CMSG_DATA(cmsg))->ipi_ifindex; + if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) { + *ret_iface = ((struct in6_pktinfo*) CMSG_DATA(cmsg))->ipi6_ifindex; found_iface = TRUE; } } - g_assert(found_iface && found_ttl); + g_assert(found_iface); + g_assert(found_ttl); return p;