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

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

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

86.19
/rust/htp/src/c_api/connection_parser.rs
1
#![deny(missing_docs)]
2
use crate::{
3
    config::Config,
4
    connection::Connection,
5
    connection_parser::{ConnectionParser, HtpStreamState, ParserData},
6
    transaction::Transaction,
7
};
8
use std::{
9
    convert::{TryFrom, TryInto},
10
    ffi::CStr,
11
};
12
use time::{Duration, OffsetDateTime};
13

14
/// Take seconds and microseconds and return a OffsetDateTime
15
fn datetime_from_sec_usec(sec: i64, usec: i64) -> Option<OffsetDateTime> {
111,527✔
16
    match OffsetDateTime::from_unix_timestamp(sec) {
111,527✔
17
        Ok(date) => Some(date + Duration::microseconds(usec)),
111,129✔
18
        Err(_) => None,
398✔
19
    }
20
}
111,527✔
21

22
/// Closes the connection associated with the supplied parser.
23
///
24
/// timestamp is optional
25
/// # Safety
26
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
27
#[no_mangle]
28
#[allow(clippy::useless_conversion)]
29
pub unsafe extern "C" fn htp_connp_close(
3,762✔
30
    connp: *mut ConnectionParser, timestamp: *const libc::timeval,
3,762✔
31
) {
3,762✔
32
    if let Some(connp) = connp.as_mut() {
3,762✔
33
        connp.close(
3,762✔
34
            timestamp
3,762✔
35
                .as_ref()
3,762✔
36
                .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
3,762✔
37
                .unwrap_or(None),
3,762✔
38
        )
3,762✔
39
    }
×
40
}
3,762✔
41

42
/// Creates a new connection parser using the provided configuration or a default configuration if NULL provided.
43
/// Note the provided config will be copied into the created connection parser. Therefore, subsequent modification
44
/// to the original config will have no effect.
45
///
46
/// Returns a new connection parser instance, or NULL on error.
47
/// # Safety
48
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
49
#[no_mangle]
50
pub unsafe extern "C" fn htp_connp_create(cfg: *const Config) -> *mut ConnectionParser {
9,433✔
51
    Box::into_raw(Box::new(ConnectionParser::new(cfg.as_ref().unwrap())))
9,433✔
52
}
9,433✔
53

54
/// Destroys the connection parser, its data structures, as well
55
/// as the connection and its transactions.
56
/// # Safety
57
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
58
#[no_mangle]
59
pub unsafe extern "C" fn htp_connp_destroy_all(connp: *mut ConnectionParser) {
9,433✔
60
    drop(Box::from_raw(connp));
9,433✔
61
}
9,433✔
62

63
/// Returns the connection associated with the connection parser.
64
///
65
/// Returns Connection instance, or NULL if one is not available.
66
/// # Safety
67
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
68
#[no_mangle]
69
pub unsafe extern "C" fn htp_connp_connection(connp: *const ConnectionParser) -> *const Connection {
9,433✔
70
    connp
9,433✔
71
        .as_ref()
9,433✔
72
        .map(|val| &val.conn as *const Connection)
9,433✔
73
        .unwrap_or(std::ptr::null())
9,433✔
74
}
9,433✔
75

76
/// Retrieve the user data associated with this connection parser.
77
/// Returns user data, or NULL if there isn't any.
78
/// # Safety
79
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
80
#[no_mangle]
81
pub unsafe extern "C" fn htp_connp_user_data(connp: *const ConnectionParser) -> *mut libc::c_void {
102,917✔
82
    connp
102,917✔
83
        .as_ref()
102,917✔
84
        .and_then(|val| val.user_data::<*mut libc::c_void>())
102,917✔
85
        .copied()
102,917✔
86
        .unwrap_or(std::ptr::null_mut())
102,917✔
87
}
102,917✔
88

89
/// Associate user data with the supplied parser.
90
/// # Safety
91
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
92
#[no_mangle]
93
pub unsafe extern "C" fn htp_connp_set_user_data(
9,433✔
94
    connp: *mut ConnectionParser, user_data: *mut libc::c_void,
9,433✔
95
) {
9,433✔
96
    if let Some(connp) = connp.as_mut() {
9,433✔
97
        connp.set_user_data(Box::new(user_data))
9,433✔
98
    }
×
99
}
9,433✔
100

