vinyl-cache/bin/vinyltest/vtest2/src/vtc_proxy.c
0
/*-
1
 * Copyright (c) 2015 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
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 "config.h"
31
32
#include <stdlib.h>
33
#include <string.h>
34
#include <sys/socket.h>
35
36
#include <netinet/in.h>
37
38
#include <unistd.h>
39
40
#include "vtc.h"
41
42
#include "vend.h"
43
#include "vsa.h"
44
#include "vtcp.h"
45
46
static const char vpx1_sig[] = {'P', 'R', 'O', 'X', 'Y'};
47
static const char vpx2_sig[] = {
48
        '\r', '\n', '\r', '\n', '\0', '\r', '\n',
49
        'Q', 'U', 'I', 'T', '\n',
50
};
51
52
//lint -esym(750, PP2_*)
53
#define PP2_TYPE_ALPN           0x01
54
#define PP2_TYPE_AUTHORITY      0x02
55
#define PP2_TYPE_CRC32C         0x03
56
#define PP2_TYPE_NOOP           0x04
57
#define PP2_TYPE_UNIQUE_ID      0x05
58
#define PP2_TYPE_SSL            0x20
59
#define PP2_SUBTYPE_SSL_VERSION 0x21
60
#define PP2_SUBTYPE_SSL_CN      0x22
61
#define PP2_SUBTYPE_SSL_CIPHER  0x23
62
#define PP2_SUBTYPE_SSL_SIG_ALG 0x24
63
#define PP2_SUBTYPE_SSL_KEY_ALG 0x25
64
#define PP2_SUBTYPE_SSL_MAX     0x25
65
#define PP2_TYPE_NETNS          0x30
66
67
struct pp2_type {
68
        const char * name;
69
        uint8_t type;
70
};
71
72
/* sorted ! */
73
static const struct pp2_type pp2_types[] = {
74
        {"alpn",        PP2_TYPE_ALPN},
75
        {"authority",   PP2_TYPE_AUTHORITY},
76
        {"crc32c",      PP2_TYPE_CRC32C},
77
        {"netns",       PP2_TYPE_NETNS},
78
        {"noop",        PP2_TYPE_NOOP},
79
        {"unique_id",   PP2_TYPE_UNIQUE_ID}
80
};
81
82
static int
83 126
pp2cmp(const void *va, const void *vb)
84
{
85 126
        const struct pp2_type *a = va;
86 126
        const struct pp2_type *b = vb;
87 126
        return (strcmp(a->name, b->name));
88
}
89
90
void
91 42
vtc_proxy_tlv(struct vtclog *vl, struct vsb *vsb, const char *kva)
92
{
93
        const struct pp2_type *pp2;
94
        struct pp2_type needle;
95 42
        char *save = NULL, *kv;
96
        struct vsb *vsb2;
97
        const char *p;
98
        uint16_t le;
99
        ssize_t sz;
100
101 42
        kv = strdup(kva);
102 42
        AN(kv);
103
104 42
        p = strtok_r(kv, "=", &save);
105 42
        AN(p);
106 42
        if (p[0] == '0' && p[1] == 'x') {
107 0
                p += 2;
108 0
                vsb2 = vtc_hex_to_bin(vl, p);
109 0
                AN(vsb2);
110 0
                if (VSB_len(vsb2) != 1)
111 0
                        vtc_fatal(vl, "tlv hex type has wrong length");
112 0
                VSB_bcat(vsb, VSB_data(vsb2), 1);
113 0
                VSB_destroy(&vsb2);
114 0
        }
115
        else {
116 42
                needle = (typeof(needle)){p, 0};
117 42
                pp2 = bsearch(&needle, pp2_types, sizeof pp2_types / sizeof pp2_types[0],
118
                    sizeof pp2_types[0], pp2cmp);
119 42
                if (pp2 == NULL)
120 0
                        vtc_fatal(vl, "tlv type %s not found", p);
121 42
                VSB_putc(vsb, pp2->type);
122
        }
123
124 42
        p = strtok_r(NULL, "", &save);
125 42
        if (p == NULL)
126 0
                vtc_fatal(vl, "tlv value missing");
127 42
        if (p[0] == '0' && p[1] == 'x')
128 0
                vsb2 = vtc_hex_to_bin(vl, p + 2);
129
        else {
130 42
                vsb2 = VSB_new_auto();
131 42
                AN(vsb2);
132 42
                VSB_cat(vsb2, p);
133 42
                AZ(VSB_finish(vsb2));
134
        }
135 42
        AN(vsb2);
136 42
        free(kv);
137
138 42
        sz = VSB_len(vsb2);
139 42
        assert(sz >= 0);
140 42
        assert(sz <= UINT16_MAX);
141
142 42
        vbe16enc(&le, (uint16_t)sz);
143 42
        assert(sizeof(le) == 2);
144 42
        VSB_bcat(vsb, &le, 2);
145 42
        VSB_bcat(vsb, VSB_data(vsb2), sz);
146 42
        VSB_destroy(&vsb2);
147 42
}
148
149
static void
150 168
vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s)
151
{
152
        const struct sockaddr_in *sin4;
153
        const struct sockaddr_in6 *sin6;
154
        socklen_t sl;
155
156 168
        if (proto == PF_INET6) {
157 84
                sin6 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
158 84
                AN(sin6);
159 84
                assert(sl >= sizeof(*sin6));
160 84
                VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
161 84
        } else {
162 84
                sin4 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
163 84
                AN(sin4);
164 84
                assert(sl >= sizeof(*sin4));
165 84
                VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr));
