suricata
decode-udp.h
Go to the documentation of this file.
1/* Copyright (C) 2007-2022 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 */
23
24#ifndef SURICATA_DECODE_UDP_H
25#define SURICATA_DECODE_UDP_H
26
27#define UDP_HEADER_LEN 8
28
29/* XXX RAW* needs to be really 'raw', so no SCNtohs there */
30#define UDP_GET_RAW_LEN(udph) SCNtohs((udph)->uh_len)
31#define UDP_GET_RAW_SRC_PORT(udph) SCNtohs((udph)->uh_sport)
32#define UDP_GET_RAW_DST_PORT(udph) SCNtohs((udph)->uh_dport)
33#define UDP_GET_RAW_SUM(udph) SCNtohs((udph)->uh_sum)
34
35#define UDP_GET_LEN(p) UDP_GET_RAW_LEN(p->udph)
36#define UDP_GET_SRC_PORT(p) UDP_GET_RAW_SRC_PORT(p->udph)
37#define UDP_GET_DST_PORT(p) UDP_GET_RAW_DST_PORT(p->udph)
38#define UDP_GET_SUM(p) UDP_GET_RAW_SUM(p->udph)
39
40/* UDP header structure */
41typedef struct UDPHdr_
42{
43 uint16_t uh_sport; /* source port */
44 uint16_t uh_dport; /* destination port */
45 uint16_t uh_len; /* length */
46 uint16_t uh_sum; /* checksum */
48
50
51/** ------ Inline function ------ */
52
53/**
54 * \brief Calculate or valid the checksum for the UDP packet
55 *
56 * \param shdr Pointer to source address field from the IP packet. Used as a
57 * part of the psuedoheader for computing the checksum
58 * \param pkt Pointer to the start of the UDP packet
59 * \param hlen Total length of the UDP packet(header + payload)
60 * \param init For validation this is the UDP checksum, for calculation this
61 * value should be set to 0.
62 *
63 * \retval csum For validation 0 will be returned for success, for calculation
64 * this will be the checksum.
65 */
66static inline uint16_t UDPV4Checksum(
67 const uint16_t *shdr, const uint16_t *pkt, uint16_t tlen, uint16_t init)
68{
69 uint16_t pad = 0;
70 uint32_t csum = init;
71
72 csum += shdr[0] + shdr[1] + shdr[2] + shdr[3] + htons(17) + htons(tlen);
73
74 csum += pkt[0] + pkt[1] + pkt[2];
75
76 tlen -= 8;
77 pkt += 4;
78
79 while (tlen >= 32) {
80 csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
81 pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
82 pkt[14] + pkt[15];
83 tlen -= 32;
84 pkt += 16;
85 }
86
87 while(tlen >= 8) {
88 csum += pkt[0] + pkt[1] + pkt[2] + pkt[3];
89 tlen -= 8;
90 pkt += 4;
91 }
92
93 while(tlen >= 4) {
94 csum += pkt[0] + pkt[1];
95 tlen -= 4;
96 pkt += 2;
97 }
98
99 while (tlen > 1) {
100 csum += pkt[0];
101 pkt += 1;
102 tlen -= 2;
103 }
104
105 if (tlen == 1) {
106 *(uint8_t *)(&pad) = (*(uint8_t *)pkt);
107 csum += pad;
108 }
109
110 csum = (csum >> 16) + (csum & 0x0000FFFF);
111 csum += (csum >> 16);
112
113 uint16_t csum_u16 = (uint16_t)~csum;
114 if (init == 0 && csum_u16 == 0)
115 return 0xFFFF;
116 else
117 return csum_u16;
118}
119
120/**
121 * \brief Calculate or valid the checksum for the UDP packet
122 *
123 * \param shdr Pointer to source address field from the IPV6 packet. Used as a
124 * part of the psuedoheader for computing the checksum
125 * \param pkt Pointer to the start of the UDP packet
126 * \param tlen Total length of the UDP packet(header + payload)
127 * \param init For validation this is the UDP checksum, for calculation this
128 * value should be set to 0.
129 *
130 * \retval csum For validation 0 will be returned for success, for calculation
131 * this will be the checksum.
132 */
133static inline uint16_t UDPV6Checksum(
134 const uint16_t *shdr, const uint16_t *pkt, uint16_t tlen, uint16_t init)
135{
136 uint16_t pad = 0;
137 uint32_t csum = init;
138
139 csum += shdr[0] + shdr[1] + shdr[2] + shdr[3] + shdr[4] + shdr[5] + shdr[6] +
140 shdr[7] + shdr[8] + shdr[9] + shdr[10] + shdr[11] + shdr[12] +
141 shdr[13] + shdr[14] + shdr[15] + htons(17) + htons(tlen);
142
143 csum += pkt[0] + pkt[1] + pkt[2];
144
145 tlen -= 8;
146 pkt += 4;
147
148 while (tlen >= 32) {
149 csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
150 pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
151 pkt[14] + pkt[15];
152 tlen -= 32;
153 pkt += 16;
154 }
155
156 while(tlen >= 8) {
157 csum += pkt[0] + pkt[1] + pkt[2] + pkt[3];
158 tlen -= 8;
159 pkt += 4;
160 }
161
162 while(tlen >= 4) {
163 csum += pkt[0] + pkt[1];
164 tlen -= 4;
165 pkt += 2;
166 }
167
168 while (tlen > 1) {
169 csum += pkt[0];
170 pkt += 1;
171 tlen -= 2;
172 }
173
174 if (tlen == 1) {
175 *(uint8_t *)(&pad) = (*(uint8_t *)pkt);
176 csum += pad;
177 }
178
179 csum = (csum >> 16) + (csum & 0x0000FFFF);
180 csum += (csum >> 16);
181
182 uint16_t csum_u16 = (uint16_t)~csum;
183 if (init == 0 && csum_u16 == 0)
184 return 0xFFFF;
185 else
186 return csum_u16;
187}
188
189#endif /* SURICATA_DECODE_UDP_H */
struct UDPHdr_ UDPHdr
void DecodeUDPV4RegisterTests(void)
Definition decode-udp.c:221
uint16_t pad
uint16_t uh_len
Definition decode-udp.h:45
uint16_t uh_sum
Definition decode-udp.h:46
uint16_t uh_dport
Definition decode-udp.h:44
uint16_t uh_sport
Definition decode-udp.h:43