Coverage Report

Created: 2025-07-11 06:11

/src/openvswitch/lib/stream-unix.c
Line
Count
Source (jump to first uncovered line)
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 "stream.h"
19
#include <errno.h>
20
#include <inttypes.h>
21
#include <netdb.h>
22
#include <poll.h>
23
#include <sys/socket.h>
24
#include <sys/types.h>
25
#include <sys/un.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <unistd.h>
29
#include "ovs-atomic.h"
30
#include "packets.h"
31
#include "openvswitch/poll-loop.h"
32
#include "socket-util.h"
33
#include "dirs.h"
34
#include "util.h"
35
#include "stream-provider.h"
36
#include "stream-fd.h"
37
#include "openvswitch/vlog.h"
38
39
VLOG_DEFINE_THIS_MODULE(stream_unix);
40
41
/* Active UNIX socket. */
42
43
static int
44
unix_open(const char *name, char *suffix, struct stream **streamp,
45
          uint8_t dscp OVS_UNUSED)
46
0
{
47
0
    char *connect_path;
48
0
    int fd;
49
50
0
    connect_path = abs_file_name(ovs_rundir(), suffix);
51
0
    fd = make_unix_socket(SOCK_STREAM, true, NULL, connect_path);
52
53
0
    if (fd < 0) {
54
0
        VLOG_DBG("%s: connection failed (%s)",
55
0
                 connect_path, ovs_strerror(-fd));
56
0
        free(connect_path);
57
0
        return -fd;
58
0
    }
59
60
0
    free(connect_path);
61
0
    return new_fd_stream(xstrdup(name), fd, check_connection_completion(fd),
62
0
                         AF_UNIX, streamp);
63
0
}
64
65
const struct stream_class unix_stream_class = {
66
    "unix",                     /* name */
67
    false,                      /* needs_probes */
68
    unix_open,                  /* open */
69
    NULL,                       /* close */
70
    NULL,                       /* connect */
71
    NULL,                       /* recv */
72
    NULL,                       /* send */
73
    NULL,                       /* run */
74
    NULL,                       /* run_wait */
75
    NULL,                       /* wait */
76
};
77

78
/* Passive UNIX socket. */
79
80
static int punix_accept(int fd, const struct sockaddr_storage *ss,
81
                        size_t ss_len, struct stream **streamp);
82
83
static int
84
punix_open(const char *name OVS_UNUSED, char *suffix,
85
           struct pstream **pstreamp, uint8_t dscp OVS_UNUSED)
86
0
{
87
0
    char *bind_path;
88
0
    int fd, error;
89
90
0
    bind_path = abs_file_name(ovs_rundir(), suffix);
91
0
    fd = make_unix_socket(SOCK_STREAM, true, bind_path, NULL);
92
0
    if (fd < 0) {
93
0
        VLOG_ERR("%s: binding failed: %s", bind_path, ovs_strerror(errno));
94
0
        free(bind_path);
95
0
        return errno;
96
0
    }
97
98
0
    if (listen(fd, 64) < 0) {
99
0
        error = errno;
100
0
        VLOG_ERR("%s: listen: %s", name, ovs_strerror(error));
101
0
        close(fd);
102
0
        free(bind_path);
103
0
        return error;
104
0
    }
105
106
0
    return new_fd_pstream(xstrdup(name), fd,
107
0
                          punix_accept, bind_path, pstreamp);
108
0
}
109
110
static int
111
punix_accept(int fd, const struct sockaddr_storage *ss, size_t ss_len,
112
             struct stream **streamp)
113
0
{
114
0
    const struct sockaddr_un *sun = (const struct sockaddr_un *) ss;
115
0
    int name_len = get_unix_name_len(sun, ss_len);
116
0
    char *bound_name;
117
118
0
    if (name_len > 0) {
119
0
        bound_name = xasprintf("unix:%.*s", name_len, sun->sun_path);
120
0
    } else {
121
        /* When a Unix socket connects to us without first binding a name, we
122
         * don't get any name for it.  It's useful nevertheless to be able to
123
         * distinguish separate sockets in log messages, so use a counter. */
124
0
        static atomic_count next_idx = ATOMIC_COUNT_INIT(0);
125
0
        bound_name = xasprintf("unix#%u", atomic_count_inc(&next_idx));
126
0
    }
127
0
    return new_fd_stream(bound_name, fd, 0, AF_UNIX, streamp);
128
0
}
129
130
const struct pstream_class punix_pstream_class = {
131
    "punix",
132
    false,
133
    punix_open,
134
    NULL,
135
    NULL,
136
    NULL,
137
};
138