LCOV - code coverage report
Current view: top level - basic - socket-label.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 0 73 0.0 %
Date: 2015-07-29 18:47:03 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2010 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <string.h>
      23             : #include <unistd.h>
      24             : #include <errno.h>
      25             : #include <sys/stat.h>
      26             : #include <stddef.h>
      27             : 
      28             : #include "macro.h"
      29             : #include "util.h"
      30             : #include "mkdir.h"
      31             : #include "missing.h"
      32             : #include "selinux-util.h"
      33             : #include "socket-util.h"
      34             : 
      35           0 : int socket_address_listen(
      36             :                 const SocketAddress *a,
      37             :                 int flags,
      38             :                 int backlog,
      39             :                 SocketAddressBindIPv6Only only,
      40             :                 const char *bind_to_device,
      41             :                 bool reuse_port,
      42             :                 bool free_bind,
      43             :                 bool transparent,
      44             :                 mode_t directory_mode,
      45             :                 mode_t socket_mode,
      46             :                 const char *label) {
      47             : 
      48           0 :         _cleanup_close_ int fd = -1;
      49             :         int r, one;
      50             : 
      51           0 :         assert(a);
      52             : 
      53           0 :         r = socket_address_verify(a);
      54           0 :         if (r < 0)
      55           0 :                 return r;
      56             : 
      57           0 :         if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported())
      58           0 :                 return -EAFNOSUPPORT;
      59             : 
      60           0 :         if (label) {
      61           0 :                 r = mac_selinux_create_socket_prepare(label);
      62           0 :                 if (r < 0)
      63           0 :                         return r;
      64             :         }
      65             : 
      66           0 :         fd = socket(socket_address_family(a), a->type | flags, a->protocol);
      67           0 :         r = fd < 0 ? -errno : 0;
      68             : 
      69           0 :         if (label)
      70           0 :                 mac_selinux_create_socket_clear();
      71             : 
      72           0 :         if (r < 0)
      73           0 :                 return r;
      74             : 
      75           0 :         if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) {
      76           0 :                 int flag = only == SOCKET_ADDRESS_IPV6_ONLY;
      77             : 
      78           0 :                 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0)
      79           0 :                         return -errno;
      80             :         }
      81             : 
      82           0 :         if (socket_address_family(a) == AF_INET || socket_address_family(a) == AF_INET6) {
      83           0 :                 if (bind_to_device)
      84           0 :                         if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bind_to_device, strlen(bind_to_device)+1) < 0)
      85           0 :                                 return -errno;
      86             : 
      87           0 :                 if (reuse_port) {
      88           0 :                         one = 1;
      89           0 :                         if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
      90           0 :                                 log_warning_errno(errno, "SO_REUSEPORT failed: %m");
      91             :                 }
      92             : 
      93           0 :                 if (free_bind) {
      94           0 :                         one = 1;
      95           0 :                         if (setsockopt(fd, IPPROTO_IP, IP_FREEBIND, &one, sizeof(one)) < 0)
      96           0 :                                 log_warning_errno(errno, "IP_FREEBIND failed: %m");
      97             :                 }
      98             : 
      99           0 :                 if (transparent) {
     100           0 :                         one = 1;
     101           0 :                         if (setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0)
     102           0 :                                 log_warning_errno(errno, "IP_TRANSPARENT failed: %m");
     103             :                 }
     104             :         }
     105             : 
     106           0 :         one = 1;
     107           0 :         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
     108           0 :                 return -errno;
     109             : 
     110           0 :         if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
     111             :                 mode_t old_mask;
     112             : 
     113             :                 /* Create parents */
     114           0 :                 mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
     115             : 
     116             :                 /* Enforce the right access mode for the socket */
     117           0 :                 old_mask = umask(~ socket_mode);
     118             : 
     119           0 :                 r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
     120             : 
     121           0 :                 if (r < 0 && errno == EADDRINUSE) {
     122             :                         /* Unlink and try again */
     123           0 :                         unlink(a->sockaddr.un.sun_path);
     124           0 :                         r = bind(fd, &a->sockaddr.sa, a->size);
     125             :                 }
     126             : 
     127           0 :                 umask(old_mask);
     128             :         } else
     129           0 :                 r = bind(fd, &a->sockaddr.sa, a->size);
     130             : 
     131           0 :         if (r < 0)
     132           0 :                 return -errno;
     133             : 
     134           0 :         if (socket_address_can_accept(a))
     135           0 :                 if (listen(fd, backlog) < 0)
     136           0 :                         return -errno;
     137             : 
     138           0 :         r = fd;
     139           0 :         fd = -1;
     140             : 
     141           0 :         return r;
     142             : }
     143             : 
     144           0 : int make_socket_fd(int log_level, const char* address, int flags) {
     145             :         SocketAddress a;
     146             :         int fd, r;
     147             : 
     148           0 :         r = socket_address_parse(&a, address);
     149           0 :         if (r < 0) {
     150           0 :                 log_error("Failed to parse socket address \"%s\": %s",
     151             :                           address, strerror(-r));
     152           0 :                 return r;
     153             :         }
     154             : 
     155           0 :         fd = socket_address_listen(&a, flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT,
     156             :                                    NULL, false, false, false, 0755, 0644, NULL);
     157           0 :         if (fd < 0 || log_get_max_level() >= log_level) {
     158           0 :                 _cleanup_free_ char *p = NULL;
     159             : 
     160           0 :                 r = socket_address_print(&a, &p);
     161           0 :                 if (r < 0)
     162           0 :                         return log_error_errno(r, "socket_address_print(): %m");
     163             : 
     164           0 :                 if (fd < 0)
     165           0 :                         log_error_errno(fd, "Failed to listen on %s: %m", p);
     166             :                 else
     167           0 :                         log_full(log_level, "Listening on %s", p);
     168             :         }
     169             : 
     170           0 :         return fd;
     171             : }

Generated by: LCOV version 1.11