166
        }
167 168
}
168
169
static void
170 168
vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
171
{
172
        uint8_t b[2];
173
174 168
        vbe16enc(b, (uint16_t)VSA_Port(s));
175 168
        VSB_bcat(vsb, b, sizeof(b));
176 168
}
177
178
int
179 273
vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
180
    const struct suckaddr *sas, struct vsb *tlv)
181
{
182
        struct vsb *vsb;
183
        char hc[VTCP_ADDRBUFSIZE];
184
        char pc[VTCP_PORTBUFSIZE];
185
        char hs[VTCP_ADDRBUFSIZE];
186
        char ps[VTCP_PORTBUFSIZE];
187
        uint16_t le, l;
188
        int i;
189
        int proto;
190
191 273
        AN(sac);
192 273
        AN(sas);
193
194 273
        assert(version == 1 || version == 2);
195 273
        vsb = VSB_new_auto();
196 273
        AN(vsb);
197
198 273
        proto = VSA_Get_Proto(sas);
199 273
        assert(proto == PF_INET6 || proto == PF_INET);
200
201 273
        if (tlv == NULL)
202 0
                l = 0;
203
        else
204 273
                l = VSB_len(tlv);
205
206 273
        assert(l <= UINT16_MAX - 0x24);
207
208 273
        if (version == 1) {
209 189
                VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
210 189
                if (proto == PF_INET6)
211 84
                        VSB_cat(vsb, " TCP6 ");
212 105
                else if (proto == PF_INET)
213 105
                        VSB_cat(vsb, " TCP4 ");
214 189
                VTCP_name(sac, hc, sizeof(hc), pc, sizeof(pc));
215 189
                VTCP_name(sas, hs, sizeof(hs), ps, sizeof(ps));
216 189
                VSB_printf(vsb, "%s %s %s %s\r\n", hc, hs, pc, ps);
217 273
        } else if (version == 2) {
218 84
                VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
219 84
                VSB_putc(vsb, 0x21);
220 84
                if (proto == PF_INET6) {
221 42
                        VSB_putc(vsb, 0x21);
222 42
                        l += 0x24;
223 84
                } else if (proto == PF_INET) {
224 42
                        VSB_putc(vsb, 0x11);
225 42
                        l += 0x0c;
226 42
                } else
227 0
                        WRONG("proto");
228
229 84
                vbe16enc(&le, l);
230 84
                assert(sizeof(le) == 2);
231 84
                VSB_bcat(vsb, &le, 2);
232 84
                vpx_enc_addr(vsb, proto, sac);
233 84
                vpx_enc_addr(vsb, proto, sas);
234 84
                vpx_enc_port(vsb, sac);
235 84
                vpx_enc_port(vsb, sas);
236 84
        } else
237 0
                WRONG("Wrong proxy version");
238
239 273
        AZ(VSB_finish(vsb));
240 273
        i = VSB_tofile(vsb, fd);
241 273
        VSB_destroy(&vsb);
242 273
        if (i != 0 && tlv != NULL)
243 0
                VSB_destroy(&tlv);
244 273
        if (i != 0 || tlv == NULL)
245 0
                return (i);
246
247 273
        i = VSB_tofile(tlv, fd);
248 273
        VSB_destroy(&tlv);
249 273
        return (i);
250 273
}