Coverage Report

Created: 2025-11-16 07:09

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
220k
{
47
220k
    if (unlikely(len < UDP_HEADER_LEN)) {
48
841
        ENGINE_SET_INVALID_EVENT(p, UDP_HLEN_TOO_SMALL);
49
841
        return -1;
50
841
    }
51
52
220k
    p->udph = (UDPHdr *)pkt;
53
54
220k
    if (unlikely(len < UDP_GET_LEN(p))) {
55
9.06k
        ENGINE_SET_INVALID_EVENT(p, UDP_PKT_TOO_SMALL);
56
9.06k
        return -1;
57
9.06k
    }
58
59
211k
    if (unlikely(UDP_GET_LEN(p) < UDP_HEADER_LEN)) {
60
1.99k
        ENGINE_SET_INVALID_EVENT(p, UDP_LEN_INVALID);
61
1.99k
        return -1;
62
1.99k
    }
63
64
209k
    SET_UDP_SRC_PORT(p,&p->sp);
65
209k
    SET_UDP_DST_PORT(p,&p->dp);
66
67
209k
    p->payload = (uint8_t *)pkt + UDP_HEADER_LEN;
68
209k
    p->payload_len = UDP_GET_LEN(p) - UDP_HEADER_LEN;
69
70
209k
    p->proto = IPPROTO_UDP;
71
72
209k
    return 0;
73
211k
}
74
75
int DecodeUDP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
76
        const uint8_t *pkt, uint16_t len)
77
220k
{
78
220k
    StatsIncr(tv, dtv->counter_udp);
79
80
220k
    if (unlikely(DecodeUDPPacket(tv, p, pkt,len) < 0)) {
81
11.9k
        CLEAR_UDP_PACKET(p);
82
11.9k
        return TM_ECODE_FAILED;
83
11.9k
    }
84
85
209k
    SCLogDebug("UDP sp: %" PRIu32 " -> dp: %" PRIu32 " - HLEN: %" PRIu32 " LEN: %" PRIu32 "",
86
209k
        UDP_GET_SRC_PORT(p), UDP_GET_DST_PORT(p), UDP_HEADER_LEN, p->payload_len);
87
88
209k
    if (DecodeTeredoEnabledForPort(p->sp, p->dp) &&
89
209k
            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.25k
        FlowSetupPacket(p);
93
1.25k
        return TM_ECODE_OK;
94
1.25k
    }
95
96
    /* Handle Geneve if configured */
97
207k
    if (DecodeGeneveEnabledForPort(p->sp, p->dp) &&
98
5.10k
            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.32k
        FlowSetupPacket(p);
102
2.32k
        return TM_ECODE_OK;
103
2.32k
    }
104
105
    /* Handle VXLAN if configured */
106
205k
    if (DecodeVXLANEnabledForPort(p->sp, p->dp) &&
107
5.18k
            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.26k
        FlowSetupPacket(p);
111
3.26k
        return TM_ECODE_OK;
112
3.26k
    }
113
114
202k
    FlowSetupPacket(p);
115
116
202k
    return TM_ECODE_OK;
117
205k
}
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
 */