Elements.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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 
14 #include <algorithm>
15 #include <limits>
16 #include <vector>
17 
18 namespace ProxyProtocol {
19 namespace Two {
20 
22 typedef std::vector< std::pair<SBuf, FieldType> > FieldMap;
23 static 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 }
30 };
31 
32 } // namespace Two
33 
34 static Two::FieldType NameToFieldType(const SBuf &);
35 static Two::FieldType IntegerToFieldType(const SBuf &);
36 
37 } // namespace ProxyProtocol
38 
39 const SBuf &
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 
54 {
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())
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 
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 
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 
Definition: SBuf.h:93
bool atEnd() const
whether the end of the buffer has been reached
Definition: Tokenizer.h:41
const A & max(A const &lhs, A const &rhs)
bool skip(const SBuf &tokenToSkip)
Definition: Tokenizer.cc:189
const SBuf & PseudoFieldTypeToFieldName(const Two::FieldType)
Definition: Elements.cc:40
bool startsWith(const SBuf &S, const SBufCaseSensitive isCaseSensitive=caseSensitive) const
Definition: SBuf.cc:442
static const FieldMap PseudoHeaderFields
Definition: Elements.cc:23
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
Definition: TextException.h:63
Two::FieldType FieldNameToFieldType(const SBuf &nameOrId)
Definition: Elements.cc:102
#define assert(EX)
Definition: assert.h:17
static const CharacterSet DIGIT
Definition: CharacterSet.h:84
bool int64(int64_t &result, int base=0, bool allowSign=true, SBuf::size_type limit=SBuf::npos)
Definition: Tokenizer.cc:238
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
#define Must(condition)
Definition: TextException.h:75
std::vector< std::pair< SBuf, FieldType > > FieldMap
a mapping between pseudo header names and ids
Definition: Elements.cc:22
bool skipOne(const CharacterSet &discardables)
Definition: Tokenizer.cc:161
static Two::FieldType NameToFieldType(const SBuf &)
FieldNameToFieldType() helper that handles pseudo headers.
Definition: Elements.cc:53
FieldType
numeric IDs of registered PROXY protocol TLV types and pseudo headers
Definition: Elements.h:19
static Two::FieldType IntegerToFieldType(const SBuf &)
FieldNameToFieldType() helper that handles integer TLV types.
Definition: Elements.cc:73

 

Introduction

Documentation

Support

Miscellaneous