Coverage Report

Created: 2026-02-14 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/decode-udp.c
Line
Count
Source
1
/* Copyright (C) 2007-2020 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
 * \ingroup decode
20
 *
21
 * @{
22
 */
23
24
25
/**
26
 * \file
27
 *
28
 * \author Victor Julien <victor@inliniac.net>
29
 *
30
 * Decode UDP
31
 */
32
33
#include "suricata-common.h"
34
#include "decode.h"
35
#include "decode-geneve.h"
36
#include "decode-udp.h"
37
#include "decode-teredo.h"
38
#include "decode-vxlan.h"
39
#include "decode-events.h"
40
#include "util-unittest.h"
41
#include "util-debug.h"
42
#include "flow.h"
43
#include "app-layer.h"
44
45
static int DecodeUDPPacket(ThreadVars *t, Packet *p, const uint8_t *pkt, uint16_t len)
46
278k
{
47
278k
    if (unlikely(len < UDP_HEADER_LEN)) {
48
909
        ENGINE_SET_INVALID_EVENT(p, UDP_HLEN_TOO_SMALL);
49
909
        return -1;
50
909
    }
51
52
277k
    p->udph = (UDPHdr *)pkt;
53
54
277k
    if (unlikely(len < UDP_GET_LEN(p))) {
55
10.4k
        ENGINE_SET_INVALID_EVENT(p, UDP_PKT_TOO_SMALL);
56
10.4k
        return -1;
57
10.4k
    }
58
59
267k
    if (unlikely(UDP_GET_LEN(p) < UDP_HEADER_LEN)) {
60
2.51k
        ENGINE_SET_INVALID_EVENT(p, UDP_LEN_INVALID);
61
2.51k
        return -1;
62
2.51k
    }
63
64
265k
    SET_UDP_SRC_PORT(p,&p->sp);
65
265k
    SET_UDP_DST_PORT(p,&p->dp);
66
67
265k
    p->payload = (uint8_t *)pkt + UDP_HEADER_LEN;
68
265k
    p->payload_len = UDP_GET_LEN(p) - UDP_HEADER_LEN;
69
70
265k
    p->proto = IPPROTO_UDP;
71
72
265k
    return 0;
73
267k
}
74
75
int DecodeUDP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
76
        const uint8_t *pkt, uint16_t len)
