• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 22618661228

02 Mar 2026 09:33PM UTC coverage: 42.258% (-34.4%) from 76.611%
22618661228

push

github

victorjulien
github-actions: bump actions/download-artifact from 7.0.0 to 8.0.0

Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7.0.0 to 8.0.0.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/37930b1c2...70fc10c6e)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

91511 of 216553 relevant lines covered (42.26%)

3416852.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

23.27
/src/decode-ppp.c
1
/* Copyright (C) 2007-2024 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
 * \file
26
 *
27
 * \author Breno Silva Pinto <breno.silva@gmail.com>
28
 *
29
 * Decode PPP
30
 */
31

32
#include "suricata-common.h"
33
#include "decode.h"
34
#include "decode-ppp.h"
35
#include "decode-events.h"
36

37
#include "flow.h"
38

39
#include "util-validate.h"
40
#include "util-unittest.h"
41
#include "util-debug.h"
42

43
static int DecodePPPCompressedProto(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
44
        const uint8_t *pkt, uint32_t len, uint16_t proto_offset)
45
{
1,030✔
46
    const uint32_t data_offset = proto_offset + 1;
1,030✔
47
    switch (*(pkt + proto_offset)) {
1,030✔
48
        case 0x21: { /* PPP_IP */
1,027✔
49
            if (unlikely(len < (data_offset + IPV4_HEADER_LEN))) {
1,027✔
50
                ENGINE_SET_INVALID_EVENT(p, PPPVJU_PKT_TOO_SMALL);
×
51
                return TM_ECODE_FAILED;
×
52
            }
×
53
            DEBUG_VALIDATE_BUG_ON(len < data_offset);
1,027✔
54
            uint16_t iplen = (uint16_t)MIN((uint32_t)USHRT_MAX, len - data_offset);
1,027✔
55
            return DecodeIPV4(tv, dtv, p, pkt + data_offset, iplen);
1,027✔
56
        }
1,027✔
57
        case 0x57: { /* PPP_IPV6 */
3✔
58
            if (unlikely(len < (data_offset + IPV6_HEADER_LEN))) {
3✔
59
                ENGINE_SET_INVALID_EVENT(p, PPPIPV6_PKT_TOO_SMALL);
×
60
                return TM_ECODE_FAILED;
×
61
            }
×
62
            DEBUG_VALIDATE_BUG_ON(len < data_offset);
3✔
63
            uint16_t iplen = (uint16_t)MIN((uint32_t)USHRT_MAX, len - data_offset);
3✔
64
            return DecodeIPV6(tv, dtv, p, pkt + data_offset, iplen);
3✔
65
        }
3✔
66
        case 0x2f: /* PPP_VJ_UCOMP */
×
67
            if (unlikely(len < (data_offset + IPV4_HEADER_LEN))) {
×
68
                ENGINE_SET_INVALID_EVENT(p, PPPVJU_PKT_TOO_SMALL);
×
69
                return TM_ECODE_FAILED;
×
70
            }
×
71

72
            if (unlikely(len > data_offset + USHRT_MAX)) {
×
73
                return TM_ECODE_FAILED;
×
74
            }
×
75

76
            if (likely(IPV4_GET_RAW_VER((IPV4Hdr *)(pkt + data_offset)) == 4)) {
×
77
                p->flags |= PKT_PPP_VJ_UCOMP;
×
78
                return DecodeIPV4(tv, dtv, p, pkt + data_offset, (uint16_t)(len - data_offset));
×
79
            } else
×
80
                return TM_ECODE_FAILED;
×
81
            break;
×
82

83
        default:
×
84
            ENGINE_SET_EVENT(p, PPP_UNSUP_PROTO);
×
85
            return TM_ECODE_OK;
×
86
    }
1,030✔
87
}
1,030✔
88

89
static int DecodePPPUncompressedProto(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
90
        const uint8_t *pkt, uint32_t len, const uint16_t proto, const uint32_t data_offset)
