From owner-p4-projects@FreeBSD.ORG Wed Jun 20 10:24:13 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id B1AB616A46B; Wed, 20 Jun 2007 10:24:13 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 7186B16A421 for ; Wed, 20 Jun 2007 10:24:13 +0000 (UTC) (envelope-from fli@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id 61FCD13C4DA for ; Wed, 20 Jun 2007 10:24:13 +0000 (UTC) (envelope-from fli@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l5KAOD3a076951 for ; Wed, 20 Jun 2007 10:24:13 GMT (envelope-from fli@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l5KAODiu076942 for perforce@freebsd.org; Wed, 20 Jun 2007 10:24:13 GMT (envelope-from fli@FreeBSD.org) Date: Wed, 20 Jun 2007 10:24:13 GMT Message-Id: <200706201024.l5KAODiu076942@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to fli@FreeBSD.org using -f From: Fredrik Lindberg To: Perforce Change Reviews Cc: Subject: PERFORCE change 122018 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Jun 2007 10:24:14 -0000 http://perforce.freebsd.org/chv.cgi?CH=122018 Change 122018 by fli@fli_genesis on 2007/06/20 10:23:35 - Several setsockopt() IPv6 related fixes. - Fix MTU retrieval code. - Follow buffer changes. - Make sockets non-blocking. Affected files ... .. //depot/projects/soc2007/fli-mdns_sd/mdnsd/stack_mdns.c#5 edit Differences ... ==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/stack_mdns.c#5 (text+ko) ==== @@ -48,6 +48,7 @@ #include "mdns.h" #include "stack_mdns.h" #include "debug.h" +#include "log.h" static int mdns_udp_open(struct mdns *, int); static int mdns_udp_close(struct mdns *, int); @@ -103,8 +104,9 @@ md->md_ifindex = idx; md->md_bp = bp; + bzero(&req, sizeof(struct ifreq)); strlcpy(req.ifr_name, md->md_ifnam, IFNAMSIZ); - sock = socket(IPPROTO_IP, SOCK_DGRAM, 0); + sock = socket(PF_INET, SOCK_DGRAM, 0); error = ioctl(sock, SIOCGIFMTU, &req); close(sock); /* @@ -119,13 +121,15 @@ md->md_maxpkgsz = MDNS_PKG_MAX_LEN; } #undef _HDR_OVERHEAD + dprintf(DEBUG_STACK, "Max packet size %d bytes on %s\n", + md->md_maxpkgsz, md->md_ifnam); /* * Adjust the global buffer pool segment size upwards if needed */ len = mdns_bufpool_getsize(bp); if (md->md_maxpkgsz > len) - mdns_bufpool_setsize(bp, len); + mdns_bufpool_setsize(bp, md->md_maxpkgsz); TAILQ_INIT(&md->md_pkglist); @@ -219,10 +223,10 @@ static int mdns_udp_open(struct mdns *md, int family) { - int sock, so, error, level; + int sock, so, error; struct sockaddr_in sin, *sinptr; #ifdef INET6 - struct sockaddr_in6 sin6, *sin6ptr; + struct sockaddr_in6 sin6; #endif struct ifreq ifreq; @@ -242,46 +246,45 @@ sock = socket(family, SOCK_DGRAM, 0); if (sock < 0) return (-1); - - if (family == PF_INET) - level = IPPROTO_IP; -#ifdef INET6 - else if (family == PF_INET6) - level = IPPROTO_IPV6; -#endif - else { + error = fcntl(sock, F_SETFL, O_NONBLOCK); + if (error != 0) goto out; - } so = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &so, sizeof(so)); - error = setsockopt(sock, level, IP_RECVIF, &so, sizeof(so)); - if (error != 0) - goto out; - so = 0; - /* Ignore our own multicast packets */ - error = setsockopt(sock, level, IP_MULTICAST_LOOP, &so, sizeof(so)); - if (error != 0) - goto out; + switch (family) { + case PF_INET: + /* + * Set IP TTL to 255, this is to be comaptible with older + * MDNS responders that discard packets with ttl != 255 + * We do not care if it fails. + */ + so = 255; + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &so, sizeof(so)); + setsockopt(sock, IPPROTO_IP, IP_TTL, &so, sizeof(so)); - /* - * Set IP TTL to 255, this is to be comaptible with older - * MDNS responders that discard packets with ttl != 255 - * We do not care if it fails. - */ - so = 255; - setsockopt(sock, level, IP_MULTICAST_TTL, &so, sizeof(so)); - setsockopt(sock, level, IP_TTL, &so, sizeof(so)); + so = 1; + error = setsockopt(sock, IPPROTO_IP, IP_RECVIF, &so, sizeof(so)); + if (error != 0) + goto out; + /* Ignore our own multicast packets */ + so = 0; + error = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &so, + sizeof(so)); + if (error != 0) + goto out; - if_indextoname(md->md_ifindex, ifreq.ifr_name); - switch (family) { - case PF_INET: /* Make sure we transmit on the correct interface */ + if_indextoname(md->md_ifindex, ifreq.ifr_name); error = ioctl(sock, SIOCGIFADDR, &ifreq); + if (error != 0) + goto out; sinptr = (struct sockaddr_in *)&ifreq.ifr_addr; setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &sinptr->sin_addr.s_addr, sizeof(sinptr->sin_addr.s_addr)); + if (error != 0) + goto out; /* Bind udp socket */ bzero(&sin, sizeof(struct sockaddr_in)); @@ -302,11 +305,18 @@ break; #ifdef INET6 case PF_INET6: + /* Receive interface information */ + so = 1; + error = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &so, + sizeof(so)); + if (error != 0) + goto out; /* Make sure we transmit on the correct interface */ - error = ioctl(sock, SIOCGIFADDR, &ifreq); - sin6ptr = (struct sockaddr_in6 *)&ifreq.ifr_addr; - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, - &sin6ptr->sin6_addr, sizeof(sin6ptr->sin6_addr)); + so = md->md_ifindex; + error = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &so, + sizeof(so)); + if (error != 0) + goto out; /* Bind udp socket */ bzero(&sin6, sizeof(struct sockaddr_in6)); @@ -605,7 +615,7 @@ TAILQ_FOREACH(pkg, &pc->pc_head, p_list) { iov = malloc(sizeof(struct iovec) * MDNS_BUFHSZ(&pkg->p_buflist)); i = 0; - TAILQ_FOREACH(buf, &MDNS_BUFHEAD(&pkg->p_buflist), b_list) { + TAILQ_FOREACH(buf, &MDNS_BUFHEAD(&pkg->p_buflist), b_next) { iov[i].iov_base = MDNS_BUF(buf); iov[i].iov_len = MDNS_BUFLEN(buf); i++; @@ -703,7 +713,8 @@ mdns_recv(struct mdns *md, struct mdns_pkgchain *pc, int family, struct sockaddr *from, socklen_t *fromlen) { - int sock, ret; + int sock; + ssize_t ret; struct mdns_packet *pkg; struct mdns_buf *buf; struct msghdr msg; @@ -714,6 +725,13 @@ struct cmsghdr cmsg; struct sockaddr_dl sdl; } control; +#ifdef INET6 + struct { + struct cmsghdr cmsg; + struct in6_pktinfo pkt; + } control6; + struct in6_pktinfo *ipi6; +#endif MDNS_INIT_ASSERT(md, md_magic); MDNS_INIT_ASSERT(pc, pc_magic); @@ -721,10 +739,14 @@ switch (family) { case PF_INET: sock = md->md_udp4; + msg.msg_control = &control; + msg.msg_controllen = sizeof(control); break; #ifdef INET6 case PF_INET6: sock = md->md_udp6; + msg.msg_control = &control6; + msg.msg_controllen = sizeof(control6); break; #endif default: @@ -737,7 +759,7 @@ return (-1); buf = MDNS_BUFH(&pkg->p_buflist) != NULL ? MDNS_BUFH(&pkg->p_buflist) : - mdns_buf_alloc(md->md_bp, &pkg->p_buflist, 0, 0); + mdns_buf_alloc(md->md_bp, &pkg->p_buflist, 0, MDNS_BP_HUGE); if (buf == NULL) return (-1); @@ -746,21 +768,35 @@ msg.msg_name = from; msg.msg_namelen = *fromlen; - msg.msg_control = &control; - msg.msg_controllen = sizeof(control); msg.msg_iov = iov; msg.msg_iovlen = 1; ret = recvmsg(sock, &msg, 0); + if (ret < 0) + goto error; + pkg->p_len = MDNS_BUFLEN(buf) = ret; + dprintf(DEBUG_STACK, "Buffer filled %d bytes (size %d)", + MDNS_BUFLEN(buf), MDNS_BUFSZ(buf)); cmptr = CMSG_FIRSTHDR(&msg); - if (cmptr->cmsg_type == IP_RECVIF && cmptr->cmsg_level == IPPROTO_IP) { - sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr); - if (sdl->sdl_index != md->md_ifindex) - return (-1); + if (cmptr->cmsg_level == IPPROTO_IP) { + if (cmptr->cmsg_type == IP_RECVIF) { + sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr); + if (sdl->sdl_index != md->md_ifindex) + goto error; + } + } +#ifdef INET6 + else if (cmptr->cmsg_level == IPPROTO_IPV6) { + ipi6 = (struct in6_pktinfo *) CMSG_DATA(cmptr); + if (ipi6->ipi6_ifindex != (unsigned int)md->md_ifindex) + goto error; } +#endif - pkg->p_len = MDNS_BUFLEN(buf) = ret; - return (ret); + return (pkg->p_len); +error: + mdns_buf_free(md->md_bp, &pkg->p_buflist, buf, 0); + return (-1); } /* @@ -772,7 +808,7 @@ * fromlen - Socket address length */ int -mdns_tcp_client(struct mdns *md, int sock, +mdns_tcp_client(__unused struct mdns *md, int sock, struct sockaddr *from, socklen_t *fromlen) { int nsock; @@ -830,7 +866,7 @@ TAILQ_FOREACH(pkg, &pc->pc_head, p_list) { iov = malloc(sizeof(struct iovec) * MDNS_BUFHSZ(&pkg->p_buflist)); i = 0; - TAILQ_FOREACH(buf, &MDNS_BUFHEAD(&pkg->p_buflist), b_list) { + TAILQ_FOREACH(buf, &MDNS_BUFHEAD(&pkg->p_buflist), b_next) { iov[i].iov_base = MDNS_BUF(buf); iov[i].iov_len = MDNS_BUFLEN(buf); i++; @@ -864,17 +900,17 @@ return (-1); buf = MDNS_BUFH(&pkg->p_buflist) != NULL ? MDNS_BUFH(&pkg->p_buflist) : - mdns_buf_alloc(md->md_bp, &pkg->p_buflist, 0, 0); + mdns_buf_alloc(md->md_bp, &pkg->p_buflist, 0, MDNS_BP_HUGE); if (buf == NULL) return (-1); for (;;) { n = read(sock, MDNS_BUF(buf), MDNS_BUFSZ(buf)); - if (n > 0) { - pkg->p_len += n; - MDNS_BUFLEN(buf) = n; - } - if ((unsigned int)n < MDNS_BUFSZ(buf) || pkg->p_len >= MDNS_PKG_MAX_LEN) + if (n < 0) + break; + pkg->p_len += n; + MDNS_BUFLEN(buf) = n; + if ((size_t)n < MDNS_BUFSZ(buf) || pkg->p_len >= MDNS_PKG_MAX_LEN) break; buf = mdns_buf_alloc(md->md_bp, &pkg->p_buflist, 0, 0); @@ -888,7 +924,7 @@ * very rare. TCP operations are only present to provide compability * with legacy clients. */ - buf = mdns_buf_merge(md->md_bp, &pkg->p_buflist, 1); + buf = mdns_buf_merge(md->md_bp, &pkg->p_buflist, 0); if (buf == NULL) return (-1);