X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fsocket-util.c;h=7f34ea2e939ea86b0e27e482b5ba4ab477e106a1;hb=b0fb94a346e52f36aeef238dd5f9bef9a10c14ef;hp=fa55480d3e1fbd14a1c9001d77bab47c33b9bd96;hpb=10a89ef04df5669c5cdd02f786150a7ab8454e01;p=sliver-openvswitch.git diff --git a/lib/socket-util.c b/lib/socket-util.c index fa55480d3..7f34ea2e9 100644 --- a/lib/socket-util.c +++ b/lib/socket-util.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -132,8 +133,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 +144,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; } @@ -197,7 +202,8 @@ lookup_hostname(const char *host_name, struct in_addr *addr) switch (getaddrinfo(host_name, NULL, &hints, &result)) { case 0: - *addr = ((struct sockaddr_in *) result->ai_addr)->sin_addr; + *addr = ALIGNED_CAST(struct sockaddr_in *, + result->ai_addr)->sin_addr; freeaddrinfo(result); return 0; @@ -802,15 +808,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", ovs_strerror(error)); - return -error; + null_fd = -error; } + ovsthread_once_done(&once); } + return null_fd; } @@ -1318,7 +1328,7 @@ recv_data_and_fds(int sock, goto error; } else { size_t n_fds = (p->cmsg_len - CMSG_LEN(0)) / sizeof *fds; - const int *fds_data = (const int *) CMSG_DATA(p); + const int *fds_data = ALIGNED_CAST(const int *, CMSG_DATA(p)); ovs_assert(n_fds > 0); if (n_fds > SOUTIL_MAX_FDS) { @@ -1344,3 +1354,42 @@ error: *n_fdsp = 0; return EPROTO; } + +/* Calls ioctl() on an AF_INET sock, passing the specified 'command' and + * 'arg'. Returns 0 if successful, otherwise a positive errno value. */ +int +af_inet_ioctl(unsigned long int command, const void *arg) +{ + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; + static int sock; + + if (ovsthread_once_start(&once)) { + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + sock = -errno; + VLOG_ERR("failed to create inet socket: %s", ovs_strerror(errno)); + } + ovsthread_once_done(&once); + } + + return (sock < 0 ? -sock + : ioctl(sock, command, arg) == -1 ? errno + : 0); +} + +int +af_inet_ifreq_ioctl(const char *name, struct ifreq *ifr, unsigned long int cmd, + const char *cmd_name) +{ + int error; + + ovs_strzcpy(ifr->ifr_name, name, sizeof ifr->ifr_name); + error = af_inet_ioctl(cmd, ifr); + if (error) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); + VLOG_DBG_RL(&rl, "%s: ioctl(%s) failed: %s", name, cmd_name, + ovs_strerror(error)); + } + return error; +} +