91
{
×
92
    switch (proto) {
×
93
        case PPP_VJ_UCOMP:
×
94
            if (unlikely(len < (data_offset + IPV4_HEADER_LEN))) {
×
95
                ENGINE_SET_INVALID_EVENT(p, PPPVJU_PKT_TOO_SMALL);
×
96
                return TM_ECODE_FAILED;
×
97
            }
×
98

99
            if (unlikely(len > data_offset + USHRT_MAX)) {
×
100
                return TM_ECODE_FAILED;
×
101
            }
×
102

103
            if (likely(IPV4_GET_RAW_VER((IPV4Hdr *)(pkt + data_offset)) == 4)) {
×
104
                return DecodeIPV4(tv, dtv, p, pkt + data_offset, (uint16_t)(len - data_offset));
×
105
            } else
×
106
                return TM_ECODE_FAILED;
×
107
            break;
×
108

109
        case PPP_IP:
×
110
            if (unlikely(len < (data_offset + IPV4_HEADER_LEN))) {
×
111
                ENGINE_SET_INVALID_EVENT(p, PPPIPV4_PKT_TOO_SMALL);
×
112
                return TM_ECODE_FAILED;
×
113
            }
×
114
            if (unlikely(len > data_offset + USHRT_MAX)) {
×
115
                return TM_ECODE_FAILED;
×
116
            }
×
117

118
            return DecodeIPV4(tv, dtv, p, pkt + data_offset, (uint16_t)(len - data_offset));
×
119

120
            /* PPP IPv6 was not tested */
121
        case PPP_IPV6:
×
122
            if (unlikely(len < (data_offset + IPV6_HEADER_LEN))) {
×
123
                ENGINE_SET_INVALID_EVENT(p, PPPIPV6_PKT_TOO_SMALL);
×
124
                return TM_ECODE_FAILED;
×
125
            }
×
126
            if (unlikely(len > data_offset + USHRT_MAX)) {
×
127
                return TM_ECODE_FAILED;
×
128
            }
×
129

130
            return DecodeIPV6(tv, dtv, p, pkt + data_offset, (uint16_t)(len - data_offset));
×
131

132
        case PPP_IPCP:
×
133
        case PPP_IPV6CP:
×
134
        case PPP_LCP:
×
135
        case PPP_PAP:
×
136
        case PPP_CHAP:
×
137
        case PPP_CCP:
×
138
        case PPP_LQM:
×
139
        case PPP_CBCP:
×
140
        case PPP_COMP_DGRAM:
×
141
        case PPP_CDPCP:
×
142
            /* Valid types to be in PPP but don't inspect validity. */
143
            return TM_ECODE_OK;
×
144

145
        case PPP_VJ_COMP:
×
146
        case PPP_IPX:
×
147
        case PPP_OSI:
×
148
        case PPP_NS:
×
149
        case PPP_DECNET:
×
150
        case PPP_APPLE:
×
151
        case PPP_BRPDU:
×
152
        case PPP_STII:
×
153
        case PPP_VINES:
×
154
        case PPP_HELLO:
×
155
        case PPP_LUXCOM:
×
156
        case PPP_SNS:
×
157
        case PPP_MPLS_UCAST:
×
158
        case PPP_MPLS_MCAST:
×
159
        case PPP_OSICP:
×
160
        case PPP_NSCP:
×
161
        case PPP_DECNETCP:
×
162
        case PPP_APPLECP:
×
163
        case PPP_IPXCP:
×
164
        case PPP_STIICP:
×
165
        case PPP_VINESCP:
×
166
        case PPP_MPLSCP:
×
167
            ENGINE_SET_EVENT(p, PPP_UNSUP_PROTO);
×
168
            return TM_ECODE_OK;
×
169

170
        default:
×
171
            SCLogDebug("unknown PPP protocol: %x", proto);
×
172
            ENGINE_SET_INVALID_EVENT(p, PPP_WRONG_TYPE);
×
173
            return TM_ECODE_OK;
×
174
    }
×
175
}
×
176

