-/* Copyright (C) 2019 Open Information Security Foundation
+/* Copyright (C) 2019-2022 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
pub path: String,
pub version: String,
pub headers: HashMap<String, String>,
+
+ pub request_line_len: u16,
+ pub headers_len: u16,
+ pub body_offset: u16,
+ pub body_len: u16,
}
#[derive(Debug)]
pub version: String,
pub code: String,
pub reason: String,
+
+ pub response_line_len: u16,
+ pub headers_len: u16,
+ pub body_offset: u16,
+ pub body_len: u16,
}
#[derive(PartialEq, Debug, Clone)]
is_alphanumeric(b) || is_token_char(b) || b"\"#$&(),/;:<=>?@[]{}()^|~\\\t\n\r ".contains(&b)
}
-pub fn sip_parse_request(i: &[u8]) -> IResult<&[u8], Request> {
- let (i, method) = parse_method(i)?;
+pub fn sip_parse_request(oi: &[u8]) -> IResult<&[u8], Request> {
+ let (i, method) = parse_method(oi)?;
let (i, _) = char(' ')(i)?;
let (i, path) = parse_request_uri(i)?;
let (i, _) = char(' ')(i)?;
let (i, version) = parse_version(i)?;
- let (i, _) = crlf(i)?;
- let (i, headers) = parse_headers(i)?;
- let (i, _) = crlf(i)?;
+ let (hi, _) = crlf(i)?;
+ let request_line_len = oi.len() - hi.len();
+ let (phi, headers) = parse_headers(hi)?;
+ let headers_len = hi.len() - phi.len();
+ let (bi, _) = crlf(phi)?;
+ let body_offset = oi.len() - bi.len();
Ok((
- i,
+ bi,
Request {
method: method.into(),
path: path.into(),
version: version.into(),
headers,
+
+ request_line_len: request_line_len as u16,
+ headers_len: headers_len as u16,
+ body_offset: body_offset as u16,
+ body_len: bi.len() as u16,
},
))
}
-pub fn sip_parse_response(i: &[u8]) -> IResult<&[u8], Response> {
- let (i, version) = parse_version(i)?;
+pub fn sip_parse_response(oi: &[u8]) -> IResult<&[u8], Response> {
+ let (i, version) = parse_version(oi)?;
let (i, _) = char(' ')(i)?;
let (i, code) = parse_code(i)?;
let (i, _) = char(' ')(i)?;
let (i, reason) = parse_reason(i)?;
- let (i, _) = crlf(i)?;
+ let (hi, _) = crlf(i)?;
+ let response_line_len = oi.len() - hi.len();
+ let (phi, _headers) = parse_headers(hi)?;
+ let headers_len = hi.len() - phi.len();
+ let (bi, _) = crlf(phi)?;
+ let body_offset = oi.len() - bi.len();
Ok((
- i,
+ bi,
Response {
version: version.into(),
code: code.into(),
reason: reason.into(),
+
+ response_line_len: response_line_len as u16,
+ headers_len: headers_len as u16,
+ body_offset: body_offset as u16,
+ body_len: bi.len() as u16,
},
))
}
let buf: &[u8] = "REGISTER sip:sip.cybercity.dk SIP/2.0\r\n\
From: <sip:voi18063@sip.cybercity.dk>;tag=903df0a\r\n\
To: <sip:voi18063@sip.cybercity.dk>\r\n\
- Content-Length: 0 \r\n\
- \r\n"
+ Content-Length: 4 \r\n\
+ \r\nABCD"
.as_bytes();
- let (_, req) = sip_parse_request(buf).expect("parsing failed");
+ let (body, req) = sip_parse_request(buf).expect("parsing failed");
assert_eq!(req.method, "REGISTER");
assert_eq!(req.path, "sip:sip.cybercity.dk");
assert_eq!(req.version, "SIP/2.0");
- assert_eq!(req.headers["Content-Length"], "0");
+ assert_eq!(req.headers["Content-Length"], "4");
+ assert_eq!(body, "ABCD".as_bytes());
}
#[test]
-/* Copyright (C) 2019-2020 Open Information Security Foundation
+/* Copyright (C) 2019-2022 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
// written by Giuseppe Longo <giuseppe@glongo.it>
+use crate::frames::*;
use crate::applayer::{self, *};
use crate::core;
use crate::core::{AppProto, Flow, ALPROTO_UNKNOWN};
use std;
use std::ffi::CString;
+#[derive(AppLayerFrameType)]
+pub enum SIPFrameType {
+ Pdu,
+ RequestLine,
+ ResponseLine,
+ RequestHeaders,
+ ResponseHeaders,
+ RequestBody,
+ ResponseBody,
+}
+
#[derive(AppLayerEvent)]
pub enum SIPEvent {
IncompleteData,
}
}
- fn parse_request(&mut self, input: &[u8]) -> bool {
+ fn parse_request(&mut self, flow: *const core::Flow, stream_slice: StreamSlice) -> bool {
+ let input = stream_slice.as_slice();
+ let _pdu = Frame::new_ts(flow, &stream_slice, input, input.len() as i64, SIPFrameType::Pdu as u8);
+ SCLogDebug!("ts: pdu {:?}", _pdu);
+
match sip_parse_request(input) {
Ok((_, request)) => {
+ sip_frames_ts(flow, &stream_slice, &request);
let mut tx = self.new_tx();
tx.request = Some(request);
if let Ok((_, req_line)) = sip_take_line(input) {
}
}
- fn parse_response(&mut self, input: &[u8]) -> bool {
+ fn parse_response(&mut self, flow: *const core::Flow, stream_slice: StreamSlice) -> bool {
+ let input = stream_slice.as_slice();
+ let _pdu = Frame::new_tc(flow, &stream_slice, input, input.len() as i64, SIPFrameType::Pdu as u8);
+ SCLogDebug!("tc: pdu {:?}", _pdu);
+
match sip_parse_response(input) {
Ok((_, response)) => {
+ sip_frames_tc(flow, &stream_slice, &response);
let mut tx = self.new_tx();
tx.response = Some(response);
if let Ok((_, resp_line)) = sip_take_line(input) {
}
}
+
+fn sip_frames_ts(flow: *const core::Flow, stream_slice: &StreamSlice, r: &Request) {
+ let oi = stream_slice.as_slice();
+ let _f = Frame::new_ts(flow, stream_slice, oi, r.request_line_len as i64, SIPFrameType::RequestLine as u8);
+ SCLogDebug!("ts: request_line {:?}", _f);
+ let hi = &oi[r.request_line_len as usize ..];
+ let _f = Frame::new_ts(flow, stream_slice, hi, r.headers_len as i64, SIPFrameType::RequestHeaders as u8);
+ SCLogDebug!("ts: request_headers {:?}", _f);
+ if r.body_len > 0 {
+ let bi = &oi[r.body_offset as usize ..];
+ let _f = Frame::new_ts(flow, stream_slice, bi, r.body_len as i64, SIPFrameType::RequestBody as u8);
+ SCLogDebug!("ts: request_body {:?}", _f);
+ }
+}
+
+fn sip_frames_tc(flow: *const core::Flow, stream_slice: &StreamSlice, r: &Response) {
+ let oi = stream_slice.as_slice();
+ let _f = Frame::new_tc(flow, stream_slice, oi, r.response_line_len as i64, SIPFrameType::ResponseLine as u8);
+ let hi = &oi[r.response_line_len as usize ..];
+ SCLogDebug!("tc: response_line {:?}", _f);
+ let _f = Frame::new_tc(flow, stream_slice, hi, r.headers_len as i64, SIPFrameType::ResponseHeaders as u8);
+ SCLogDebug!("tc: response_headers {:?}", _f);
+ if r.body_len > 0 {
+ let bi = &oi[r.body_offset as usize ..];
+ let _f = Frame::new_tc(flow, stream_slice, bi, r.body_len as i64, SIPFrameType::ResponseBody as u8);
+ SCLogDebug!("tc: response_body {:?}", _f);
+ }
+}
+
#[no_mangle]
pub extern "C" fn rs_sip_state_new(_orig_state: *mut std::os::raw::c_void, _orig_proto: AppProto) -> *mut std::os::raw::c_void {
let state = SIPState::new();
#[no_mangle]
pub unsafe extern "C" fn rs_sip_parse_request(
- _flow: *const core::Flow,
+ flow: *const core::Flow,
state: *mut std::os::raw::c_void,
_pstate: *mut std::os::raw::c_void,
stream_slice: StreamSlice,
_data: *const std::os::raw::c_void,
) -> AppLayerResult {
let state = cast_pointer!(state, SIPState);
- state.parse_request(stream_slice.as_slice()).into()
+ state.parse_request(flow, stream_slice).into()
}
#[no_mangle]
pub unsafe extern "C" fn rs_sip_parse_response(
- _flow: *const core::Flow,
+ flow: *const core::Flow,
state: *mut std::os::raw::c_void,
_pstate: *mut std::os::raw::c_void,
stream_slice: StreamSlice,
_data: *const std::os::raw::c_void,
) -> AppLayerResult {
let state = cast_pointer!(state, SIPState);
- state.parse_response(stream_slice.as_slice()).into()
+ state.parse_response(flow, stream_slice).into()
}
export_tx_data_get!(rs_sip_get_tx_data, SIPTransaction);
apply_tx_config: None,
flags: APP_LAYER_PARSER_OPT_UNIDIR_TXS,
truncate: None,
- get_frame_id_by_name: None,
- get_frame_name_by_id: None,
+ get_frame_id_by_name: Some(SIPFrameType::ffi_id_from_name),
+ get_frame_name_by_id: Some(SIPFrameType::ffi_name_from_id),
};
let ip_proto_str = CString::new("udp").unwrap();