77
278k
{
78
278k
    StatsIncr(tv, dtv->counter_udp);
79
80
278k
    if (unlikely(DecodeUDPPacket(tv, p, pkt,len) < 0)) {
81
13.8k
        CLEAR_UDP_PACKET(p);
82
13.8k
        return TM_ECODE_FAILED;
83
13.8k
    }
84
85
265k
    SCLogDebug("UDP sp: %" PRIu32 " -> dp: %" PRIu32 " - HLEN: %" PRIu32 " LEN: %" PRIu32 "",
86
265k
        UDP_GET_SRC_PORT(p), UDP_GET_DST_PORT(p), UDP_HEADER_LEN, p->payload_len);
87
88
265k
    if (DecodeTeredoEnabledForPort(p->sp, p->dp) &&
89
265k
            likely(DecodeTeredo(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) {
90
        /* Here we have a Teredo packet and don't need to handle app
91
         * layer */
92
1.23k
        FlowSetupPacket(p);
93
1.23k
        return TM_ECODE_OK;
94
1.23k
    }
95
96
    /* Handle Geneve if configured */
97
263k
    if (DecodeGeneveEnabledForPort(p->sp, p->dp) &&
98
5.50k
            unlikely(DecodeGeneve(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) {
99
        /* Here we have a Geneve packet and don't need to handle app
100
         * layer */
101
2.70k
        FlowSetupPacket(p);
102
2.70k
        return TM_ECODE_OK;
103
2.70k
    }
104
105
    /* Handle VXLAN if configured */
106
261k
    if (DecodeVXLANEnabledForPort(p->sp, p->dp) &&
107
5.59k
            unlikely(DecodeVXLAN(tv, dtv, p, p->payload, p->payload_len) == TM_ECODE_OK)) {
108
        /* Here we have a VXLAN packet and don't need to handle app
109
         * layer */
110
3.51k
        FlowSetupPacket(p);
111
3.51k
        return TM_ECODE_OK;
112
3.51k
    }
113
114
257k
    FlowSetupPacket(p);
115
116
257k
    return TM_ECODE_OK;
117
261k
}
118
119
#ifdef UNITTESTS
120
static int UDPV4CalculateValidChecksumtest01(void)
121
{
122
    uint16_t csum = 0;
123
124
    uint8_t raw_ipshdr[] = {
125
        0xd0, 0x43, 0xdc, 0xdc, 0xc0, 0xa8, 0x01, 0x3};
126
127
    uint8_t raw_udp[] = {
128
        0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0,
129
        0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
130
        0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67,
131
        0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f,
132
        0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69,
133
        0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63,
134
        0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0,
135
        0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b,
136
        0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65,
137
        0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
138
        0x67, 0x6c, 0x65, 0xc0, 0x26};
139
140
    csum = *( ((uint16_t *)raw_udp) + 3);
141
142
    FAIL_IF(UDPV4Checksum((uint16_t *) raw_ipshdr,
143
            (uint16_t *)raw_udp, sizeof(raw_udp), csum) != 0);
144
    PASS;
145
}
146
147
static int UDPV4CalculateInvalidChecksumtest02(void)
148
{
149
    uint16_t csum = 0;
150
151
    uint8_t raw_ipshdr[] = {
152
        0xd0, 0x43, 0xdc, 0xdc, 0xc0, 0xa8, 0x01, 0x3};
153
154
    uint8_t raw_udp[] = {
155
        0x00, 0x35, 0xcf, 0x34, 0x00, 0x55, 0x6c, 0xe0,
156
        0x83, 0xfc, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
157
        0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67,
158
        0x65, 0x61, 0x64, 0x32, 0x11, 0x67, 0x6f, 0x6f,
159
        0x67, 0x6c, 0x65, 0x73, 0x79, 0x6e, 0x64, 0x69,
160
        0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x03, 0x63,
161
        0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01, 0xc0,
162
        0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x4b,
163
        0x50, 0x00, 0x12, 0x06, 0x70, 0x61, 0x67, 0x65,
164
        0x61, 0x64, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
165
        0x67, 0x6c, 0x65, 0xc0, 0x27};
166
167
    csum = *( ((uint16_t *)raw_udp) + 3);
168
169
    FAIL_IF(UDPV4Checksum((uint16_t *) raw_ipshdr,
170
            (uint16_t *)raw_udp, sizeof(raw_udp), csum) == 0);
171
    PASS;
172
}
173
174
static int UDPV6CalculateValidChecksumtest03(void)
175
{
176
    uint16_t csum = 0;
177
178
    static uint8_t raw_ipv6[] = {
179
        0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
180
        0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00,
181
        0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe,
182
        0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
183
        0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
184
        0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
185
        0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
186
        0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
187
        0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
188
        0x09, 0x00};
189
190
    csum = *( ((uint16_t *)(raw_ipv6 + 60)));
191
192
    FAIL_IF(UDPV6Checksum((uint16_t *)(raw_ipv6 + 14 + 8),
193
            (uint16_t *)(raw_ipv6 + 54), 20, csum) != 0);
194
    PASS;
195
}
196
197
static int UDPV6CalculateInvalidChecksumtest04(void)
198
{
199
    uint16_t csum = 0;
200
201
    static uint8_t raw_ipv6[] = {
202
        0x00, 0x60, 0x97, 0x07, 0x69, 0xea, 0x00, 0x00,
203
        0x86, 0x05, 0x80, 0xda, 0x86, 0xdd, 0x60, 0x00,
204
        0x00, 0x00, 0x00, 0x14, 0x11, 0x02, 0x3f, 0xfe,
205
        0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
206
        0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe,
207
        0x05, 0x01, 0x04, 0x10, 0x00, 0x00, 0x02, 0xc0,
208
        0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0xa0, 0x75,
209
        0x82, 0xa0, 0x00, 0x14, 0x1a, 0xc3, 0x06, 0x02,
210
        0x00, 0x00, 0xf9, 0xc8, 0xe7, 0x36, 0x57, 0xb0,
211
        0x09, 0x01};
212
213
    csum = *( ((uint16_t *)(raw_ipv6 + 60)));
214
215
    FAIL_IF(UDPV6Checksum((uint16_t *)(raw_ipv6 + 14 + 8),
216
            (uint16_t *)(raw_ipv6 + 54), 20, csum) == 0);
217
    PASS;
218
}
219
#endif /* UNITTESTS */
220
221
void DecodeUDPV4RegisterTests(void)
222
0
{
223
#ifdef UNITTESTS
224
    UtRegisterTest("UDPV4CalculateValidChecksumtest01",
225
                   UDPV4CalculateValidChecksumtest01);
226
    UtRegisterTest("UDPV4CalculateInvalidChecksumtest02",
227
                   UDPV4CalculateInvalidChecksumtest02);
228
    UtRegisterTest("UDPV6CalculateValidChecksumtest03",
229
                   UDPV6CalculateValidChecksumtest03);
230
    UtRegisterTest("UDPV6CalculateInvalidChecksumtest04",
231
                   UDPV6CalculateInvalidChecksumtest04);
232
#endif /* UNITTESTS */
233
0
}
234
/**
235
 * @}
236
 */