177
int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
178
{
1,030✔
179
    DEBUG_VALIDATE_BUG_ON(pkt == NULL);
1,030✔
180

181
    StatsCounterIncr(&tv->stats, dtv->counter_ppp);
1,030✔
182
    if (unlikely(len < 1)) {
1,030✔
183
        ENGINE_SET_INVALID_EVENT(p, PPP_PKT_TOO_SMALL);
×
184
        return TM_ECODE_FAILED;
×
185
    }
×
186

187
    uint16_t proto_offset = 0;
1,030✔
188
    /* 0xff means we have a HDLC header: proto will start at offset 2 */
189
    if (*pkt == 0xff) {
1,030✔
190
        proto_offset = 2;
×
191
        /* make sure the proto field at the offset fits */
192
        if (len < 3) {
×
193
            ENGINE_SET_INVALID_EVENT(p, PPP_PKT_TOO_SMALL);
×
194
            return TM_ECODE_FAILED;
×
195
        }
×
196
    }
×
197
    uint8_t proto_size = 0;
1,030✔
198
    uint8_t proto_byte = *(pkt + proto_offset);
1,030✔
199
    /* check if compressed protocol bit is set. */
200
    if (proto_byte & 0x01) {
1,030✔
201
        proto_size = 1;
1,030✔
202
    } else {
1,030✔
203
        proto_size = 2;
×
204
    }
×
205
    if (len < (proto_size + proto_offset)) {
1,030✔
206
        ENGINE_SET_INVALID_EVENT(p, PPP_PKT_TOO_SMALL);
×
207
        return TM_ECODE_FAILED;
×
208
    }
×
209
    if (!PacketIncreaseCheckLayers(p)) {
1,030✔
210
        return TM_ECODE_FAILED;
×
211
    }
×
212

213
    const uint32_t data_offset = proto_offset + proto_size;
1,030✔
214
    if (data_offset != 4) {
1,030✔
215
        if (proto_size == 1) {
1,030✔
216
            return DecodePPPCompressedProto(tv, dtv, p, pkt, len, proto_offset);
1,030✔
217
        } else {
1,030✔
218
            const uint16_t proto = SCNtohs(*(uint16_t *)(pkt + proto_offset));
×
219
            return DecodePPPUncompressedProto(tv, dtv, p, pkt, len, proto, data_offset);
×
220
        }
×
221
    }
1,030✔
222
    /* implied proto_offset + proto_size == 4, so continue below */
223

224
    const PPPHdr *ppph = (PPPHdr *)pkt;
×
225
    SCLogDebug(
×
226
            "p %p pkt %p PPP protocol %04x Len: %" PRIu32 "", p, pkt, SCNtohs(ppph->protocol), len);
×
227
    return DecodePPPUncompressedProto(tv, dtv, p, pkt, len, SCNtohs(ppph->protocol), data_offset);
×
228
}
1,030✔
229

230
/* TESTS BELOW */
231
#ifdef UNITTESTS
232

233
/*  DecodePPPtest01
234
 *  Decode malformed ip layer PPP packet
235
 *  Expected test value: 1
236
 */
237
static int DecodePPPtest01(void)
238
{
239
    uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00 };
240
    Packet *p = PacketGetFromAlloc();
241
    if (unlikely(p == NULL))
242
        return 0;
243
    ThreadVars tv;
244
    DecodeThreadVars dtv;
245

246
    memset(&tv, 0, sizeof(ThreadVars));
247
    memset(&dtv, 0, sizeof(DecodeThreadVars));
248

249
    DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp));
250

251
    /* Function my returns here with expected value */
252

253
    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, PPPIPV4_PKT_TOO_SMALL));
254
    PacketFree(p);
255
    PASS;
256
}
257

258
/*  DecodePPPtest02
259
 *  Decode malformed ppp layer packet
260
 *  Expected test value: 1
261
 */
262
static int DecodePPPtest02(void)
263
{
264
    uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0xff, 0x45, 0xc0, 0x00, 0x2c, 0x4d, 0xed, 0x00, 0x00,
265
        0xff, 0x06, 0xd5, 0x17, 0xbf, 0x01, 0x0d, 0x01, 0xbf, 0x01, 0x0d, 0x03, 0xea, 0x37, 0x00,
266
        0x17, 0x6d, 0x0b, 0xba, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x10, 0x20, 0xdd, 0xe1,
267
        0x00, 0x00 };
268
    Packet *p = PacketGetFromAlloc();
269
    if (unlikely(p == NULL))
270
        return 0;
271
    ThreadVars tv;
