]> git.ipfire.org Git - thirdparty/squid.git/blame - src/proxyp/Elements.cc
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / proxyp / Elements.cc
CommitLineData
36c774f7 1/*
b8ae064d 2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
36c774f7
EB
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10#include "parser/Tokenizer.h"
11#include "proxyp/Elements.h"
12#include "sbuf/Stream.h"
13
e015580e 14#include <algorithm>
36c774f7 15#include <limits>
e015580e 16#include <vector>
36c774f7 17
e015580e
EB
18namespace ProxyProtocol {
19namespace Two {
20
21/// a mapping between pseudo header names and ids
22typedef std::vector< std::pair<SBuf, FieldType> > FieldMap;
23static const FieldMap PseudoHeaderFields = {
24 { SBuf(":version"), htPseudoVersion },
25 { SBuf(":command"), htPseudoCommand },
26 { SBuf(":src_addr"), htPseudoSrcAddr },
27 { SBuf(":dst_addr"), htPseudoDstAddr },
28 { SBuf(":src_port"), htPseudoSrcPort },
29 { SBuf(":dst_port"), htPseudoDstPort }
36c774f7
EB
30};
31
e015580e
EB
32} // namespace Two
33
36c774f7
EB
34static Two::FieldType NameToFieldType(const SBuf &);
35static Two::FieldType IntegerToFieldType(const SBuf &);
e015580e 36
36c774f7
EB
37} // namespace ProxyProtocol
38
e015580e
EB
39const SBuf &
40ProxyProtocol::PseudoFieldTypeToFieldName(const Two::FieldType fieldType)
41{
42 const auto it = std::find_if(Two::PseudoHeaderFields.begin(), Two::PseudoHeaderFields.end(),
43 [fieldType](const Two::FieldMap::value_type &item) {
44 return item.second == fieldType;
45 });
46
47 assert(it != Two::PseudoHeaderFields.end());
48 return it->first;
49}
50
36c774f7
EB
51/// FieldNameToFieldType() helper that handles pseudo headers
52ProxyProtocol::Two::FieldType
53ProxyProtocol::NameToFieldType(const SBuf &name)
54{
e015580e
EB
55 const auto it = std::find_if(Two::PseudoHeaderFields.begin(), Two::PseudoHeaderFields.end(),
56 [&name](const Two::FieldMap::value_type &item) {
57 return item.first == name;
58 });
59
60 if (it != Two::PseudoHeaderFields.end())
36c774f7
EB
61 return it->second;
62
63 static const SBuf pseudoMark(":");
64 if (name.startsWith(pseudoMark))
65 throw TexcHere(ToSBuf("Unsupported PROXY protocol pseudo header: ", name));
66
67 throw TexcHere(ToSBuf("Invalid PROXY protocol pseudo header or TLV type name. ",
68 "Expected a pseudo header like :src_addr but got '", name, "'"));
69}
70
71/// FieldNameToFieldType() helper that handles integer TLV types
72ProxyProtocol::Two::FieldType
73ProxyProtocol::IntegerToFieldType(const SBuf &rawInteger)
74{
75 int64_t tlvType = 0;
76
77 Parser::Tokenizer ptok(rawInteger);
78 if (ptok.skip('0')) {
79 if (!ptok.atEnd())
80 throw TexcHere(ToSBuf("Invalid PROXY protocol TLV type value. ",
81 "Expected a decimal integer without leading zeros but got '",
82 rawInteger, "'")); // e.g., 077, 0xFF, or 0b101
83 // tlvType stays zero
84 } else {
85 Must(ptok.int64(tlvType, 10, false)); // the first character is a DIGIT
86 if (!ptok.atEnd())
87 throw TexcHere(ToSBuf("Invalid PROXY protocol TLV type value. ",
88 "Trailing garbage after ", tlvType, " in '",
89 rawInteger, "'")); // e.g., 1.0 or 5e0
90 }
91
92 const auto limit = std::numeric_limits<uint8_t>::max();
93 if (tlvType > limit)
94 throw TexcHere(ToSBuf("Invalid PROXY protocol TLV type value. ",
95 "Expected an integer less than ", limit,
96 " but got '", tlvType, "'"));
97
98 return Two::FieldType(tlvType);
99}
100
101ProxyProtocol::Two::FieldType
102ProxyProtocol::FieldNameToFieldType(const SBuf &tlvTypeRaw)
103{
104 // we could branch on ":" instead of DIGIT but then field names that lack a
105 // leading ":" (like "version") would get a less accurate error message
106 return Parser::Tokenizer(tlvTypeRaw).skipOne(CharacterSet::DIGIT) ?
107 IntegerToFieldType(tlvTypeRaw):
108 NameToFieldType(tlvTypeRaw);
109}
110