101
/// Opens connection.
102
///
103
/// timestamp is optional
104
/// # Safety
105
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
106
#[no_mangle]
107
#[allow(clippy::useless_conversion)]
108
pub unsafe extern "C" fn htp_connp_open(
9,433✔
109
    connp: *mut ConnectionParser, client_addr: *const libc::c_char, client_port: libc::c_int,
9,433✔
110
    server_addr: *const libc::c_char, server_port: libc::c_int, timestamp: *const libc::timeval,
9,433✔
111
) {
9,433✔
112
    if let Some(connp) = connp.as_mut() {
9,433✔
113
        connp.open(
9,433✔
114
            client_addr.as_ref().and_then(|client_addr| {
9,433✔
115
                CStr::from_ptr(client_addr)
×
116
                    .to_str()
×
117
                    .ok()
×
118
                    .and_then(|val| val.parse().ok())
×
119
            }),
9,433✔
120
            client_port.try_into().ok(),
9,433✔
121
            server_addr.as_ref().and_then(|server_addr| {
9,433✔
122
                CStr::from_ptr(server_addr)
×
123
                    .to_str()
×
124
                    .ok()
×
125
                    .and_then(|val| val.parse().ok())
×
126
            }),
9,433✔
127
            server_port.try_into().ok(),
9,433✔
128
            timestamp
9,433✔
129
                .as_ref()
9,433✔
130
                .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
9,433✔
131
                .unwrap_or(None),
9,433✔
132
        )
9,433✔
133
    }
×
134
}
9,433✔
135

136
/// Closes the connection associated with the supplied parser.
137
///
138
/// timestamp is optional
139
/// # Safety
140
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
141
#[no_mangle]
142
#[allow(clippy::useless_conversion)]
143
pub unsafe extern "C" fn htp_connp_request_close(
3,742✔
144
    connp: *mut ConnectionParser, timestamp: *const libc::timeval,
3,742✔
145
) {
3,742✔
146
    if let Some(connp) = connp.as_mut() {
3,742✔
147
        connp.request_close(
3,742✔
148
            timestamp
3,742✔
149
                .as_ref()
3,742✔
150
                .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
3,742✔
151
                .unwrap_or(None),
3,742✔
152
        )
3,742✔
153
    }
×
154
}
3,742✔
155

156
/// Process a chunk of inbound client request data
157
///
158
/// timestamp is optional
159
/// Returns HTP_STREAM_STATE_DATA, HTP_STREAM_STATE_ERROR or HTP_STREAM_STATE_DATA_OTHER (see QUICK_START).
160
///         HTP_STREAM_STATE_CLOSED and HTP_STREAM_STATE_TUNNEL are also possible.
161
/// # Safety
162
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
163
#[no_mangle]
164
#[allow(clippy::useless_conversion)]
165
pub unsafe extern "C" fn htp_connp_request_data(
70,509✔
166
    connp: *mut ConnectionParser, timestamp: *const libc::timeval, data: *const libc::c_void,
70,509✔
167
    len: libc::size_t,
70,509✔
168
) -> HtpStreamState {
70,509✔
169
    connp
70,509✔
170
        .as_mut()
70,509✔
171
        .map(|connp| {
70,509✔
172
            connp.request_data(
70,509✔
173
                ParserData::from((data as *const u8, len)),
70,509✔
174
                timestamp
70,509✔
175
                    .as_ref()
70,509✔
176
                    .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
70,509✔
177
                    .unwrap_or(None),
70,509✔
178
            )
70,509✔
179
        })
70,509✔
180
        .unwrap_or(HtpStreamState::ERROR)
70,509✔
181
}
70,509✔
182

183
/// Process a chunk of outbound (server or response) data.
184
///
185
/// timestamp is optional.
186
/// Returns HTP_STREAM_STATE_OK on state change, HTP_STREAM_STATE_ERROR on error, or HTP_STREAM_STATE_DATA when more data is needed
187
/// # Safety
188
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
189
#[no_mangle]
190
#[allow(clippy::useless_conversion)]
191
pub unsafe extern "C" fn htp_connp_response_data(
24,081✔
192
    connp: *mut ConnectionParser, timestamp: *const libc::timeval, data: *const libc::c_void,
24,081✔
193
    len: libc::size_t,
24,081✔
194
) -> HtpStreamState {
24,081✔
195
    connp
24,081✔
196
        .as_mut()
24,081✔
197
        .map(|connp| {
24,081✔
198
            connp.response_data(
24,081✔
199
                ParserData::from((data as *const u8, len)),
24,081✔
200
                timestamp
24,081✔
201
                    .as_ref()
24,081✔
202
                    .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
24,081✔
203
                    .unwrap_or(None),
24,081✔
204
            )
24,081✔
205
        })
24,081✔
206
        .unwrap_or(HtpStreamState::ERROR)
24,081✔
207
}
24,081✔
208

209
/// Get the number of transactions processed on this connection.
210
///
211
/// Returns the number of transactions or -1 on error.
212
/// # Safety
213
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
214
#[no_mangle]
215
pub unsafe extern "C" fn htp_connp_tx_size(connp: *const ConnectionParser) -> isize {
2,165,185✔
216
    connp
2,165,185✔
217
        .as_ref()
2,165,185✔
218
        .map(|connp| isize::try_from(connp.tx_size()).unwrap_or(-1))
2,165,185✔
219
        .unwrap_or(-1)
2,165,185✔
220
}
2,165,185✔
221

