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

OISF / suricata / 22712336922

05 Mar 2026 09:55AM UTC coverage: 66.796% (-12.5%) from 79.283%
22712336922

Pull #14946

github

web-flow
Merge 91559149c into 7e97dfd52
Pull Request #14946: Stack 8001 v15

14 of 19 new or added lines in 7 files covered. (73.68%)

11298 existing lines in 298 files now uncovered.

155282 of 232473 relevant lines covered (66.8%)

5923441.93 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> {
183,336✔
16
    match OffsetDateTime::from_unix_timestamp(sec) {
183,336✔
17
        Ok(date) => Some(date + Duration::microseconds(usec)),
182,938✔
18
        Err(_) => None,
398✔
19
    }
20
}
183,336✔
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(
6,743✔
30
    connp: *mut ConnectionParser, timestamp: *const libc::timeval,
6,743✔
31
) {
6,743✔
32
    if let Some(connp) = connp.as_mut() {
6,743✔
33
        connp.close(
6,743✔
34
            timestamp
6,743✔
35
                .as_ref()
6,743✔
36
                .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
6,743✔
37
                .unwrap_or(None),
6,743✔
38
        )
6,743✔
39
    }
×
40
}
6,743✔
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 {
14,315✔
51
    Box::into_raw(Box::new(ConnectionParser::new(cfg.as_ref().unwrap())))
14,315✔
52
}
14,315✔
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) {
14,315✔
60
    drop(Box::from_raw(connp));
14,315✔
61
}
14,315✔
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 {
14,315✔
70
    connp
14,315✔
71
        .as_ref()
14,315✔
72
        .map(|val| &val.conn as *const Connection)
14,315✔
73
        .unwrap_or(std::ptr::null())
14,315✔
74
}
14,315✔
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 {
159,504✔
82
    connp
159,504✔
83
        .as_ref()
159,504✔
84
        .and_then(|val| val.user_data::<*mut libc::c_void>())
159,504✔
85
        .copied()
159,504✔
86
        .unwrap_or(std::ptr::null_mut())
159,504✔
87
}
159,504✔
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(
14,315✔
94
    connp: *mut ConnectionParser, user_data: *mut libc::c_void,
14,315✔
95
) {
14,315✔
96
    if let Some(connp) = connp.as_mut() {
14,315✔
97
        connp.set_user_data(Box::new(user_data))
14,315✔
98
    }
×
99
}
14,315✔
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(
14,315✔
109
    connp: *mut ConnectionParser, client_addr: *const libc::c_char, client_port: libc::c_int,
14,315✔
110
    server_addr: *const libc::c_char, server_port: libc::c_int, timestamp: *const libc::timeval,
14,315✔
111
) {
14,315✔
112
    if let Some(connp) = connp.as_mut() {
14,315✔
113
        connp.open(
14,315✔
114
            client_addr.as_ref().and_then(|client_addr| {
14,315✔
115
                CStr::from_ptr(client_addr)
×
116
                    .to_str()
×
117
                    .ok()
×
118
                    .and_then(|val| val.parse().ok())
×
119
            }),
14,315✔
120
            client_port.try_into().ok(),
14,315✔
121
            server_addr.as_ref().and_then(|server_addr| {
14,315✔
122
                CStr::from_ptr(server_addr)
×
123
                    .to_str()
×
124
                    .ok()
×
125
                    .and_then(|val| val.parse().ok())
×
126
            }),
14,315✔
127
            server_port.try_into().ok(),
14,315✔
128
            timestamp
14,315✔
129
                .as_ref()
14,315✔
130
                .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
14,315✔
131
                .unwrap_or(None),
14,315✔
132
        )
14,315✔
133
    }
×
134
}
14,315✔
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(
6,842✔
144
    connp: *mut ConnectionParser, timestamp: *const libc::timeval,
6,842✔
145
) {
6,842✔
146
    if let Some(connp) = connp.as_mut() {
6,842✔
147
        connp.request_close(
6,842✔
148
            timestamp
6,842✔
149
                .as_ref()
6,842✔
150
                .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
6,842✔
151
                .unwrap_or(None),
6,842✔
152
        )
6,842✔
153
    }
×
154
}
6,842✔
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(
113,548✔
166
    connp: *mut ConnectionParser, timestamp: *const libc::timeval, data: *const libc::c_void,
113,548✔
167
    len: libc::size_t,
113,548✔
168
) -> HtpStreamState {
113,548✔
169
    connp
113,548✔
170
        .as_mut()
113,548✔
171
        .map(|connp| {
113,548✔
172
            connp.request_data(
113,548✔
173
                ParserData::from((data as *const u8, len)),
113,548✔
174
                timestamp
113,548✔
175
                    .as_ref()
113,548✔
176
                    .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
113,548✔
177
                    .unwrap_or(None),
113,548✔
178
            )
113,548✔
179
        })
113,548✔
180
        .unwrap_or(HtpStreamState::ERROR)
113,548✔
181
}
113,548✔
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(
41,888✔
192
    connp: *mut ConnectionParser, timestamp: *const libc::timeval, data: *const libc::c_void,
41,888✔
193
    len: libc::size_t,
41,888✔
194
) -> HtpStreamState {
41,888✔
195
    connp
41,888✔
196
        .as_mut()
41,888✔
197
        .map(|connp| {
41,888✔
198
            connp.response_data(
41,888✔
199
                ParserData::from((data as *const u8, len)),
41,888✔
200
                timestamp
41,888✔
201
                    .as_ref()
41,888✔
202
                    .map(|val| datetime_from_sec_usec(val.tv_sec.into(), val.tv_usec.into()))
41,888✔
203
                    .unwrap_or(None),
41,888✔
204
            )
41,888✔
205
        })
41,888✔
206
        .unwrap_or(HtpStreamState::ERROR)
41,888✔
207
}
41,888✔
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 {
3,153,982✔
216
    connp
3,153,982✔
217
        .as_ref()
3,153,982✔
218
        .map(|connp| isize::try_from(connp.tx_size()).unwrap_or(-1))
3,153,982✔
219
        .unwrap_or(-1)
3,153,982✔
220
}
3,153,982✔
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,902,914✔
227
    connp: *mut ConnectionParser, index: usize,
