varnish-cache/lib/libvarnish/vus.c
0
/*-
1
 * Copyright 2018 UPLEX - Nils Goroll Systemoptimierung
2
 * All rights reserved.
3
 *
4
 * Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include <sys/socket.h>
31
#include <sys/un.h>
32
33
#include <unistd.h>
34
#include <string.h>
35
#include <poll.h>
36
#include <stdio.h>
37
38
#include "vdef.h"
39
#include "vas.h"
40
#include "vus.h"
41
#include "vtcp.h"
42
43
static int
44 9207
sun_init(struct sockaddr_un *uds, const char *path, const char **err)
45
{
46 9207
        AN(uds);
47 9207
        AN(path);
48 9207
        assert(VUS_is(path));
49
50 9207
        if (err)
51 6183
                *err = NULL;
52
53 9207
        if (strlen(path) + 1 > sizeof(uds->sun_path)) {
54 54
                errno = ENAMETOOLONG;
55 54
                if (err)
56 54
                        *err = "Path too long for a Unix domain socket";
57 54
                return (-1);
58
        }
59 9153
        if (! strcmp(path, "@")) {
60 0
                errno = EINVAL;
61 0
                if (err)
62 0
                        *err = "The empty abstract socket name is not"
63
                            " supported";
64 0
                return (-1);
65
        }
66 9153
        memset(uds->sun_path, 0, sizeof(uds->sun_path));
67 9153
        if (*path == '@')
68 27
                bprintf(uds->sun_path, "%c%s", 0, path + 1);
69
        else
70 9126
                bprintf(uds->sun_path, "%s", path);
71 9153
        uds->sun_family = PF_UNIX;
72 9153
        return (0);
73 9207
}
74
75
int
76 6210
VUS_resolver(const char *path, vus_resolved_f *func, void *priv,
77
             const char **err)
78
{
79
        struct sockaddr_un uds;
80
        int ret;
81
82 6210
        AN(err);
83
84 6210
        ret = sun_init(&uds, path, err);
85 6210
        if (ret)
86 54
                return (ret);
87
88 6156
        if (func != NULL)
89 6129
                ret = func(priv, &uds);
90 6156
        return (ret);
91 6156
}
92
93
int
94 3105
VUS_bind(const struct sockaddr_un *uds, const char **errp)
95
{
96
        int sd, e;
97 3105
        socklen_t sl = sizeof(*uds);
98
99 3105
        if (errp != NULL)
100 1593
                *errp = NULL;
101
102 3105
        sd = socket(PF_UNIX, SOCK_STREAM, 0);
103 3105
        if (sd < 0) {
104 0
                if (errp != NULL)
105 0
                        *errp = "socket(2)";
106 0
                return (-1);
107
        }
108
109 3105
        if (unlink(uds->sun_path) != 0 && errno != ENOENT) {
110 0
                if (errp != NULL)
111 0
                        *errp = "unlink(2)";
112 0
                e = errno;
113 0
                closefd(&sd);
114 0
                errno = e;
115 0
                return (-1);
116
        }
117
118 3105
        if (bind(sd, (const void*)uds, sl) != 0) {
119 27
                if (errp != NULL)
120 0
                        *errp = "bind(2)";
121 27
                e = errno;
122 27
                closefd(&sd);
123 27
                errno = e;
124 27
                return (-1);
125
        }
126 3078
        return (sd);
127 3105
}
128
129
int
130 3024
VUS_connect(const char *path, int msec)
131
{
132
        int s, i;
133
        struct pollfd fds[1];
134
        struct sockaddr_un uds;
135 3024
        socklen_t sl = (socklen_t) sizeof(uds);
136
137 3024
        if (path == NULL)
138 0
                return (-1);
139 3024
        i = sun_init(&uds, path, NULL);
140 3024
        if (i)
141 0
                return (i);
142 3024
        AN(sl);
143
144 3024
        s = socket(PF_UNIX, SOCK_STREAM, 0);
145 3024
        if (s < 0)
146 0
                return (s);
147
148
        /* Set the socket non-blocking */
149 3024
        if (msec != 0)
150 3023
                VTCP_nonblocking(s);
151
152 3024
        i = connect(s, (const void*)&uds, sl);
153 3024
        if (i == 0)
154 3022
                return (s);
155 2
        if (errno != EINPROGRESS) {
156 2
                closefd(&s);
157 2
                return (-1);
158
        }
159
160 0
        if (msec < 0) {
161
                /*
162
                 * Caller is responsible for waiting and
163
                 * calling VTCP_connected
164
                 */
165 0
                return (s);
166
        }
167
168 0
        assert(msec > 0);
169
        /* Exercise our patience, polling for write */
170 0
        fds[0].fd = s;
171 0
        fds[0].events = POLLWRNORM;
172 0
        fds[0].revents = 0;
173 0
        i = poll(fds, 1, msec);
174
175 0
        if (i == 0) {
176
                /* Timeout, close and give up */
177 0
                closefd(&s);
178 0
                errno = ETIMEDOUT;
179 0
                return (-1);
180
        }
181
182 0
        return (VTCP_connected(s));
183 3024
}