},
"version": {
"type": "string"
+ },
+ "sdp": {
+ "type": "object",
+ "description": "SDP message body",
+ "optional": true,
+ "properties": {
+ "version": {
+ "type": "integer",
+ "description": "SDP protocol version"
+ },
+ "origin": {
+ "type": "string",
+ "description": "Owner of the session"
+ },
+ "session_name": {
+ "type": "string",
+ "description": "Session name"
+ },
+ "session_info": {
+ "type": "string",
+ "optional": true,
+ "description": "Textual information about the session"
+ },
+ "uri": {
+ "type": "string",
+ "optional": true,
+ "description": "A pointer to additional information about the session"
+ },
+ "email": {
+ "type": "string",
+ "optional": true,
+ "description": "Email address for the person responsible for the conference"
+ },
+ "phone_number": {
+ "type": "string",
+ "optional": true,
+ "description": "Phone number for the person responsible for the conference"
+ },
+ "connection_data": {
+ "type": "string",
+ "optional": true,
+ "description": "Connection data"
+ },
+ "bandwidths": {
+ "type": "array",
+ "optional": true,
+ "description": "Proposed bandwidths to be used by the session or media",
+ "minItems": 1,
+ "items": {
+ "type": "string"
+ }
+ },
+ "time": {
+ "type": "string",
+ "optional": true,
+ "description": "Start and stop times for a session"
+ },
+ "repeat_time": {
+ "type": "string",
+ "optional": true,
+ "description": "Specify repeat times for a session"
+ },
+ "timezone": {
+ "type": "string",
+ "optional": true,
+ "description": "Timezone to specify adjustments for times and offsets from the base time"
+ },
+ "encryption_key": {
+ "type": "string",
+ "optional": true,
+ "description": "Field used to convey encryption keys if SDP is used over a secure channel"
+ },
+ "attributes": {
+ "type": "array",
+ "optional": true,
+ "description": "A list of attributes to extend SDP",
+ "minItems": 1,
+ "items": {
+ "type": "string",
+ "description": "Attribute's name and value"
+ }
+ },
+ "media_descriptions": {
+ "type": "array",
+ "description": "A list of media descriptions for a session",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "optional": true,
+ "properties": {
+ "media": {
+ "type": "string",
+ "description": "Media description"
+ },
+ "media_info": {
+ "type": "string",
+ "optional": true,
+ "description": "Media information primarily intended for labelling media streams"
+ },
+ "bandwidths": {
+ "type": "array",
+ "optional": true,
+ "description": "A list of bandwidth proposed for a media",
+ "minItems": 1,
+ "items": {
+ "type": "string"
+ }
+ },
+ "connection_data": {
+ "type": "string",
+ "optional": true,
+ "description": "Connection data per media description"
+ },
+ "attributes": {
+ "type": "array",
+ "description": "A list of attributes specified for a media description",
+ "optional": true,
+ "minItems": 1,
+ "items": {
+ "type": "string",
+ "description": "Attribute's name and value"
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
}
},
"additionalProperties": false
--- /dev/null
+/* Copyright (C) 2024 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
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+// written by Giuseppe Longo <giuseppe@glongo.it>
+
+use crate::jsonbuilder::{JsonBuilder, JsonError};
+
+use super::parser::{ConnectionData, MediaDescription, SdpMessage};
+
+pub fn sdp_log(msg: &SdpMessage, js: &mut JsonBuilder) -> Result<(), JsonError> {
+ js.open_object("sdp")?;
+
+ let origin = format!(
+ "{} {} {} {} {} {}",
+ &msg.origin.username,
+ &msg.origin.sess_id,
+ &msg.origin.sess_version,
+ &msg.origin.nettype,
+ &msg.origin.addrtype,
+ &msg.origin.unicast_address
+ );
+
+ js.set_string("origin", &origin)?;
+ js.set_string("session_name", &msg.session_name)?;
+
+ if let Some(session_info) = &msg.session_info {
+ js.set_string("session_info", session_info)?;
+ }
+ if let Some(uri) = &msg.uri {
+ js.set_string("uri", uri)?;
+ }
+ if let Some(email) = &msg.email {
+ js.set_string("email", email)?;
+ }
+ if let Some(phone_number) = &msg.phone_number {
+ js.set_string("phone_number", phone_number)?;
+ }
+ if let Some(conn_data) = &msg.connection_data {
+ log_connection_data(conn_data, js)?;
+ }
+ if let Some(bws) = &msg.bandwidths {
+ log_bandwidth(bws, js)?;
+ }
+ js.set_string("time", &msg.time)?;
+ if let Some(repeat_time) = &msg.repeat_time {
+ js.set_string("repeat_time", repeat_time)?;
+ }
+ if let Some(tz) = &msg.time_zone {
+ js.set_string("timezone", tz)?;
+ }
+ if let Some(enc_key) = &msg.encryption_key {
+ js.set_string("encryption_key", enc_key)?;
+ }
+ if let Some(attrs) = &msg.attributes {
+ log_attributes(attrs, js)?;
+ }
+ if let Some(media) = &msg.media_description {
+ log_media_description(media, js)?;
+ }
+ js.close()?;
+ Ok(())
+}
+
+fn log_media_description(
+ media: &Vec<MediaDescription>, js: &mut JsonBuilder,
+) -> Result<(), JsonError> {
+ if !media.is_empty() {
+ js.open_array("media_descriptions")?;
+ for m in media {
+ js.start_object()?;
+ let port = if let Some(num_ports) = m.number_of_ports {
+ format!("{}/{}", m.port, num_ports)
+ } else {
+ format!("{}", m.port)
+ };
+ let mut media = format!("{} {} {}", &m.media, &port, &m.proto);
+ for f in &m.fmt {
+ media = format!("{} {}", media, f);
+ }
+ js.set_string("media", &media)?;
+
+ if let Some(session_info) = &m.session_info {
+ js.set_string("media_info", session_info)?;
+ };
+ if let Some(bws) = &m.bandwidths {
+ log_bandwidth(bws, js)?;
+ }
+ if let Some(conn_data) = &m.connection_data {
+ log_connection_data(conn_data, js)?;
+ }
+ if let Some(attrs) = &m.attributes {
+ log_attributes(attrs, js)?;
+ }
+ js.close()?;
+ }
+ }
+ js.close()?;
+
+ Ok(())
+}
+
+fn log_bandwidth(bws: &Vec<String>, js: &mut JsonBuilder) -> Result<(), JsonError> {
+ if !bws.is_empty() {
+ js.open_array("bandwidths")?;
+ for bw in bws {
+ js.append_string(bw)?;
+ }
+ js.close()?;
+ }
+ Ok(())
+}
+
+fn log_connection_data(conn_data: &ConnectionData, js: &mut JsonBuilder) -> Result<(), JsonError> {
+ let mut conn = format!(
+ "{} {} {}",
+ &conn_data.nettype,
+ &conn_data.addrtype,
+ &conn_data.connection_address.to_string()
+ );
+ if let Some(ttl) = conn_data.ttl {
+ conn = format!("{}/{}", conn, ttl);
+ js.set_uint("ttl", ttl as u64)?;
+ }
+ if let Some(num_addrs) = conn_data.number_of_addresses {
+ conn = format!("{}/{}", conn, num_addrs);
+ }
+ js.set_string("connection_data", &conn)?;
+ Ok(())
+}
+
+fn log_attributes(attrs: &Vec<String>, js: &mut JsonBuilder) -> Result<(), JsonError> {
+ if !attrs.is_empty() {
+ js.open_array("attributes")?;
+ for attr in attrs {
+ js.append_string(attr)?;
+ }
+ js.close()?;
+ }
+ Ok(())
+}