LCOV - code coverage report
Current view: top level - basic - socket-label.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 78 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 2 0.0 %

          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