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