Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Jun 2007 10:24:13 GMT
From:      Fredrik Lindberg <fli@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 122018 for review
Message-ID:  <200706201024.l5KAODiu076942@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 		



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200706201024.l5KAODiu076942>