blob: 85f8c28be113d2347d7f88a5416b44ddcacb7bec [file] [log] [blame]
Harald Welteaa00f992016-12-02 15:30:02 +01001/* GSMTAP network logging support code */
2
3/* (C) 2016 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 */
21
22/*! \addtogroup logging
23 * @{
24 */
25
26/*! \file logging_gsmtap.c */
27
28#include "../config.h"
29
30#include <stdarg.h>
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <stdbool.h>
35#include <arpa/inet.h>
36
37#ifdef HAVE_STRINGS_H
38#include <strings.h>
39#endif
40
41#include <osmocom/core/talloc.h>
42#include <osmocom/core/utils.h>
43#include <osmocom/core/gsmtap.h>
44#include <osmocom/core/gsmtap_util.h>
45#include <osmocom/core/logging.h>
46#include <osmocom/core/timer.h>
47
48#define GSMTAP_LOG_MAX_SIZE 4096
49
50static void _gsmtap_raw_output(struct log_target *target, int subsys,
51 unsigned int level, const char *file,
52 int line, int cont, const char *format,
53 va_list ap)
54{
55 struct msgb *msg;
56 struct gsmtap_hdr *gh;
57 struct gsmtap_osmocore_log_hdr *golh;
58 const char *subsys_name = log_category_name(subsys);
59 struct timeval tv;
60 int rc;
61
62 /* get timestamp ASAP */
63 osmo_gettimeofday(&tv, NULL);
64
65 msg = msgb_alloc(sizeof(*gh)+sizeof(*golh)+GSMTAP_LOG_MAX_SIZE,
66 "GSMTAP logging");
67
68 /* GSMTAP header */
69 gh = (struct gsmtap_hdr *) msgb_put(msg, sizeof(*gh));
70 memset(gh, 0, sizeof(*gh));
71 gh->version = GSMTAP_VERSION;
72 gh->hdr_len = sizeof(*gh)/4;
73 gh->type = GSMTAP_TYPE_OSMOCORE_LOG;
74
75 /* Logging header */
76 golh = (struct gsmtap_osmocore_log_hdr *) msgb_put(msg, sizeof(*golh));
77 osmo_strlcpy(golh->proc_name, target->tgt_gsmtap.ident,
78 sizeof(golh->proc_name));
79 if (subsys_name)
80 osmo_strlcpy(golh->subsys, subsys_name+1, sizeof(golh->subsys));
81 else
82 golh->subsys[0] = '\0';
83 osmo_strlcpy(golh->src_file.name, file, sizeof(golh->src_file.name));
84 golh->src_file.line_nr = htonl(line);
85 golh->level = level;
86 /* we always store the timestamp in the message, irrespective
87 * of hat prrint_[ext_]timestamp say */
88 golh->ts.sec = htonl(tv.tv_sec);
89 golh->ts.usec = htonl(tv.tv_usec);
90
91 rc = vsnprintf((char *) msg->tail, msgb_tailroom(msg), format, ap);
92 if (rc < 0)
93 return;
94 msgb_put(msg, rc);
95
96 gsmtap_sendmsg(target->tgt_gsmtap.gsmtap_inst, msg);
97}
98
99/*! \brief Create a new logging target for GSMTAP logging
100 * \param[in] ident string identifier
101 * \returns Log target in case of success, NULL in case of error
102 */
103struct log_target *log_target_create_gsmtap(const char *host, uint16_t port,
104 const char *ident,
105 bool ofd_wq_mode,
106 bool add_sink)
107{
108 struct log_target *target;
109 struct gsmtap_inst *gti;
110
111 target = log_target_create();
112 if (!target)
113 return NULL;
114
115 gti = gsmtap_source_init(host, port, ofd_wq_mode);
116 if (!gti) {
117 log_target_destroy(target);
118 return NULL;
119 }
120
121 if (add_sink)
122 gsmtap_source_add_sink(gti);
123
124 target->tgt_gsmtap.gsmtap_inst = gti;
125 target->tgt_gsmtap.ident = talloc_strdup(target, ident);
126 target->tgt_gsmtap.hostname = talloc_strdup(target, host);
127
128 target->type = LOG_TGT_TYPE_GSMTAP;
129 target->raw_output = _gsmtap_raw_output;
130
131 return target;
132}
133
134/* @} */