1,902,914✔
228
) -> *mut Transaction {
1,902,914✔
229
    if let Some(tx) = connp.as_mut().unwrap().tx_index(index) {
1,902,914✔
230
        if tx.is_started() {
1,900,869✔
231
            return tx as *mut Transaction;
1,818,542✔
232
        }
82,327✔
233
    }
2,045✔
234
    std::ptr::null_mut()
84,372✔
235
}
1,902,914✔
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(
64,555✔
244
    connp: *mut ConnectionParser, tx_id: usize,
64,555✔
245
) -> *const Transaction {
64,555✔
246
    connp
64,555✔
247
        .as_ref()
64,555✔
248
        .map(|connp| {
64,555✔
249
            connp
64,555✔
250
                .tx(tx_id)
64,555✔
251
                .map(|tx| {
64,555✔
252
                    if tx.is_started() {
64,512✔
253
                        tx as *const Transaction
62,738✔
254
                    } else {
255
                        std::ptr::null()
1,774✔
256
                    }
257
                })
64,555✔
258
                .unwrap_or(std::ptr::null())
64,555✔
259
        })
64,555✔
260
        .unwrap_or(std::ptr::null())
64,555✔
261
}
64,555✔
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(
958✔
270
    connp: *mut ConnectionParser,
958✔
271
) -> *const Transaction {
958✔
272
    if let Some(connp) = connp.as_mut() {
958✔
273
        if let Some(req) = connp.response() {
958✔
274
            return req;
958✔
275
        }
×
276
    }
×
277
    std::ptr::null()
×
278
}
958✔
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 {
34,506✔
302
    connp
34,506✔
303
        .as_ref()
34,506✔
304
        .map(|connp| connp.request_data_consumed().try_into().ok().unwrap_or(-1))
34,506✔
305
        .unwrap_or(-1)
34,506✔
306
}
34,506✔
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 {
32,831✔
319
    connp
32,831✔
320
        .as_ref()
32,831✔
321
        .map(|connp| connp.response_data_consumed().try_into().ok().unwrap_or(-1))
32,831✔
322
        .unwrap_or(-1)
32,831✔
323
}
32,831✔
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