varnish-cache/bin/varnishtest/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 <sys/socket.h>
33
34
#include <netinet/in.h>
35
36
#include <unistd.h>
37
38
#include "vtc.h"
39
40
#include "vend.h"
41
#include "vsa.h"
42
#include "vtcp.h"
43
44
static const char vpx1_sig[] = {'P', 'R', 'O', 'X', 'Y'};
45
static const char vpx2_sig[] = {
46
        '\r', '\n', '\r', '\n', '\0', '\r', '\n',
47
        'Q', 'U', 'I', 'T', '\n',
48
};
49
50
static void
51 160
vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s)
52
{
53
        const struct sockaddr_in *sin4;
54
        const struct sockaddr_in6 *sin6;
55
        socklen_t sl;
56
57 160
        if (proto == PF_INET6) {
58 80
                sin6 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
59 80
                AN(sin6);
60 80
                assert(sl >= sizeof(*sin6));
61 80
                VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
62 80
        } else {
63 80
                sin4 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
64 80
                AN(sin4);
65 80
                assert(sl >= sizeof(*sin4));
66 80
                VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr));
67
        }
68 160
}
69
70
static void
71 160
vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
72
{
73
        uint8_t b[2];
74
75 160
        vbe16enc(b, (uint16_t)VSA_Port(s));
76 160
        VSB_bcat(vsb, b, sizeof(b));
77 160
}
78
79
int
80 400
vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
81
    const struct suckaddr *sas)
82
{
83
        struct vsb *vsb;
84
        char hc[VTCP_ADDRBUFSIZE];
85
        char pc[VTCP_PORTBUFSIZE];
86
        char hs[VTCP_ADDRBUFSIZE];
87
        char ps[VTCP_PORTBUFSIZE];
88
        int i;
89
        int proto;
90
91 400
        AN(sac);
92 400
        AN(sas);
93
94 400
        assert(version == 1 || version == 2);
95 400
        vsb = VSB_new_auto();
96 400
        AN(vsb);
97
98 400
        proto = VSA_Get_Proto(sas);
99 400
        assert(proto == PF_INET6 || proto == PF_INET);
100
101 400
        if (version == 1) {
102 320
                VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
103 320
                if (proto == PF_INET6)
104 160
                        VSB_cat(vsb, " TCP6 ");
105 160
                else if (proto == PF_INET)
106 160
                        VSB_cat(vsb, " TCP4 ");
107 320
                VTCP_name(sac, hc, sizeof(hc), pc, sizeof(pc));
108 320
                VTCP_name(sas, hs, sizeof(hs), ps, sizeof(ps));
109 320
                VSB_printf(vsb, "%s %s %s %s\r\n", hc, hs, pc, ps);
110 400
        } else if (version == 2) {
111 80
                VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
112 80
                VSB_putc(vsb, 0x21);
113 80
                if (proto == PF_INET6) {
114 40
                        VSB_putc(vsb, 0x21);
115 40
                        VSB_putc(vsb, 0x00);
116 40
                        VSB_putc(vsb, 0x24);
117 80
                } else if (proto == PF_INET) {
118 40
                        VSB_putc(vsb, 0x11);
119 40
                        VSB_putc(vsb, 0x00);
120 40
                        VSB_putc(vsb, 0x0c);
121 40
                }
122 80
                vpx_enc_addr(vsb, proto, sac);
123 80
                vpx_enc_addr(vsb, proto, sas);
124 80
                vpx_enc_port(vsb, sac);
125 80
                vpx_enc_port(vsb, sas);
126 80
        } else
127 0
                WRONG("Wrong proxy version");
128
129 400
        AZ(VSB_finish(vsb));
130 400
        i = VSB_tofile(vsb, fd);
131 400
        VSB_destroy(&vsb);
132 400
        return (i);
133
}