xref: /openbsd-src/usr.sbin/unbound/util/proxy_protocol.h (revision 9c7f0a49a49eaaf8a541e2c1c60150e851bc44d2)
10e9b6f9fSsthen /*
20e9b6f9fSsthen  * util/proxy_protocol.h - PROXY protocol
30e9b6f9fSsthen  *
40e9b6f9fSsthen  * Copyright (c) 2022, NLnet Labs. All rights reserved.
50e9b6f9fSsthen  *
60e9b6f9fSsthen  * This software is open source.
70e9b6f9fSsthen  *
80e9b6f9fSsthen  * Redistribution and use in source and binary forms, with or without
90e9b6f9fSsthen  * modification, are permitted provided that the following conditions
100e9b6f9fSsthen  * are met:
110e9b6f9fSsthen  *
120e9b6f9fSsthen  * Redistributions of source code must retain the above copyright notice,
130e9b6f9fSsthen  * this list of conditions and the following disclaimer.
140e9b6f9fSsthen  *
150e9b6f9fSsthen  * Redistributions in binary form must reproduce the above copyright notice,
160e9b6f9fSsthen  * this list of conditions and the following disclaimer in the documentation
170e9b6f9fSsthen  * and/or other materials provided with the distribution.
180e9b6f9fSsthen  *
190e9b6f9fSsthen  * Neither the name of the NLNET LABS nor the names of its contributors may
200e9b6f9fSsthen  * be used to endorse or promote products derived from this software without
210e9b6f9fSsthen  * specific prior written permission.
220e9b6f9fSsthen  *
230e9b6f9fSsthen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
240e9b6f9fSsthen  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
250e9b6f9fSsthen  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
260e9b6f9fSsthen  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
270e9b6f9fSsthen  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
280e9b6f9fSsthen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
290e9b6f9fSsthen  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
300e9b6f9fSsthen  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
310e9b6f9fSsthen  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
320e9b6f9fSsthen  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
330e9b6f9fSsthen  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
340e9b6f9fSsthen  */
350e9b6f9fSsthen 
360e9b6f9fSsthen /**
370e9b6f9fSsthen  * \file
380e9b6f9fSsthen  *
390e9b6f9fSsthen  * This file contains PROXY protocol structs and functions.
400e9b6f9fSsthen  * Only v2 is supported. TLVs are not currently supported.
410e9b6f9fSsthen  */
420e9b6f9fSsthen #ifndef PROXY_PROTOCOL_H
430e9b6f9fSsthen #define PROXY_PROTOCOL_H
440e9b6f9fSsthen 
45*9c7f0a49Ssthen #include "config.h"
460e9b6f9fSsthen 
470e9b6f9fSsthen /** PROXYv2 minimum header size */
480e9b6f9fSsthen #define PP2_HEADER_SIZE 16
490e9b6f9fSsthen 
500e9b6f9fSsthen /** PROXYv2 header signature */
510e9b6f9fSsthen #define PP2_SIG "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
520e9b6f9fSsthen #define PP2_SIG_LEN 12
530e9b6f9fSsthen 
54*9c7f0a49Ssthen /** PROXYv2 version (protocol value) */
550e9b6f9fSsthen #define PP2_VERSION 0x2
560e9b6f9fSsthen 
570e9b6f9fSsthen /**
58*9c7f0a49Ssthen  * PROXYv2 command (protocol value).
590e9b6f9fSsthen  */
600e9b6f9fSsthen enum pp2_command {
610e9b6f9fSsthen 	PP2_CMD_LOCAL = 0x0,
620e9b6f9fSsthen 	PP2_CMD_PROXY = 0x1
630e9b6f9fSsthen };
640e9b6f9fSsthen 
650e9b6f9fSsthen /**
66*9c7f0a49Ssthen  * PROXYv2 address family (protocol value).
670e9b6f9fSsthen  */
680e9b6f9fSsthen enum pp2_af {
690e9b6f9fSsthen 	PP2_AF_UNSPEC = 0x0,
700e9b6f9fSsthen 	PP2_AF_INET = 0x1,
710e9b6f9fSsthen 	PP2_AF_INET6 = 0x2,
720e9b6f9fSsthen 	PP2_AF_UNIX = 0x3
730e9b6f9fSsthen };
740e9b6f9fSsthen 
750e9b6f9fSsthen /**
76*9c7f0a49Ssthen  * PROXYv2 protocol (protocol value).
770e9b6f9fSsthen  */
780e9b6f9fSsthen enum pp2_protocol {
790e9b6f9fSsthen 	PP2_PROT_UNSPEC = 0x0,
800e9b6f9fSsthen 	PP2_PROT_STREAM = 0x1,
810e9b6f9fSsthen 	PP2_PROT_DGRAM = 0x2
820e9b6f9fSsthen };
830e9b6f9fSsthen 
840e9b6f9fSsthen /**
85*9c7f0a49Ssthen  * Expected combinations of address family and protocol values used in checks.
86*9c7f0a49Ssthen  */
87*9c7f0a49Ssthen enum pp2_af_protocol_combination {
88*9c7f0a49Ssthen 	PP2_UNSPEC_UNSPEC = (PP2_AF_UNSPEC<<4)|PP2_PROT_UNSPEC,
89*9c7f0a49Ssthen 	PP2_INET_STREAM = (PP2_AF_INET<<4)|PP2_PROT_STREAM,
90*9c7f0a49Ssthen 	PP2_INET_DGRAM = (PP2_AF_INET<<4)|PP2_PROT_DGRAM,
91*9c7f0a49Ssthen 	PP2_INET6_STREAM = (PP2_AF_INET6<<4)|PP2_PROT_STREAM,
92*9c7f0a49Ssthen 	PP2_INET6_DGRAM = (PP2_AF_INET6<<4)|PP2_PROT_DGRAM,
93*9c7f0a49Ssthen 	PP2_UNIX_STREAM = (PP2_AF_UNIX<<4)|PP2_PROT_STREAM,
94*9c7f0a49Ssthen 	PP2_UNIX_DGRAM = (PP2_AF_UNIX<<4)|PP2_PROT_DGRAM
95*9c7f0a49Ssthen };
96*9c7f0a49Ssthen 
97*9c7f0a49Ssthen /**
980e9b6f9fSsthen  * PROXYv2 header.
990e9b6f9fSsthen  */
1000e9b6f9fSsthen struct pp2_header {
1010e9b6f9fSsthen 	uint8_t sig[PP2_SIG_LEN];
1020e9b6f9fSsthen 	uint8_t ver_cmd;
1030e9b6f9fSsthen 	uint8_t fam_prot;
1040e9b6f9fSsthen 	uint16_t len;
1050e9b6f9fSsthen 	union {
1060e9b6f9fSsthen 		struct {  /* for TCP/UDP over IPv4, len = 12 */
1070e9b6f9fSsthen 			uint32_t src_addr;
1080e9b6f9fSsthen 			uint32_t dst_addr;
1090e9b6f9fSsthen 			uint16_t src_port;
1100e9b6f9fSsthen 			uint16_t dst_port;
1110e9b6f9fSsthen 		} addr4;
1120e9b6f9fSsthen 		struct {  /* for TCP/UDP over IPv6, len = 36 */
1130e9b6f9fSsthen 			uint8_t  src_addr[16];
1140e9b6f9fSsthen 			uint8_t  dst_addr[16];
1150e9b6f9fSsthen 			uint16_t src_port;
1160e9b6f9fSsthen 			uint16_t dst_port;
1170e9b6f9fSsthen 		} addr6;
1180e9b6f9fSsthen 		struct {  /* for AF_UNIX sockets, len = 216 */
1190e9b6f9fSsthen 			uint8_t src_addr[108];
1200e9b6f9fSsthen 			uint8_t dst_addr[108];
1210e9b6f9fSsthen 		} addru;
1220e9b6f9fSsthen 	} addr;
1230e9b6f9fSsthen };
1240e9b6f9fSsthen 
1250e9b6f9fSsthen /**
126*9c7f0a49Ssthen  * PROXY parse errors.
127*9c7f0a49Ssthen  */
128*9c7f0a49Ssthen enum pp_parse_errors {
129*9c7f0a49Ssthen 	PP_PARSE_NOERROR = 0,
130*9c7f0a49Ssthen 	PP_PARSE_SIZE,
131*9c7f0a49Ssthen 	PP_PARSE_WRONG_HEADERv2,
132*9c7f0a49Ssthen 	PP_PARSE_UNKNOWN_CMD,
133*9c7f0a49Ssthen 	PP_PARSE_UNKNOWN_FAM_PROT,
134*9c7f0a49Ssthen };
135*9c7f0a49Ssthen 
136*9c7f0a49Ssthen /**
137*9c7f0a49Ssthen  * Initialize the internal proxy structure.
138*9c7f0a49Ssthen  * @param write_uint16: pointer to a function that can write uint16.
139*9c7f0a49Ssthen  * @param write_uint32: pointer to a function that can write uint32.
140*9c7f0a49Ssthen  */
141*9c7f0a49Ssthen void pp_init(void (*write_uint16)(void* buf, uint16_t data),
142*9c7f0a49Ssthen 	void (*write_uint32)(void* buf, uint32_t data));
143*9c7f0a49Ssthen 
144*9c7f0a49Ssthen /**
145*9c7f0a49Ssthen  * Lookup the parsing error description.
146*9c7f0a49Ssthen  * @param error: parsing error from pp2_read_header.
147*9c7f0a49Ssthen  * @return the description.
148*9c7f0a49Ssthen  */
149*9c7f0a49Ssthen const char* pp_lookup_error(enum pp_parse_errors error);
150*9c7f0a49Ssthen 
151*9c7f0a49Ssthen /**
1520e9b6f9fSsthen  * Write a PROXYv2 header at the current position of the buffer.
153*9c7f0a49Ssthen  * @param buf: pointer to the buffer to write data to.
154*9c7f0a49Ssthen  * @param buflen: available size on the buffer.
1550e9b6f9fSsthen  * @param src: the source address.
1560e9b6f9fSsthen  * @param stream: if the protocol is stream or datagram.
1570e9b6f9fSsthen  * @return 1 on success, 0 on failure.
1580e9b6f9fSsthen  */
159*9c7f0a49Ssthen size_t pp2_write_to_buf(uint8_t* buf, size_t buflen,
160*9c7f0a49Ssthen #ifdef INET6
161*9c7f0a49Ssthen 	struct sockaddr_storage* src,
162*9c7f0a49Ssthen #else
163*9c7f0a49Ssthen 	struct sockaddr_in* src,
164*9c7f0a49Ssthen #endif
1650e9b6f9fSsthen 	int stream);
1660e9b6f9fSsthen 
1670e9b6f9fSsthen /**
1680e9b6f9fSsthen  * Read a PROXYv2 header from the current position of the buffer.
1690e9b6f9fSsthen  * It does initial validation and returns a pointer to the buffer position on
1700e9b6f9fSsthen  * success.
171*9c7f0a49Ssthen  * @param buf: pointer to the buffer data to read from.
172*9c7f0a49Ssthen  * @param buflen: available size on the buffer.
173*9c7f0a49Ssthen  * @return parsing error, 0 on success.
1740e9b6f9fSsthen  */
175*9c7f0a49Ssthen int pp2_read_header(uint8_t* buf, size_t buflen);
1760e9b6f9fSsthen 
1770e9b6f9fSsthen #endif /* PROXY_PROTOCOL_H */
178