LCOV - code coverage report
Current view: top level - lib - socket-util.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 232 391 59.3 %
Date: 2016-09-14 01:02:56 Functions: 27 31 87.1 %
Branches: 108 300 36.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : #include "socket-util.h"
      19                 :            : #include <arpa/inet.h>
      20                 :            : #include <errno.h>
      21                 :            : #include <fcntl.h>
      22                 :            : #include <net/if.h>
      23                 :            : #include <netdb.h>
      24                 :            : #include <netinet/tcp.h>
      25                 :            : #include <poll.h>
      26                 :            : #include <stddef.h>
      27                 :            : #include <stdio.h>
      28                 :            : #include <stdlib.h>
      29                 :            : #include <string.h>
      30                 :            : #include <sys/socket.h>
      31                 :            : #include <sys/stat.h>
      32                 :            : #include <sys/uio.h>
      33                 :            : #include <sys/un.h>
      34                 :            : #include <unistd.h>
      35                 :            : #include "openvswitch/dynamic-string.h"
      36                 :            : #include "ovs-thread.h"
      37                 :            : #include "packets.h"
      38                 :            : #include "poll-loop.h"
      39                 :            : #include "util.h"
      40                 :            : #include "openvswitch/vlog.h"
      41                 :            : #ifdef __linux__
      42                 :            : #include <linux/if_packet.h>
      43                 :            : #endif
      44                 :            : #ifdef HAVE_NETLINK
      45                 :            : #include "netlink-protocol.h"
      46                 :            : #include "netlink-socket.h"
      47                 :            : #endif
      48                 :            : 
      49                 :      53956 : VLOG_DEFINE_THIS_MODULE(socket_util);
      50                 :            : 
      51                 :            : static int getsockopt_int(int fd, int level, int option, const char *optname,
      52                 :            :                           int *valuep);
      53                 :            : 
      54                 :            : /* Sets 'fd' to non-blocking mode.  Returns 0 if successful, otherwise a
      55                 :            :  * positive errno value. */
      56                 :            : int
      57                 :     115414 : set_nonblocking(int fd)
      58                 :            : {
      59                 :            : #ifndef _WIN32
      60                 :     115414 :     int flags = fcntl(fd, F_GETFL, 0);
      61         [ +  - ]:     115414 :     if (flags != -1) {
      62         [ +  - ]:     115414 :         if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1) {
      63                 :     115414 :             return 0;
      64                 :            :         } else {
      65         [ #  # ]:          0 :             VLOG_ERR("fcntl(F_SETFL) failed: %s", ovs_strerror(errno));
      66                 :          0 :             return errno;
      67                 :            :         }
      68                 :            :     } else {
      69         [ #  # ]:          0 :         VLOG_ERR("fcntl(F_GETFL) failed: %s", ovs_strerror(errno));
      70                 :          0 :         return errno;
      71                 :            :     }
      72                 :            : #else
      73                 :            :     unsigned long arg = 1;
      74                 :            :     if (ioctlsocket(fd, FIONBIO, &arg)) {
      75                 :            :         int error = sock_errno();
      76                 :            :         VLOG_ERR("set_nonblocking failed: %s", sock_strerror(error));
      77                 :            :         return error;
      78                 :            :     }
      79                 :            :     return 0;
      80                 :            : #endif
      81                 :            : }
      82                 :            : 
      83                 :            : void
      84                 :      61824 : xset_nonblocking(int fd)
      85                 :            : {
      86         [ -  + ]:      61824 :     if (set_nonblocking(fd)) {
      87                 :          0 :         exit(EXIT_FAILURE);
      88                 :            :     }
      89                 :      61824 : }
      90                 :            : 
      91                 :            : void
      92                 :        695 : setsockopt_tcp_nodelay(int fd)
      93                 :            : {
      94                 :        695 :     int on = 1;
      95                 :            :     int retval;
      96                 :            : 
      97                 :        695 :     retval = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof on);
      98         [ -  + ]:        695 :     if (retval) {
      99                 :          0 :         retval = sock_errno();
     100         [ #  # ]:          0 :         VLOG_ERR("setsockopt(TCP_NODELAY): %s", sock_strerror(retval));
     101                 :            :     }
     102                 :        695 : }
     103                 :            : 
     104                 :            : /* Sets the DSCP value of socket 'fd' to 'dscp', which must be 63 or less.
     105                 :            :  * 'family' must indicate the socket's address family (AF_INET or AF_INET6, to
     106                 :            :  * do anything useful). */
     107                 :            : int
     108                 :        456 : set_dscp(int fd, int family, uint8_t dscp)
     109                 :            : {
     110                 :            :     int retval;
     111                 :            :     int val;
     112                 :            : 
     113                 :            : #ifdef _WIN32
     114                 :            :     /* XXX: Consider using QoS2 APIs for Windows to set dscp. */
     115                 :            :     return 0;
     116                 :            : #endif
     117                 :            : 
     118         [ -  + ]:        456 :     if (dscp > 63) {
     119                 :          0 :         return EINVAL;
     120                 :            :     }
     121                 :        456 :     val = dscp << 2;
     122                 :            : 
     123      [ +  +  - ]:        456 :     switch (family) {
     124                 :            :     case AF_INET:
     125                 :        382 :         retval = setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof val);
     126                 :        382 :         break;
     127                 :            : 
     128                 :            :     case AF_INET6:
     129                 :         74 :         retval = setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof val);
     130                 :         74 :         break;
     131                 :            : 
     132                 :            :     default:
     133                 :          0 :         return ENOPROTOOPT;
     134                 :            :     }
     135                 :            : 
     136         [ -  + ]:        456 :     return retval ? sock_errno() : 0;
     137                 :            : }
     138                 :            : 
     139                 :            : /* Checks whether 'host_name' is an IPv4 or IPv6 address.  It is assumed
     140                 :            :  * that 'host_name' is valid.  Returns false if it is IPv4 address, true if
     141                 :            :  * it is IPv6 address. */
     142                 :            : bool
     143                 :      20400 : addr_is_ipv6(const char *host_name)
     144                 :            : {
     145                 :      20400 :     return strchr(host_name, ':') != NULL;
     146                 :            : }
     147                 :            : 
     148                 :            : /* Translates 'host_name', which must be a string representation of an IP
     149                 :            :  * address, into a numeric IP address in '*addr'.  Returns 0 if successful,
     150                 :            :  * otherwise a positive errno value. */
     151                 :            : int
     152                 :      20399 : lookup_ip(const char *host_name, struct in_addr *addr)
     153                 :            : {
     154         [ -  + ]:      20399 :     if (!ip_parse(host_name, &addr->s_addr)) {
     155                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     156         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "\"%s\" is not a valid IP address", host_name);
     157                 :          0 :         return ENOENT;
     158                 :            :     }
     159                 :      20399 :     return 0;
     160                 :            : }
     161                 :            : 
     162                 :            : /* Translates 'host_name', which must be a string representation of an IPv6
     163                 :            :  * address, into a numeric IPv6 address in '*addr'.  Returns 0 if successful,
     164                 :            :  * otherwise a positive errno value. */
     165                 :            : int
     166                 :          7 : lookup_ipv6(const char *host_name, struct in6_addr *addr)
     167                 :            : {
     168         [ -  + ]:          7 :     if (!ipv6_parse(host_name, addr)) {
     169                 :            :         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
     170         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "\"%s\" is not a valid IPv6 address", host_name);
     171                 :          0 :         return ENOENT;
     172                 :            :     }
     173                 :          7 :     return 0;
     174                 :            : }
     175                 :            : 
     176                 :            : /* Translates 'host_name', which must be a host name or a string representation
     177                 :            :  * of an IP address, into a numeric IP address in '*addr'.  Returns 0 if
     178                 :            :  * successful, otherwise a positive errno value.
     179                 :            :  *
     180                 :            :  * Most Open vSwitch code should not use this because it causes deadlocks:
     181                 :            :  * getaddrinfo() sends out a DNS request but that starts a new flow for which
     182                 :            :  * OVS must set up a flow, but it can't because it's waiting for a DNS reply.
     183                 :            :  * The synchronous lookup also delays other activity.  (Of course we can solve
     184                 :            :  * this but it doesn't seem worthwhile quite yet.)  */
     185                 :            : int
     186                 :          0 : lookup_hostname(const char *host_name, struct in_addr *addr)
     187                 :            : {
     188                 :            :     struct addrinfo *result;
     189                 :            :     struct addrinfo hints;
     190                 :            : 
     191         [ #  # ]:          0 :     if (ip_parse(host_name, &addr->s_addr)) {
     192                 :          0 :         return 0;
     193                 :            :     }
     194                 :            : 
     195                 :          0 :     memset(&hints, 0, sizeof hints);
     196                 :          0 :     hints.ai_family = AF_INET;
     197                 :            : 
     198   [ #  #  #  #  :          0 :     switch (getaddrinfo(host_name, NULL, &hints, &result)) {
             #  #  #  #  
                      # ]
     199                 :            :     case 0:
     200                 :          0 :         *addr = ALIGNED_CAST(struct sockaddr_in *,
     201                 :            :                              result->ai_addr)->sin_addr;
     202                 :          0 :         freeaddrinfo(result);
     203                 :          0 :         return 0;
     204                 :            : 
     205                 :            : #ifdef EAI_ADDRFAMILY
     206                 :            :     case EAI_ADDRFAMILY:
     207                 :            : #endif
     208                 :            :     case EAI_NONAME:
     209                 :            :     case EAI_SERVICE:
     210                 :          0 :         return ENOENT;
     211                 :            : 
     212                 :            :     case EAI_AGAIN:
     213                 :          0 :         return EAGAIN;
     214                 :            : 
     215                 :            :     case EAI_BADFLAGS:
     216                 :            :     case EAI_FAMILY:
     217                 :            :     case EAI_SOCKTYPE:
     218                 :          0 :         return EINVAL;
     219                 :            : 
     220                 :            :     case EAI_FAIL:
     221                 :          0 :         return EIO;
     222                 :            : 
     223                 :            :     case EAI_MEMORY:
     224                 :          0 :         return ENOMEM;
     225                 :            : 
     226                 :            : #if defined (EAI_NODATA) && EAI_NODATA != EAI_NONAME
     227                 :            :     case EAI_NODATA:
     228                 :          0 :         return ENXIO;
     229                 :            : #endif
     230                 :            : 
     231                 :            : #ifdef EAI_SYSTEM
     232                 :            :     case EAI_SYSTEM:
     233                 :          0 :         return sock_errno();
     234                 :            : #endif
     235                 :            : 
     236                 :            :     default:
     237                 :          0 :         return EPROTO;
     238                 :            :     }
     239                 :            : }
     240                 :            : 
     241                 :            : int
     242                 :      22682 : check_connection_completion(int fd)
     243                 :            : {
     244                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 10);
     245                 :            :     struct pollfd pfd;
     246                 :            :     int retval;
     247                 :            : 
     248                 :      22682 :     pfd.fd = fd;
     249                 :      22682 :     pfd.events = POLLOUT;
     250                 :            : 
     251                 :            : #ifndef _WIN32
     252                 :            :     do {
     253                 :      22682 :         retval = poll(&pfd, 1, 0);
     254 [ -  + ][ #  # ]:      22682 :     } while (retval < 0 && errno == EINTR);
     255                 :            : #else
     256                 :            :     retval = WSAPoll(&pfd, 1, 0);
     257                 :            : #endif
     258         [ +  + ]:      22682 :     if (retval == 1) {
     259         [ +  + ]:      22625 :         if (pfd.revents & POLLERR) {
     260                 :          1 :             ssize_t n = send(fd, "", 1, 0);
     261         [ +  - ]:          1 :             if (n < 0) {
     262                 :          1 :                 return sock_errno();
     263                 :            :             } else {
     264         [ #  # ]:          0 :                 VLOG_ERR_RL(&rl, "poll return POLLERR but send succeeded");
     265                 :          0 :                 return EPROTO;
     266                 :            :             }
     267                 :            :         }
     268                 :      22624 :         return 0;
     269         [ -  + ]:         57 :     } else if (retval < 0) {
     270         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "poll: %s", sock_strerror(sock_errno()));
     271                 :          0 :         return errno;
     272                 :            :     } else {
     273                 :      22682 :         return EAGAIN;
     274                 :            :     }
     275                 :            : }
     276                 :            : 
     277                 :            : /* Returns the size of socket 'sock''s receive buffer (SO_RCVBUF), or a
     278                 :            :  * negative errno value if an error occurs. */
     279                 :            : int
     280                 :       3975 : get_socket_rcvbuf(int sock)
     281                 :            : {
     282                 :            :     int rcvbuf;
     283                 :            :     int error;
     284                 :            : 
     285                 :       3975 :     error = getsockopt_int(sock, SOL_SOCKET, SO_RCVBUF, "SO_RCVBUF", &rcvbuf);
     286         [ -  + ]:       3975 :     return error ? -error : rcvbuf;
     287                 :            : }
     288                 :            : 
     289                 :            : /* Reads and discards up to 'n' datagrams from 'fd', stopping as soon as no
     290                 :            :  * more data can be immediately read.  ('fd' should therefore be in
     291                 :            :  * non-blocking mode.)*/
     292                 :            : void
     293                 :          0 : drain_fd(int fd, size_t n_packets)
     294                 :            : {
     295         [ #  # ]:          0 :     for (; n_packets > 0; n_packets--) {
     296                 :            :         /* 'buffer' only needs to be 1 byte long in most circumstances.  This
     297                 :            :          * size is defensive against the possibility that we someday want to
     298                 :            :          * use a Linux tap device without TUN_NO_PI, in which case a buffer
     299                 :            :          * smaller than sizeof(struct tun_pi) will give EINVAL on read. */
     300                 :            :         char buffer[128];
     301         [ #  # ]:          0 :         if (read(fd, buffer, sizeof buffer) <= 0) {
     302                 :          0 :             break;
     303                 :            :         }
     304                 :            :     }
     305                 :          0 : }
     306                 :            : 
     307                 :            : ovs_be32
     308                 :          0 : guess_netmask(ovs_be32 ip_)
     309                 :            : {
     310                 :          0 :     uint32_t ip = ntohl(ip_);
     311                 :          0 :     return ((ip >> 31) == 0 ? htonl(0xff000000)   /* Class A */
     312 [ #  # ][ #  # ]:          0 :             : (ip >> 30) == 2 ? htonl(0xffff0000) /* Class B */
                 [ #  # ]
     313                 :          0 :             : (ip >> 29) == 6 ? htonl(0xffffff00) /* Class C */
     314                 :            :             : htonl(0));                          /* ??? */
     315                 :            : }
     316                 :            : 
     317                 :            : /* This is like strsep() except:
     318                 :            :  *
     319                 :            :  *    - The separator string is ":".
     320                 :            :  *
     321                 :            :  *    - Square brackets [] quote ":" separators and are removed from the
     322                 :            :  *      tokens. */
     323                 :            : static char *
     324                 :        922 : parse_bracketed_token(char **pp)
     325                 :            : {
     326                 :        922 :     char *p = *pp;
     327                 :            : 
     328         [ -  + ]:        922 :     if (p == NULL) {
     329                 :          0 :         return NULL;
     330         [ -  + ]:        922 :     } else if (*p == '\0') {
     331                 :          0 :         *pp = NULL;
     332                 :          0 :         return p;
     333         [ +  + ]:        922 :     } else if (*p == '[') {
     334                 :         74 :         char *start = p + 1;
     335                 :         74 :         char *end = start + strcspn(start, "]");
     336                 :        148 :         *pp = (*end == '\0' ? NULL
     337         [ +  - ]:        148 :                : end[1] == ':' ? end + 2
     338         [ +  + ]:         74 :                : end + 1);
     339                 :         74 :         *end = '\0';
     340                 :         74 :         return start;
     341                 :            :     } else {
     342                 :        848 :         char *start = p;
     343                 :        848 :         char *end = start + strcspn(start, ":");
     344         [ +  + ]:        848 :         *pp = *end == '\0' ? NULL : end + 1;
     345                 :        848 :         *end = '\0';
     346                 :        848 :         return start;
     347                 :            :     }
     348                 :            : }
     349                 :            : 
     350                 :            : static bool
     351                 :        461 : parse_sockaddr_components(struct sockaddr_storage *ss,
     352                 :            :                           const char *host_s,
     353                 :            :                           const char *port_s, uint16_t default_port,
     354                 :            :                           const char *s)
     355                 :            : {
     356                 :        461 :     struct sockaddr_in *sin = ALIGNED_CAST(struct sockaddr_in *, ss);
     357                 :            :     int port;
     358                 :            : 
     359 [ +  - ][ +  - ]:        461 :     if (port_s && port_s[0]) {
     360 [ +  - ][ +  - ]:        461 :         if (!str_to_int(port_s, 10, &port) || port < 0 || port > 65535) {
                 [ -  + ]
     361         [ #  # ]:          0 :             VLOG_ERR("%s: bad port number \"%s\"", s, port_s);
     362                 :          0 :             goto exit;
     363                 :            :         }
     364                 :            :     } else {
     365                 :          0 :         port = default_port;
     366                 :            :     }
     367                 :            : 
     368                 :        461 :     memset(ss, 0, sizeof *ss);
     369         [ +  + ]:        461 :     if (strchr(host_s, ':')) {
     370                 :         74 :         struct sockaddr_in6 *sin6
     371                 :            :             = ALIGNED_CAST(struct sockaddr_in6 *, ss);
     372                 :            : 
     373                 :         74 :         sin6->sin6_family = AF_INET6;
     374                 :         74 :         sin6->sin6_port = htons(port);
     375         [ -  + ]:         74 :         if (!ipv6_parse(host_s, &sin6->sin6_addr)) {
     376         [ #  # ]:          0 :             VLOG_ERR("%s: bad IPv6 address \"%s\"", s, host_s);
     377                 :         74 :             goto exit;
     378                 :            :         }
     379                 :            :     } else {
     380                 :        387 :         sin->sin_family = AF_INET;
     381                 :        387 :         sin->sin_port = htons(port);
     382         [ -  + ]:        387 :         if (!ip_parse(host_s, &sin->sin_addr.s_addr)) {
     383         [ #  # ]:          0 :             VLOG_ERR("%s: bad IPv4 address \"%s\"", s, host_s);
     384                 :          0 :             goto exit;
     385                 :            :         }
     386                 :            :     }
     387                 :            : 
     388                 :        461 :     return true;
     389                 :            : 
     390                 :            : exit:
     391                 :          0 :     memset(ss, 0, sizeof *ss);
     392                 :        461 :     return false;
     393                 :            : }
     394                 :            : 
     395                 :            : /* Parses 'target', which should be a string in the format "<host>[:<port>]".
     396                 :            :  * <host>, which is required, may be an IPv4 address or an IPv6 address
     397                 :            :  * enclosed in square brackets.  If 'default_port' is nonzero then <port> is
     398                 :            :  * optional and defaults to 'default_port'.
     399                 :            :  *
     400                 :            :  * On success, returns true and stores the parsed remote address into '*ss'.
     401                 :            :  * On failure, logs an error, stores zeros into '*ss', and returns false. */
     402                 :            : bool
     403                 :        304 : inet_parse_active(const char *target_, uint16_t default_port,
     404                 :            :                   struct sockaddr_storage *ss)
     405                 :            : {
     406                 :        304 :     char *target = xstrdup(target_);
     407                 :            :     const char *port;
     408                 :            :     const char *host;
     409                 :            :     char *p;
     410                 :            :     bool ok;
     411                 :            : 
     412                 :        304 :     p = target;
     413                 :        304 :     host = parse_bracketed_token(&p);
     414                 :        304 :     port = parse_bracketed_token(&p);
     415         [ -  + ]:        304 :     if (!host) {
     416         [ #  # ]:          0 :         VLOG_ERR("%s: host must be specified", target_);
     417                 :          0 :         ok = false;
     418 [ -  + ][ #  # ]:        304 :     } else if (!port && !default_port) {
     419         [ #  # ]:          0 :         VLOG_ERR("%s: port must be specified", target_);
     420                 :          0 :         ok = false;
     421                 :            :     } else {
     422                 :        304 :         ok = parse_sockaddr_components(ss, host, port, default_port, target_);
     423                 :            :     }
     424         [ -  + ]:        304 :     if (!ok) {
     425                 :          0 :         memset(ss, 0, sizeof *ss);
     426                 :            :     }
     427                 :        304 :     free(target);
     428                 :        304 :     return ok;
     429                 :            : }
     430                 :            : 
     431                 :            : 
     432                 :            : /* Opens a non-blocking IPv4 or IPv6 socket of the specified 'style' and
     433                 :            :  * connects to 'target', which should be a string in the format
     434                 :            :  * "<host>[:<port>]".  <host>, which is required, may be an IPv4 address or an
     435                 :            :  * IPv6 address enclosed in square brackets.  If 'default_port' is nonzero then
     436                 :            :  * <port> is optional and defaults to 'default_port'.
     437                 :            :  *
     438                 :            :  * 'style' should be SOCK_STREAM (for TCP) or SOCK_DGRAM (for UDP).
     439                 :            :  *
     440                 :            :  * On success, returns 0 (indicating connection complete) or EAGAIN (indicating
     441                 :            :  * connection in progress), in which case the new file descriptor is stored
     442                 :            :  * into '*fdp'.  On failure, returns a positive errno value other than EAGAIN
     443                 :            :  * and stores -1 into '*fdp'.
     444                 :            :  *
     445                 :            :  * If 'ss' is non-null, then on success stores the target address into '*ss'.
     446                 :            :  *
     447                 :            :  * 'dscp' becomes the DSCP bits in the IP headers for the new connection.  It
     448                 :            :  * should be in the range [0, 63] and will automatically be shifted to the
     449                 :            :  * appropriately place in the IP tos field. */
     450                 :            : int
     451                 :        299 : inet_open_active(int style, const char *target, uint16_t default_port,
     452                 :            :                  struct sockaddr_storage *ssp, int *fdp, uint8_t dscp)
     453                 :            : {
     454                 :            :     struct sockaddr_storage ss;
     455                 :        299 :     int fd = -1;
     456                 :            :     int error;
     457                 :            : 
     458                 :            :     /* Parse. */
     459         [ -  + ]:        299 :     if (!inet_parse_active(target, default_port, &ss)) {
     460                 :          0 :         error = EAFNOSUPPORT;
     461                 :          0 :         goto exit;
     462                 :            :     }
     463                 :            : 
     464                 :            :     /* Create non-blocking socket. */
     465                 :        299 :     fd = socket(ss.ss_family, style, 0);
     466         [ -  + ]:        299 :     if (fd < 0) {
     467                 :          0 :         error = sock_errno();
     468         [ #  # ]:          0 :         VLOG_ERR("%s: socket: %s", target, sock_strerror(error));
     469                 :          0 :         goto exit;
     470                 :            :     }
     471                 :        299 :     error = set_nonblocking(fd);
     472         [ -  + ]:        299 :     if (error) {
     473                 :          0 :         goto exit;
     474                 :            :     }
     475                 :            : 
     476                 :            :     /* The dscp bits must be configured before connect() to ensure that the
     477                 :            :      * TOS field is set during the connection establishment.  If set after
     478                 :            :      * connect(), the handshake SYN frames will be sent with a TOS of 0. */
     479                 :        299 :     error = set_dscp(fd, ss.ss_family, dscp);
     480         [ -  + ]:        299 :     if (error) {
     481         [ #  # ]:          0 :         VLOG_ERR("%s: set_dscp: %s", target, sock_strerror(error));
     482                 :          0 :         goto exit;
     483                 :            :     }
     484                 :            : 
     485                 :            :     /* Connect. */
     486                 :        299 :     error = connect(fd, (struct sockaddr *) &ss, ss_length(&ss)) == 0
     487                 :            :                     ? 0
     488         [ +  + ]:        299 :                     : sock_errno();
     489         [ +  + ]:        299 :     if (error == EINPROGRESS
     490                 :            : #ifdef _WIN32
     491                 :            :         || error == WSAEALREADY || error == WSAEWOULDBLOCK
     492                 :            : #endif
     493                 :            :         ) {
     494                 :        282 :         error = EAGAIN;
     495                 :            :     }
     496                 :            : 
     497                 :            : exit:
     498 [ +  + ][ -  + ]:        299 :     if (error && error != EAGAIN) {
     499         [ #  # ]:          0 :         if (ssp) {
     500                 :          0 :             memset(ssp, 0, sizeof *ssp);
     501                 :            :         }
     502         [ #  # ]:          0 :         if (fd >= 0) {
     503                 :          0 :             closesocket(fd);
     504                 :          0 :             fd = -1;
     505                 :            :         }
     506                 :            :     } else {
     507         [ -  + ]:        299 :         if (ssp) {
     508                 :          0 :             *ssp = ss;
     509                 :            :         }
     510                 :            :     }
     511                 :        299 :     *fdp = fd;
     512                 :        299 :     return error;
     513                 :            : }
     514                 :            : 
     515                 :            : /* Parses 'target', which should be a string in the format "[<port>][:<host>]":
     516                 :            :  *
     517                 :            :  *      - If 'default_port' is -1, then <port> is required.  Otherwise, if
     518                 :            :  *        <port> is omitted, then 'default_port' is used instead.
     519                 :            :  *
     520                 :            :  *      - If <port> (or 'default_port', if used) is 0, then no port is bound
     521                 :            :  *        and the TCP/IP stack will select a port.
     522                 :            :  *
     523                 :            :  *      - <host> is optional.  If supplied, it may be an IPv4 address or an
     524                 :            :  *        IPv6 address enclosed in square brackets.  If omitted, the IP address
     525                 :            :  *        is wildcarded.
     526                 :            :  *
     527                 :            :  * If successful, stores the address into '*ss' and returns true; otherwise
     528                 :            :  * zeros '*ss' and returns false. */
     529                 :            : bool
     530                 :        157 : inet_parse_passive(const char *target_, int default_port,
     531                 :            :                    struct sockaddr_storage *ss)
     532                 :            : {
     533                 :        157 :     char *target = xstrdup(target_);
     534                 :            :     const char *port;
     535                 :            :     const char *host;
     536                 :            :     char *p;
     537                 :            :     bool ok;
     538                 :            : 
     539                 :        157 :     p = target;
     540                 :        157 :     port = parse_bracketed_token(&p);
     541                 :        157 :     host = parse_bracketed_token(&p);
     542 [ -  + ][ #  # ]:        157 :     if (!port && default_port < 0) {
     543         [ #  # ]:          0 :         VLOG_ERR("%s: port must be specified", target_);
     544                 :          0 :         ok = false;
     545                 :            :     } else {
     546         [ +  - ]:        157 :         ok = parse_sockaddr_components(ss, host ? host : "0.0.0.0",
     547                 :            :                                        port, default_port, target_);
     548                 :            :     }
     549         [ -  + ]:        157 :     if (!ok) {
     550                 :          0 :         memset(ss, 0, sizeof *ss);
     551                 :            :     }
     552                 :        157 :     free(target);
     553                 :        157 :     return ok;
     554                 :            : }
     555                 :            : 
     556                 :            : 
     557                 :            : /* Opens a non-blocking IPv4 or IPv6 socket of the specified 'style', binds to
     558                 :            :  * 'target', and listens for incoming connections.  Parses 'target' in the same
     559                 :            :  * way was inet_parse_passive().
     560                 :            :  *
     561                 :            :  * 'style' should be SOCK_STREAM (for TCP) or SOCK_DGRAM (for UDP).
     562                 :            :  *
     563                 :            :  * For TCP, the socket will have SO_REUSEADDR turned on.
     564                 :            :  *
     565                 :            :  * On success, returns a non-negative file descriptor.  On failure, returns a
     566                 :            :  * negative errno value.
     567                 :            :  *
     568                 :            :  * If 'ss' is non-null, then on success stores the bound address into '*ss'.
     569                 :            :  *
     570                 :            :  * 'dscp' becomes the DSCP bits in the IP headers for the new connection.  It
     571                 :            :  * should be in the range [0, 63] and will automatically be shifted to the
     572                 :            :  * appropriately place in the IP tos field.
     573                 :            :  *
     574                 :            :  * If 'kernel_print_port' is true and the port is dynamically assigned by
     575                 :            :  * the kernel, print the chosen port. */
     576                 :            : int
     577                 :        157 : inet_open_passive(int style, const char *target, int default_port,
     578                 :            :                   struct sockaddr_storage *ssp, uint8_t dscp,
     579                 :            :                   bool kernel_print_port)
     580                 :            : {
     581                 :            :     bool kernel_chooses_port;
     582                 :            :     struct sockaddr_storage ss;
     583                 :        157 :     int fd = 0, error;
     584                 :        157 :     unsigned int yes = 1;
     585                 :            : 
     586         [ -  + ]:        157 :     if (!inet_parse_passive(target, default_port, &ss)) {
     587                 :          0 :         return -EAFNOSUPPORT;
     588                 :            :     }
     589                 :        157 :     kernel_chooses_port = ss_get_port(&ss) == 0;
     590                 :            : 
     591                 :            :     /* Create non-blocking socket, set SO_REUSEADDR. */
     592                 :        157 :     fd = socket(ss.ss_family, style, 0);
     593         [ -  + ]:        157 :     if (fd < 0) {
     594                 :          0 :         error = sock_errno();
     595         [ #  # ]:          0 :         VLOG_ERR("%s: socket: %s", target, sock_strerror(error));
     596                 :          0 :         return -error;
     597                 :            :     }
     598                 :        157 :     error = set_nonblocking(fd);
     599         [ -  + ]:        157 :     if (error) {
     600                 :          0 :         goto error;
     601                 :            :     }
     602         [ +  + ]:        157 :     if (style == SOCK_STREAM
     603         [ -  + ]:        145 :         && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
     604                 :          0 :         error = sock_errno();
     605         [ #  # ]:          0 :         VLOG_ERR("%s: setsockopt(SO_REUSEADDR): %s",
     606                 :            :                  target, sock_strerror(error));
     607                 :          0 :         goto error;
     608                 :            :     }
     609                 :            : 
     610                 :            :     /* Bind. */
     611         [ -  + ]:        157 :     if (bind(fd, (struct sockaddr *) &ss, ss_length(&ss)) < 0) {
     612                 :          0 :         error = sock_errno();
     613         [ #  # ]:          0 :         VLOG_ERR("%s: bind: %s", target, sock_strerror(error));
     614                 :          0 :         goto error;
     615                 :            :     }
     616                 :            : 
     617                 :            :     /* The dscp bits must be configured before connect() to ensure that the TOS
     618                 :            :      * field is set during the connection establishment.  If set after
     619                 :            :      * connect(), the handshake SYN frames will be sent with a TOS of 0. */
     620                 :        157 :     error = set_dscp(fd, ss.ss_family, dscp);
     621         [ -  + ]:        157 :     if (error) {
     622         [ #  # ]:          0 :         VLOG_ERR("%s: set_dscp: %s", target, sock_strerror(error));
     623                 :          0 :         goto error;
     624                 :            :     }
     625                 :            : 
     626                 :            :     /* Listen. */
     627 [ +  + ][ -  + ]:        157 :     if (style == SOCK_STREAM && listen(fd, 10) < 0) {
     628                 :          0 :         error = sock_errno();
     629         [ #  # ]:          0 :         VLOG_ERR("%s: listen: %s", target, sock_strerror(error));
     630                 :          0 :         goto error;
     631                 :            :     }
     632                 :            : 
     633 [ +  + ][ +  - ]:        157 :     if (ssp || kernel_chooses_port) {
     634                 :        157 :         socklen_t ss_len = sizeof ss;
     635         [ -  + ]:        157 :         if (getsockname(fd, (struct sockaddr *) &ss, &ss_len) < 0) {
     636                 :          0 :             error = sock_errno();
     637         [ #  # ]:          0 :             VLOG_ERR("%s: getsockname: %s", target, sock_strerror(error));
     638                 :          0 :             goto error;
     639                 :            :         }
     640 [ +  - ][ +  - ]:        157 :         if (kernel_chooses_port && kernel_print_port) {
     641         [ +  - ]:        157 :             VLOG_INFO("%s: listening on port %"PRIu16,
     642                 :            :                       target, ss_get_port(&ss));
     643                 :            :         }
     644         [ +  + ]:        157 :         if (ssp) {
     645                 :        157 :             *ssp = ss;
     646                 :            :         }
     647                 :            :     }
     648                 :            : 
     649                 :        157 :     return fd;
     650                 :            : 
     651                 :            : error:
     652         [ #  # ]:          0 :     if (ssp) {
     653                 :          0 :         memset(ssp, 0, sizeof *ssp);
     654                 :            :     }
     655                 :          0 :     closesocket(fd);
     656                 :        157 :     return -error;
     657                 :            : }
     658                 :            : 
     659                 :            : int
     660                 :      29499 : read_fully(int fd, void *p_, size_t size, size_t *bytes_read)
     661                 :            : {
     662                 :      29499 :     uint8_t *p = p_;
     663                 :            : 
     664                 :      29499 :     *bytes_read = 0;
     665         [ +  + ]:      58995 :     while (size > 0) {
     666                 :      29499 :         ssize_t retval = read(fd, p, size);
     667         [ +  + ]:      29499 :         if (retval > 0) {
     668                 :      29496 :             *bytes_read += retval;
     669                 :      29496 :             size -= retval;
     670                 :      29496 :             p += retval;
     671         [ +  - ]:          3 :         } else if (retval == 0) {
     672                 :          3 :             return EOF;
     673         [ #  # ]:          0 :         } else if (errno != EINTR) {
     674                 :          0 :             return errno;
     675                 :            :         }
     676                 :            :     }
     677                 :      29496 :     return 0;
     678                 :            : }
     679                 :            : 
     680                 :            : int
     681                 :       2071 : write_fully(int fd, const void *p_, size_t size, size_t *bytes_written)
     682                 :            : {
     683                 :       2071 :     const uint8_t *p = p_;
     684                 :            : 
     685                 :       2071 :     *bytes_written = 0;
     686         [ +  + ]:       4142 :     while (size > 0) {
     687                 :       2071 :         ssize_t retval = write(fd, p, size);
     688         [ +  - ]:       2071 :         if (retval > 0) {
     689                 :       2071 :             *bytes_written += retval;
     690                 :       2071 :             size -= retval;
     691                 :       2071 :             p += retval;
     692         [ #  # ]:          0 :         } else if (retval == 0) {
     693         [ #  # ]:          0 :             VLOG_WARN("write returned 0");
     694                 :          0 :             return EPROTO;
     695         [ #  # ]:          0 :         } else if (errno != EINTR) {
     696                 :          0 :             return errno;
     697                 :            :         }
     698                 :            :     }
     699                 :       2071 :     return 0;
     700                 :            : }
     701                 :            : 
     702                 :            : /* Given file name 'file_name', fsyncs the directory in which it is contained.
     703                 :            :  * Returns 0 if successful, otherwise a positive errno value. */
     704                 :            : int
     705                 :       1277 : fsync_parent_dir(const char *file_name)
     706                 :            : {
     707                 :       1277 :     int error = 0;
     708                 :            : #ifndef _WIN32
     709                 :            :     char *dir;
     710                 :            :     int fd;
     711                 :            : 
     712                 :       1277 :     dir = dir_name(file_name);
     713                 :       1277 :     fd = open(dir, O_RDONLY);
     714         [ +  - ]:       1277 :     if (fd >= 0) {
     715         [ -  + ]:       1277 :         if (fsync(fd)) {
     716 [ #  # ][ #  # ]:          0 :             if (errno == EINVAL || errno == EROFS) {
     717                 :            :                 /* This directory does not support synchronization.  Not
     718                 :            :                  * really an error. */
     719                 :            :             } else {
     720                 :          0 :                 error = errno;
     721         [ #  # ]:          0 :                 VLOG_ERR("%s: fsync failed (%s)", dir, ovs_strerror(error));
     722                 :            :             }
     723                 :            :         }
     724                 :       1277 :         close(fd);
     725                 :            :     } else {
     726                 :          0 :         error = errno;
     727         [ #  # ]:          0 :         VLOG_ERR("%s: open failed (%s)", dir, ovs_strerror(error));
     728                 :            :     }
     729                 :       1277 :     free(dir);
     730                 :            : #endif
     731                 :            : 
     732                 :       1277 :     return error;
     733                 :            : }
     734                 :            : 
     735                 :            : /* Obtains the modification time of the file named 'file_name' to the greatest
     736                 :            :  * supported precision.  If successful, stores the mtime in '*mtime' and
     737                 :            :  * returns 0.  On error, returns a positive errno value and stores zeros in
     738                 :            :  * '*mtime'. */
     739                 :            : int
     740                 :       2979 : get_mtime(const char *file_name, struct timespec *mtime)
     741                 :            : {
     742                 :            :     struct stat s;
     743                 :            : 
     744         [ +  + ]:       2979 :     if (!stat(file_name, &s)) {
     745                 :       2957 :         mtime->tv_sec = s.st_mtime;
     746                 :            : 
     747                 :            : #if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
     748                 :       2957 :         mtime->tv_nsec = s.st_mtim.tv_nsec;
     749                 :            : #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
     750                 :            :         mtime->tv_nsec = s.st_mtimensec;
     751                 :            : #else
     752                 :            :         mtime->tv_nsec = 0;
     753                 :            : #endif
     754                 :            : 
     755                 :       2957 :         return 0;
     756                 :            :     } else {
     757                 :         22 :         mtime->tv_sec = mtime->tv_nsec = 0;
     758                 :       2979 :         return errno;
     759                 :            :     }
     760                 :            : }
     761                 :            : 
     762                 :            : static int
     763                 :       3975 : getsockopt_int(int fd, int level, int option, const char *optname, int *valuep)
     764                 :            : {
     765                 :            :     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 10);
     766                 :            :     socklen_t len;
     767                 :            :     int value;
     768                 :            :     int error;
     769                 :            : 
     770                 :       3975 :     len = sizeof value;
     771         [ -  + ]:       3975 :     if (getsockopt(fd, level, option, &value, &len)) {
     772                 :          0 :         error = sock_errno();
     773         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "getsockopt(%s): %s", optname, sock_strerror(error));
     774         [ -  + ]:       3975 :     } else if (len != sizeof value) {
     775                 :          0 :         error = EINVAL;
     776         [ #  # ]:          0 :         VLOG_ERR_RL(&rl, "getsockopt(%s): value is %u bytes (expected %"PRIuSIZE")",
     777                 :            :                     optname, (unsigned int) len, sizeof value);
     778                 :            :     } else {
     779                 :       3975 :         error = 0;
     780                 :            :     }
     781                 :            : 
     782         [ +  - ]:       3975 :     *valuep = error ? 0 : value;
     783                 :       3975 :     return error;
     784                 :            : }
     785                 :            : 
     786                 :            : static void
     787                 :        174 : describe_sockaddr(struct ds *string, int fd,
     788                 :            :                   int (*getaddr)(int, struct sockaddr *, socklen_t *))
     789                 :            : {
     790                 :            :     struct sockaddr_storage ss;
     791                 :        174 :     socklen_t len = sizeof ss;
     792                 :            : 
     793         [ +  + ]:        174 :     if (!getaddr(fd, (struct sockaddr *) &ss, &len)) {
     794 [ +  + ][ -  + ]:        224 :         if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) {
     795                 :            :             char addrbuf[SS_NTOP_BUFSIZE];
     796                 :            : 
     797                 :         68 :             ds_put_format(string, "%s:%"PRIu16,
     798                 :            :                           ss_format_address(&ss, addrbuf, sizeof addrbuf),
     799                 :         68 :                           ss_get_port(&ss));
     800                 :            : #ifndef _WIN32
     801         [ +  - ]:         88 :         } else if (ss.ss_family == AF_UNIX) {
     802                 :            :             struct sockaddr_un sun;
     803                 :            :             const char *null;
     804                 :            :             size_t maxlen;
     805                 :            : 
     806                 :         88 :             memcpy(&sun, &ss, sizeof sun);
     807                 :         88 :             maxlen = len - offsetof(struct sockaddr_un, sun_path);
     808                 :         88 :             null = memchr(sun.sun_path, '\0', maxlen);
     809         [ +  + ]:         88 :             ds_put_buffer(string, sun.sun_path,
     810                 :         53 :                           null ? null - sun.sun_path : maxlen);
     811                 :            : #endif
     812                 :            :         }
     813                 :            : #ifdef HAVE_NETLINK
     814         [ #  # ]:          0 :         else if (ss.ss_family == AF_NETLINK) {
     815                 :            :             int protocol;
     816                 :            : 
     817                 :            : /* SO_PROTOCOL was introduced in 2.6.32.  Support it regardless of the version
     818                 :            :  * of the Linux kernel headers in use at build time. */
     819                 :            : #ifndef SO_PROTOCOL
     820                 :            : #define SO_PROTOCOL 38
     821                 :            : #endif
     822                 :            : 
     823         [ #  # ]:          0 :             if (!getsockopt_int(fd, SOL_SOCKET, SO_PROTOCOL, "SO_PROTOCOL",
     824                 :            :                                 &protocol)) {
     825      [ #  #  # ]:          0 :                 switch (protocol) {
     826                 :            :                 case NETLINK_ROUTE:
     827                 :          0 :                     ds_put_cstr(string, "NETLINK_ROUTE");
     828                 :          0 :                     break;
     829                 :            : 
     830                 :            :                 case NETLINK_GENERIC:
     831                 :          0 :                     ds_put_cstr(string, "NETLINK_GENERIC");
     832                 :          0 :                     break;
     833                 :            : 
     834                 :            :                 default:
     835                 :          0 :                     ds_put_format(string, "AF_NETLINK family %d", protocol);
     836                 :          0 :                     break;
     837                 :            :                 }
     838                 :            :             } else {
     839                 :          0 :                 ds_put_cstr(string, "AF_NETLINK");
     840                 :            :             }
     841                 :            :         }
     842                 :            : #endif
     843                 :            : #if __linux__
     844         [ #  # ]:          0 :         else if (ss.ss_family == AF_PACKET) {
     845                 :            :             struct sockaddr_ll sll;
     846                 :            : 
     847                 :          0 :             memcpy(&sll, &ss, sizeof sll);
     848                 :          0 :             ds_put_cstr(string, "AF_PACKET");
     849         [ #  # ]:          0 :             if (sll.sll_ifindex) {
     850                 :            :                 char name[IFNAMSIZ];
     851                 :            : 
     852         [ #  # ]:          0 :                 if (if_indextoname(sll.sll_ifindex, name)) {
     853                 :          0 :                     ds_put_format(string, "(%s)", name);
     854                 :            :                 } else {
     855                 :          0 :                     ds_put_format(string, "(ifindex=%d)", sll.sll_ifindex);
     856                 :            :                 }
     857                 :            :             }
     858         [ #  # ]:          0 :             if (sll.sll_protocol) {
     859                 :          0 :                 ds_put_format(string, "(protocol=0x%"PRIu16")",
     860                 :          0 :                               ntohs(sll.sll_protocol));
     861                 :            :             }
     862                 :            :         }
     863                 :            : #endif
     864         [ #  # ]:          0 :         else if (ss.ss_family == AF_UNSPEC) {
     865                 :          0 :             ds_put_cstr(string, "AF_UNSPEC");
     866                 :            :         } else {
     867                 :          0 :             ds_put_format(string, "AF_%d", (int) ss.ss_family);
     868                 :            :         }
     869                 :            :     }
     870                 :        174 : }
     871                 :            : 
     872                 :            : 
     873                 :            : #ifdef __linux__
     874                 :            : static void
     875                 :          0 : put_fd_filename(struct ds *string, int fd)
     876                 :            : {
     877                 :            :     char buf[1024];
     878                 :            :     char *linkname;
     879                 :            :     int n;
     880                 :            : 
     881                 :          0 :     linkname = xasprintf("/proc/self/fd/%d", fd);
     882                 :          0 :     n = readlink(linkname, buf, sizeof buf);
     883         [ #  # ]:          0 :     if (n > 0) {
     884                 :          0 :         ds_put_char(string, ' ');
     885                 :          0 :         ds_put_buffer(string, buf, n);
     886         [ #  # ]:          0 :         if (n > sizeof buf) {
     887                 :          0 :             ds_put_cstr(string, "...");
     888                 :            :         }
     889                 :            :     }
     890                 :          0 :     free(linkname);
     891                 :          0 : }
     892                 :            : #endif
     893                 :            : 
     894                 :            : /* Returns a malloc()'d string describing 'fd', for use in logging. */
     895                 :            : char *
     896                 :         87 : describe_fd(int fd)
     897                 :            : {
     898                 :            :     struct ds string;
     899                 :            :     struct stat s;
     900                 :            : 
     901                 :         87 :     ds_init(&string);
     902                 :            : #ifndef _WIN32
     903         [ -  + ]:         87 :     if (fstat(fd, &s)) {
     904                 :          0 :         ds_put_format(&string, "fstat failed (%s)", ovs_strerror(errno));
     905         [ +  - ]:         87 :     } else if (S_ISSOCK(s.st_mode)) {
     906                 :         87 :         describe_sockaddr(&string, fd, getsockname);
     907                 :         87 :         ds_put_cstr(&string, "<->");
     908                 :         87 :         describe_sockaddr(&string, fd, getpeername);
     909                 :            :     } else {
     910         [ #  # ]:          0 :         ds_put_cstr(&string, (isatty(fd) ? "tty"
     911 [ #  # ][ #  # ]:          0 :                               : S_ISDIR(s.st_mode) ? "directory"
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     912                 :          0 :                               : S_ISCHR(s.st_mode) ? "character device"
     913                 :          0 :                               : S_ISBLK(s.st_mode) ? "block device"
     914                 :          0 :                               : S_ISREG(s.st_mode) ? "file"
     915                 :          0 :                               : S_ISFIFO(s.st_mode) ? "FIFO"
     916                 :          0 :                               : S_ISLNK(s.st_mode) ? "symbolic link"
     917                 :            :                               : "unknown"));
     918                 :            : #ifdef __linux__
     919                 :          0 :         put_fd_filename(&string, fd);
     920                 :            : #endif
     921                 :            :     }
     922                 :            : #else
     923                 :            :     ds_put_format(&string,"file descriptor");
     924                 :            : #endif /* _WIN32 */
     925                 :         87 :     return ds_steal_cstr(&string);
     926                 :            : }
     927                 :            : 
     928                 :            : 
     929                 :            : /* sockaddr_storage helpers. */
     930                 :            : 
     931                 :            : /* Returns the IPv4 or IPv6 port in 'ss'. */
     932                 :            : uint16_t
     933                 :        945 : ss_get_port(const struct sockaddr_storage *ss)
     934                 :            : {
     935         [ +  + ]:        945 :     if (ss->ss_family == AF_INET) {
     936                 :        723 :         const struct sockaddr_in *sin
     937                 :            :             = ALIGNED_CAST(const struct sockaddr_in *, ss);
     938                 :        723 :         return ntohs(sin->sin_port);
     939         [ +  - ]:        222 :     } else if (ss->ss_family == AF_INET6) {
     940                 :        222 :         const struct sockaddr_in6 *sin6
     941                 :            :             = ALIGNED_CAST(const struct sockaddr_in6 *, ss);
     942                 :        222 :         return ntohs(sin6->sin6_port);
     943                 :            :     } else {
     944                 :          0 :         OVS_NOT_REACHED();
     945                 :            :     }
     946                 :            : }
     947                 :            : 
     948                 :            : /* Formats the IPv4 or IPv6 address in 'ss' into the 'bufsize' bytes in 'buf'.
     949                 :            :  * If 'ss' is an IPv6 address, puts square brackets around the address.
     950                 :            :  * 'bufsize' should be at least SS_NTOP_BUFSIZE.
     951                 :            :  *
     952                 :            :  * Returns 'buf'. */
     953                 :            : char *
     954                 :        631 : ss_format_address(const struct sockaddr_storage *ss,
     955                 :            :                   char *buf, size_t bufsize)
     956                 :            : {
     957         [ -  + ]:        631 :     ovs_assert(bufsize >= SS_NTOP_BUFSIZE);
     958         [ +  + ]:        631 :     if (ss->ss_family == AF_INET) {
     959                 :        493 :         const struct sockaddr_in *sin
     960                 :            :             = ALIGNED_CAST(const struct sockaddr_in *, ss);
     961                 :            : 
     962                 :        493 :         snprintf(buf, bufsize, IP_FMT, IP_ARGS(sin->sin_addr.s_addr));
     963         [ +  - ]:        138 :     } else if (ss->ss_family == AF_INET6) {
     964                 :        138 :         const struct sockaddr_in6 *sin6
     965                 :            :             = ALIGNED_CAST(const struct sockaddr_in6 *, ss);
     966                 :            : 
     967                 :        138 :         buf[0] = '[';
     968                 :        138 :         inet_ntop(AF_INET6, sin6->sin6_addr.s6_addr, buf + 1, bufsize - 1);
     969                 :        138 :         strcpy(strchr(buf, '\0'), "]");
     970                 :            :     } else {
     971                 :          0 :         OVS_NOT_REACHED();
     972                 :            :     }
     973                 :            : 
     974                 :        631 :     return buf;
     975                 :            : }
     976                 :            : 
     977                 :            : size_t
     978                 :        456 : ss_length(const struct sockaddr_storage *ss)
     979                 :            : {
     980      [ +  +  - ]:        456 :     switch (ss->ss_family) {
     981                 :            :     case AF_INET:
     982                 :        382 :         return sizeof(struct sockaddr_in);
     983                 :            : 
     984                 :            :     case AF_INET6:
     985                 :         74 :         return sizeof(struct sockaddr_in6);
     986                 :            : 
     987                 :            :     default:
     988                 :          0 :         OVS_NOT_REACHED();
     989                 :            :     }
     990                 :            : }
     991                 :            : 
     992                 :            : /* For Windows socket calls, 'errno' is not set.  One has to call
     993                 :            :  * WSAGetLastError() to get the error number and then pass it to
     994                 :            :  * this function to get the correct error string.
     995                 :            :  *
     996                 :            :  * ovs_strerror() calls strerror_r() and would not get the correct error
     997                 :            :  * string for Windows sockets, but is good for POSIX. */
     998                 :            : const char *
     999                 :          4 : sock_strerror(int error)
    1000                 :            : {
    1001                 :            : #ifdef _WIN32
    1002                 :            :     return ovs_format_message(error);
    1003                 :            : #else
    1004                 :          4 :     return ovs_strerror(error);
    1005                 :            : #endif
    1006                 :            : }

Generated by: LCOV version 1.12