X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fmdnsd.git;a=blobdiff_plain;f=interface.c;h=712d3c520ca810e2bbb2f7982c4b451051e9a01f;hp=b5022a724b8ba608fdb970c85daea75ea68c6dc3;hb=4059fe10c18e7ea7309198741f18cf71c6afc911;hpb=e4cd9b52ef1e73c81143e5c3d09e08e86a5a49ae diff --git a/interface.c b/interface.c index b5022a7..712d3c5 100644 --- a/interface.c +++ b/interface.c @@ -40,10 +40,7 @@ int interface_send_packet(struct interface *iface, struct iovec *iov, int iov_len) { static size_t cmsg_data[( CMSG_SPACE(sizeof(struct in_pktinfo)) / sizeof(size_t)) + 1]; - static struct sockaddr_in a = { - .sin_family = AF_INET, - .sin_port = htons(MCAST_PORT), - }; + static struct sockaddr_in a; static struct msghdr m = { .msg_name = (struct sockaddr *) &a, .msg_namelen = sizeof(a), @@ -54,6 +51,8 @@ interface_send_packet(struct interface *iface, struct iovec *iov, int iov_len) struct cmsghdr *cmsg; int fd = iface->fd.fd; + a.sin_family = AF_INET; + a.sin_port = htons(MCAST_PORT); m.msg_iov = iov; m.msg_iovlen = iov_len; @@ -110,6 +109,57 @@ read_socket(struct uloop_fd *u, unsigned int events) dns_handle_packet(iface, buffer, len); } +static int +interface_socket_setup(struct interface *iface) +{ + struct ip_mreqn mreq; + uint8_t ttl = 255; + int yes = 1; + int no = 0; + struct sockaddr_in sa = { 0 }; + int fd = iface->fd.fd; + + sa.sin_family = AF_INET; + sa.sin_port = htons(MCAST_PORT); + inet_pton(AF_INET, MCAST_ADDR, &sa.sin_addr); + + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_address.s_addr = iface->v4_addr.s_addr; + mreq.imr_multiaddr = sa.sin_addr; + mreq.imr_ifindex = iface->ifindex; + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) + fprintf(stderr, "ioctl failed: IP_MULTICAST_TTL\n"); + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) + fprintf(stderr, "ioctl failed: SO_REUSEADDR\n"); + + /* Some network drivers have issues with dropping membership of + * mcast groups when the iface is down, but don't allow rejoining + * when it comes back up. This is an ugly workaround + * -- this was copied from avahi -- + */ + setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); + + if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + fprintf(stderr, "failed to join multicast group: %s\n", strerror(errno)); + close(fd); + fd = -1; + return -1; + } + + if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) + fprintf(stderr, "ioctl failed: IP_RECVTTL\n"); + + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) + fprintf(stderr, "ioctl failed: IP_PKTINFO\n"); + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no, sizeof(no)) < 0) + fprintf(stderr, "ioctl failed: IP_MULTICAST_LOOP\n"); + + return 0; +} + static void reconnect_socket(struct uloop_timeout *timeout) { @@ -160,105 +210,50 @@ iface_update_cb(struct vlist_tree *tree, struct vlist_node *node_new, } } -int interface_socket_setup(struct interface *iface) +static int +get_iface_ipv4(struct interface *iface) { - struct ip_mreqn mreq; - uint8_t ttl = 255; - int yes = 1; - int no = 0; - struct sockaddr_in sa = { 0 }; - struct in_addr in; - int fd = iface->fd.fd; - - inet_aton(iface->ip, &in); - - sa.sin_family = AF_INET; - sa.sin_port = htons(MCAST_PORT); - inet_pton(AF_INET, MCAST_ADDR, &sa.sin_addr); - - memset(&mreq, 0, sizeof(mreq)); - mreq.imr_address.s_addr = in.s_addr; - mreq.imr_multiaddr = sa.sin_addr; - mreq.imr_ifindex = iface->ifindex; - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) - fprintf(stderr, "ioctl failed: IP_MULTICAST_TTL\n"); - - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) - fprintf(stderr, "ioctl failed: SO_REUSEADDR\n"); - - /* Some network drivers have issues with dropping membership of - * mcast groups when the iface is down, but don't allow rejoining - * when it comes back up. This is an ugly workaround - * -- this was copied from avahi -- - */ - setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); - - if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { - fprintf(stderr, "failed to join multicast group: %s\n", strerror(errno)); - close(fd); - fd = -1; - return -1; - } - - if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) - fprintf(stderr, "ioctl failed: IP_RECVTTL\n"); - - if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) - fprintf(stderr, "ioctl failed: IP_PKTINFO\n"); - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &no, sizeof(no)) < 0) - fprintf(stderr, "ioctl failed: IP_MULTICAST_LOOP\n"); - - return 0; -} - -static const char* -get_iface_ipv4(const char *ifname) -{ - static char buffer[INET_ADDRSTRLEN]; + struct sockaddr_in *sin; struct ifreq ir; - const char *ret; - int sock; + int sock, ret = -1; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) - return NULL; + return -1; memset(&ir, 0, sizeof(struct ifreq)); - strncpy(ir.ifr_name, ifname, sizeof(ir.ifr_name)); + strncpy(ir.ifr_name, iface->name, sizeof(ir.ifr_name)); - if (ioctl(sock, SIOCGIFADDR, &ir) < 0) - return NULL; + ret = ioctl(sock, SIOCGIFADDR, &ir); + if (ret < 0) + goto out; - ret = inet_ntop(AF_INET, &((struct sockaddr_in *) &ir.ifr_addr)->sin_addr, buffer, sizeof(buffer)); - close(sock); + sin = (struct sockaddr_in *) &ir.ifr_addr; + memcpy(&iface->v4_addr, &sin->sin_addr, sizeof(iface->v4_addr)); +out: + close(sock); return ret; } int interface_add(const char *name) { struct interface *iface; - const char *ip_str; - char *name_buf, *ip_buf; - - ip_str = get_iface_ipv4(name); - if (!ip_str) - return -1; + char *name_buf; iface = calloc_a(sizeof(*iface), - &name_buf, strlen(name) + 1, - &ip_buf, strlen(ip_str) + 1); + &name_buf, strlen(name) + 1); iface->name = strcpy(name_buf, name); - iface->ip = strcpy(ip_buf, ip_str); iface->ifindex = if_nametoindex(name); iface->fd.fd = -1; if (iface->ifindex <= 0) goto error; + if (get_iface_ipv4(iface)) + goto error; + vlist_add(&interfaces, &iface->node, name); return 0;