tport_logging.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  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. /**@CFILE tport_logging.c Logging transported messages.
  25. *
  26. * See tport.docs for more detailed description of tport interface.
  27. *
  28. * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  29. * @author Martti Mela <Martti.Mela@nokia.com>
  30. *
  31. * @date Created: Fri Mar 24 08:45:49 EET 2006 ppessi
  32. */
  33. #include "config.h"
  34. #include "msg_internal.h"
  35. #include "tport_internal.h"
  36. #include <sofia-sip/su.h>
  37. #include <sofia-sip/su_string.h>
  38. #include <stdlib.h>
  39. #include <time.h>
  40. #include <assert.h>
  41. #include <errno.h>
  42. #include <limits.h>
  43. #define TPORT_STAMP_SIZE 144
  44. /**@var TPORT_LOG
  45. *
  46. * Environment variable determining if parsed message contents are logged.
  47. *
  48. * If the TPORT_LOG environment variable is set, the tport module logs the
  49. * contents of parsed messages. This eases debugging the signaling greatly.
  50. *
  51. * @sa TPORT_DUMP, TPORT_DEBUG, tport_log
  52. */
  53. #ifdef DOXYGEN
  54. extern char const TPORT_LOG[]; /* dummy declaration for Doxygen */
  55. #endif
  56. /**@var TPORT_DUMP
  57. *
  58. * Environment variable for transport data dump.
  59. *
  60. * The received and sent data is dumped to the file specified by TPORT_DUMP
  61. * environment variable. This can be used to save message traces and help
  62. * hairy debugging tasks.
  63. *
  64. * @sa TPORT_LOG, TPORT_DEBUG, tport_log
  65. */
  66. #ifdef DOXYGEN
  67. extern char const TPORT_DUMP[]; /* dummy declaration for Doxygen */
  68. #endif
  69. /**@var TPORT_CAPT
  70. *
  71. * Environment variable for transport data capturing.
  72. *
  73. * The received and sent data is dumped to the capture server specified by TPORT_CAPT
  74. * environment variable. This can be used to save message traces into database and help
  75. * hairy debugging tasks.
  76. *
  77. * @sa TPORT_LOG, TPORT_DEBUG, TPORT_CAPT, TPORT_CAPT_SRC, tport_log
  78. */
  79. #ifdef DOXYGEN
  80. extern char const TPORT_CAPT[]; /* dummy declaration for Doxygen */
  81. #endif
  82. /**@var TPORT_DEBUG
  83. *
  84. * Environment variable determining the debug log level for @b tport module.
  85. *
  86. * The TPORT_DEBUG environment variable is used to determine the debug logging
  87. * level for @b tport module. The default level is 3.
  88. *
  89. * @sa <sofia-sip/su_debug.h>, tport_log, SOFIA_DEBUG
  90. */
  91. #ifdef DOXYGEN
  92. extern char const TPORT_DEBUG[]; /* dummy declaration for Doxygen */
  93. #endif
  94. /**Debug log for @b tport module.
  95. *
  96. * The tport_log is the log object used by @b tport module. The level of
  97. * #tport_log is set using #TPORT_DEBUG environment variable.
  98. */
  99. su_log_t tport_log[] = {
  100. SU_LOG_INIT("tport", "TPORT_DEBUG", SU_DEBUG)
  101. };
  102. /** Initialize logging. */
  103. int tport_open_log(tport_master_t *mr, tagi_t *tags)
  104. {
  105. int n;
  106. int log_msg = mr->mr_log != 0;
  107. char const *dump = NULL;
  108. char const *capt = NULL;;
  109. char const *capt_src = NULL;
  110. if(mr->mr_capt_name) capt = mr->mr_capt_name;
  111. n = tl_gets(tags,
  112. TPTAG_LOG_REF(log_msg),
  113. TPTAG_DUMP_REF(dump),
  114. TPTAG_CAPT_REF(capt),
  115. TPTAG_CAPT_SRC_REF(capt_src),
  116. TAG_END());
  117. if (getenv("MSG_STREAM_LOG") != NULL || getenv("TPORT_LOG") != NULL)
  118. log_msg = 1;
  119. mr->mr_log = log_msg ? MSG_DO_EXTRACT_COPY : 0;
  120. if (getenv("TPORT_CAPT"))
  121. capt = getenv("TPORT_CAPT");
  122. if (getenv("MSG_DUMP"))
  123. dump = getenv("MSG_DUMP");
  124. if (getenv("TPORT_DUMP"))
  125. dump = getenv("TPORT_DUMP");
  126. /* Overriding src address for HEP */
  127. if (capt_src && !mr->mr_capt_src_addr) {
  128. su_addrinfo_t *ai = NULL, hints[1] = {{ 0 }};
  129. hints->ai_flags = AI_NUMERICSERV;
  130. hints->ai_family = AF_UNSPEC;
  131. if (su_getaddrinfo(capt_src, "", hints, &ai)) {
  132. su_perror("capture_src: su_getaddrinfo()");
  133. } else {
  134. mr->mr_capt_src_addr = ai;
  135. }
  136. }
  137. if(capt) {
  138. char *captname, *p, *host_s;
  139. char port[10];
  140. su_addrinfo_t *ai = NULL, hints[1] = {{ 0 }};
  141. unsigned len =0, iport = 0;
  142. if (mr->mr_capt_name && mr->mr_capt_sock && strcmp(capt, mr->mr_capt_name) == 0)
  143. return n;
  144. captname = su_strdup(mr->mr_home, capt);
  145. if (captname == NULL)
  146. return n;
  147. if(strncmp(captname, "udp:",4) != 0) {
  148. su_log("tport_open_log: capturing. Only udp protocol supported [%s]\n", captname);
  149. return n;
  150. }
  151. /* separate proto and host */
  152. p = captname+4;
  153. if( (*(p)) == '\0') {
  154. su_log("malformed ip address\n");
  155. return n;
  156. }
  157. host_s = p;
  158. if( (p = strrchr(p+1, ':')) == 0 ) {
  159. su_log("no host or port specified\n");
  160. return n;
  161. }
  162. /*the address contains a port number*/
  163. *p = '\0';
  164. p++;
  165. iport = atoi(p);
  166. if (iport <1024 || iport >65536)
  167. {
  168. su_log("invalid port number; must be in [1024,65536]\n");
  169. return n;
  170. }
  171. snprintf(port, sizeof(port), "%d", iport);
  172. /* default values for capture protocol and agent id */
  173. mr->mr_prot_ver = 3;
  174. mr->mr_agent_id = 200;
  175. /* get all params */
  176. while(p)
  177. {
  178. /* check ; in the URL */
  179. if( (p = strchr(p+1, ';')) == 0 ) {
  180. break;
  181. }
  182. *p = '\0';
  183. p++;
  184. SU_DEBUG_7(("events HEP RRR DATA [%s]\n", p));
  185. if(strncmp(p, "hep=",4) == 0) {
  186. p+=4;
  187. mr->mr_prot_ver = atoi(p);
  188. /* hepv3 come later */
  189. if (mr->mr_prot_ver < 1 || mr->mr_prot_ver > 3)
  190. {
  191. su_log("invalid hep version number; must be in [1-3]\n");
  192. mr->mr_prot_ver = 3;
  193. return n;
  194. }
  195. }
  196. else if(strncmp(p, "capture_id=", 11) == 0) {
  197. p+=11;
  198. if((mr->mr_agent_id = atoi(p)) == 0)
  199. {
  200. mr->mr_agent_id = 200;
  201. su_log("invalid capture id number; must be uint32 \n");
  202. return n;
  203. }
  204. }
  205. else {
  206. su_log("unsupported capture param\n");
  207. return n;
  208. }
  209. }
  210. /* check if we have [] */
  211. if (host_s[0] == '[') {
  212. len = strlen(host_s + 1) - 1;
  213. if(host_s[len+1] != ']') {
  214. su_log("bracket not closed\n");
  215. return n;
  216. }
  217. memmove(host_s, host_s + 1, len);
  218. host_s[len] = '\0';
  219. }
  220. /* and again */
  221. captname = su_strdup(mr->mr_home, capt);
  222. if (captname == NULL) return n;
  223. su_free(mr->mr_home, mr->mr_capt_name);
  224. mr->mr_capt_name = captname;
  225. if (mr->mr_capt_sock)
  226. su_close(mr->mr_capt_sock), mr->mr_capt_sock = 0;
  227. /* HINTS && getaddrinfo */
  228. hints->ai_flags = AI_NUMERICSERV;
  229. hints->ai_family = AF_UNSPEC;
  230. hints->ai_socktype = SOCK_DGRAM;
  231. hints->ai_protocol = IPPROTO_UDP;
  232. if (su_getaddrinfo(host_s, port, hints, &ai)) {
  233. su_perror("capture: su_getaddrinfo()");
  234. return n;
  235. }
  236. mr->mr_capt_sock = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  237. if (mr->mr_capt_sock == INVALID_SOCKET) {
  238. su_perror("capture: invalid socket");
  239. return n;
  240. }
  241. su_setblocking(mr->mr_capt_sock, 0); /* Don't block */
  242. if (connect(mr->mr_capt_sock, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == -1) {
  243. if (errno != EINPROGRESS) {
  244. su_perror("capture: socket connect");
  245. return n;
  246. }
  247. }
  248. su_freeaddrinfo(ai);
  249. }
  250. else if(mr->mr_capt_sock) {
  251. /* close capture server*/
  252. su_close(mr->mr_capt_sock);
  253. mr->mr_capt_sock = 0;
  254. }
  255. if (dump) {
  256. time_t now;
  257. char *dumpname;
  258. if (mr->mr_dump && strcmp(dump, mr->mr_dump) == 0)
  259. return n;
  260. dumpname = su_strdup(mr->mr_home, dump);
  261. if (dumpname == NULL)
  262. return n;
  263. su_free(mr->mr_home, mr->mr_dump);
  264. mr->mr_dump = dumpname;
  265. if (mr->mr_dump_file && mr->mr_dump_file != stdout)
  266. fclose(mr->mr_dump_file), mr->mr_dump_file = NULL;
  267. if (strcmp(dumpname, "-"))
  268. mr->mr_dump_file = fopen(dumpname, "ab"); /* XXX */
  269. else
  270. mr->mr_dump_file = stdout;
  271. if (mr->mr_dump_file) {
  272. time(&now);
  273. fprintf(mr->mr_dump_file, "dump started at %s\n\n", ctime(&now));
  274. }
  275. }
  276. return n;
  277. }
  278. /** Create log stamp */
  279. void tport_stamp(tport_t const *self, msg_t *msg,
  280. char *stamp, char const *what,
  281. size_t n, char const *via,
  282. su_time_t now)
  283. {
  284. char label[24] = "";
  285. char *comp = "";
  286. char name[SU_ADDRSIZE] = "";
  287. su_sockaddr_t const *su;
  288. unsigned short second, minute, hour;
  289. /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
  290. #if defined(HAVE_GETTIMEOFDAY) || defined(HAVE_CLOCK_MONOTONIC)
  291. struct tm nowtm = { 0 };
  292. time_t nowtime = (now.tv_sec - SU_TIME_EPOCH); /* see su_time0.c 'now' is not really 'now', so we decrease it by SU_TIME_EPOCH */
  293. #endif
  294. assert(self); assert(msg);
  295. #if defined(HAVE_GETTIMEOFDAY) || defined(HAVE_CLOCK_MONOTONIC)
  296. localtime_r(&nowtime, &nowtm);
  297. second = nowtm.tm_sec;
  298. minute = nowtm.tm_min;
  299. hour = nowtm.tm_hour;
  300. #else
  301. second = (unsigned short)(now.tv_sec % 60);
  302. minute = (unsigned short)((now.tv_sec / 60) % 60);
  303. hour = (unsigned short)((now.tv_sec / 3600) % 24);
  304. #endif
  305. su = msg_addr(msg);
  306. #if SU_HAVE_IN6
  307. if (su->su_family == AF_INET6) {
  308. if (su->su_sin6.sin6_flowinfo)
  309. snprintf(label, sizeof(label), "/%u", ntohl(su->su_sin6.sin6_flowinfo));
  310. }
  311. #endif
  312. if (msg_addrinfo(msg)->ai_flags & TP_AI_COMPRESSED)
  313. comp = ";comp=sigcomp";
  314. su_inet_ntop(su->su_family, SU_ADDR(su), name, sizeof(name));
  315. snprintf(stamp, TPORT_STAMP_SIZE,
  316. "%s "MOD_ZU" bytes %s %s/[%s]:%u%s%s at %02u:%02u:%02u.%06lu:\n",
  317. what, (size_t)n, via, self->tp_name->tpn_proto,
  318. name, ntohs(su->su_port), label[0] ? label : "", comp,
  319. hour, minute, second, now.tv_usec);
  320. }
  321. /** Dump the data from the iovec */
  322. void tport_dump_iovec(tport_t const *self, msg_t *msg,
  323. size_t n, su_iovec_t const iov[], size_t iovused,
  324. char const *what, char const *how)
  325. {
  326. tport_master_t *mr;
  327. char stamp[TPORT_STAMP_SIZE];
  328. size_t i;
  329. assert(self); assert(msg);
  330. mr = self->tp_master;
  331. if (!mr->mr_dump_file)
  332. return;
  333. tport_stamp(self, msg, stamp, what, n, how, su_now());
  334. fputs(stamp, mr->mr_dump_file);
  335. for (i = 0; i < iovused && n > 0; i++) {
  336. size_t len = iov[i].mv_len;
  337. if (len > n)
  338. len = n;
  339. if (fwrite(iov[i].mv_base, len, 1, mr->mr_dump_file) != 1)
  340. break;
  341. n -= len;
  342. }
  343. fputs("\v\n", mr->mr_dump_file);
  344. fflush(mr->mr_dump_file);
  345. }
  346. /** Capture the data from the iovec */
  347. void tport_capt_msg(tport_t const *self, msg_t *msg, size_t n,
  348. su_iovec_t const iov[], size_t iovused, char const *what)
  349. {
  350. int buflen = 0;
  351. char* buffer = NULL;
  352. tport_master_t *mr;
  353. assert(self);
  354. mr = self->tp_master;
  355. /* If we don't have socket, go out */
  356. if (!mr->mr_capt_sock) {
  357. su_log("error: capture socket is not open\n");
  358. return;
  359. }
  360. switch(mr->mr_prot_ver)
  361. {
  362. case 3:
  363. buflen = tport_capt_msg_hepv3(self, msg, n, iov, iovused, what, &buffer);
  364. break;
  365. case 2:
  366. case 1:
  367. buflen = tport_capt_msg_hepv2(self, msg, n, iov, iovused, what, &buffer);
  368. break;
  369. default:
  370. su_log("error: unsupported hep version\n");
  371. break;
  372. }
  373. if(buflen > 0) {
  374. /* check if we have error i.e. capture server is down */
  375. if (su_soerror(mr->mr_capt_sock)) {
  376. su_perror("error: tport_logging: capture socket error");
  377. goto done;
  378. }
  379. su_send(mr->mr_capt_sock, buffer, buflen, 0);
  380. }
  381. done:
  382. /* Now we release it */
  383. if(buffer) free(buffer);
  384. return;
  385. }
  386. /** Capture the data from the iovec */
  387. int tport_capt_msg_hepv2 (tport_t const *self, msg_t *msg, size_t n,
  388. su_iovec_t const iov[], size_t iovused, char const *what, char **buffer)
  389. {
  390. int buflen = 0;
  391. su_sockaddr_t const *su, *su_self, *su_self_ext;
  392. struct hep_hdr hep_header;
  393. struct hep_timehdr hep_time = {0};
  394. su_time_t now;
  395. #if __sun__
  396. struct hep_iphdr hep_ipheader = {{{{0}}}};
  397. #else
  398. struct hep_iphdr hep_ipheader = {{0}};
  399. #endif
  400. #if SU_HAVE_IN6
  401. struct hep_ip6hdr hep_ip6header = {{{{0}}}};
  402. #endif
  403. int eth_frame_len = 16000;
  404. size_t i, dst = 1;
  405. tport_master_t *mr;
  406. assert(self); assert(msg);
  407. su = msg_addr(msg);
  408. su_self = self->tp_pri->pri_primary->tp_addr;
  409. mr = self->tp_master;
  410. if (mr->mr_capt_src_addr) {
  411. /* override SRC address with configuration */
  412. su_self_ext = (void *)mr->mr_capt_src_addr->ai_addr;
  413. } else {
  414. /* use the SRC address from the socket */
  415. su_self_ext = su_self;
  416. }
  417. /* If we don't have socket, go out */
  418. if (!mr->mr_capt_sock) {
  419. su_log("error: capture socket is not open\n");
  420. return 0;
  421. }
  422. /*buffer for ethernet frame*/
  423. *buffer = (void*)malloc(eth_frame_len);
  424. /* VOIP Header */
  425. hep_header.hp_v = mr->mr_prot_ver;
  426. hep_header.hp_f = su->su_family;
  427. /* Header Length */
  428. hep_header.hp_l = sizeof(struct hep_hdr);
  429. /* PROTOCOL */
  430. if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hep_header.hp_p = IPPROTO_TCP;
  431. else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hep_header.hp_p = IPPROTO_IDP; /* FAKE*/
  432. else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hep_header.hp_p = IPPROTO_SCTP;
  433. else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hep_header.hp_p = IPPROTO_TCP;
  434. else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hep_header.hp_p = IPPROTO_TCP;
  435. else hep_header.hp_p = IPPROTO_UDP; /* DEFAULT UDP */
  436. /* Check destination */
  437. if(strncmp("sent", what, 4) == 0) dst = 0;
  438. /* copy destination and source IPs*/
  439. if(su->su_family == AF_INET) {
  440. 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));
  441. 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));
  442. hep_header.hp_l += sizeof(struct hep_iphdr);
  443. }
  444. #if SU_HAVE_IN6
  445. else {
  446. 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));
  447. 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));
  448. hep_header.hp_l += sizeof(struct hep_ip6hdr);
  449. }
  450. #endif
  451. hep_header.hp_dport = dst ? su_self->su_port : su->su_port;
  452. hep_header.hp_sport = dst ? su->su_port : su_self->su_port;
  453. if (hep_header.hp_v == 2){
  454. hep_header.hp_l += sizeof(struct hep_timehdr);
  455. }
  456. /* Copy hepheader */
  457. memset(*buffer, '\0', eth_frame_len);
  458. memcpy(*buffer, &hep_header, sizeof(struct hep_hdr));
  459. buflen = sizeof(struct hep_hdr);
  460. if(su->su_family == AF_INET) {
  461. memcpy(*buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
  462. buflen += sizeof(struct hep_iphdr);
  463. }
  464. #if SU_HAVE_IN6
  465. else if(su->su_family == AF_INET6) {
  466. memcpy(*buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
  467. buflen += sizeof(struct hep_ip6hdr);
  468. }
  469. #endif
  470. else {
  471. su_perror("error: tport_logging: capture: unsupported protocol family");
  472. goto done;
  473. }
  474. /* copy time header */
  475. if (hep_header.hp_v == 2) {
  476. /* now */
  477. now = su_now();
  478. /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
  479. #if defined(HAVE_GETTIMEOFDAY) || defined(HAVE_CLOCK_MONOTONIC)
  480. hep_time.tv_sec = (now.tv_sec - SU_TIME_EPOCH); /* see su_time0.c 'now' is not really 'now', so we decrease it by SU_TIME_EPOCH */
  481. #else
  482. hep_time.tv_sec = now.tv_sec;
  483. #endif
  484. hep_time.tv_usec = now.tv_usec;
  485. hep_time.captid = mr->mr_agent_id;
  486. memcpy((char*)*buffer+buflen, &hep_time, sizeof(struct hep_timehdr));
  487. buflen += sizeof(struct hep_timehdr);
  488. }
  489. for (i = 0; i < iovused && n > 0; i++) {
  490. size_t len = iov[i].mv_len;
  491. if (len > n)
  492. len = n;
  493. /* if the packet too big for us */
  494. if((buflen + len) > eth_frame_len)
  495. break;
  496. memcpy(*buffer + buflen , (void*)iov[i].mv_base, len);
  497. buflen +=len;
  498. n -= len;
  499. }
  500. return buflen;
  501. done:
  502. /* Now we release it */
  503. if(*buffer) {
  504. free(*buffer);
  505. *buffer = NULL;
  506. }
  507. return 0;
  508. }
  509. /** Capture the data from the iovec */
  510. int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
  511. su_iovec_t const iov[], size_t iovused, char const *what, char **buffer)
  512. {
  513. su_sockaddr_t const *su, *su_self, *su_self_ext;
  514. struct hep_generic *hg=NULL;
  515. unsigned int buflen=0, iplen=0,tlen=0, payload_len = 0;
  516. su_time_t now;
  517. hep_chunk_ip4_t src_ip4 = {{0}}, dst_ip4 = {{0}};
  518. hep_chunk_t payload_chunk;
  519. int orig_n = 0;
  520. #if SU_HAVE_IN6
  521. hep_chunk_ip6_t src_ip6 = {{0}}, dst_ip6 = {{0}};
  522. #endif
  523. int eth_frame_len = 16000;
  524. size_t i, dst = 1;
  525. tport_master_t *mr;
  526. assert(self); assert(msg);
  527. su = msg_addr(msg);
  528. su_self = self->tp_pri->pri_primary->tp_addr;
  529. mr = self->tp_master;
  530. if (mr->mr_capt_src_addr) {
  531. /* override SRC address with configuration */
  532. su_self_ext = (void *)mr->mr_capt_src_addr->ai_addr;
  533. } else {
  534. /* use the SRC address from the socket */
  535. su_self_ext = su_self;
  536. }
  537. /* If we don't have socket, go out */
  538. if (!mr->mr_capt_sock) {
  539. su_log("error: capture socket is not open\n");
  540. return 0;
  541. }
  542. /*buffer for ethernet frame*/
  543. hg = malloc(sizeof(struct hep_generic));
  544. memset(hg, 0, sizeof(struct hep_generic));
  545. /* header set */
  546. memcpy(hg->header.id, "\x48\x45\x50\x33", 4);
  547. /* IP proto */
  548. hg->ip_family.chunk.vendor_id = htons(0x0000);
  549. hg->ip_family.chunk.type_id = htons(0x0001);
  550. hg->ip_family.data = su->su_family;
  551. hg->ip_family.chunk.length = htons(sizeof(hg->ip_family));
  552. /* PROTOCOL */
  553. if(strcmp(self->tp_name->tpn_proto, "tcp") == 0) hg->ip_proto.data = IPPROTO_TCP;
  554. else if(strcmp(self->tp_name->tpn_proto, "tls") == 0) hg->ip_proto.data = IPPROTO_IDP; /* FAKE*/
  555. else if(strcmp(self->tp_name->tpn_proto, "sctp") == 0) hg->ip_proto.data = IPPROTO_SCTP;
  556. else if(strcmp(self->tp_name->tpn_proto, "ws") == 0) hg->ip_proto.data = IPPROTO_TCP;
  557. else if(strcmp(self->tp_name->tpn_proto, "wss") == 0) hg->ip_proto.data = IPPROTO_TCP;
  558. else hg->ip_proto.data = IPPROTO_UDP; /* DEFAULT UDP */
  559. /* Proto ID */
  560. hg->ip_proto.chunk.vendor_id = htons(0x0000);
  561. hg->ip_proto.chunk.type_id = htons(0x0002);
  562. hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto));
  563. /* Check destination */
  564. if(strncmp("sent", what, 4) == 0) dst = 0;
  565. /* copy destination and source IPs*/
  566. if(su->su_family == AF_INET) {
  567. /* SRC IP */
  568. src_ip4.chunk.vendor_id = htons(0x0000);
  569. src_ip4.chunk.type_id = htons(0x0003);
  570. memcpy(dst ? &src_ip4.data : &dst_ip4.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
  571. src_ip4.chunk.length = htons(sizeof(src_ip4));
  572. /* DST IP */
  573. dst_ip4.chunk.vendor_id = htons(0x0000);
  574. dst_ip4.chunk.type_id = htons(0x0004);
  575. memcpy(dst ? &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));
  576. dst_ip4.chunk.length = htons(sizeof(dst_ip4));
  577. iplen = sizeof(dst_ip4) + sizeof(src_ip4);
  578. }
  579. #if SU_HAVE_IN6
  580. else if(su->su_family == AF_INET6) {
  581. /* SRC IPv6 */
  582. src_ip6.chunk.vendor_id = htons(0x0000);
  583. src_ip6.chunk.type_id = htons(0x0005);
  584. memcpy(dst ? &src_ip6.data : &dst_ip6.data, &su->su_sin.sin_addr.s_addr, sizeof(su->su_sin.sin_addr.s_addr));
  585. src_ip6.chunk.length = htons(sizeof(src_ip6));
  586. /* DST IPv6 */
  587. dst_ip6.chunk.vendor_id = htons(0x0000);
  588. dst_ip6.chunk.type_id = htons(0x0006);
  589. 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));
  590. dst_ip6.chunk.length = htons(sizeof(dst_ip6));
  591. iplen = sizeof(dst_ip6) + sizeof(src_ip6);
  592. }
  593. #endif
  594. else {
  595. su_perror("error: tport_logging hepv3: capture: unsupported protocol family");
  596. goto done;
  597. }
  598. /* SRC PORT */
  599. hg->src_port.chunk.vendor_id = htons(0x0000);
  600. hg->src_port.chunk.type_id = htons(0x0007);
  601. hg->src_port.data = dst ? su->su_port : su_self->su_port;
  602. hg->src_port.chunk.length = htons(sizeof(hg->src_port));
  603. /* DST PORT */
  604. hg->dst_port.chunk.vendor_id = htons(0x0000);
  605. hg->dst_port.chunk.type_id = htons(0x0008);
  606. hg->dst_port.data = dst ? su_self->su_port : su->su_port;
  607. hg->dst_port.chunk.length = htons(sizeof(hg->dst_port));
  608. /* TIMESTAMP SEC */
  609. hg->time_sec.chunk.vendor_id = htons(0x0000);
  610. hg->time_sec.chunk.type_id = htons(0x0009);
  611. hg->time_sec.chunk.length = htons(sizeof(hg->time_sec));
  612. now = su_now();
  613. /* should check for ifdef HAVE_LOCALTIME_R instead -_- */
  614. #if defined(HAVE_GETTIMEOFDAY) || defined(HAVE_CLOCK_MONOTONIC)
  615. hg->time_sec.data = htonl(now.tv_sec - SU_TIME_EPOCH); /* see su_time0.c 'now' is not really 'now', so we decrease it by SU_TIME_EPOCH */
  616. #else
  617. hg->time_sec.data = htonl(now.tv_sec);
  618. #endif
  619. /* TIMESTAMP USEC */
  620. hg->time_usec.chunk.vendor_id = htons(0x0000);
  621. hg->time_usec.chunk.type_id = htons(0x000a);
  622. hg->time_usec.data = htonl(now.tv_usec);
  623. hg->time_usec.chunk.length = htons(sizeof(hg->time_usec));
  624. /* Protocol TYPE */
  625. hg->proto_t.chunk.vendor_id = htons(0x0000);
  626. hg->proto_t.chunk.type_id = htons(0x000b);
  627. hg->proto_t.data = 0x001; //SIP
  628. hg->proto_t.chunk.length = htons(sizeof(hg->proto_t));
  629. /* Capture ID */
  630. hg->capt_id.chunk.vendor_id = htons(0x0000);
  631. hg->capt_id.chunk.type_id = htons(0x000c);
  632. hg->capt_id.data = htonl(mr->mr_agent_id);
  633. hg->capt_id.chunk.length = htons(sizeof(hg->capt_id));
  634. /* Payload caclulation */
  635. orig_n = n;
  636. for (i = 0; i < iovused && n > 0; i++) {
  637. size_t len = iov[i].mv_len;
  638. if (len > n) len = n;
  639. if((payload_len + len) > eth_frame_len) break;
  640. payload_len +=len;
  641. n -= len;
  642. }
  643. /* restore n */
  644. n = orig_n;
  645. /* Payload */
  646. payload_chunk.vendor_id = htons(0x0000);
  647. payload_chunk.type_id = htons(0x000f);
  648. payload_chunk.length = htons(sizeof(payload_chunk) + payload_len);
  649. tlen = sizeof(struct hep_generic) + payload_len + iplen + sizeof(hep_chunk_t);
  650. /* total */
  651. hg->header.length = htons(tlen);
  652. *buffer = (void*)malloc(tlen);
  653. if (*buffer==NULL){
  654. su_perror("error: tport_logging hepv3: no memory for buffer");
  655. goto done;
  656. }
  657. memcpy((void*) *buffer, hg, sizeof(struct hep_generic));
  658. buflen = sizeof(struct hep_generic);
  659. /* IPv4 */
  660. if(su->su_family == AF_INET) {
  661. /* SRC IP */
  662. memcpy((char*) *buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip4));
  663. buflen += sizeof(struct hep_chunk_ip4);
  664. memcpy((char*) *buffer+buflen, &dst_ip4, sizeof(struct hep_chunk_ip4));
  665. buflen += sizeof(struct hep_chunk_ip4);
  666. }
  667. #if SU_HAVE_IN6
  668. /* IPv6 */
  669. else if(su->su_family == AF_INET6) {
  670. /* SRC IPv6 */
  671. memcpy((char*) *buffer+buflen, &src_ip6, sizeof(struct hep_chunk_ip6));
  672. buflen += sizeof(struct hep_chunk_ip6);
  673. memcpy((char*) *buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6));
  674. buflen += sizeof(struct hep_chunk_ip6);
  675. }
  676. #endif
  677. /* PAYLOAD CHUNK */
  678. memcpy((char*) *buffer+buflen, &payload_chunk, sizeof(struct hep_chunk));
  679. buflen += sizeof(struct hep_chunk);
  680. /* PAYLOAD */
  681. for (i = 0; i < iovused && n > 0; i++) {
  682. size_t len = iov[i].mv_len;
  683. if (len > n) len = n;
  684. /* if the packet too big for us */
  685. if((buflen + len) > eth_frame_len)
  686. break;
  687. memcpy(*buffer + buflen , (void*)iov[i].mv_base, len);
  688. buflen +=len;
  689. n -= len;
  690. }
  691. free(hg);
  692. return buflen;
  693. done:
  694. /* Now we release it */
  695. if(hg) free(hg);
  696. return 0;
  697. }
  698. /** Log the message. */
  699. void tport_log_msg(tport_t *self, msg_t *msg,
  700. char const *what, char const *via,
  701. su_time_t now)
  702. {
  703. msg_iovec_t iov[80];
  704. size_t i, iovlen = msg_iovec(msg, iov, 80);
  705. size_t n;
  706. int skip_lf = 0;
  707. char *buffer = NULL;
  708. size_t buffer_size = 0;
  709. size_t buffer_pos = 0;
  710. size_t bytes_written = 0;
  711. #define MSG_SEPARATOR \
  712. "------------------------------------------------------------------------\n"
  713. for (i = n = 0; i < iovlen && i < 80; i++)
  714. n += iov[i].mv_len;
  715. buffer_size = sizeof(char) * n + 1 + TPORT_STAMP_SIZE + sizeof(MSG_SEPARATOR);
  716. if (buffer_size > 16000) {
  717. buffer_size = 16000;
  718. }
  719. buffer = malloc(buffer_size);
  720. buffer[0] = '\0';
  721. tport_stamp(self, msg, buffer, what, n, via, now);
  722. buffer_pos = strlen(buffer);
  723. if (buffer_pos < buffer_size) {
  724. bytes_written = snprintf(buffer + buffer_pos, buffer_size - buffer_pos, "%s", MSG_SEPARATOR);
  725. if (bytes_written > 0) {
  726. buffer_pos += bytes_written;
  727. }
  728. }
  729. for (i = 0; buffer_pos < buffer_size && i < iovlen && i < 80; i++) {
  730. char *s = iov[i].mv_base, *end = s + iov[i].mv_len;
  731. if (skip_lf && s < end && s[0] == '\n') { s++; skip_lf = 0; }
  732. while (s < end) {
  733. if (s[0] == '\0') {
  734. break;
  735. }
  736. n = su_strncspn(s, end - s, "\r\n");
  737. if (buffer_pos > buffer_size) {
  738. break;
  739. }
  740. bytes_written = snprintf(buffer + buffer_pos, buffer_size - buffer_pos, "%.*s", (int)n, s);
  741. if (bytes_written > 0) {
  742. buffer_pos += bytes_written;
  743. }
  744. s += n;
  745. if (s == end)
  746. break;
  747. if (buffer_pos < buffer_size) {
  748. buffer[buffer_pos++] = '\n';
  749. }
  750. /* Skip eol */
  751. if (s[0] == '\r') {
  752. s++;
  753. if (s == end) {
  754. skip_lf = 1;
  755. continue;
  756. }
  757. }
  758. if (s[0] == '\n') {
  759. s++;
  760. }
  761. }
  762. }
  763. if (buffer_pos >= buffer_size) {
  764. buffer_pos = buffer_size - 1;
  765. }
  766. buffer[buffer_pos] = '\0';
  767. su_log("%s\n", buffer);
  768. free(buffer);
  769. }