|
@@ -113,18 +113,26 @@ static str direction_column = str_init("direction"); /* 09 */
|
|
|
|
|
|
#define NR_KEYS 10
|
|
|
|
|
|
+#define XHEADERS_BUFSIZE 512
|
|
|
+
|
|
|
int trace_flag = -1;
|
|
|
int trace_on = 0;
|
|
|
int trace_sl_acks = 1;
|
|
|
|
|
|
int trace_to_database = 1;
|
|
|
|
|
|
+int xheaders_write = 0;
|
|
|
+int xheaders_read = 0;
|
|
|
+
|
|
|
str dup_uri_str = {0, 0};
|
|
|
struct sip_uri *dup_uri = 0;
|
|
|
|
|
|
int *trace_on_flag = NULL;
|
|
|
int *trace_to_database_flag = NULL;
|
|
|
|
|
|
+int *xheaders_write_flag = NULL;
|
|
|
+int *xheaders_read_flag = NULL;
|
|
|
+
|
|
|
static unsigned short traced_user_avp_type = 0;
|
|
|
static int_str traced_user_avp;
|
|
|
static str traced_user_avp_str = {NULL, 0};
|
|
@@ -172,6 +180,8 @@ static param_export_t params[] = {
|
|
|
{"trace_to_database", INT_PARAM, &trace_to_database },
|
|
|
{"trace_local_ip", STR_PARAM, &trace_local_ip.s },
|
|
|
{"trace_sl_acks", INT_PARAM, &trace_sl_acks },
|
|
|
+ {"xheaders_write", INT_PARAM, &xheaders_write },
|
|
|
+ {"xheaders_read", INT_PARAM, &xheaders_read },
|
|
|
{0, 0, 0}
|
|
|
};
|
|
|
|
|
@@ -294,6 +304,15 @@ static int mod_init(void)
|
|
|
|
|
|
*trace_to_database_flag = trace_to_database;
|
|
|
|
|
|
+ xheaders_write_flag = (int*)shm_malloc(sizeof(int));
|
|
|
+ xheaders_read_flag = (int*)shm_malloc(sizeof(int));
|
|
|
+ if (!(xheaders_write_flag && xheaders_read_flag)) {
|
|
|
+ LM_ERR("no more shm memory left\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ *xheaders_write_flag = xheaders_write;
|
|
|
+ *xheaders_read_flag = xheaders_read;
|
|
|
+
|
|
|
/* register callbacks to TM */
|
|
|
if (load_tm_api(&tmb)!=0)
|
|
|
{
|
|
@@ -474,6 +493,153 @@ error:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+// Appends x-headers to the message in sto->body containing data from sto
|
|
|
+static int sip_trace_xheaders_write(struct _siptrace_data *sto)
|
|
|
+{
|
|
|
+ if(xheaders_write_flag==NULL || *xheaders_write_flag==0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ // Memory for the message with some additional headers.
|
|
|
+ // It gets free()ed in sip_trace_xheaders_free().
|
|
|
+ char* buf = malloc(sto->body.len + XHEADERS_BUFSIZE);
|
|
|
+ if (buf == NULL) {
|
|
|
+ LM_ERR("sip_trace_xheaders_write: out of memory\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Copy the whole message to buf first; it must be \0-terminated for
|
|
|
+ // strstr() to work. Then search for the end-of-header sequence.
|
|
|
+ memcpy(buf, sto->body.s, sto->body.len);
|
|
|
+ buf[sto->body.len] = '\0';
|
|
|
+ char* eoh = strstr(buf, "\r\n\r\n");
|
|
|
+ if (eoh == NULL) {
|
|
|
+ LM_ERR("sip_trace_xheaders_write: malformed message\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ eoh += 2; // the first \r\n belongs to the last header => skip it
|
|
|
+
|
|
|
+ // Write the new headers a the end-of-header position. This overwrites
|
|
|
+ // the \r\n terminating the old headers and the beginning of the message
|
|
|
+ // body. Both will be recovered later.
|
|
|
+ int bytes_written = snprintf(eoh, XHEADERS_BUFSIZE,
|
|
|
+ "X-Siptrace-Fromip: %.*s\r\n"
|
|
|
+ "X-Siptrace-Toip: %.*s\r\n"
|
|
|
+ "X-Siptrace-Method: %.*s\r\n"
|
|
|
+ "X-Siptrace-Dir: %s\r\n",
|
|
|
+ sto->fromip.len, sto->fromip.s,
|
|
|
+ sto->toip.len, sto->toip.s,
|
|
|
+ sto->method.len, sto->method.s,
|
|
|
+ sto->dir);
|
|
|
+ if (bytes_written >= XHEADERS_BUFSIZE) {
|
|
|
+ LM_ERR("sip_trace_xheaders_write: string too long\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Copy the \r\n terminating the old headers and the message body from the
|
|
|
+ // old buffer in sto->body.s to the new end-of-header in buf.
|
|
|
+ int eoh_offset = eoh - buf;
|
|
|
+ char* new_eoh = eoh + bytes_written;
|
|
|
+ memcpy(new_eoh, sto->body.s + eoh_offset, sto->body.len - eoh_offset);
|
|
|
+
|
|
|
+ // Change sto to point to the new buffer.
|
|
|
+ sto->body.s = buf;
|
|
|
+ sto->body.len += bytes_written;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+// Parses x-headers, saves the data back to sto, and removes the x-headers
|
|
|
+// from the message in sto->buf
|
|
|
+static int sip_trace_xheaders_read(struct _siptrace_data *sto)
|
|
|
+{
|
|
|
+ if(xheaders_read_flag==NULL || *xheaders_read_flag==0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ // Find the end-of-header marker \r\n\r\n
|
|
|
+ char* searchend = sto->body.s + sto->body.len - 3;
|
|
|
+ char* eoh = memchr(sto->body.s, '\r', searchend - eoh);
|
|
|
+ while (eoh != NULL && eoh < searchend) {
|
|
|
+ if (memcmp(eoh, "\r\n\r\n", 4) == 0)
|
|
|
+ break;
|
|
|
+ eoh = memchr(eoh + 1, '\r', searchend - eoh);
|
|
|
+ }
|
|
|
+ if (eoh == NULL) {
|
|
|
+ LM_ERR("sip_trace_xheaders_read: malformed message\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Find x-headers: eoh will be overwritten by \0 to allow the use of
|
|
|
+ // strstr(). The byte at eoh will later be recovered, when the
|
|
|
+ // message body is shifted towards the beginning of the message
|
|
|
+ // to remove the x-headers.
|
|
|
+ *eoh = '\0';
|
|
|
+ char* xheaders = strstr(sto->body.s, "\r\nX-Siptrace-Fromip: ");
|
|
|
+ if (xheaders == NULL) {
|
|
|
+ LM_ERR("sip_trace_xheaders_read: message without x-headers "
|
|
|
+ "from %.*s, callid %.*s\n",
|
|
|
+ sto->fromip.len, sto->fromip.s, sto->callid.len, sto->callid.s);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Allocate memory for new strings in sto
|
|
|
+ // (gets free()ed in sip_trace_xheaders_free() )
|
|
|
+ sto->fromip.s = malloc(51);
|
|
|
+ sto->toip.s = malloc(51);
|
|
|
+ sto->method.s = malloc(51);
|
|
|
+ sto->dir = malloc(4);
|
|
|
+ if (!(sto->fromip.s && sto->toip.s && sto->method.s && sto->dir)) {
|
|
|
+ LM_ERR("sip_trace_xheaders_read: out of memory\n");
|
|
|
+ goto erroraftermalloc;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Parse the x-headers: scanf()
|
|
|
+ if (sscanf(xheaders, "\r\n"
|
|
|
+ "X-Siptrace-Fromip: %50s\r\n"
|
|
|
+ "X-Siptrace-Toip: %50s\r\n"
|
|
|
+ "X-Siptrace-Method: %50s\r\n"
|
|
|
+ "X-Siptrace-Dir: %3s",
|
|
|
+ sto->fromip.s, sto->toip.s,
|
|
|
+ sto->method.s,
|
|
|
+ sto->dir) == EOF) {
|
|
|
+ LM_ERR("sip_trace_xheaders_read: malformed x-headers\n");
|
|
|
+ goto erroraftermalloc;
|
|
|
+ }
|
|
|
+ sto->fromip.len = strlen(sto->fromip.s);
|
|
|
+ sto->toip.len = strlen(sto->toip.s);
|
|
|
+ sto->method.len = strlen(sto->method.s);
|
|
|
+
|
|
|
+ // Remove the x-headers: the message body is shifted towards the beginning
|
|
|
+ // of the message, overwriting the x-headers. Before that, the byte at eoh
|
|
|
+ // is recovered.
|
|
|
+ *eoh = '\r';
|
|
|
+ memmove(xheaders, eoh, sto->body.len - (eoh - sto->body.s));
|
|
|
+ sto->body.len -= eoh - xheaders;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+erroraftermalloc:
|
|
|
+ if (sto->fromip.s) free(sto->fromip.s);
|
|
|
+ if (sto->toip.s) free(sto->toip.s);
|
|
|
+ if (sto->method.s) free(sto->method.s);
|
|
|
+ if (sto->dir) free(sto->dir);
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+// Frees the memory allocated by sip_trace_xheaders_{write,read}
|
|
|
+static int sip_trace_xheaders_free(struct _siptrace_data *sto)
|
|
|
+{
|
|
|
+ if (xheaders_write_flag != NULL && *xheaders_write_flag != 0) {
|
|
|
+ free(sto->body.s);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (xheaders_read_flag != NULL && *xheaders_read_flag != 0) {
|
|
|
+ free(sto->fromip.s);
|
|
|
+ free(sto->toip.s);
|
|
|
+ free(sto->dir);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int sip_trace_store(struct _siptrace_data *sto)
|
|
|
{
|
|
|
if(sto==NULL)
|
|
@@ -482,8 +648,15 @@ static int sip_trace_store(struct _siptrace_data *sto)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+ if (sip_trace_xheaders_read(sto) != 0) return -1;
|
|
|
+ int ret = sip_trace_store_db(sto);
|
|
|
+
|
|
|
+ if (sip_trace_xheaders_write(sto) != 0) return -1;
|
|
|
trace_send_duplicate(sto->body.s, sto->body.len);
|
|
|
- return sip_trace_store_db(sto);
|
|
|
+
|
|
|
+ if (sip_trace_xheaders_free(sto) != 0) return -1;
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int sip_trace_store_db(struct _siptrace_data *sto)
|