222
/// Get a transaction by its index for the iterator.
223
/// # Safety
224
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
225
#[no_mangle]
226
pub unsafe extern "C" fn htp_connp_tx_index(
1,329,612✔
227
    connp: *mut ConnectionParser, index: usize,
1,329,612✔
228
) -> *mut Transaction {
1,329,612✔
229
    if let Some(tx) = connp.as_mut().unwrap().tx_index(index) {
1,329,612✔
230
        if tx.is_started() {
1,328,051✔
231
            return tx as *mut Transaction;
1,280,992✔
232
        }
47,059✔
233
    }
1,561✔
234
    std::ptr::null_mut()
48,620✔
235
}
1,329,612✔
236

237
/// Get a transaction.
238
///
239
/// Returns the transaction or NULL on error.
240
/// # Safety
241
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
242
#[no_mangle]
243
pub unsafe extern "C" fn htp_connp_tx(
50,584✔
244
    connp: *mut ConnectionParser, tx_id: usize,
50,584✔
245
) -> *const Transaction {
50,584✔
246
    connp
50,584✔
247
        .as_ref()
50,584✔
248
        .map(|connp| {
50,584✔
249
            connp
50,584✔
250
                .tx(tx_id)
50,584✔
251
                .map(|tx| {
50,584✔
252
                    if tx.is_started() {
50,545✔
253
                        tx as *const Transaction
49,597✔
254
                    } else {
255
                        std::ptr::null()
948✔
256
                    }
257
                })
50,584✔
258
                .unwrap_or(std::ptr::null())
50,584✔
259
        })
50,584✔
260
        .unwrap_or(std::ptr::null())
50,584✔
261
}
50,584✔
262

263
/// Retrieves the pointer to the active response transaction. In connection
264
/// parsing mode there can be many open transactions, and up to 2 active
265
/// transactions at any one time. This is due to HTTP pipelining. Can be NULL.
266
/// # Safety
267
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
268
#[no_mangle]
269
pub unsafe extern "C" fn htp_connp_get_response_tx(
924✔
270
    connp: *mut ConnectionParser,
924✔
271
) -> *const Transaction {
924✔
272
    if let Some(connp) = connp.as_mut() {
924✔
273
        if let Some(req) = connp.response() {
924✔
274
            return req;
924✔
275
        }
×
276
    }
×
277
    std::ptr::null()
×
278
}
924✔
279

280
/// Retrieves the pointer to the active request transaction. In connection
281
/// parsing mode there can be many open transactions, and up to 2 active
282
/// transactions at any one time. This is due to HTTP pipelining. Call be NULL.
283
/// # Safety
284
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
285
#[no_mangle]
UNCOV
286
pub unsafe extern "C" fn htp_connp_get_request_tx(
×
UNCOV
287
    connp: *mut ConnectionParser,
×
UNCOV
288
) -> *const Transaction {
×
UNCOV
289
    if let Some(connp) = connp.as_mut() {
×
UNCOV
290
        if let Some(req) = connp.request() {
×
UNCOV
291
            return req;
×
292
        }
×
293
    }
×
294
    std::ptr::null()
×
UNCOV
295
}
×
296

297
/// Returns the number of bytes consumed from the current data chunks so far or -1 on error.
298
/// # Safety
299
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
300
#[no_mangle]
301
pub unsafe extern "C" fn htp_connp_request_data_consumed(connp: *const ConnectionParser) -> i64 {
23,550✔
302
    connp
23,550✔
303
        .as_ref()
23,550✔
304
        .map(|connp| connp.request_data_consumed().try_into().ok().unwrap_or(-1))
23,550✔
305
        .unwrap_or(-1)
23,550✔
306
}
23,550✔
307

308
/// Returns the number of bytes consumed from the most recent outbound data chunk. Normally, an invocation
309
/// of htp_connp_response_data() will consume all data from the supplied buffer, but there are circumstances
310
/// where only partial consumption is possible. In such cases HTP_STREAM_DATA_OTHER will be returned.
311
/// Consumed bytes are no longer necessary, but the remainder of the buffer will be need to be saved
312
/// for later.
313
/// Returns the number of bytes consumed from the last data chunk sent for outbound processing
314
/// or -1 on error.
315
/// # Safety
316
/// When calling this method, you have to ensure that connp is either properly initialized or NULL
317
#[no_mangle]
318
pub unsafe extern "C" fn htp_connp_response_data_consumed(connp: *const ConnectionParser) -> i64 {
20,580✔
319
    connp
20,580✔
320
        .as_ref()
20,580✔
321
        .map(|connp| connp.response_data_consumed().try_into().ok().unwrap_or(-1))
20,580✔
322
        .unwrap_or(-1)
20,580✔
323
}
20,580✔
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