LCOV - code coverage report
Current view: top level - basic - socket-label.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 78 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 2 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 92 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <netinet/in.h>
       5                 :            : #include <stdbool.h>
       6                 :            : #include <stddef.h>
       7                 :            : #include <string.h>
       8                 :            : #include <sys/socket.h>
       9                 :            : #include <sys/un.h>
      10                 :            : #include <unistd.h>
      11                 :            : 
      12                 :            : #include "alloc-util.h"
      13                 :            : #include "fd-util.h"
      14                 :            : #include "fs-util.h"
      15                 :            : #include "log.h"
      16                 :            : #include "macro.h"
      17                 :            : #include "missing.h"
      18                 :            : #include "mkdir.h"
      19                 :            : #include "selinux-util.h"
      20                 :            : #include "socket-util.h"
      21                 :            : #include "umask-util.h"
      22                 :            : 
      23                 :          0 : int socket_address_listen(
      24                 :            :                 const SocketAddress *a,
      25                 :            :                 int flags,
      26                 :            :                 int backlog,
      27                 :            :                 SocketAddressBindIPv6Only only,
      28                 :            :                 const char *bind_to_device,
      29                 :            :                 bool reuse_port,
      30                 :            :                 bool free_bind,
      31                 :            :                 bool transparent,
      32                 :            :                 mode_t directory_mode,
      33                 :            :                 mode_t socket_mode,
      34                 :            :                 const char *label) {
      35                 :            : 
      36                 :          0 :         _cleanup_close_ int fd = -1;
      37                 :            :         const char *p;
      38                 :            :         int r;
      39                 :            : 
      40         [ #  # ]:          0 :         assert(a);
      41                 :            : 
      42                 :          0 :         r = socket_address_verify(a, true);
      43         [ #  # ]:          0 :         if (r < 0)
      44                 :          0 :                 return r;
      45                 :            : 
      46   [ #  #  #  # ]:          0 :         if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported())
      47                 :          0 :                 return -EAFNOSUPPORT;
      48                 :            : 
      49         [ #  # ]:          0 :         if (label) {
      50                 :          0 :                 r = mac_selinux_create_socket_prepare(label);
      51         [ #  # ]:          0 :                 if (r < 0)
      52                 :          0 :                         return r;
      53                 :            :         }
      54                 :            : 
      55                 :          0 :         fd = socket(socket_address_family(a), a->type | flags, a->protocol);
      56         [ #  # ]:          0 :         r = fd < 0 ? -errno : 0;
      57                 :            : 
      58         [ #  # ]:          0 :         if (label)
      59                 :          0 :                 mac_selinux_create_socket_clear();
      60                 :            : 
      61         [ #  # ]:          0 :         if (r < 0)
      62                 :          0 :                 return r;
      63                 :            : 
      64   [ #  #  #  # ]:          0 :         if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) {
      65                 :          0 :                 r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, only == SOCKET_ADDRESS_IPV6_ONLY);
      66         [ #  # ]:          0 :                 if (r < 0)
      67                 :          0 :                         return r;
      68                 :            :         }
      69                 :            : 
      70   [ #  #  #  # ]:          0 :         if (IN_SET(socket_address_family(a), AF_INET, AF_INET6)) {
      71         [ #  # ]:          0 :                 if (bind_to_device) {
      72                 :          0 :                         r = socket_bind_to_ifname(fd, bind_to_device);
      73         [ #  # ]:          0 :                         if (r < 0)
      74                 :          0 :                                 return r;
      75                 :            :                 }
      76                 :            : 
      77         [ #  # ]:          0 :                 if (reuse_port) {
      78                 :          0 :                         r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEPORT, true);
      79         [ #  # ]:          0 :                         if (r < 0)
      80         [ #  # ]:          0 :                                 log_warning_errno(r, "SO_REUSEPORT failed: %m");
      81                 :            :                 }
      82                 :            : 
      83         [ #  # ]:          0 :                 if (free_bind) {
      84                 :          0 :                         r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
      85         [ #  # ]:          0 :                         if (r < 0)
      86         [ #  # ]:          0 :                                 log_warning_errno(r, "IP_FREEBIND failed: %m");
      87                 :            :                 }
      88                 :            : 
      89         [ #  # ]:          0 :                 if (transparent) {
      90                 :          0 :                         r = setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, true);
      91         [ #  # ]:          0 :                         if (r < 0)
      92         [ #  # ]:          0 :                                 log_warning_errno(r, "IP_TRANSPARENT failed: %m");
      93                 :            :                 }
      94                 :            :         }
      95                 :            : 
      96                 :          0 :         r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
      97         [ #  # ]:          0 :         if (r < 0)
      98                 :          0 :                 return r;
      99                 :            : 
     100                 :          0 :         p = socket_address_get_path(a);
     101         [ #  # ]:          0 :         if (p) {
     102                 :            :                 /* Create parents */
     103                 :          0 :                 (void) mkdir_parents_label(p, directory_mode);
     104                 :            : 
     105                 :            :                 /* Enforce the right access mode for the socket */
     106   [ #  #  #  # ]:          0 :                 RUN_WITH_UMASK(~socket_mode) {
     107                 :          0 :                         r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
     108         [ #  # ]:          0 :                         if (r == -EADDRINUSE) {
     109                 :            :                                 /* Unlink and try again */
     110                 :            : 
     111         [ #  # ]:          0 :                                 if (unlink(p) < 0)
     112                 :          0 :                                         return r; /* didn't work, return original error */
     113                 :            : 
     114                 :          0 :                                 r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
     115                 :            :                         }
     116         [ #  # ]:          0 :                         if (r < 0)
     117                 :          0 :                                 return r;
     118                 :            :                 }
     119                 :            :         } else {
     120         [ #  # ]:          0 :                 if (bind(fd, &a->sockaddr.sa, a->size) < 0)
     121                 :          0 :                         return -errno;
     122                 :            :         }
     123                 :            : 
     124         [ #  # ]:          0 :         if (socket_address_can_accept(a))
     125         [ #  # ]:          0 :                 if (listen(fd, backlog) < 0)
     126                 :          0 :                         return -errno;
     127                 :            : 
     128                 :            :         /* Let's trigger an inotify event on the socket node, so that anyone waiting for this socket to be connectable
     129                 :            :          * gets notified */
     130         [ #  # ]:          0 :         if (p)
     131                 :          0 :                 (void) touch(p);
     132                 :            : 
     133                 :          0 :         r = fd;
     134                 :          0 :         fd = -1;
     135                 :            : 
     136                 :          0 :         return r;
     137                 :            : }
     138                 :            : 
     139                 :          0 : int make_socket_fd(int log_level, const char* address, int type, int flags) {
     140                 :            :         SocketAddress a;
     141                 :            :         int fd, r;
     142                 :            : 
     143                 :          0 :         r = socket_address_parse(&a, address);
     144         [ #  # ]:          0 :         if (r < 0)
     145         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to parse socket address \"%s\": %m", address);
     146                 :            : 
     147                 :          0 :         a.type = type;
     148                 :            : 
     149                 :          0 :         fd = socket_address_listen(&a, type | flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
     150                 :            :                                    NULL, false, false, false, 0755, 0644, NULL);
     151   [ #  #  #  # ]:          0 :         if (fd < 0 || log_get_max_level() >= log_level) {
     152         [ #  # ]:          0 :                 _cleanup_free_ char *p = NULL;
     153                 :            : 
     154                 :          0 :                 r = socket_address_print(&a, &p);
     155         [ #  # ]:          0 :                 if (r < 0)
     156         [ #  # ]:          0 :                         return log_error_errno(r, "socket_address_print(): %m");
     157                 :            : 
     158         [ #  # ]:          0 :                 if (fd < 0)
     159         [ #  # ]:          0 :                         log_error_errno(fd, "Failed to listen on %s: %m", p);
     160                 :            :                 else
     161         [ #  # ]:          0 :                         log_full(log_level, "Listening on %s", p);
     162                 :            :         }
     163                 :            : 
     164                 :          0 :         return fd;
     165                 :            : }

Generated by: LCOV version 1.14