Bug Summary

File:tport_logging.c
Warning:line 835, column 12
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name tport_logging.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-11/lib/clang/11.0.1 -D HAVE_CONFIG_H -I . -I ../.. -I ../../libsofia-sip-ua/su/sofia-sip -I ./../bnf -I ../bnf -I ./../stun -I ../stun -I ./../ipt -I ../ipt -I ./../msg -I ../msg -I ./../http -I ../http -I ./../url -I ../url -I ./../sip -I ../sip -I ./../su -I ../su -I ./include -D SU_DEBUG=0 -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /drone/src/libsofia-sip-ua/tport -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -o /drone/src/scan-build/2022-10-18-034115-12-1 -x c tport_logging.c
1/*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2006 Nokia Corporation.
5 *
6 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25/**@CFILE tport_logging.c Logging transported messages.
26 *
27 * See tport.docs for more detailed description of tport interface.
28 *
29 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
30 * @author Martti Mela <Martti.Mela@nokia.com>
31 *
32 * @date Created: Fri Mar 24 08:45:49 EET 2006 ppessi
33 */
34
35#include "config.h"
36#include "msg_internal.h"
37
38#include "tport_internal.h"
39
40#include <sofia-sip/su.h>
41#include <sofia-sip/su_string.h>
42#include <stdlib.h>
43#include <time.h>
44#include <assert.h>
45#include <errno(*__errno_location ()).h>
46#include <limits.h>
47
48#define TPORT_STAMP_SIZE144 144
49
50/**@var TPORT_LOG
51 *
52 * Environment variable determining if parsed message contents are logged.
53 *
54 * If the TPORT_LOG environment variable is set, the tport module logs the
55 * contents of parsed messages. This eases debugging the signaling greatly.
56 *
57 * @sa TPORT_DUMP, TPORT_DEBUG, tport_log
58 */
59#ifdef DOXYGEN
60extern char const TPORT_LOG[]; /* dummy declaration for Doxygen */
61#endif
62
63/**@var TPORT_DUMP
64 *
65 * Environment variable for transport data dump.
66 *
67 * The received and sent data is dumped to the file specified by TPORT_DUMP
68 * environment variable. This can be used to save message traces and help
69 * hairy debugging tasks.
70 *
71 * @sa TPORT_LOG, TPORT_DEBUG, tport_log
72 */
73#ifdef DOXYGEN
74extern char const TPORT_DUMP[]; /* dummy declaration for Doxygen */
75#endif
76
77/**@var TPORT_CAPT
78 *
79 * Environment variable for transport data capturing.
80 *
81 * The received and sent data is dumped to the capture server specified by TPORT_CAPT
82 * environment variable. This can be used to save message traces into database and help
83 * hairy debugging tasks.
84 *
85 * @sa TPORT_LOG, TPORT_DEBUG, TPORT_CAPT, TPORT_CAPT_SRC, tport_log
86 */
87#ifdef DOXYGEN
88extern char const TPORT_CAPT[]; /* dummy declaration for Doxygen */
89#endif
90
91/**@var TPORT_DEBUG
92 *
93 * Environment variable determining the debug log level for @b tport module.
94 *
95 * The TPORT_DEBUG environment variable is used to determine the debug logging
96 * level for @b tport module. The default level is 3.
97 *
98 * @sa <sofia-sip/su_debug.h>, tport_log, SOFIA_DEBUG
99 */
100#ifdef DOXYGEN
101extern char const TPORT_DEBUG[]; /* dummy declaration for Doxygen */
102#endif
103
104/**Debug log for @b tport module.
105 *
106 * The tport_log is the log object used by @b tport module. The level of
107 * #tport_log is set using #TPORT_DEBUG environment variable.
108 */
109su_log_t tport_log[] = {
110 SU_LOG_INIT("tport", "TPORT_DEBUG", SU_DEBUG){ sizeof(su_log_t), "tport", "TPORT_DEBUG", 0, SU_LOG_MAX, 0,
((void*)0), ((void*)0), }
111};
112
113
114
115/** Initialize logging. */
116int tport_open_log(tport_master_t *mr, tagi_t *tags)
117{
118 int n;
119 int log_msg = mr->mr_log != 0;
120 char const *dump = NULL((void*)0);
121 char const *capt = NULL((void*)0);;
122 char const *capt_src = NULL((void*)0);
123
124 if(mr->mr_capt_name) capt = mr->mr_capt_name;
125
126 n = tl_gets(tags,
127 TPTAG_LOG_REF(log_msg)tptag_log_ref, tag_bool_vr(&(log_msg)),
128 TPTAG_DUMP_REF(dump)tptag_dump_ref, tag_str_vr(&(dump)),
129 TPTAG_CAPT_REF(capt)tptag_capt_ref, tag_str_vr(&(capt)),
130 TPTAG_CAPT_SRC_REF(capt_src)tptag_capt_src_ref, tag_str_vr(&(capt_src)),
131 TAG_END()(tag_type_t)0, (tag_value_t)0);
132
133 if (getenv("MSG_STREAM_LOG") != NULL((void*)0) || getenv("TPORT_LOG") != NULL((void*)0))
134 log_msg = 1;
135 mr->mr_log = log_msg ? MSG_DO_EXTRACT_COPYMSG_FLG_EXTRACT_COPY : 0;
136
137 if (getenv("TPORT_CAPT"))
138 capt = getenv("TPORT_CAPT");
139 if (getenv("MSG_DUMP"))
140 dump = getenv("MSG_DUMP");
141 if (getenv("TPORT_DUMP"))
142 dump = getenv("TPORT_DUMP");
143
144 /* Overriding src address for HEP */
145 if (capt_src && !mr->mr_capt_src_addr) {
146 su_addrinfo_t *ai = NULL((void*)0), hints[1] = {{ 0 }};
147 hints->ai_flags = AI_NUMERICSERV0x0400;
148 hints->ai_family = AF_UNSPEC0;
149 if (su_getaddrinfo(capt_src, "", hints, &ai)) {
150 su_perror("capture_src: su_getaddrinfo()");
151 } else {
152 mr->mr_capt_src_addr = ai;
153 }
154 }
155
156 if(capt) {
157
158 char *captname, *p, *host_s;
159 char port[10];
160 su_addrinfo_t *ai = NULL((void*)0), hints[1] = {{ 0 }};
161 unsigned len =0, iport = 0;
162
163
164
165 if (mr->mr_capt_name && mr->mr_capt_sock && strcmp(capt, mr->mr_capt_name) == 0)
166 return n;
167
168 captname = su_strdup(mr->mr_homemr_master->tp_home, capt);
169 if (captname == NULL((void*)0))
170 return n;
171
172 if(strncmp(captname, "udp:",4) != 0) {
173 su_log("tport_open_log: capturing. Only udp protocol supported [%s]\n", captname);
174 return n;
175 }
176
177 /* separate proto and host */
178 p = captname+4;
179 if( (*(p)) == '\0') {
180 su_log("malformed ip address\n");
181 return n;
182 }
183 host_s = p;
184
185 if( (p = strrchr(p+1, ':')) == 0 ) {
186 su_log("no host or port specified\n");
187 return n;
188 }
189
190 /*the address contains a port number*/
191 *p = '\0';
192 p++;
193
194 iport = atoi(p);
195
196 if (iport <1024 || iport >65536)
197 {
198 su_log("invalid port number; must be in [1024,65536]\n");
199 return n;
200 }
201
202 snprintf(port, sizeof(port), "%d", iport);
203
204 /* default values for capture protocol and agent id */
205 mr->mr_prot_ver = 3;
206 mr->mr_agent_id = 200;
207 mr->mr_agent_nodename = "default";
208 /* get all params */
209 while(p)
210 {
211 /* check ; in the URL */
212 if( (p = strchr(p+1, ';')) == 0 ) {
213 break;
214 }
215
216 *p = '\0';
217 p++;
218
219 SU_DEBUG_7(("events HEP RRR DATA [%s]\n", p))(((tport_log != ((void*)0) && tport_log->log_init)
== 0 ? 9 : ((tport_log != ((void*)0) && tport_log->
log_init > 1) ? tport_log->log_level : su_log_default->
log_level)) >= 7 ? (_su_llog(tport_log, 7, "tport_logging.c"
, (const char *)__func__, 219, "events HEP RRR DATA [%s]\n", p
)) : (void)0)
;
220
221 if(strncmp(p, "hep=",4) == 0) {
222 p+=4;
223 mr->mr_prot_ver = atoi(p);
224 /* hepv3 come later */
225 if (mr->mr_prot_ver < 1 || mr->mr_prot_ver > 3)
226 {
227 su_log("invalid hep version number; must be in [1-3]\n");
228 mr->mr_prot_ver = 3;
229 return n;
230 }
231 }
232 else if(strncmp(p, "capture_id=", 11) == 0) {
233 p+=11;
234 if((mr->mr_agent_id = atoi(p)) == 0)
235 {
236 mr->mr_agent_id = 200;
237 su_log("invalid capture id number; must be uint32 \n");
238 return n;
239 }
240 }
241 else if(strncmp(p, "capture_nodename=", 17) == 0) {
242 p+=17;
243 mr->mr_agent_nodename = p;
244 }
245 else {
246 su_log("unsupported capture param\n");
247 return n;
248 }
249 }
250
251 /* check if we have [] */
252 if (host_s[0] == '[') {
253 len = strlen(host_s + 1) - 1;
254 if(host_s[len+1] != ']') {
255 su_log("bracket not closed\n");
256 return n;
257 }
258 memmove(host_s, host_s + 1, len);
259 host_s[len] = '\0';
260 }
261
262 /* and again */
263 captname = su_strdup(mr->mr_homemr_master->tp_home, capt);
264 if (captname == NULL((void*)0)) return n;
265
266 su_free(mr->mr_homemr_master->tp_home, mr->mr_capt_name);
267 mr->mr_capt_name = captname;
268
269 if (mr->mr_capt_sock)
270 su_close(mr->mr_capt_sock), mr->mr_capt_sock = 0;
271
272 /* HINTS && getaddrinfo */
273 hints->ai_flags = AI_NUMERICSERV0x0400;
274 hints->ai_family = AF_UNSPEC0;
275 hints->ai_socktype = SOCK_DGRAMSOCK_DGRAM;
276 hints->ai_protocol = IPPROTO_UDPIPPROTO_UDP;
277
278 if (su_getaddrinfo(host_s, port, hints, &ai)) {
279 su_perror("capture: su_getaddrinfo()");
280 return n;
281 }
282
283 mr->mr_capt_sock = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
284 if (mr->mr_capt_sock == INVALID_SOCKET((su_socket_t)INVALID_SOCKET)) {
285 su_perror("capture: invalid socket");
286 return n;
287 }
288
289 su_setblocking(mr->mr_capt_sock, 0); /* Don't block */
290
291 if (connect(mr->mr_capt_sock, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == -1) {
292 if (errno(*__errno_location ()) != EINPROGRESS115) {
293 su_perror("capture: socket connect");
294 return n;
295 }
296 }
297
298 su_freeaddrinfo(ai);
299 }
300 else if(mr->mr_capt_sock) {
301 /* close capture server*/
302 su_close(mr->mr_capt_sock);
303 mr->mr_capt_sock = 0;
304 }
305
306 if (dump) {
307 time_t now;
308 char *dumpname;
309
310 if (mr->mr_dump && strcmp(dump, mr->mr_dump) == 0)
311 return n;
312 dumpname = su_strdup(mr->mr_homemr_master->tp_home, dump);
313 if (dumpname == NULL((void*)0))
314 return n;
315 su_free(mr->mr_homemr_master->tp_home, mr->mr_dump);
316 mr->mr_dump = dumpname;
317
318 if (mr->mr_dump_file && mr->mr_dump_file != stdoutstdout)
319 fclose(mr->mr_dump_file), mr->mr_dump_file = NULL((void*)0);
320
321 if (strcmp(dumpname, "-"))
322 mr->mr_dump_file = fopen(dumpname, "ab"); /* XXX */
323 else
324 mr->mr_dump_file = stdoutstdout;
325
326 if (mr->mr_dump_file) {
327 time(&now);
328 fprintf(mr->mr_dump_file, "dump started at %s\n\n", ctime(&now));
329 }
330 }
331
332 return n;
333}
334
335/** Create log stamp */
336void tport_stamp(tport_t const *self, msg_t *msg,
337 char *stamp, char const *what,
338 size_t n, char const *via,
339 su_time_t now)
340{
341 char label[24] = "";
342 char *comp = "";
343 char name[SU_ADDRSIZE(48)] = "";
344 su_sockaddr_t const *su;
345 unsigned short second, minute, hour;
346 /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
347#if defined(HAVE_GETTIMEOFDAY1) || defined(HAVE_CLOCK_MONOTONIC1)
348 struct tm nowtm = { 0 };
349 time_t nowtime = (now.tv_sec - SU_TIME_EPOCH2208988800UL); /* see su_time0.c 'now' is not really 'now', so we decrease it by SU_TIME_EPOCH */
350#endif
351
352 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 352, __extension__
__PRETTY_FUNCTION__); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport_logging.c", 352, __extension__ __PRETTY_FUNCTION__
); }))
;
353
354#if defined(HAVE_GETTIMEOFDAY1) || defined(HAVE_CLOCK_MONOTONIC1)
355 localtime_r(&nowtime, &nowtm);
356 second = nowtm.tm_sec;
357 minute = nowtm.tm_min;
358 hour = nowtm.tm_hour;
359#else
360 second = (unsigned short)(now.tv_sec % 60);
361 minute = (unsigned short)((now.tv_sec / 60) % 60);
362 hour = (unsigned short)((now.tv_sec / 3600) % 24);
363#endif
364
365 su = msg_addr(msg);
366
367#if SU_HAVE_IN61
368 if (su->su_familysu_sa.sa_family == AF_INET610) {
369 if (su->su_sin6.sin6_flowinfo)
370 snprintf(label, sizeof(label), "/%u", ntohl(su->su_sin6.sin6_flowinfo));
371 }
372#endif
373
374 if (msg_addrinfo(msg)->ai_flags & TP_AI_COMPRESSED0x01000)
375 comp = ";comp=sigcomp";
376
377 su_inet_ntopinet_ntop(su->su_familysu_sa.sa_family, SU_ADDR(su)((su)->su_sa.sa_family == 2 ? (void *)&(su)->su_sin
.sin_addr : ((su)->su_sa.sa_family == 10 ? (void *)&(su
)->su_sin6.sin6_addr : (void *)&(su)->su_sa.sa_data
))
, name, sizeof(name));
378
379 snprintf(stamp, TPORT_STAMP_SIZE144,
380 "%s "MOD_ZU"%zu"" bytes %s %s/[%s]:%u%s%s at %02u:%02u:%02u.%06lu:\n",
381 what, (size_t)n, via, self->tp_name->tpn_proto,
382 name, ntohs(su->su_portsu_sin.sin_port), label[0] ? label : "", comp,
383 hour, minute, second, now.tv_usec);
384}
385
386/** Dump the data from the iovec */
387void tport_dump_iovec(tport_t const *self, msg_t *msg,
388 size_t n, su_iovec_t const iov[], size_t iovused,
389 char const *what, char const *how)
390{
391 tport_master_t *mr;
392 char stamp[TPORT_STAMP_SIZE144];
393 size_t i;
394
395 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 395, __extension__
__PRETTY_FUNCTION__); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport_logging.c", 395, __extension__ __PRETTY_FUNCTION__
); }))
;
396
397 mr = self->tp_master;
398 if (!mr->mr_dump_file)
399 return;
400
401 tport_stamp(self, msg, stamp, what, n, how, su_now());
402 fputs(stamp, mr->mr_dump_file);
403
404 for (i = 0; i < iovused && n > 0; i++) {
405 size_t len = iov[i].mv_lensiv_len;
406 if (len > n)
407 len = n;
408 if (fwrite(iov[i].mv_basesiv_base, len, 1, mr->mr_dump_file) != 1)
409 break;
410 n -= len;
411 }
412
413 fputs("\v\n", mr->mr_dump_file);
414 fflush(mr->mr_dump_file);
415}
416
417/** Capture the data from the iovec */
418void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
419 su_iovec_t const iov[], size_t iovused, char const *what)
420{
421
422 int buflen = 0;
423 char* buffer = NULL((void*)0);
424 tport_master_t *mr;
425
426 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 426, __extension__
__PRETTY_FUNCTION__); }))
;
1
Assuming 'self' is non-null
2
Taking true branch
427
428 mr = self->tp_master;
429
430 /* If we don't have socket, go out */
431 if (!mr->mr_capt_sock) {
3
Assuming field 'mr_capt_sock' is not equal to 0
4
Taking false branch
432 su_log("error: capture socket is not open\n");
433 return;
434 }
435
436 switch(mr->mr_prot_ver)
5
Control jumps to 'case 3:' at line 439
437 {
438
439 case 3:
440 buflen = tport_capt_msg_hepv3(self, msg, n, iov, iovused, what, &buffer);
6
Calling 'tport_capt_msg_hepv3'
441 break;
442
443 case 2:
444 case 1:
445 buflen = tport_capt_msg_hepv2(self, msg, n, iov, iovused, what, &buffer);
446 break;
447
448 default:
449 su_log("error: unsupported hep version\n");
450 break;
451 }
452
453 if(buflen > 0) {
454 /* check if we have error i.e. capture server is down */
455 if (su_soerror(mr->mr_capt_sock)) {
456 su_perror("error: tport_logging: capture socket error");
457 goto done;
458 }
459
460 su_send(mr->mr_capt_sock, buffer, buflen, 0)send((mr->mr_capt_sock),(buffer),(buflen),(0));
461 }
462
463
464done:
465 /* Now we release it */
466 if(buffer) free(buffer);
467 return;
468}
469
470/** Capture the data from the iovec */
471int tport_capt_msg_hepv2 (tport_t const *self, msg_t *msg, size_t n,
472 su_iovec_t const iov[], size_t iovused, char const *what, char **buffer)
473{
474
475 int buflen = 0;
476 su_sockaddr_t const *su, *su_self, *su_self_ext;
477 struct hep_hdr hep_header;
478 struct hep_timehdr hep_time = {0};
479 su_time_t now;
480#if __sun__
481 struct hep_iphdr hep_ipheader = {{{{0}}}};
482#else
483 struct hep_iphdr hep_ipheader = {{0}};
484#endif
485#if SU_HAVE_IN61
486 struct hep_ip6hdr hep_ip6header = {{{{0}}}};
487#endif
488 int eth_frame_len = 16000;
489 size_t i, dst = 1;
490 tport_master_t *mr;
491
492 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 492, __extension__
__PRETTY_FUNCTION__); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport_logging.c", 492, __extension__ __PRETTY_FUNCTION__
); }))
;
493
494 su = msg_addr(msg);
495 su_self = self->tp_pri->pri_primary->tp_addr;
496
497 mr = self->tp_master;
498 if (mr->mr_capt_src_addr) {
499 /* override SRC address with configuration */
500 su_self_ext = (void *)mr->mr_capt_src_addr->ai_addr;
501 } else {
502 /* use the SRC address from the socket */
503 su_self_ext = su_self;
504 }
505
506 /* If we don't have socket, go out */
507 if (!mr->mr_capt_sock) {
508 su_log("error: capture socket is not open\n");
509 return 0;
510 }
511
512 /*buffer for ethernet frame*/
513 *buffer = (void*)malloc(eth_frame_len);
514
515 /* VOIP Header */
516 hep_header.hp_v = mr->mr_prot_ver;
517 hep_header.hp_f = su->su_familysu_sa.sa_family;
518 /* Header Length */
519 hep_header.hp_l = sizeof(struct hep_hdr);
520
521 /* PROTOCOL */
522 if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hep_header.hp_p = IPPROTO_TCPIPPROTO_TCP;
523 else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hep_header.hp_p = IPPROTO_IDPIPPROTO_IDP; /* FAKE*/
524 else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hep_header.hp_p = IPPROTO_SCTPIPPROTO_SCTP;
525 else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hep_header.hp_p = IPPROTO_TCPIPPROTO_TCP;
526 else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hep_header.hp_p = IPPROTO_TCPIPPROTO_TCP;
527 else hep_header.hp_p = IPPROTO_UDPIPPROTO_UDP; /* DEFAULT UDP */
528
529 /* Check destination */
530 if(strncmp("sent", what, 4) == 0) dst = 0;
531
532 /* copy destination and source IPs*/
533 if(su->su_familysu_sa.sa_family == AF_INET2) {
534
535 memcpy(dst ? &hep_ipheader.hp_src : &hep_ipheader.hp_dst, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
536 memcpy(dst ? &hep_ipheader.hp_dst : &hep_ipheader.hp_src, &su_self_ext->su_sin.sin_addr.s_addr, sizeof(su_self_ext->su_sin.sin_addr.s_addr));
537 hep_header.hp_l += sizeof(struct hep_iphdr);
538 }
539#if SU_HAVE_IN61
540 else {
541 memcpy(dst ? &hep_ip6header.hp6_src : &hep_ip6header.hp6_dst, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
542 memcpy(dst ? &hep_ip6header.hp6_dst : &hep_ip6header.hp6_src, &su_self_ext->su_sin.sin_addr.s_addr, sizeof(su_self_ext->su_sin.sin_addr.s_addr));
543 hep_header.hp_l += sizeof(struct hep_ip6hdr);
544 }
545#endif
546
547 hep_header.hp_dport = dst ? su_self->su_portsu_sin.sin_port : su->su_portsu_sin.sin_port;
548 hep_header.hp_sport = dst ? su->su_portsu_sin.sin_port : su_self->su_portsu_sin.sin_port;
549
550 if (hep_header.hp_v == 2){
551 hep_header.hp_l += sizeof(struct hep_timehdr);
552 }
553
554 /* Copy hepheader */
555 memset(*buffer, '\0', eth_frame_len);
556 memcpy(*buffer, &hep_header, sizeof(struct hep_hdr));
557 buflen = sizeof(struct hep_hdr);
558
559 if(su->su_familysu_sa.sa_family == AF_INET2) {
560 memcpy(*buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
561 buflen += sizeof(struct hep_iphdr);
562 }
563#if SU_HAVE_IN61
564 else if(su->su_familysu_sa.sa_family == AF_INET610) {
565 memcpy(*buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
566 buflen += sizeof(struct hep_ip6hdr);
567 }
568#endif
569 else {
570 su_perror("error: tport_logging: capture: unsupported protocol family");
571 goto done;
572 }
573
574 /* copy time header */
575 if (hep_header.hp_v == 2) {
576 /* now */
577 now = su_now();
578 /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
579#if defined(HAVE_GETTIMEOFDAY1) || defined(HAVE_CLOCK_MONOTONIC1)
580 hep_time.tv_sec = (now.tv_sec - SU_TIME_EPOCH2208988800UL); /* see su_time0.c 'now' is not really 'now', so we decrease it by SU_TIME_EPOCH */
581#else
582 hep_time.tv_sec = now.tv_sec;
583#endif
584 hep_time.tv_usec = now.tv_usec;
585
586 hep_time.captid = mr->mr_agent_id;
587 memcpy((char*)*buffer+buflen, &hep_time, sizeof(struct hep_timehdr));
588 buflen += sizeof(struct hep_timehdr);
589 }
590
591 for (i = 0; i < iovused && n > 0; i++) {
592 size_t len = iov[i].mv_lensiv_len;
593 if (len > n)
594 len = n;
595 /* if the packet too big for us */
596 if((buflen + len) > eth_frame_len)
597 break;
598
599 memcpy(*buffer + buflen , (void*)iov[i].mv_basesiv_base, len);
600 buflen +=len;
601 n -= len;
602 }
603
604 return buflen;
605
606done:
607 /* Now we release it */
608 if(*buffer) {
609 free(*buffer);
610 *buffer = NULL((void*)0);
611 }
612 return 0;
613}
614
615
616/** Capture the data from the iovec */
617int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
618 su_iovec_t const iov[], size_t iovused, char const *what, char **buffer)
619{
620
621 su_sockaddr_t const *su, *su_self, *su_self_ext;
622 struct hep_generic *hg=NULL((void*)0);
623 unsigned int buflen=0, iplen=0,tlen=0, payload_len = 0;
624 su_time_t now;
625 hep_chunk_ip4_t src_ip4 = {{0}}, dst_ip4 = {{0}};
626 hep_chunk_t payload_chunk;
627 hep_chunk_t nodename_chunk;
628 int orig_n = 0;
629
630#if SU_HAVE_IN61
631 hep_chunk_ip6_t src_ip6 = {{0}}, dst_ip6 = {{0}};
632#endif
633
634 int eth_frame_len = 16000;
635 size_t i, dst = 1;
636 tport_master_t *mr;
637
638 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 638, __extension__
__PRETTY_FUNCTION__); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport_logging.c", 638, __extension__ __PRETTY_FUNCTION__
); }))
;
7
Taking true branch
8
Assuming 'msg' is non-null
9
Taking true branch
639
640 su = msg_addr(msg);
641 su_self = self->tp_pri->pri_primary->tp_addr;
642
643 mr = self->tp_master;
644 if (mr->mr_capt_src_addr) {
10
Assuming field 'mr_capt_src_addr' is null
11
Taking false branch
645 /* override SRC address with configuration */
646 su_self_ext = (void *)mr->mr_capt_src_addr->ai_addr;
647 } else {
648 /* use the SRC address from the socket */
649 su_self_ext = su_self;
650 }
651
652 /* If we don't have socket, go out */
653 if (!mr->mr_capt_sock
11.1
Field 'mr_capt_sock' is not equal to 0
) {
12
Taking false branch
654 su_log("error: capture socket is not open\n");
655 return 0;
656 }
657
658 /*buffer for ethernet frame*/
659
660 hg = malloc(sizeof(struct hep_generic));
661 memset(hg, 0, sizeof(struct hep_generic));
662
663 /* header set */
664 memcpy(hg->header.id, "\x48\x45\x50\x33", 4);
665
666 /* IP proto */
667 hg->ip_family.chunk.vendor_id = htons(0x0000);
668 hg->ip_family.chunk.type_id = htons(0x0001);
669 hg->ip_family.data = su->su_familysu_sa.sa_family;
670 hg->ip_family.chunk.length = htons(sizeof(hg->ip_family));
671
672 /* PROTOCOL */
673 if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hg->ip_proto.data = IPPROTO_TCPIPPROTO_TCP;
13
Taking true branch
674 else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hg->ip_proto.data = IPPROTO_IDPIPPROTO_IDP; /* FAKE*/
675 else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hg->ip_proto.data = IPPROTO_SCTPIPPROTO_SCTP;
676 else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hg->ip_proto.data = IPPROTO_TCPIPPROTO_TCP;
677 else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hg->ip_proto.data = IPPROTO_TCPIPPROTO_TCP;
678 else hg->ip_proto.data = IPPROTO_UDPIPPROTO_UDP; /* DEFAULT UDP */
679
680 /* Proto ID */
681 hg->ip_proto.chunk.vendor_id = htons(0x0000);
682 hg->ip_proto.chunk.type_id = htons(0x0002);
683 hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto));
684
685 /* Check destination */
686 if(strncmp("sent", what, 4) == 0) dst = 0;
14
Assuming the condition is false
15
Taking false branch
687
688 /* copy destination and source IPs*/
689 if(su->su_familysu_sa.sa_family == AF_INET2) {
16
Assuming field 'sa_family' is equal to AF_INET
17
Taking true branch
690
691 /* SRC IP */
692 src_ip4.chunk.vendor_id = htons(0x0000);
693 src_ip4.chunk.type_id = htons(0x0003);
694 memcpy(dst
17.1
'dst' is 1
? &src_ip4.data : &dst_ip4.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
18
'?' condition is true
695 src_ip4.chunk.length = htons(sizeof(src_ip4));
696
697 /* DST IP */
698 dst_ip4.chunk.vendor_id = htons(0x0000);
699 dst_ip4.chunk.type_id = htons(0x0004);
700 memcpy(dst
18.1
'dst' is 1
? &dst_ip4.data : &src_ip4.data, &su_self_ext->su_sin.sin_addr.s_addr, sizeof(su_self_ext->su_sin.sin_addr.s_addr));
19
'?' condition is true
701 dst_ip4.chunk.length = htons(sizeof(dst_ip4));
702
703 iplen = sizeof(dst_ip4) + sizeof(src_ip4);
704 }
705#if SU_HAVE_IN61
706 else if(su->su_familysu_sa.sa_family == AF_INET610) {
707
708 /* SRC IPv6 */
709 src_ip6.chunk.vendor_id = htons(0x0000);
710 src_ip6.chunk.type_id = htons(0x0005);
711 memcpy(dst ? &src_ip6.data : &dst_ip6.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
712 src_ip6.chunk.length = htons(sizeof(src_ip6));
713
714 /* DST IPv6 */
715 dst_ip6.chunk.vendor_id = htons(0x0000);
716 dst_ip6.chunk.type_id = htons(0x0006);
717 memcpy(dst ? &dst_ip6.data : &src_ip6.data, &su_self_ext->su_sin.sin_addr.s_addr, sizeof(su_self_ext->su_sin.sin_addr.s_addr));
718 dst_ip6.chunk.length = htons(sizeof(dst_ip6));
719
720 iplen = sizeof(dst_ip6) + sizeof(src_ip6);
721 }
722#endif
723 else {
724 su_perror("error: tport_logging hepv3: capture: unsupported protocol family");
725 goto done;
726 }
727
728 /* SRC PORT */
729 hg->src_port.chunk.vendor_id = htons(0x0000);
730 hg->src_port.chunk.type_id = htons(0x0007);
731 hg->src_port.data = dst
19.1
'dst' is 1
? su->su_portsu_sin.sin_port : su_self->su_portsu_sin.sin_port;
20
'?' condition is true
732 hg->src_port.chunk.length = htons(sizeof(hg->src_port));
733
734 /* DST PORT */
735 hg->dst_port.chunk.vendor_id = htons(0x0000);
736 hg->dst_port.chunk.type_id = htons(0x0008);
737 hg->dst_port.data = dst
20.1
'dst' is 1
? su_self->su_portsu_sin.sin_port : su->su_portsu_sin.sin_port;
21
'?' condition is true
738 hg->dst_port.chunk.length = htons(sizeof(hg->dst_port));
739
740
741 /* TIMESTAMP SEC */
742 hg->time_sec.chunk.vendor_id = htons(0x0000);
743 hg->time_sec.chunk.type_id = htons(0x0009);
744 hg->time_sec.chunk.length = htons(sizeof(hg->time_sec));
745
746 now = su_now();
747 /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
748#if defined(HAVE_GETTIMEOFDAY1) || defined(HAVE_CLOCK_MONOTONIC1)
749 hg->time_sec.data = htonl(now.tv_sec - SU_TIME_EPOCH2208988800UL); /* see su_time0.c 'now' is not really 'now', so we decrease it by SU_TIME_EPOCH */
750#else
751 hg->time_sec.data = htonl(now.tv_sec);
752#endif
753
754 /* TIMESTAMP USEC */
755 hg->time_usec.chunk.vendor_id = htons(0x0000);
756 hg->time_usec.chunk.type_id = htons(0x000a);
757 hg->time_usec.data = htonl(now.tv_usec);
758 hg->time_usec.chunk.length = htons(sizeof(hg->time_usec));
759
760 /* Protocol TYPE */
761 hg->proto_t.chunk.vendor_id = htons(0x0000);
762 hg->proto_t.chunk.type_id = htons(0x000b);
763 hg->proto_t.data = 0x001; //SIP
764 hg->proto_t.chunk.length = htons(sizeof(hg->proto_t));
765
766 /* Capture ID */
767 hg->capt_id.chunk.vendor_id = htons(0x0000);
768 hg->capt_id.chunk.type_id = htons(0x000c);
769 hg->capt_id.data = htonl(mr->mr_agent_id);
770 hg->capt_id.chunk.length = htons(sizeof(hg->capt_id));
771
772
773 /* Payload caclulation */
774 orig_n = n;
775 for (i = 0; i < iovused && n > 0; i++) {
22
Assuming 'i' is >= 'iovused'
776 size_t len = iov[i].mv_lensiv_len;
777 if (len > n) len = n;
778 if((payload_len + len) > eth_frame_len) break;
779 payload_len +=len;
780 n -= len;
781 }
782 /* restore n */
783 n = orig_n;
784
785 /* Payload */
786 payload_chunk.vendor_id = htons(0x0000);
787 payload_chunk.type_id = htons(0x000f);
788 payload_chunk.length = htons(sizeof(payload_chunk) + payload_len);
789
790 tlen = sizeof(struct hep_generic) + payload_len + iplen + sizeof(hep_chunk_t);
791
792 /* NODE NAME */
793 tlen += sizeof(hep_chunk_t);
794 nodename_chunk.vendor_id = htons(0x0000);
795 nodename_chunk.type_id = htons(0x0013);
796 nodename_chunk.length = htons(sizeof(nodename_chunk) + strlen(mr->mr_agent_nodename));
797 tlen += strlen(mr->mr_agent_nodename);
798
799 /* total */
800 hg->header.length = htons(tlen);
801
802 *buffer = (void*)malloc(tlen);
23
Memory is allocated
803
804 if (*buffer==NULL((void*)0)){
24
Assuming the condition is false
25
Taking false branch
805 su_perror("error: tport_logging hepv3: no memory for buffer");
806 goto done;
807 }
808
809 memcpy((void*) *buffer, hg, sizeof(struct hep_generic));
810 buflen = sizeof(struct hep_generic);
811
812 /* IPv4 */
813 if(su->su_familysu_sa.sa_family == AF_INET2) {
26
Taking true branch
814 /* SRC IP */
815 memcpy((char*) *buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip4));
816 buflen += sizeof(struct hep_chunk_ip4);
817
818 memcpy((char*) *buffer+buflen, &dst_ip4, sizeof(struct hep_chunk_ip4));
819 buflen += sizeof(struct hep_chunk_ip4);
820 }
821#if SU_HAVE_IN61
822 /* IPv6 */
823 else if(su->su_familysu_sa.sa_family == AF_INET610) {
824 /* SRC IPv6 */
825 memcpy((char*) *buffer+buflen, &src_ip6, sizeof(struct hep_chunk_ip6));
826 buflen += sizeof(struct hep_chunk_ip6);
827
828 memcpy((char*) *buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6));
829 buflen += sizeof(struct hep_chunk_ip6);
830 }
831#endif
832
833 /* NODE NAME */
834 memcpy((void*) buffer + buflen, &nodename_chunk, sizeof(struct hep_chunk));
835 buflen += sizeof(struct hep_chunk);
27
Potential memory leak
836 /* Now copying payload self */
837 memcpy((void*) buffer + buflen, mr->mr_agent_nodename, strlen(mr->mr_agent_nodename));
838 buflen += strlen(mr->mr_agent_nodename);
839
840 /* PAYLOAD CHUNK */
841 memcpy((char*) *buffer+buflen, &payload_chunk, sizeof(struct hep_chunk));
842 buflen += sizeof(struct hep_chunk);
843
844 /* PAYLOAD */
845 for (i = 0; i < iovused && n > 0; i++) {
846 size_t len = iov[i].mv_lensiv_len;
847 if (len > n) len = n;
848 /* if the packet too big for us */
849 if((buflen + len) > eth_frame_len)
850 break;
851
852 memcpy(*buffer + buflen , (void*)iov[i].mv_basesiv_base, len);
853 buflen +=len;
854 n -= len;
855 }
856
857 free(hg);
858 return buflen;
859
860done:
861 /* Now we release it */
862 if(hg) free(hg);
863 return 0;
864}
865
866
867/** Log the message. */
868void tport_log_msg(tport_t *self, msg_t *msg,
869 char const *what, char const *via,
870 su_time_t now)
871{
872 msg_iovec_t iov[80];
873 size_t i, iovlen = msg_iovec(msg, iov, 80);
874 size_t n;
875 int skip_lf = 0;
876 char *buffer = NULL((void*)0);
877 size_t buffer_size = 0;
878 size_t buffer_pos = 0;
879 size_t bytes_written = 0;
880
881#define MSG_SEPARATOR"------------------------------------------------------------------------\n" \
882 "------------------------------------------------------------------------\n"
883
884 for (i = n = 0; i < iovlen && i < 80; i++)
885 n += iov[i].mv_lensiv_len;
886
887 buffer_size = sizeof(char) * n + 1 + TPORT_STAMP_SIZE144 + sizeof(MSG_SEPARATOR"------------------------------------------------------------------------\n");
888 if (buffer_size > 16000) {
889 buffer_size = 16000;
890 }
891
892 buffer = malloc(buffer_size);
893 buffer[0] = '\0';
894
895 tport_stamp(self, msg, buffer, what, n, via, now);
896 buffer_pos = strlen(buffer);
897 if (buffer_pos < buffer_size) {
898 bytes_written = snprintf(buffer + buffer_pos, buffer_size - buffer_pos, "%s", MSG_SEPARATOR"------------------------------------------------------------------------\n");
899 if (bytes_written > 0) {
900 buffer_pos += bytes_written;
901 }
902 }
903
904 for (i = 0; buffer_pos < buffer_size && i < iovlen && i < 80; i++) {
905 char *s = iov[i].mv_basesiv_base, *end = s + iov[i].mv_lensiv_len;
906
907 if (skip_lf && s < end && s[0] == '\n') { s++; skip_lf = 0; }
908
909 while (s < end) {
910 if (s[0] == '\0') {
911 break;
912 }
913
914 n = su_strncspn(s, end - s, "\r\n");
915 if (buffer_pos > buffer_size) {
916 break;
917 }
918 bytes_written = snprintf(buffer + buffer_pos, buffer_size - buffer_pos, "%.*s", (int)n, s);
919 if (bytes_written > 0) {
920 buffer_pos += bytes_written;
921 }
922
923 s += n;
924
925 if (s == end)
926 break;
927
928 if (buffer_pos < buffer_size) {
929 buffer[buffer_pos++] = '\n';
930 }
931 /* Skip eol */
932 if (s[0] == '\r') {
933 s++;
934 if (s == end) {
935 skip_lf = 1;
936 continue;
937 }
938 }
939
940 if (s[0] == '\n') {
941 s++;
942 }
943 }
944 }
945
946 if (buffer_pos >= buffer_size) {
947 buffer_pos = buffer_size - 1;
948 }
949 buffer[buffer_pos] = '\0';
950 su_log("%s\n", buffer);
951 free(buffer);
952}