/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <config.h>
#include "socket-util.h"
#include <arpa/inet.h>
-#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
* successful, otherwise a positive errno value.
*
* Most Open vSwitch code should not use this because it causes deadlocks:
- * gethostbyname() sends out a DNS request but that starts a new flow for which
+ * getaddrinfo() sends out a DNS request but that starts a new flow for which
* OVS must set up a flow, but it can't because it's waiting for a DNS reply.
* The synchronous lookup also delays other activity. (Of course we can solve
* this but it doesn't seem worthwhile quite yet.) */
int
lookup_hostname(const char *host_name, struct in_addr *addr)
{
- struct hostent *h;
+ struct addrinfo *result;
+ struct addrinfo hints;
if (inet_aton(host_name, addr)) {
return 0;
}
- h = gethostbyname(host_name);
- if (h) {
- *addr = *(struct in_addr *) h->h_addr;
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET;
+
+ switch (getaddrinfo(host_name, NULL, &hints, &result)) {
+ case 0:
+ *addr = ((struct sockaddr_in *) result->ai_addr)->sin_addr;
+ freeaddrinfo(result);
return 0;
- }
- return (h_errno == HOST_NOT_FOUND ? ENOENT
- : h_errno == TRY_AGAIN ? EAGAIN
- : h_errno == NO_RECOVERY ? EIO
- : h_errno == NO_ADDRESS ? ENXIO
- : EINVAL);
+#ifdef EAI_ADDRFAMILY
+ case EAI_ADDRFAMILY:
+#endif
+ case EAI_NONAME:
+ case EAI_SERVICE:
+ return ENOENT;
+
+ case EAI_AGAIN:
+ return EAGAIN;
+
+ case EAI_BADFLAGS:
+ case EAI_FAMILY:
+ case EAI_SOCKTYPE:
+ return EINVAL;
+
+ case EAI_FAIL:
+ return EIO;
+
+ case EAI_MEMORY:
+ return ENOMEM;
+
+#ifdef EAI_NODATA
+ case EAI_NODATA:
+ return ENXIO;
+#endif
+
+ case EAI_SYSTEM:
+ return errno;
+
+ default:
+ return EPROTO;
+ }
}
int
* it will only happen if style is SOCK_STREAM or SOCK_SEQPACKET, and only
* if a backlog of un-accepted connections has built up in the kernel.) */
if (nonblock) {
- int flags = fcntl(fd, F_GETFL, 0);
- if (flags == -1) {
- error = errno;
- goto error;
- }
- if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
- error = errno;
+ error = set_nonblocking(fd);
+ if (error) {
goto error;
}
}
inet_open_passive(int style, const char *target, int default_port,
struct sockaddr_in *sinp, uint8_t dscp)
{
+ bool kernel_chooses_port;
struct sockaddr_in sin;
int fd = 0, error;
unsigned int yes = 1;
goto error;
}
- if (sinp) {
+ kernel_chooses_port = sin.sin_port == htons(0);
+ if (sinp || kernel_chooses_port) {
socklen_t sin_len = sizeof sin;
- if (getsockname(fd, (struct sockaddr *) &sin, &sin_len) < 0){
+ if (getsockname(fd, (struct sockaddr *) &sin, &sin_len) < 0) {
error = errno;
VLOG_ERR("%s: getsockname: %s", target, strerror(error));
goto error;
VLOG_ERR("%s: getsockname: invalid socket name", target);
goto error;
}
- *sinp = sin;
+ if (sinp) {
+ *sinp = sin;
+ }
+ if (kernel_chooses_port) {
+ VLOG_INFO("%s: listening on port %"PRIu16,
+ target, ntohs(sin.sin_port));
+ }
}
return fd;
memcpy(&sin, &ss, sizeof sin);
ds_put_format(string, IP_FMT":%"PRIu16,
- IP_ARGS(&sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ IP_ARGS(sin.sin_addr.s_addr), ntohs(sin.sin_port));
} else if (ss.ss_family == AF_UNIX) {
struct sockaddr_un sun;
const char *null;
const struct iovec *iovs, size_t n_iovs,
const int fds[], size_t n_fds)
{
- assert(sock >= 0);
+ ovs_assert(sock >= 0);
if (n_fds > 0) {
union {
struct cmsghdr cm;
} cmsg;
struct msghdr msg;
- assert(!iovec_is_empty(iovs, n_iovs));
- assert(n_fds <= SOUTIL_MAX_FDS);
+ ovs_assert(!iovec_is_empty(iovs, n_iovs));
+ ovs_assert(n_fds <= SOUTIL_MAX_FDS);
memset(&cmsg, 0, sizeof cmsg);
cmsg.cm.cmsg_len = CMSG_LEN(n_fds * sizeof *fds);
msg.msg_name = NULL;
msg.msg_namelen = 0;
- msg.msg_iov = (struct iovec *) iovs;
+ msg.msg_iov = CONST_CAST(struct iovec *, iovs);
msg.msg_iovlen = n_iovs;
msg.msg_control = &cmsg.cm;
msg.msg_controllen = CMSG_SPACE(n_fds * sizeof *fds);
size_t n_fds = (p->cmsg_len - CMSG_LEN(0)) / sizeof *fds;
const int *fds_data = (const int *) CMSG_DATA(p);
- assert(n_fds > 0);
+ ovs_assert(n_fds > 0);
if (n_fds > SOUTIL_MAX_FDS) {
VLOG_ERR("%zu fds received but only %d supported",
n_fds, SOUTIL_MAX_FDS);