PERFORCE change 122018 for review
Fredrik Lindberg
fli at FreeBSD.org
Wed Jun 20 10:24:14 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=122018
Change 122018 by fli at 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);
More information about the p4-projects
mailing list