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