Bug Summary

File:libsofia-sip-ua/tport/tport_logging.c
Warning:line 438, column 18
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'

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-06-23-181620-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_log
86 */
87#ifdef DOXYGEN
88extern char const TPORT_CAPT[]; /* dummy declaration for Doxygen */
89#endif
90
91
92/**@var TPORT_DEBUG
93 *
94 * Environment variable determining the debug log level for @b tport module.
95 *
96 * The TPORT_DEBUG environment variable is used to determine the debug logging
97 * level for @b tport module. The default level is 3.
98 *
99 * @sa <sofia-sip/su_debug.h>, tport_log, SOFIA_DEBUG
100 */
101#ifdef DOXYGEN
102extern char const TPORT_DEBUG[]; /* dummy declaration for Doxygen */
103#endif
104
105/**Debug log for @b tport module.
106 *
107 * The tport_log is the log object used by @b tport module. The level of
108 * #tport_log is set using #TPORT_DEBUG environment variable.
109 */
110su_log_t tport_log[] = {
111 SU_LOG_INIT("tport", "TPORT_DEBUG", SU_DEBUG){ sizeof(su_log_t), "tport", "TPORT_DEBUG", 0, SU_LOG_MAX, 0,
((void*)0), ((void*)0), }
112};
113
114
115
116/** Initialize logging. */
117int tport_open_log(tport_master_t *mr, tagi_t *tags)
118{
119 int n;
120 int log_msg = mr->mr_log != 0;
121 char const *dump = NULL((void*)0);
122 char const *capt = 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 TAG_END()(tag_type_t)0, (tag_value_t)0);
131
132 if (getenv("MSG_STREAM_LOG") != NULL((void*)0) || getenv("TPORT_LOG") != NULL((void*)0))
133 log_msg = 1;
134 mr->mr_log = log_msg ? MSG_DO_EXTRACT_COPYMSG_FLG_EXTRACT_COPY : 0;
135
136 if (getenv("TPORT_CAPT"))
137 capt = getenv("TPORT_CAPT");
138 if (getenv("MSG_DUMP"))
139 dump = getenv("MSG_DUMP");
140 if (getenv("TPORT_DUMP"))
141 dump = getenv("TPORT_DUMP");
142
143 if(capt) {
144
145 char *captname, *p, *host_s;
146 char port[10];
147 su_addrinfo_t *ai = NULL((void*)0), hints[1] = {{ 0 }};
148 unsigned len =0, iport = 0;
149
150
151
152 if (mr->mr_capt_name && mr->mr_capt_sock && strcmp(capt, mr->mr_capt_name) == 0)
153 return n;
154
155 captname = su_strdup(mr->mr_homemr_master->tp_home, capt);
156 if (captname == NULL((void*)0))
157 return n;
158
159 if(strncmp(captname, "udp:",4) != 0) {
160 su_log("tport_open_log: capturing. Only udp protocol supported [%s]\n", captname);
161 return n;
162 }
163
164 /* separate proto and host */
165 p = captname+4;
166 if( (*(p)) == '\0') {
167 su_log("malformed ip address\n");
168 return n;
169 }
170 host_s = p;
171
172 if( (p = strrchr(p+1, ':')) == 0 ) {
173 su_log("no host or port specified\n");
174 return n;
175 }
176
177 /*the address contains a port number*/
178 *p = '\0';
179 p++;
180
181 iport = atoi(p);
182
183 if (iport <1024 || iport >65536)
184 {
185 su_log("invalid port number; must be in [1024,65536]\n");
186 return n;
187 }
188
189 snprintf(port, sizeof(port), "%d", iport);
190
191 /* default values for capture protocol and agent id */
192 mr->mr_prot_ver = 3;
193 mr->mr_agent_id = 200;
194
195 /* get all params */
196 while(p)
197 {
198 /* check ; in the URL */
199 if( (p = strchr(p+1, ';')) == 0 ) {
200 break;
201 }
202
203 *p = '\0';
204 p++;
205
206 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__, 206, "events HEP RRR DATA [%s]\n", p
)) : (void)0)
;
207
208 if(strncmp(p, "hep=",4) == 0) {
209 p+=4;
210 mr->mr_prot_ver = atoi(p);
211 /* hepv3 come later */
212 if (mr->mr_prot_ver < 1 || mr->mr_prot_ver > 3)
213 {
214 su_log("invalid hep version number; must be in [1-3]\n");
215 mr->mr_prot_ver = 3;
216 return n;
217 }
218 }
219 else if(strncmp(p, "capture_id=", 11) == 0) {
220 p+=11;
221 if((mr->mr_agent_id = atoi(p)) == 0)
222 {
223 mr->mr_agent_id = 200;
224 su_log("invalid capture id number; must be uint32 \n");
225 return n;
226 }
227 }
228 else {
229 su_log("unsupported capture param\n");
230 return n;
231 }
232 }
233
234 /* check if we have [] */
235 if (host_s[0] == '[') {
236 len = strlen(host_s + 1) - 1;
237 if(host_s[len+1] != ']') {
238 su_log("bracket not closed\n");
239 return n;
240 }
241 memmove(host_s, host_s + 1, len);
242 host_s[len] = '\0';
243 }
244
245 /* and again */
246 captname = su_strdup(mr->mr_homemr_master->tp_home, capt);
247 if (captname == NULL((void*)0)) return n;
248
249 su_free(mr->mr_homemr_master->tp_home, mr->mr_capt_name);
250 mr->mr_capt_name = captname;
251
252 if (mr->mr_capt_sock)
253 su_close(mr->mr_capt_sock), mr->mr_capt_sock = 0;
254
255 /* HINTS && getaddrinfo */
256 hints->ai_flags = AI_NUMERICSERV0x0400;
257 hints->ai_family = AF_UNSPEC0;
258 hints->ai_socktype = SOCK_DGRAMSOCK_DGRAM;
259 hints->ai_protocol = IPPROTO_UDPIPPROTO_UDP;
260
261 if (su_getaddrinfo(host_s, port, hints, &ai)) {
262 su_perror("capture: su_getaddrinfo()");
263 return n;
264 }
265
266 mr->mr_capt_sock = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
267 if (mr->mr_capt_sock == INVALID_SOCKET((su_socket_t)INVALID_SOCKET)) {
268 su_perror("capture: invalid socket");
269 return n;
270 }
271
272 su_setblocking(mr->mr_capt_sock, 0); /* Don't block */
273
274 if (connect(mr->mr_capt_sock, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == -1) {
275 if (errno(*__errno_location ()) != EINPROGRESS115) {
276 su_perror("capture: socket connect");
277 return n;
278 }
279 }
280
281 su_freeaddrinfo(ai);
282 }
283 else if(mr->mr_capt_sock) {
284 /* close capture server*/
285 su_close(mr->mr_capt_sock);
286 mr->mr_capt_sock = 0;
287 }
288
289 if (dump) {
290 time_t now;
291 char *dumpname;
292
293 if (mr->mr_dump && strcmp(dump, mr->mr_dump) == 0)
294 return n;
295 dumpname = su_strdup(mr->mr_homemr_master->tp_home, dump);
296 if (dumpname == NULL((void*)0))
297 return n;
298 su_free(mr->mr_homemr_master->tp_home, mr->mr_dump);
299 mr->mr_dump = dumpname;
300
301 if (mr->mr_dump_file && mr->mr_dump_file != stdoutstdout)
302 fclose(mr->mr_dump_file), mr->mr_dump_file = NULL((void*)0);
303
304 if (strcmp(dumpname, "-"))
305 mr->mr_dump_file = fopen(dumpname, "ab"); /* XXX */
306 else
307 mr->mr_dump_file = stdoutstdout;
308
309 if (mr->mr_dump_file) {
310 time(&now);
311 fprintf(mr->mr_dump_file, "dump started at %s\n\n", ctime(&now));
312 }
313 }
314
315 return n;
316}
317
318/** Create log stamp */
319void tport_stamp(tport_t const *self, msg_t *msg,
320 char *stamp, char const *what,
321 size_t n, char const *via,
322 su_time_t now)
323{
324 char label[24] = "";
325 char *comp = "";
326 char name[SU_ADDRSIZE(48)] = "";
327 su_sockaddr_t const *su;
328 unsigned short second, minute, hour;
329 /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
330#if defined(HAVE_GETTIMEOFDAY1) || defined(HAVE_CLOCK_MONOTONIC1)
331 struct tm nowtm = { 0 };
332 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 */
333#endif
334
335 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 335, __extension__
__PRETTY_FUNCTION__); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport_logging.c", 335, __extension__ __PRETTY_FUNCTION__
); }))
;
336
337#if defined(HAVE_GETTIMEOFDAY1) || defined(HAVE_CLOCK_MONOTONIC1)
338 localtime_r(&nowtime, &nowtm);
339 second = nowtm.tm_sec;
340 minute = nowtm.tm_min;
341 hour = nowtm.tm_hour;
342#else
343 second = (unsigned short)(now.tv_sec % 60);
344 minute = (unsigned short)((now.tv_sec / 60) % 60);
345 hour = (unsigned short)((now.tv_sec / 3600) % 24);
346#endif
347
348 su = msg_addr(msg);
349
350#if SU_HAVE_IN61
351 if (su->su_familysu_sa.sa_family == AF_INET610) {
352 if (su->su_sin6.sin6_flowinfo)
353 snprintf(label, sizeof(label), "/%u", ntohl(su->su_sin6.sin6_flowinfo));
354 }
355#endif
356
357 if (msg_addrinfo(msg)->ai_flags & TP_AI_COMPRESSED0x01000)
358 comp = ";comp=sigcomp";
359
360 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));
361
362 snprintf(stamp, TPORT_STAMP_SIZE144,
363 "%s "MOD_ZU"%zu"" bytes %s %s/[%s]:%u%s%s at %02u:%02u:%02u.%06lu:\n",
364 what, (size_t)n, via, self->tp_name->tpn_proto,
365 name, ntohs(su->su_portsu_sin.sin_port), label[0] ? label : "", comp,
366 hour, minute, second, now.tv_usec);
367}
368
369/** Dump the data from the iovec */
370void tport_dump_iovec(tport_t const *self, msg_t *msg,
371 size_t n, su_iovec_t const iov[], size_t iovused,
372 char const *what, char const *how)
373{
374 tport_master_t *mr;
375 char stamp[TPORT_STAMP_SIZE144];
376 size_t i;
377
378 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 378, __extension__
__PRETTY_FUNCTION__); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport_logging.c", 378, __extension__ __PRETTY_FUNCTION__
); }))
;
379
380 mr = self->tp_master;
381 if (!mr->mr_dump_file)
382 return;
383
384 tport_stamp(self, msg, stamp, what, n, how, su_now());
385 fputs(stamp, mr->mr_dump_file);
386
387 for (i = 0; i < iovused && n > 0; i++) {
388 size_t len = iov[i].mv_lensiv_len;
389 if (len > n)
390 len = n;
391 if (fwrite(iov[i].mv_basesiv_base, len, 1, mr->mr_dump_file) != 1)
392 break;
393 n -= len;
394 }
395
396 fputs("\v\n", mr->mr_dump_file);
397 fflush(mr->mr_dump_file);
398}
399
400/** Capture the data from the iovec */
401void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
402 su_iovec_t const iov[], size_t iovused, char const *what)
403{
404
405 int buflen = 0, error;
406 char* buffer = NULL((void*)0);
407 tport_master_t *mr;
408
409 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 409, __extension__
__PRETTY_FUNCTION__); }))
;
410
411 mr = self->tp_master;
412
413 /* If we don't have socket, go out */
414 if (!mr->mr_capt_sock) {
415 su_log("error: capture socket is not open\n");
416 return;
417 }
418
419 switch(mr->mr_prot_ver)
420 {
421
422 case 3:
423 buflen = tport_capt_msg_hepv3(self, msg, n, iov, iovused, what, &buffer);
424 break;
425
426 case 2:
427 case 1:
428 buflen = tport_capt_msg_hepv2(self, msg, n, iov, iovused, what, &buffer);
429 break;
430
431 default:
432 su_log("error: unsupported hep version\n");
433 break;
434 }
435
436 if(buflen > 0) {
437 /* check if we have error i.e. capture server is down */
438 if ((error = su_soerror(mr->mr_capt_sock))) {
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'
439 su_perror("error: tport_logging: capture socket error");
440 goto done;
441 }
442
443 su_send(mr->mr_capt_sock, buffer, buflen, 0)send((mr->mr_capt_sock),(buffer),(buflen),(0));
444 }
445
446
447done:
448 /* Now we release it */
449 if(buffer) free(buffer);
450 return;
451}
452
453/** Capture the data from the iovec */
454int tport_capt_msg_hepv2 (tport_t const *self, msg_t *msg, size_t n,
455 su_iovec_t const iov[], size_t iovused, char const *what, char **buffer)
456{
457
458 int buflen = 0;
459 su_sockaddr_t const *su, *su_self;
460 struct hep_hdr hep_header;
461 struct hep_timehdr hep_time = {0};
462 su_time_t now;
463#if __sun__
464 struct hep_iphdr hep_ipheader = {{{{0}}}};
465#else
466 struct hep_iphdr hep_ipheader = {{0}};
467#endif
468#if SU_HAVE_IN61
469 struct hep_ip6hdr hep_ip6header = {{{{0}}}};
470#endif
471 int eth_frame_len = 16000;
472 size_t i, dst = 1;
473 tport_master_t *mr;
474
475 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 475, __extension__
__PRETTY_FUNCTION__); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport_logging.c", 475, __extension__ __PRETTY_FUNCTION__
); }))
;
476
477 su = msg_addr(msg);
478 su_self = self->tp_pri->pri_primary->tp_addr;
479
480 mr = self->tp_master;
481
482 /* If we don't have socket, go out */
483 if (!mr->mr_capt_sock) {
484 su_log("error: capture socket is not open\n");
485 return 0;
486 }
487
488 /*buffer for ethernet frame*/
489 *buffer = (void*)malloc(eth_frame_len);
490
491 /* VOIP Header */
492 hep_header.hp_v = mr->mr_prot_ver;
493 hep_header.hp_f = su->su_familysu_sa.sa_family;
494 /* Header Length */
495 hep_header.hp_l = sizeof(struct hep_hdr);
496
497 /* PROTOCOL */
498 if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hep_header.hp_p = IPPROTO_TCPIPPROTO_TCP;
499 else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hep_header.hp_p = IPPROTO_IDPIPPROTO_IDP; /* FAKE*/
500 else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hep_header.hp_p = IPPROTO_SCTPIPPROTO_SCTP;
501 else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hep_header.hp_p = IPPROTO_TCPIPPROTO_TCP;
502 else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hep_header.hp_p = IPPROTO_TCPIPPROTO_TCP;
503 else hep_header.hp_p = IPPROTO_UDPIPPROTO_UDP; /* DEFAULT UDP */
504
505 /* Check destination */
506 if(strncmp("sent", what, 4) == 0) dst = 0;
507
508 /* copy destination and source IPs*/
509 if(su->su_familysu_sa.sa_family == AF_INET2) {
510
511 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));
512 memcpy(dst ? &hep_ipheader.hp_dst : &hep_ipheader.hp_src, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
513 hep_header.hp_l += sizeof(struct hep_iphdr);
514 }
515#if SU_HAVE_IN61
516 else {
517 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));
518 memcpy(dst ? &hep_ip6header.hp6_dst : &hep_ip6header.hp6_src, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
519 hep_header.hp_l += sizeof(struct hep_ip6hdr);
520 }
521#endif
522
523 hep_header.hp_dport = dst ? su_self->su_portsu_sin.sin_port : su->su_portsu_sin.sin_port;
524 hep_header.hp_sport = dst ? su->su_portsu_sin.sin_port : su_self->su_portsu_sin.sin_port;
525
526 if (hep_header.hp_v == 2){
527 hep_header.hp_l += sizeof(struct hep_timehdr);
528 }
529
530 /* Copy hepheader */
531 memset(*buffer, '\0', eth_frame_len);
532 memcpy(*buffer, &hep_header, sizeof(struct hep_hdr));
533 buflen = sizeof(struct hep_hdr);
534
535 if(su->su_familysu_sa.sa_family == AF_INET2) {
536 memcpy(*buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
537 buflen += sizeof(struct hep_iphdr);
538 }
539#if SU_HAVE_IN61
540 else if(su->su_familysu_sa.sa_family == AF_INET610) {
541 memcpy(*buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
542 buflen += sizeof(struct hep_ip6hdr);
543 }
544#endif
545 else {
546 su_perror("error: tport_logging: capture: unsupported protocol family");
547 goto done;
548 }
549
550 /* copy time header */
551 if (hep_header.hp_v == 2) {
552 /* now */
553 now = su_now();
554 /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
555#if defined(HAVE_GETTIMEOFDAY1) || defined(HAVE_CLOCK_MONOTONIC1)
556 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 */
557#else
558 hep_time.tv_sec = now.tv_sec;
559#endif
560 hep_time.tv_usec = now.tv_usec;
561
562 hep_time.captid = mr->mr_agent_id;
563 memcpy((char*)*buffer+buflen, &hep_time, sizeof(struct hep_timehdr));
564 buflen += sizeof(struct hep_timehdr);
565 }
566
567 for (i = 0; i < iovused && n > 0; i++) {
568 size_t len = iov[i].mv_lensiv_len;
569 if (len > n)
570 len = n;
571 /* if the packet too big for us */
572 if((buflen + len) > eth_frame_len)
573 break;
574
575 memcpy(*buffer + buflen , (void*)iov[i].mv_basesiv_base, len);
576 buflen +=len;
577 n -= len;
578 }
579
580 return buflen;
581
582done:
583 /* Now we release it */
584 if(*buffer) {
585 free(*buffer);
586 *buffer = NULL((void*)0);
587 }
588 return 0;
589}
590
591
592/** Capture the data from the iovec */
593int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
594 su_iovec_t const iov[], size_t iovused, char const *what, char **buffer)
595{
596
597 su_sockaddr_t const *su, *su_self;
598 struct hep_generic *hg=NULL((void*)0);
599 unsigned int buflen=0, iplen=0,tlen=0, payload_len = 0;
600 su_time_t now;
601 hep_chunk_ip4_t src_ip4 = {{0}}, dst_ip4 = {{0}};
602 hep_chunk_t payload_chunk;
603 int orig_n = 0;
604
605#if SU_HAVE_IN61
606 hep_chunk_ip6_t src_ip6 = {{0}}, dst_ip6 = {{0}};
607#endif
608
609 int eth_frame_len = 16000;
610 size_t i, dst = 1;
611 tport_master_t *mr;
612
613 assert(self)((void) sizeof ((self) ? 1 : 0), __extension__ ({ if (self) ;
else __assert_fail ("self", "tport_logging.c", 613, __extension__
__PRETTY_FUNCTION__); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "tport_logging.c", 613, __extension__ __PRETTY_FUNCTION__
); }))
;
614
615 su = msg_addr(msg);
616 su_self = self->tp_pri->pri_primary->tp_addr;
617
618 mr = self->tp_master;
619
620 /* If we don't have socket, go out */
621 if (!mr->mr_capt_sock) {
622 su_log("error: capture socket is not open\n");
623 return 0;
624 }
625
626 /*buffer for ethernet frame*/
627
628 hg = malloc(sizeof(struct hep_generic));
629 memset(hg, 0, sizeof(struct hep_generic));
630
631 /* header set */
632 memcpy(hg->header.id, "\x48\x45\x50\x33", 4);
633
634 /* IP proto */
635 hg->ip_family.chunk.vendor_id = htons(0x0000);
636 hg->ip_family.chunk.type_id = htons(0x0001);
637 hg->ip_family.data = su->su_familysu_sa.sa_family;
638 hg->ip_family.chunk.length = htons(sizeof(hg->ip_family));
639
640 /* PROTOCOL */
641 if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hg->ip_proto.data = IPPROTO_TCPIPPROTO_TCP;
642 else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hg->ip_proto.data = IPPROTO_IDPIPPROTO_IDP; /* FAKE*/
643 else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hg->ip_proto.data = IPPROTO_SCTPIPPROTO_SCTP;
644 else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hg->ip_proto.data = IPPROTO_TCPIPPROTO_TCP;
645 else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hg->ip_proto.data = IPPROTO_TCPIPPROTO_TCP;
646 else hg->ip_proto.data = IPPROTO_UDPIPPROTO_UDP; /* DEFAULT UDP */
647
648 /* Proto ID */
649 hg->ip_proto.chunk.vendor_id = htons(0x0000);
650 hg->ip_proto.chunk.type_id = htons(0x0002);
651 hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto));
652
653 /* Check destination */
654 if(strncmp("sent", what, 4) == 0) dst = 0;
655
656 /* copy destination and source IPs*/
657 if(su->su_familysu_sa.sa_family == AF_INET2) {
658
659 /* SRC IP */
660 src_ip4.chunk.vendor_id = htons(0x0000);
661 src_ip4.chunk.type_id = htons(0x0003);
662 memcpy(dst ? &src_ip4.data : &dst_ip4.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
663 src_ip4.chunk.length = htons(sizeof(src_ip4));
664
665 /* DST IP */
666 dst_ip4.chunk.vendor_id = htons(0x0000);
667 dst_ip4.chunk.type_id = htons(0x0004);
668 memcpy(dst ? &dst_ip4.data : &src_ip4.data, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
669 dst_ip4.chunk.length = htons(sizeof(dst_ip4));
670
671 iplen = sizeof(dst_ip4) + sizeof(src_ip4);
672 }
673#if SU_HAVE_IN61
674 else if(su->su_familysu_sa.sa_family == AF_INET610) {
675
676 /* SRC IPv6 */
677 src_ip6.chunk.vendor_id = htons(0x0000);
678 src_ip6.chunk.type_id = htons(0x0005);
679 memcpy(dst ? &src_ip6.data : &dst_ip6.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
680 src_ip6.chunk.length = htons(sizeof(src_ip6));
681
682 /* DST IPv6 */
683 dst_ip6.chunk.vendor_id = htons(0x0000);
684 dst_ip6.chunk.type_id = htons(0x0006);
685 memcpy(dst ? &dst_ip6.data : &src_ip6.data, &su_self->su_sin.sin_addr.s_addr, sizeof(su_self->su_sin.sin_addr.s_addr));
686 dst_ip6.chunk.length = htons(sizeof(dst_ip6));
687
688 iplen = sizeof(dst_ip6) + sizeof(src_ip6);
689 }
690#endif
691 else {
692 su_perror("error: tport_logging hepv3: capture: unsupported protocol family");
693 goto done;
694 }
695
696 /* SRC PORT */
697 hg->src_port.chunk.vendor_id = htons(0x0000);
698 hg->src_port.chunk.type_id = htons(0x0007);
699 hg->src_port.data = dst ? su->su_portsu_sin.sin_port : su_self->su_portsu_sin.sin_port;
700 hg->src_port.chunk.length = htons(sizeof(hg->src_port));
701
702 /* DST PORT */
703 hg->dst_port.chunk.vendor_id = htons(0x0000);
704 hg->dst_port.chunk.type_id = htons(0x0008);
705 hg->dst_port.data = dst ? su_self->su_portsu_sin.sin_port : su->su_portsu_sin.sin_port;
706 hg->dst_port.chunk.length = htons(sizeof(hg->dst_port));
707
708
709 /* TIMESTAMP SEC */
710 hg->time_sec.chunk.vendor_id = htons(0x0000);
711 hg->time_sec.chunk.type_id = htons(0x0009);
712 hg->time_sec.chunk.length = htons(sizeof(hg->time_sec));
713
714 now = su_now();
715 /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
716#if defined(HAVE_GETTIMEOFDAY1) || defined(HAVE_CLOCK_MONOTONIC1)
717 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 */
718#else
719 hg->time_sec.data = htonl(now.tv_sec);
720#endif
721
722 /* TIMESTAMP USEC */
723 hg->time_usec.chunk.vendor_id = htons(0x0000);
724 hg->time_usec.chunk.type_id = htons(0x000a);
725 hg->time_usec.data = htonl(now.tv_usec);
726 hg->time_usec.chunk.length = htons(sizeof(hg->time_usec));
727
728 /* Protocol TYPE */
729 hg->proto_t.chunk.vendor_id = htons(0x0000);
730 hg->proto_t.chunk.type_id = htons(0x000b);
731 hg->proto_t.data = 0x001; //SIP
732 hg->proto_t.chunk.length = htons(sizeof(hg->proto_t));
733
734 /* Capture ID */
735 hg->capt_id.chunk.vendor_id = htons(0x0000);
736 hg->capt_id.chunk.type_id = htons(0x000c);
737 hg->capt_id.data = htonl(mr->mr_agent_id);
738 hg->capt_id.chunk.length = htons(sizeof(hg->capt_id));
739
740
741 /* Payload caclulation */
742 orig_n = n;
743 for (i = 0; i < iovused && n > 0; i++) {
744 size_t len = iov[i].mv_lensiv_len;
745 if (len > n) len = n;
746 if((payload_len + len) > eth_frame_len) break;
747 payload_len +=len;
748 n -= len;
749 }
750 /* restore n */
751 n = orig_n;
752
753 /* Payload */
754 payload_chunk.vendor_id = htons(0x0000);
755 payload_chunk.type_id = htons(0x000f);
756 payload_chunk.length = htons(sizeof(payload_chunk) + payload_len);
757
758 tlen = sizeof(struct hep_generic) + payload_len + iplen + sizeof(hep_chunk_t);
759
760 /* total */
761 hg->header.length = htons(tlen);
762
763 *buffer = (void*)malloc(tlen);
764
765 if (*buffer==NULL((void*)0)){
766 su_perror("error: tport_logging hepv3: no memory for buffer");
767 goto done;
768 }
769
770 memcpy((void*) *buffer, hg, sizeof(struct hep_generic));
771 buflen = sizeof(struct hep_generic);
772
773 /* IPv4 */
774 if(su->su_familysu_sa.sa_family == AF_INET2) {
775 /* SRC IP */
776 memcpy((char*) *buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip4));
777 buflen += sizeof(struct hep_chunk_ip4);
778
779 memcpy((char*) *buffer+buflen, &dst_ip4, sizeof(struct hep_chunk_ip4));
780 buflen += sizeof(struct hep_chunk_ip4);
781 }
782#if SU_HAVE_IN61
783 /* IPv6 */
784 else if(su->su_familysu_sa.sa_family == AF_INET610) {
785 /* SRC IPv6 */
786 memcpy((char*) *buffer+buflen, &src_ip6, sizeof(struct hep_chunk_ip6));
787 buflen += sizeof(struct hep_chunk_ip6);
788
789 memcpy((char*) *buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6));
790 buflen += sizeof(struct hep_chunk_ip6);
791 }
792#endif
793
794 /* PAYLOAD CHUNK */
795 memcpy((char*) *buffer+buflen, &payload_chunk, sizeof(struct hep_chunk));
796 buflen += sizeof(struct hep_chunk);
797
798 /* PAYLOAD */
799 for (i = 0; i < iovused && n > 0; i++) {
800 size_t len = iov[i].mv_lensiv_len;
801 if (len > n) len = n;
802 /* if the packet too big for us */
803 if((buflen + len) > eth_frame_len)
804 break;
805
806 memcpy(*buffer + buflen , (void*)iov[i].mv_basesiv_base, len);
807 buflen +=len;
808 n -= len;
809 }
810
811 free(hg);
812 return buflen;
813
814done:
815 /* Now we release it */
816 if(hg) free(hg);
817 return 0;
818}
819
820
821/** Log the message. */
822void tport_log_msg(tport_t *self, msg_t *msg,
823 char const *what, char const *via,
824 su_time_t now)
825{
826 msg_iovec_t iov[80];
827 size_t i, iovlen = msg_iovec(msg, iov, 80);
828 size_t n;
829 int skip_lf = 0;
830 char *buffer = NULL((void*)0);
831 size_t buffer_size = 0;
832 size_t buffer_pos = 0;
833 size_t bytes_written = 0;
834
835#define MSG_SEPARATOR"------------------------------------------------------------------------\n" \
836 "------------------------------------------------------------------------\n"
837
838 for (i = n = 0; i < iovlen && i < 80; i++)
839 n += iov[i].mv_lensiv_len;
840
841 buffer_size = sizeof(char) * n + 1 + TPORT_STAMP_SIZE144 + sizeof(MSG_SEPARATOR"------------------------------------------------------------------------\n");
842 if (buffer_size > 16000) {
843 buffer_size = 16000;
844 }
845
846 buffer = malloc(buffer_size);
847 buffer[0] = '\0';
848
849 tport_stamp(self, msg, buffer, what, n, via, now);
850 buffer_pos = strlen(buffer);
851 if (buffer_pos < buffer_size) {
852 bytes_written = snprintf(buffer + buffer_pos, buffer_size - buffer_pos, "%s", MSG_SEPARATOR"------------------------------------------------------------------------\n");
853 if (bytes_written > 0) {
854 buffer_pos += bytes_written;
855 }
856 }
857
858 for (i = 0; buffer_pos < buffer_size && i < iovlen && i < 80; i++) {
859 char *s = iov[i].mv_basesiv_base, *end = s + iov[i].mv_lensiv_len;
860
861 if (skip_lf && s < end && s[0] == '\n') { s++; skip_lf = 0; }
862
863 while (s < end) {
864 if (s[0] == '\0') {
865 break;
866 }
867
868 n = su_strncspn(s, end - s, "\r\n");
869 if (buffer_pos > buffer_size) {
870 break;
871 }
872 bytes_written = snprintf(buffer + buffer_pos, buffer_size - buffer_pos, "%.*s", (int)n, s);
873 if (bytes_written > 0) {
874 buffer_pos += bytes_written;
875 }
876
877 s += n;
878
879 if (s == end)
880 break;
881
882 if (buffer_pos < buffer_size) {
883 buffer[buffer_pos++] = '\n';
884 }
885 /* Skip eol */
886 if (s[0] == '\r') {
887 s++;
888 if (s == end) {
889 skip_lf = 1;
890 continue;
891 }
892 }
893
894 if (s[0] == '\n') {
895 s++;
896 }
897 }
898 }
899
900 if (buffer_pos >= buffer_size) {
901 buffer_pos = buffer_size - 1;
902 }
903 buffer[buffer_pos] = '\0';
904 su_log("%s\n", buffer);
905 free(buffer);
906}