Home | History | Annotate | Line # | Download | only in util
      1 /*
      2  * util/proxy_protocol.h - PROXY protocol
      3  *
      4  * Copyright (c) 2022, NLnet Labs. All rights reserved.
      5  *
      6  * This software is open source.
      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  *
     12  * Redistributions of source code must retain the above copyright notice,
     13  * this list of conditions and the following disclaimer.
     14  *
     15  * Redistributions in binary form must reproduce the above copyright notice,
     16  * this list of conditions and the following disclaimer in the documentation
     17  * and/or other materials provided with the distribution.
     18  *
     19  * Neither the name of the NLNET LABS nor the names of its contributors may
     20  * be used to endorse or promote products derived from this software without
     21  * specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
     29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34  */
     35 
     36 /**
     37  * \file
     38  *
     39  * This file contains PROXY protocol structs and functions.
     40  * Only v2 is supported. TLVs are not currently supported.
     41  */
     42 #ifndef PROXY_PROTOCOL_H
     43 #define PROXY_PROTOCOL_H
     44 
     45 #include "config.h"
     46 
     47 /** PROXYv2 minimum header size */
     48 #define PP2_HEADER_SIZE 16
     49 
     50 /** PROXYv2 header signature */
     51 #define PP2_SIG "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"
     52 #define PP2_SIG_LEN 12
     53 
     54 /** PROXYv2 version (protocol value) */
     55 #define PP2_VERSION 0x2
     56 
     57 /**
     58  * PROXYv2 command (protocol value).
     59  */
     60 enum pp2_command {
     61 	PP2_CMD_LOCAL = 0x0,
     62 	PP2_CMD_PROXY = 0x1
     63 };
     64 
     65 /**
     66  * PROXYv2 address family (protocol value).
     67  */
     68 enum pp2_af {
     69 	PP2_AF_UNSPEC = 0x0,
     70 	PP2_AF_INET = 0x1,
     71 	PP2_AF_INET6 = 0x2,
     72 	PP2_AF_UNIX = 0x3
     73 };
     74 
     75 /**
     76  * PROXYv2 protocol (protocol value).
     77  */
     78 enum pp2_protocol {
     79 	PP2_PROT_UNSPEC = 0x0,
     80 	PP2_PROT_STREAM = 0x1,
     81 	PP2_PROT_DGRAM = 0x2
     82 };
     83 
     84 /**
     85  * Expected combinations of address family and protocol values used in checks.
     86  */
     87 enum pp2_af_protocol_combination {
     88 	PP2_UNSPEC_UNSPEC = (PP2_AF_UNSPEC<<4)|PP2_PROT_UNSPEC,
     89 	PP2_INET_STREAM = (PP2_AF_INET<<4)|PP2_PROT_STREAM,
     90 	PP2_INET_DGRAM = (PP2_AF_INET<<4)|PP2_PROT_DGRAM,
     91 	PP2_INET6_STREAM = (PP2_AF_INET6<<4)|PP2_PROT_STREAM,
     92 	PP2_INET6_DGRAM = (PP2_AF_INET6<<4)|PP2_PROT_DGRAM,
     93 	PP2_UNIX_STREAM = (PP2_AF_UNIX<<4)|PP2_PROT_STREAM,
     94 	PP2_UNIX_DGRAM = (PP2_AF_UNIX<<4)|PP2_PROT_DGRAM
     95 };
     96 
     97 /**
     98  * PROXYv2 header.
     99  */
    100 struct pp2_header {
    101 	uint8_t sig[PP2_SIG_LEN];
    102 	uint8_t ver_cmd;
    103 	uint8_t fam_prot;
    104 	uint16_t len;
    105 	union {
    106 		struct {  /* for TCP/UDP over IPv4, len = 12 */
    107 			uint32_t src_addr;
    108 			uint32_t dst_addr;
    109 			uint16_t src_port;
    110 			uint16_t dst_port;
    111 		} addr4;
    112 		struct {  /* for TCP/UDP over IPv6, len = 36 */
    113 			uint8_t  src_addr[16];
    114 			uint8_t  dst_addr[16];
    115 			uint16_t src_port;
    116 			uint16_t dst_port;
    117 		} addr6;
    118 		struct {  /* for AF_UNIX sockets, len = 216 */
    119 			uint8_t src_addr[108];
    120 			uint8_t dst_addr[108];
    121 		} addru;
    122 	} addr;
    123 };
    124 
    125 /**
    126  * PROXY parse errors.
    127  */
    128 enum pp_parse_errors {
    129 	PP_PARSE_NOERROR = 0,
    130 	PP_PARSE_SIZE,
    131 	PP_PARSE_WRONG_HEADERv2,
    132 	PP_PARSE_UNKNOWN_CMD,
    133 	PP_PARSE_UNKNOWN_FAM_PROT,
    134 };
    135 
    136 /**
    137  * Initialize the internal proxy structure.
    138  * @param write_uint16: pointer to a function that can write uint16.
    139  * @param write_uint32: pointer to a function that can write uint32.
    140  */
    141 void pp_init(void (*write_uint16)(void* buf, uint16_t data),
    142 	void (*write_uint32)(void* buf, uint32_t data));
    143 
    144 /**
    145  * Lookup the parsing error description.
    146  * @param error: parsing error from pp2_read_header.
    147  * @return the description.
    148  */
    149 const char* pp_lookup_error(enum pp_parse_errors error);
    150 
    151 /**
    152  * Write a PROXYv2 header at the current position of the buffer.
    153  * @param buf: pointer to the buffer to write data to.
    154  * @param buflen: available size on the buffer.
    155  * @param src: the source address.
    156  * @param stream: if the protocol is stream or datagram.
    157  * @return 1 on success, 0 on failure.
    158  */
    159 size_t pp2_write_to_buf(uint8_t* buf, size_t buflen,
    160 #ifdef INET6
    161 	struct sockaddr_storage* src,
    162 #else
    163 	struct sockaddr_in* src,
    164 #endif
    165 	int stream);
    166 
    167 /**
    168  * Read a PROXYv2 header from the current position of the buffer.
    169  * It does initial validation and returns a pointer to the buffer position on
    170  * success.
    171  * @param buf: pointer to the buffer data to read from.
    172  * @param buflen: available size on the buffer.
    173  * @return parsing error, 0 on success.
    174  */
    175 int pp2_read_header(uint8_t* buf, size_t buflen);
    176 
    177 #endif /* PROXY_PROTOCOL_H */
    178