X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fsocket-util.c;h=2ba0fd4aa3afe5ab04e779e31db3c6c14c1e18c2;hb=79f3d50d7c178364c620c3da19fb8c66bf4cd8a6;hp=9fea7bdab55455951929e304185578f46c6f4ea6;hpb=b36db1148939c1ca7af3c3973252fea3fbf1c4e6;p=sliver-openvswitch.git diff --git a/lib/socket-util.c b/lib/socket-util.c index 9fea7bdab..2ba0fd4aa 100644 --- a/lib/socket-util.c +++ b/lib/socket-util.c @@ -1,5 +1,5 @@ /* - * 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. @@ -72,11 +72,11 @@ set_nonblocking(int fd) if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1) { return 0; } else { - VLOG_ERR("fcntl(F_SETFL) failed: %s", strerror(errno)); + VLOG_ERR("fcntl(F_SETFL) failed: %s", ovs_strerror(errno)); return errno; } } else { - VLOG_ERR("fcntl(F_GETFL) failed: %s", strerror(errno)); + VLOG_ERR("fcntl(F_GETFL) failed: %s", ovs_strerror(errno)); return errno; } } @@ -132,8 +132,10 @@ rlim_is_finite(rlim_t limit) int get_max_fds(void) { - static int max_fds = -1; - if (max_fds < 0) { + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; + static int max_fds; + + if (ovsthread_once_start(&once)) { struct rlimit r; if (!getrlimit(RLIMIT_NOFILE, &r) && rlim_is_finite(r.rlim_cur)) { max_fds = r.rlim_cur; @@ -141,7 +143,9 @@ get_max_fds(void) VLOG_WARN("failed to obtain fd limit, defaulting to 1024"); max_fds = 1024; } + ovsthread_once_done(&once); } + return max_fds; } @@ -178,30 +182,61 @@ lookup_ipv6(const char *host_name, struct in6_addr *addr) * 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 @@ -228,7 +263,7 @@ check_connection_completion(int fd) } return 0; } else if (retval < 0) { - VLOG_ERR_RL(&rl, "poll: %s", strerror(errno)); + VLOG_ERR_RL(&rl, "poll: %s", ovs_strerror(errno)); return errno; } else { return EAGAIN; @@ -421,7 +456,8 @@ make_unix_socket(int style, bool nonblock, int dirfd; if (unlink(bind_path) && errno != ENOENT) { - VLOG_WARN("unlinking \"%s\": %s\n", bind_path, strerror(errno)); + VLOG_WARN("unlinking \"%s\": %s\n", + bind_path, ovs_strerror(errno)); } fatal_signal_add_file_to_unlink(bind_path); @@ -571,7 +607,7 @@ inet_open_active(int style, const char *target, uint16_t default_port, /* Create non-blocking socket. */ fd = socket(AF_INET, style, 0); if (fd < 0) { - VLOG_ERR("%s: socket: %s", target, strerror(errno)); + VLOG_ERR("%s: socket: %s", target, ovs_strerror(errno)); error = errno; goto exit; } @@ -585,7 +621,7 @@ inet_open_active(int style, const char *target, uint16_t default_port, * connect(), the handshake SYN frames will be sent with a TOS of 0. */ error = set_dscp(fd, dscp); if (error) { - VLOG_ERR("%s: socket: %s", target, strerror(error)); + VLOG_ERR("%s: socket: %s", target, ovs_strerror(error)); goto exit; } @@ -684,6 +720,7 @@ int 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; @@ -696,7 +733,7 @@ inet_open_passive(int style, const char *target, int default_port, fd = socket(AF_INET, style, 0); if (fd < 0) { error = errno; - VLOG_ERR("%s: socket: %s", target, strerror(error)); + VLOG_ERR("%s: socket: %s", target, ovs_strerror(error)); return -error; } error = set_nonblocking(fd); @@ -706,14 +743,15 @@ inet_open_passive(int style, const char *target, int default_port, if (style == SOCK_STREAM && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) { error = errno; - VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", target, strerror(error)); + VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s", + target, ovs_strerror(error)); goto error; } /* Bind. */ if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) { error = errno; - VLOG_ERR("%s: bind: %s", target, strerror(error)); + VLOG_ERR("%s: bind: %s", target, ovs_strerror(error)); goto error; } @@ -722,22 +760,23 @@ inet_open_passive(int style, const char *target, int default_port, * connect(), the handshake SYN frames will be sent with a TOS of 0. */ error = set_dscp(fd, dscp); if (error) { - VLOG_ERR("%s: socket: %s", target, strerror(error)); + VLOG_ERR("%s: socket: %s", target, ovs_strerror(error)); goto error; } /* Listen. */ if (style == SOCK_STREAM && listen(fd, 10) < 0) { error = errno; - VLOG_ERR("%s: listen: %s", target, strerror(error)); + VLOG_ERR("%s: listen: %s", target, ovs_strerror(error)); 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)); + VLOG_ERR("%s: getsockname: %s", target, ovs_strerror(error)); goto error; } if (sin.sin_family != AF_INET || sin_len != sizeof sin) { @@ -745,7 +784,13 @@ inet_open_passive(int style, const char *target, int default_port, 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; @@ -761,15 +806,19 @@ error: int get_null_fd(void) { - static int null_fd = -1; - if (null_fd < 0) { + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; + static int null_fd; + + if (ovsthread_once_start(&once)) { null_fd = open("/dev/null", O_RDWR); if (null_fd < 0) { int error = errno; - VLOG_ERR("could not open /dev/null: %s", strerror(error)); - return -error; + VLOG_ERR("could not open /dev/null: %s", ovs_strerror(error)); + null_fd = -error; } + ovsthread_once_done(&once); } + return null_fd; } @@ -834,13 +883,13 @@ fsync_parent_dir(const char *file_name) * really an error. */ } else { error = errno; - VLOG_ERR("%s: fsync failed (%s)", dir, strerror(error)); + VLOG_ERR("%s: fsync failed (%s)", dir, ovs_strerror(error)); } } close(fd); } else { error = errno; - VLOG_ERR("%s: open failed (%s)", dir, strerror(error)); + VLOG_ERR("%s: open failed (%s)", dir, ovs_strerror(error)); } free(dir); @@ -878,7 +927,7 @@ void xpipe(int fds[2]) { if (pipe(fds)) { - VLOG_FATAL("failed to create pipe (%s)", strerror(errno)); + VLOG_FATAL("failed to create pipe (%s)", ovs_strerror(errno)); } } @@ -894,7 +943,7 @@ void xsocketpair(int domain, int type, int protocol, int fds[2]) { if (socketpair(domain, type, protocol, fds)) { - VLOG_FATAL("failed to create socketpair (%s)", strerror(errno)); + VLOG_FATAL("failed to create socketpair (%s)", ovs_strerror(errno)); } } @@ -909,7 +958,7 @@ getsockopt_int(int fd, int level, int option, const char *optname, int *valuep) len = sizeof value; if (getsockopt(fd, level, option, &value, &len)) { error = errno; - VLOG_ERR_RL(&rl, "getsockopt(%s): %s", optname, strerror(error)); + VLOG_ERR_RL(&rl, "getsockopt(%s): %s", optname, ovs_strerror(error)); } else if (len != sizeof value) { error = EINVAL; VLOG_ERR_RL(&rl, "getsockopt(%s): value is %u bytes (expected %zu)", @@ -1037,7 +1086,7 @@ describe_fd(int fd) ds_init(&string); if (fstat(fd, &s)) { - ds_put_format(&string, "fstat failed (%s)", strerror(errno)); + ds_put_format(&string, "fstat failed (%s)", ovs_strerror(errno)); } else if (S_ISSOCK(s.st_mode)) { describe_sockaddr(&string, fd, getsockname); ds_put_cstr(&string, "<->");