272
    DecodeThreadVars dtv;
273

274
    memset(&tv, 0, sizeof(ThreadVars));
275
    memset(&dtv, 0, sizeof(DecodeThreadVars));
276

277
    DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp));
278

279
    /* Function must returns here */
280

281
    FAIL_IF_NOT(ENGINE_ISSET_EVENT(p, PPP_WRONG_TYPE));
282

283
    PacketFree(p);
284
    PASS;
285
}
286

287
/** DecodePPPtest03
288
 *  \brief Decode good PPP packet, additionally the IPv4 packet inside is
289
 *         4 bytes short.
290
 *  \retval 0 Test failed
291
 *  \retval 1 Test succeeded
292
 */
293
static int DecodePPPtest03(void)
294
{
295
    uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00, 0x2c, 0x4d, 0xed, 0x00, 0x00,
296
        0xff, 0x06, 0xd5, 0x17, 0xbf, 0x01, 0x0d, 0x01, 0xbf, 0x01, 0x0d, 0x03, 0xea, 0x37, 0x00,
297
        0x17, 0x6d, 0x0b, 0xba, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x10, 0x20, 0xdd, 0xe1,
298
        0x00, 0x00 };
299
    Packet *p = PacketGetFromAlloc();
300
    if (unlikely(p == NULL))
301
        return 0;
302
    ThreadVars tv;
303
    DecodeThreadVars dtv;
304

305
    memset(&tv, 0, sizeof(ThreadVars));
306
    memset(&dtv, 0, sizeof(DecodeThreadVars));
307

308
    FlowInitConfig(FLOW_QUIET);
309

310
    DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp));
311

312
    FAIL_IF(ENGINE_ISSET_EVENT(p, PPP_PKT_TOO_SMALL));
313
    FAIL_IF(ENGINE_ISSET_EVENT(p, PPPIPV4_PKT_TOO_SMALL));
314
    FAIL_IF(ENGINE_ISSET_EVENT(p, PPP_WRONG_TYPE));
315
    FAIL_IF(!(ENGINE_ISSET_EVENT(p, IPV4_TRUNC_PKT)));
316

317
    PacketFree(p);
318
    FlowShutdown();
319
    PASS;
320
}
321

322
/*  DecodePPPtest04
323
 *  Check if ppp header is null
324
 *  Expected test value: 1
325
 */
326

327
static int DecodePPPtest04(void)
328
{
329
    uint8_t raw_ppp[] = { 0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00, 0x2c, 0x4d, 0xed, 0x00, 0x00,
330
        0xff, 0x06, 0xd5, 0x17, 0xbf, 0x01, 0x0d, 0x01, 0xbf, 0x01, 0x0d, 0x03, 0xea, 0x37, 0x00,
331
        0x17, 0x6d, 0x0b, 0xba, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x10, 0x20, 0xdd, 0xe1,
332
        0x00, 0x00 };
333
    Packet *p = PacketGetFromAlloc();
334
    if (unlikely(p == NULL))
335
        return 0;
336
    ThreadVars tv;
337
    DecodeThreadVars dtv;
338

339
    memset(&tv, 0, sizeof(ThreadVars));
340
    memset(&dtv, 0, sizeof(DecodeThreadVars));
341

342
    FlowInitConfig(FLOW_QUIET);
343

344
    DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp));
345

346
    FlowShutdown();
347

348
    FAIL_IF(!(ENGINE_ISSET_EVENT(p, IPV4_TRUNC_PKT)));
349

350
    /* Function must returns here */
351

352
    PacketFree(p);
353
    PASS;
354
}
355
#endif /* UNITTESTS */
356

357
void DecodePPPRegisterTests(void)
358
{
×
359
#ifdef UNITTESTS
360
    UtRegisterTest("DecodePPPtest01", DecodePPPtest01);
361
    UtRegisterTest("DecodePPPtest02", DecodePPPtest02);
362
    UtRegisterTest("DecodePPPtest03", DecodePPPtest03);
363
    UtRegisterTest("DecodePPPtest04", DecodePPPtest04);
364
#endif /* UNITTESTS */
365
}
×
366

367
/**
368
 * @}
369
 */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc