sngrep/src/sip.h

594 lines
15 KiB
C

/**************************************************************************
**
** sngrep - SIP Messages flow viewer
**
** Copyright (C) 2013,2014 Ivan Alonso (Kaian)
** Copyright (C) 2013,2014 Irontec SL. All rights reserved.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** 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
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
/**
* @file sip.h
* @author Ivan Alonso [aka Kaian] <kaian@irontec.com>
*
* @brief Functions to manage SIP calls and messages
*
* This file contains the functions and structures to manage the SIP calls and
* messages.
*/
#ifndef __SNGREP_SIP_H
#define __SNGREP_SIP_H
#include <pcap.h>
#include <sys/time.h>
#include <pthread.h>
#include <arpa/inet.h>
/* Some very used macros */
#define CALLID(msg) msg_get_attribute(msg, SIP_ATTR_CALLID)
#define SRC(msg) msg_get_attribute(msg, SIP_ATTR_SRC)
#define DST(msg) msg_get_attribute(msg, SIP_ATTR_DST)
//! Shorter declaration of sip_call structure
typedef struct sip_call sip_call_t;
//! Shorter declaration of sip_msg structure
typedef struct sip_msg sip_msg_t;
//! Shorter declaration of sip_attr structure
typedef struct sip_attr_hdr sip_attr_hdr_t;
//! Shorter declaration of sip_attr structure
typedef struct sip_attr sip_attr_t;
/**
* @brief Available SIP Attributes
*
* This enum contains the list of available attributes
* a call or message can have.
*/
enum sip_attr_id
{
//! SIP Message From: header
SIP_ATTR_SIPFROM = 1,
//! SIP Message To: header
SIP_ATTR_SIPTO,
//! Package IP source address and port
SIP_ATTR_SRC,
//! Package source lookup and port
SIP_ATTR_SRC_HOST,
//! Package IP destiny address and port
SIP_ATTR_DST,
//! Package destiny lookup and port
SIP_ATTR_DST_HOST,
//! SIP Message Call-ID header
SIP_ATTR_CALLID,
//! SIP Message X-Call-ID or X-CID header
SIP_ATTR_XCALLID,
//! SIP Message Date
SIP_ATTR_DATE,
//! SIP Message Time
SIP_ATTR_TIME,
//! SIP Message Method or Response code
SIP_ATTR_METHOD,
//! SIP Message is a request
SIP_ATTR_REQUEST,
//! SIP CSeq number
SIP_ATTR_CSEQ,
//! SIP Message has sdp
SIP_ATTR_SDP,
//! SDP Address
SIP_ATTR_SDP_ADDRESS,
//! SDP Port
SIP_ATTR_SDP_PORT,
//! SIP Message transport
SIP_ATTR_TRANSPORT,
//! SIP Call first message method
SIP_ATTR_STARTING,
//! SIP Call message counter
SIP_ATTR_MSGCNT,
};
/**
* @brief Attribute header data
*
* This sctructure contains the information about the
* attribute, description, id, type and so. It's the
* static information of the attributed shared by all
* attributes pointer to its type.
*
*/
struct sip_attr_hdr
{
//! Attribute id
enum sip_attr_id id;
//! Attribute name
char *name;
//! Attribute description
char *desc;
};
/**
* @brief Attribute data structure
*
* This structure contains a single attribute value and acts
* as a linked list for all attributes of a message (or call)
* Right now, all the attributed are stored as strings, which may
* not be the better option, but will fit our actual needs.
*/
struct sip_attr
{
//! Attribute header pointer
sip_attr_hdr_t *hdr;
//! Attribute value
const char *value;
//! Next attribute in the linked list
sip_attr_t *next;
};
/**
* @brief Information of a single message withing a dialog.
*
* Most of the data is just stored to be displayed in the UI so
* the formats may be no the best, but the simplest for this
* purpose. It also works as a linked lists of messages in a
* call.
*/
struct sip_msg
{
//! Message attribute list
sip_attr_t *attrs;
//! Timestamp
struct timeval ts;
//! Source address
struct in_addr src;
//! Source port
u_short sport;
//! Destiny address
struct in_addr dst;
//! Destiny port
u_short dport;
//! Temporal payload data before being parsed
char *payloadptr;
//! FIXME Payload in one struct
const char *payload[256];
//!! FIXME not required
int plines;
//! Flag to mark if payload data has been parsed
int parsed;
//! Color for this message (in color.cseq mode)
int color;
//! PCAP Packet Header data
struct pcap_pkthdr *pcap_header;
//! PCAP Packet data
u_char *pcap_packet;
//! Message owner
sip_call_t *call;
//! Messages linked list
sip_msg_t *next;
};
/**
* @brief Contains all information of a call and its messages
*
* This structure acts as header of messages list of the same
* callid (considered a dialog). It contains some replicated
* data from its messages to speed up searches.
*/
struct sip_call
{
//! Call attribute list
sip_attr_t *attrs;
//! List of messages of this call
sip_msg_t *msgs;
// Call Lock
pthread_mutex_t lock;
//! Calls double linked list
sip_call_t *next, *prev;
//! Last used color (for color.cseq)
int color;
};
/**
* @brief Create a new message from the readed header and payload
*
* Allocate required memory for a new SIP message. This function
* will only store the given information, but wont parse it until
* needed.
*
* @param payload Raw payload content
* @return a new allocated message
*/
sip_msg_t *
sip_msg_create(const char *payload);
/**
* @brief Destroy a SIP message and free its memory
*
* Deallocate memory of an existing SIP Message.
* This function will remove the message from the call and the
* passed pointer will be NULL.
*
* @param msg SIP message to be deleted
*/
void
sip_msg_destroy(sip_msg_t *msg);
/**
* @brief Create a new call with the given callid (Minimum required data)
*
* Allocated required memory for a new SIP Call. The call acts as
* header structure to all the messages with the same callid.
*
* @param callid Call-ID Header value
* @return pointer to the sip_call created
*/
sip_call_t *
sip_call_create(char *callid);
/**
* @brief Free all related memory from a call and remove from call list
*
* Deallocate memory of an existing SIP Call.
* This will also remove all messages, calling sip_msg_destroy for each
* one.
*
* @param call Call to be destroyed
*/
void
sip_call_destroy(sip_call_t *call);
/**
* @brief Parses Call-ID header of a SIP message payload
*
* Mainly used to check if a payload contains a callid.
*
* @param payload SIP message payload
* @return callid parsed from Call-ID header
*/
char *
sip_get_callid(const char* payload);
/**
* @brief Loads a new message from raw header/payload
*
* Use this function to convert raw data into call and message
* structures. This is mainly used to load data from a file or
*
* @todo This functions should stop using ngrep header format
*
* @param header Raw ngrep header
* @param payload Raw ngrep payload
* @return a SIP msg structure pointer
*/
sip_msg_t *
sip_load_message(struct timeval tv, struct in_addr src, u_short sport, struct in_addr dst,
u_short dport, u_char *payload);
/**
* @brief Getter for calls linked list size
*
* @return how many calls are linked in the list
*/
int
sip_calls_count();
/**
* @brief Check if this call is affected by filters
*
* This function is internally used to check if the call should not
* be returned by general getters because is filtered.
*
* @param call Call to check
* @return 1 if call is filtered, 0 otherwise
*/
int
sip_check_call_ignore(sip_call_t *call);
/**
* @brief Get the header information of an Attribute
*
* Retrieve header data from attribute list
*
* @param id Attribute id
* @return Attribute header data structure pointer
*/
sip_attr_hdr_t *
sip_attr_get_header(enum sip_attr_id id);
/**
* @brief Get Attribute description
*
* Retrieve description of given attribute from its
* header structure.
*
* @param id Attribut id
* @return Attribute description from its header
*/
const char *
sip_attr_get_description(enum sip_attr_id id);
/**
* @brief Get Attribute name
*
* Retrieve name of given attribute from its
* header structure.
*
* @param id Attribut id
* @return Attribute name from its header
*/
const char *
sip_attr_get_name(enum sip_attr_id id);
/**
* @brief Get Attribute id from its name
*
* Retrieve attribute id of the given attribute name.
*
* @param name Attribut name
* @return Attribute id or 0 if not found
*/
enum sip_attr_id
sip_attr_from_name(const char *name);
/**
* @brief Sets the given attribute value to an attribute
*
* Primitive for setting an attribute value of a given attribute list.
* This can be used for calls and message attributes.
*
* @param list Pointer to the attribute list
* @param id Attribute id
* @param value Attribute value
*/
void
sip_attr_set(sip_attr_t **list, enum sip_attr_id id, const char *value);
/**
* @brief Gets the given attribute value to an attribute
*
* Primitive for getting an attribute value of a given attribute list.
* This can be used for calls and message attributes.
*
*/
const char *
sip_attr_get(sip_attr_t *list, enum sip_attr_id id);
/**
* @brief Append message to the call's message list
*
* Creates a relation between this call and the message, appending it
* to the end of the message list and setting the message owner.
*
* @param call pointer to the call owner of the message
* @param msg SIP message structure
*/
void
call_add_message(sip_call_t *call, sip_msg_t *msg);
/**
* @brief Find a call structure in calls linked list given an callid
*
*
*
* @param callid Call-ID Header value
* @return pointer to the sip_call structure found or NULL
*/
sip_call_t *
call_find_by_callid(const char *callid);
/**
* @brief Find a call structure in calls linked list given an xcallid
*
* Find the call that have the xcallid attribute equal tot he given
* value.
*
* @param xcallid X-Call-ID or X-CID Header value
* @return pointer to the sip_call structure found or NULL
*/
sip_call_t *
call_find_by_xcallid(const char *xcallid);
/**
* @brief Getter for call messages linked list size
*
* Return the number of messages stored in this call. All messages
* share the same Call-ID
*
* @param call SIP call structure
* @return how many messages are in the call
*/
int
call_msg_count(sip_call_t *call);
/**
* @brief Finds the other leg of this call.
*
* If this call has a X-CID or X-Call-ID header, that call will be
* find and returned. Otherwise, a call with X-CID or X-Call-ID header
* matching the given call's Call-ID will be find or returned.
*
* @param call SIP call structure
* @return The other call structure or NULL if none found
*/
sip_call_t *
call_get_xcall(sip_call_t *call);
/**
* @brief Finds the next msg in a call.
*
* If the passed msg is NULL it returns the first message
* in the call
*
* @param call SIP call structure
* @param msg Actual SIP msg from the call (can be NULL)
* @return Next chronological message in the call
*/
sip_msg_t *
call_get_next_msg(sip_call_t *call, sip_msg_t *msg);
/**
* @brief Finds the prev msg in a call.
*
* If the passed msg is the first message in the call
* this function will return NULL
*
* @param call SIP call structure
* @param msg Actual SIP msg from the call
* @return Previous chronological message in the call
*/
sip_msg_t *
call_get_prev_msg(sip_call_t *call, sip_msg_t *msg);
/**
* @brief Get next call after applying filters and ignores
*
* General getter for call list. Never access calls list
* directly, use this instead.
*
* @param cur Current call. Pass NULL to get the first call.
* @return Next call in the list or NULL if there is no next call
*/
sip_call_t *
call_get_next(sip_call_t *cur);
/**
* @brief Get previous call after applying filters and ignores
*
* General getter for call list. Never access calls list
* directly, use this instead.
*
* @param cur Current call
* @return Prev call in the list or NULL if there is no previous call
*/
sip_call_t *
call_get_prev(sip_call_t *cur);
/**
* @brief Sets the attribute value for a given call
*
* This function acts as wrapper of sip call attributes
*
* @param call SIP call structure
* @param id Attribute id
* @param value Attribute value
*/
void
call_set_attribute(sip_call_t *call, enum sip_attr_id id, const char *value);
/**
* @brief Return a call attribute value
*
* This function will be used to avoid accessing call structure
* fields directly.
* @todo Code a proper way to store this information
*
* @param call SIP call structure
* @param id Attribute id
* @return Attribute value or NULL if not found
*/
const char *
call_get_attribute(sip_call_t *call, enum sip_attr_id id);
/**
* @brief Parse ngrep header line to get timestamps and ip addresses
*
* This function will convert the ngrep header line in format:
* U DD/MM/YY hh:mm:ss.uuuuuu fff.fff.fff.fff:pppp -> fff.fff.fff.fff:pppp
*
* to some attributes.
*
* @todo This MUST disappear someday.
*
* @param msg SIP message structure
* @param header ngrep header generated by -qpt arguments
* @return 0 on success, 1 on malformed header
*/
int
msg_parse_header(sip_msg_t *msg, const char *header);
/**
* @brief Parse SIP Message payload to fill sip_msg structe
*
* Parse the payload content to set message attributes.
*
* @param msg SIP message structure
* @param payload SIP message payload
* @return 0 in all cases
*/
int
msg_parse_payload(sip_msg_t *msg, const char *payload);
/**
* @brief Parse internal header and payload
*
* By default, only the first message of each call is parsed.
* This function will parse the message (if it's not already parsed)
* filling all internal fields.
*
* @param msg Not Parsed (or parsed) message
* @return a parsed message
*/
sip_msg_t *
msg_parse(sip_msg_t *msg);
/**
* @brief Sets the attribute value for a given message
*
* This function acts as wrapper of sip message attributes
*
* @param msg SIP message structure
* @param id Attribute id
* @param value Attribute value
*/
void
msg_set_attribute(sip_msg_t *msg, enum sip_attr_id id, const char *value);
/**
* @brief Return a message attribute value
*
* This function will be used to avoid accessing call structure
* fields directly.
*
* @param msg SIP message structure
* @param id Attribute id
* @return Attribute value or NULL if not found
*/
const char *
msg_get_attribute(sip_msg_t *msg, enum sip_attr_id id);
/**
* @brief Check if a package is a retransmission
*
* This function will compare its payload with the previous message
* in the dialog, to check if it has the same content.
*
* @param msg SIP message that will be checked
* @return 1 if the previous message is equal to msg, 0 otherwise
*/
int
msg_is_retrans(sip_msg_t *msg);
/**
* @brief Remove al calls
*
* This funtion will clear the call list invoking the destroy
* function for each one.
*/
void
sip_calls_clear();
#endif