1 //-------------------------------------------------------------------------- 2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved. 3 // 4 // This program is free software; you can redistribute it and/or modify it 5 // under the terms of the GNU General Public License Version 2 as published 6 // by the Free Software Foundation. You may not use, modify or distribute 7 // this program under any other version of the GNU General Public License. 8 // 9 // This program is distributed in the hope that it will be useful, but 10 // WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 // General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License along 15 // with this program; if not, write to the Free Software Foundation, Inc., 16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 //-------------------------------------------------------------------------- 18 // tcp_options.h author Josh Rosenbaum <jrosenba@cisco.com> 19 20 #ifndef PROTOCOLS_TCP_OPTIONS_H 21 #define PROTOCOLS_TCP_OPTIONS_H 22 23 #include "main/snort_types.h" 24 25 namespace snort 26 { 27 struct Packet; 28 29 namespace tcp 30 { 31 struct TCPHdr; 32 33 /* http://www.iana.org/assignments/tcp-parameters 34 * 35 * tcp options stuff. used to be in <netinet/tcp.h> but it breaks 36 * things on AIX 37 */ 38 39 enum class TcpOptCode : std::uint8_t 40 { 41 EOL = 0, /* End of Option List [RFC793] */ 42 NOP = 1, /* No-Option [RFC793] */ 43 MAXSEG = 2, /* Maximum Segment Size [RFC793] */ 44 WSCALE = 3, /* Window scaling option [RFC1323] */ 45 SACKOK = 4, /* Experimental [RFC2018]*/ 46 SACK = 5, /* Experimental [RFC2018] variable length */ 47 ECHO = 6, /* Echo (obsoleted by option 8) [RFC1072] */ 48 ECHOREPLY = 7, /* Echo Reply (obsoleted by option 8)[RFC1072] */ 49 TIMESTAMP = 8, /* Timestamp [RFC1323], 10 bytes */ 50 PARTIAL_PERM = 9, /* Partial Order Permitted/ Experimental [RFC1693] */ 51 PARTIAL_SVC = 10, /* Partial Order Profile [RFC1693] */ 52 CC = 11, /* T/TCP Connection count [RFC1644] */ 53 CC_NEW = 12, /* CC.NEW [RFC1644] */ 54 CC_ECHO = 13, /* CC.ECHO [RFC1644] */ 55 56 ALTCSUM = 15, /* TCP Alternate Checksum Data [RFC1146], variable length */ 57 SKEETER = 16, /* Skeeter [Knowles] */ 58 BUBBA = 17, /* Bubba [Knowles] */ 59 TRAILER_CSUM = 18, /* Trailer Checksum Option [Subbu & Monroe] */ 60 MD5SIG = 19, /* MD5 Signature Option [RFC2385] */ 61 62 /* Space Communications Protocol Standardization */ 63 SCPS = 20, /* Capabilities [Scott] */ 64 SELNEGACK = 21, /* Selective Negative Acknowledgements [Scott] */ 65 RECORDBOUND = 22, /* Record Boundaries [Scott] */ 66 CORRUPTION = 23, /* Corruption experienced [Scott] */ 67 SNAP = 24, /* SNAP [Sukonnik] -- anyone have info?*/ 68 UNASSIGNED = 25, /* Unassigned (released 12/18/00) */ 69 COMPRESSION = 26, /* TCP Compression Filter [Bellovin] */ 70 /* http://www.research.att.com/~smb/papers/draft-bellovin-tcpcomp-00.txt*/ 71 72 AUTH = 29, /* [RFC5925] - The TCP Authentication Option 73 Intended to replace MD5 Signature Option [RFC2385] */ 74 }; 75 76 /* Associated lengths */ 77 const uint8_t TCPOLEN_EOL = 1; /* Always one byte - [RFC793]*/ 78 const uint8_t TCPOLEN_NOP = 1; /* Always one byte - [RFC793]*/ 79 const uint8_t TCPOLEN_MAXSEG = 4; /* Always 4 bytes - [RFC793] */ 80 const uint8_t TCPOLEN_WSCALE = 3; /* 1 byte with logarithmic values - [RFC1323]*/ 81 const uint8_t TCPOLEN_SACKOK = 2; /* Experimental [RFC2018]*/ 82 const uint8_t TCPOLEN_ECHO = 6; /* 6 bytes - Echo (obsoleted by option 8) [RFC1072] */ 83 const uint8_t TCPOLEN_ECHOREPLY = 6; /* 6 bytes - Echo Reply (obsoleted by option 8)[RFC1072]*/ 84 const uint8_t TCPOLEN_TIMESTAMP = 10; /* Timestamp [RFC1323], 10 bytes */ 85 const uint8_t TCPOLEN_PARTIAL_PERM = 2; /* Partial Order Permitted/ Experimental [RFC1693] */ 86 const uint8_t TCPOLEN_PARTIAL_SVC = 3; /* 3 bytes long -- Experimental - [RFC1693] */ 87 88 /* at least decode T/TCP options... */ 89 const uint8_t TCPOLEN_CC = 6; /* page 17 of rfc1644 */ 90 const uint8_t TCPOLEN_CC_NEW = 6; /* page 17 of rfc1644 */ 91 const uint8_t TCPOLEN_CC_ECHO = 6; /* page 17 of rfc1644 */ 92 93 const uint8_t TCPOLEN_TRAILER_CSUM = 3; 94 const uint8_t TCPOLEN_MD5SIG = 18; 95 96 // FIXIT-L reduce all these classes to a simple pointer based approach 97 // that doesn't require any reinterpret casts (see also ipv4_options.h) 98 struct TcpOption 99 { 100 TcpOptCode code; 101 uint8_t len; 102 uint8_t data[40]; // maximum possible 103 get_lenTcpOption104 inline uint8_t get_len() const 105 { return ((uint8_t)code <= 1) ? 1 : len; } 106 get_dataTcpOption107 inline const uint8_t* get_data() const 108 { return ((uint8_t)code <= 1 || len < 2) ? nullptr : &data[0]; } 109 nextTcpOption110 inline const TcpOption& next() const 111 { 112 if ( (uint8_t)code <= 1 ) 113 return reinterpret_cast<const TcpOption&>(len); 114 else 115 return reinterpret_cast<const TcpOption&>(data[len -2]); 116 } 117 }; 118 119 class TcpOptIterator; 120 121 /* 122 * Use TcpOptIterator ... this should NOT be called directly 123 * unless you want to an actual iterator or some buggy code. 124 */ 125 class SO_PUBLIC TcpOptIteratorIter 126 { 127 public: 128 TcpOptIteratorIter(const TcpOption*, const TcpOptIterator*); 129 130 bool operator==(const TcpOptIteratorIter& rhs) 131 { return opt == rhs.opt; } 132 133 bool operator!=(const TcpOptIteratorIter& rhs) 134 { return opt != rhs.opt; } 135 136 const TcpOptIteratorIter& operator++(); 137 const TcpOption& operator*() const; 138 139 private: 140 const TcpOption* opt; 141 const TcpOptIterator* iter; 142 }; 143 144 /* 145 * Use IP ranged for loop rather than calling this directly. 146 * i.e., 147 * IpOptionIter iter(tcph, p) 148 * for (const TcpOption& opt : iter) 149 * { 150 * do_something 151 * } 152 */ 153 class SO_PUBLIC TcpOptIterator 154 { 155 public: 156 /* CONSTRUCTOR VALID AFTER DECODE() 157 * Some options in the provided header may not be valid. 158 * Provide the packet struct ensures only valid options 159 * will be returned 160 */ 161 TcpOptIterator(const TCPHdr* const, const Packet* const); 162 /* If you already know the validated option length (for instance, 163 * if you are in a decode() method), then call this constructor.*/ 164 TcpOptIterator(const TCPHdr* const, const uint32_t valid_hdr_len); 165 TcpOptIteratorIter begin() const; 166 TcpOptIteratorIter end() const; 167 168 private: 169 const uint8_t* start_ptr; 170 const uint8_t* end_ptr; 171 }; 172 } // namespace tcp 173 } // namespace snort 174 175 #endif 176 177