blob: 8674f1c1e0a0ef4e5d47d1e02f48c43f99893bf9 [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file gsmtap_util.c
2 * GSMTAP support code in libosmocore. */
Harald Weltee779c362010-06-29 20:51:13 +02003/*
Harald Welte93713a52017-07-12 23:43:40 +02004 * (C) 2010-2017 by Harald Welte <laforge@gnumonks.org>
Harald Weltee779c362010-06-29 20:51:13 +02005 *
6 * All Rights Reserved
7 *
Harald Weltee08da972017-11-13 01:00:26 +09008 * SPDX-License-Identifier: GPL-2.0+
9 *
Harald Weltee779c362010-06-29 20:51:13 +020010 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 */
25
26#include "../config.h"
27
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010028#include <osmocom/core/gsmtap_util.h>
29#include <osmocom/core/logging.h>
30#include <osmocom/core/gsmtap.h>
31#include <osmocom/core/msgb.h>
Harald Welte33cb71a2011-05-21 18:54:32 +020032#include <osmocom/core/talloc.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010033#include <osmocom/core/select.h>
Harald Welte33cb71a2011-05-21 18:54:32 +020034#include <osmocom/core/socket.h>
Harald Welte95871da2017-05-15 12:11:36 +020035#include <osmocom/core/byteswap.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010036#include <osmocom/gsm/protocol/gsm_04_08.h>
37#include <osmocom/gsm/rsl.h>
Harald Weltee779c362010-06-29 20:51:13 +020038
Harald Welte33cb71a2011-05-21 18:54:32 +020039#include <sys/types.h>
Harald Weltee4764422011-05-22 12:25:57 +020040
Harald Weltee779c362010-06-29 20:51:13 +020041#include <stdio.h>
42#include <unistd.h>
43#include <stdint.h>
44#include <string.h>
45#include <errno.h>
46
Harald Welte47379ca2011-08-17 16:35:24 +020047/*! \addtogroup gsmtap
48 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020049 * GSMTAP utility routines. Encapsulates GSM messages over UDP.
50 *
51 * \file gsmtap_util.c */
Harald Welte47379ca2011-08-17 16:35:24 +020052
53
Neels Hofmeyr87e45502017-06-20 00:17:59 +020054/*! convert RSL channel number to GSMTAP channel type
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +010055 * \param[in] rsl_chantype RSL channel type
Harald Welte47379ca2011-08-17 16:35:24 +020056 * \param[in] link_id RSL link identifier
Harald Welte67733042020-03-08 17:21:29 +010057 * \param[in] user_plane Is this voice/csd user plane (1) or signaling (0)
Harald Welte47379ca2011-08-17 16:35:24 +020058 * \returns GSMTAP channel type
59 */
Harald Welte67733042020-03-08 17:21:29 +010060uint8_t chantype_rsl2gsmtap2(uint8_t rsl_chantype, uint8_t link_id, bool user_plane)
Harald Weltee779c362010-06-29 20:51:13 +020061{
62 uint8_t ret = GSMTAP_CHANNEL_UNKNOWN;
63
64 switch (rsl_chantype) {
65 case RSL_CHAN_Bm_ACCHs:
Harald Welte67733042020-03-08 17:21:29 +010066 if (user_plane)
67 ret = GSMTAP_CHANNEL_VOICE_F;
68 else
69 ret = GSMTAP_CHANNEL_FACCH_F;
Harald Weltee779c362010-06-29 20:51:13 +020070 break;
71 case RSL_CHAN_Lm_ACCHs:
Harald Welte67733042020-03-08 17:21:29 +010072 if (user_plane)
73 ret = GSMTAP_CHANNEL_VOICE_H;
74 else
75 ret = GSMTAP_CHANNEL_FACCH_H;
Harald Weltee779c362010-06-29 20:51:13 +020076 break;
77 case RSL_CHAN_SDCCH4_ACCH:
78 ret = GSMTAP_CHANNEL_SDCCH4;
79 break;
80 case RSL_CHAN_SDCCH8_ACCH:
81 ret = GSMTAP_CHANNEL_SDCCH8;
82 break;
83 case RSL_CHAN_BCCH:
84 ret = GSMTAP_CHANNEL_BCCH;
85 break;
86 case RSL_CHAN_RACH:
87 ret = GSMTAP_CHANNEL_RACH;
88 break;
89 case RSL_CHAN_PCH_AGCH:
90 /* it could also be AGCH... */
91 ret = GSMTAP_CHANNEL_PCH;
92 break;
Harald Welte3b7cd0b2017-07-27 14:12:15 +020093 case RSL_CHAN_OSMO_PDCH:
94 ret = GSMTAP_CHANNEL_PDCH;
95 break;
Harald Welteac7fabe2020-02-26 17:24:02 +010096 case RSL_CHAN_OSMO_CBCH4:
97 ret = GSMTAP_CHANNEL_CBCH51;
98 break;
99 case RSL_CHAN_OSMO_CBCH8:
100 ret = GSMTAP_CHANNEL_CBCH52;
101 break;
Harald Weltee779c362010-06-29 20:51:13 +0200102 }
103
104 if (link_id & 0x40)
105 ret |= GSMTAP_CHANNEL_ACCH;
106
107 return ret;
108}
109
Harald Welte67733042020-03-08 17:21:29 +0100110/*! convert RSL channel number to GSMTAP channel type
111 * \param[in] rsl_chantype RSL channel type
112 * \param[in] link_id RSL link identifier
113 * \returns GSMTAP channel type
114 */
115uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t link_id)
116{
117 return chantype_rsl2gsmtap2(rsl_chantype, link_id, false);
118}
119
Harald Welte93713a52017-07-12 23:43:40 +0200120/*! convert GSMTAP channel type to RSL channel number + Link ID
121 * \param[in] gsmtap_chantype GSMTAP channel type
122 * \param[out] rsl_chantype RSL channel mumber
123 * \param[out] link_id RSL link identifier
124 */
125void chantype_gsmtap2rsl(uint8_t gsmtap_chantype, uint8_t *rsl_chantype,
126 uint8_t *link_id)
127{
128 switch (gsmtap_chantype & ~GSMTAP_CHANNEL_ACCH & 0xff) {
Harald Welte67733042020-03-08 17:21:29 +0100129 case GSMTAP_CHANNEL_FACCH_F:
130 case GSMTAP_CHANNEL_VOICE_F: // TCH/F
Harald Welte93713a52017-07-12 23:43:40 +0200131 *rsl_chantype = RSL_CHAN_Bm_ACCHs;
132 break;
Harald Welte67733042020-03-08 17:21:29 +0100133 case GSMTAP_CHANNEL_FACCH_H:
134 case GSMTAP_CHANNEL_VOICE_H: // TCH/H
Harald Welte93713a52017-07-12 23:43:40 +0200135 *rsl_chantype = RSL_CHAN_Lm_ACCHs;
136 break;
137 case GSMTAP_CHANNEL_SDCCH4: // SDCCH/4
138 *rsl_chantype = RSL_CHAN_SDCCH4_ACCH;
139 break;
140 case GSMTAP_CHANNEL_SDCCH8: // SDCCH/8
141 *rsl_chantype = RSL_CHAN_SDCCH8_ACCH;
142 break;
143 case GSMTAP_CHANNEL_BCCH: // BCCH
144 *rsl_chantype = RSL_CHAN_BCCH;
145 break;
146 case GSMTAP_CHANNEL_RACH: // RACH
147 *rsl_chantype = RSL_CHAN_RACH;
148 break;
149 case GSMTAP_CHANNEL_PCH: // PCH
150 case GSMTAP_CHANNEL_AGCH: // AGCH
151 *rsl_chantype = RSL_CHAN_PCH_AGCH;
152 break;
153 case GSMTAP_CHANNEL_PDCH:
Harald Welte3b7cd0b2017-07-27 14:12:15 +0200154 *rsl_chantype = RSL_CHAN_OSMO_PDCH;
Harald Welte93713a52017-07-12 23:43:40 +0200155 break;
156 }
157
158 *link_id = gsmtap_chantype & GSMTAP_CHANNEL_ACCH ? 0x40 : 0x00;
159}
160
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200161/*! create an arbitrary type GSMTAP message
Sylvain Munautabf66e72011-09-26 13:23:19 +0200162 * \param[in] type The GSMTAP_TYPE_xxx constant of the message to create
Harald Welte47379ca2011-08-17 16:35:24 +0200163 * \param[in] arfcn GSM ARFCN (Channel Number)
164 * \param[in] ts GSM time slot
165 * \param[in] chan_type Channel Type
166 * \param[in] ss Sub-slot
167 * \param[in] fn GSM Frame Number
168 * \param[in] signal_dbm Signal Strength (dBm)
169 * \param[in] snr Signal/Noise Ratio (SNR)
170 * \param[in] data Pointer to data buffer
171 * \param[in] len Length of \ref data
Oliver Smith12f93be2020-05-19 09:44:49 +0200172 * \return dynamically allocated message buffer containing data,
173 * or NULL for unknown chan_type
Harald Welte47379ca2011-08-17 16:35:24 +0200174 *
175 * This function will allocate a new msgb and fill it with a GSMTAP
176 * header containing the information
177 */
Sylvain Munaut15ae7152011-09-26 13:05:07 +0200178struct msgb *gsmtap_makemsg_ex(uint8_t type, uint16_t arfcn, uint8_t ts, uint8_t chan_type,
Harald Weltee34a9402010-06-29 22:31:21 +0200179 uint8_t ss, uint32_t fn, int8_t signal_dbm,
180 uint8_t snr, const uint8_t *data, unsigned int len)
Harald Weltee779c362010-06-29 20:51:13 +0200181{
182 struct msgb *msg;
183 struct gsmtap_hdr *gh;
184 uint8_t *dst;
185
Oliver Smith12f93be2020-05-19 09:44:49 +0200186 if (chan_type == GSMTAP_CHANNEL_UNKNOWN)
187 return NULL;
188
Harald Weltee779c362010-06-29 20:51:13 +0200189 msg = msgb_alloc(sizeof(*gh) + len, "gsmtap_tx");
190 if (!msg)
Harald Weltee34a9402010-06-29 22:31:21 +0200191 return NULL;
Harald Weltee779c362010-06-29 20:51:13 +0200192
193 gh = (struct gsmtap_hdr *) msgb_put(msg, sizeof(*gh));
194
195 gh->version = GSMTAP_VERSION;
196 gh->hdr_len = sizeof(*gh)/4;
Sylvain Munaut15ae7152011-09-26 13:05:07 +0200197 gh->type = type;
Harald Weltee779c362010-06-29 20:51:13 +0200198 gh->timeslot = ts;
199 gh->sub_slot = ss;
Harald Welte95871da2017-05-15 12:11:36 +0200200 gh->arfcn = osmo_htons(arfcn);
Harald Weltee779c362010-06-29 20:51:13 +0200201 gh->snr_db = snr;
202 gh->signal_dbm = signal_dbm;
Harald Welte95871da2017-05-15 12:11:36 +0200203 gh->frame_number = osmo_htonl(fn);
Harald Weltee779c362010-06-29 20:51:13 +0200204 gh->sub_type = chan_type;
205 gh->antenna_nr = 0;
206
207 dst = msgb_put(msg, len);
208 memcpy(dst, data, len);
209
Harald Weltee34a9402010-06-29 22:31:21 +0200210 return msg;
211}
212
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200213/*! create L1/L2 data and put it into GSMTAP
Sylvain Munautabf66e72011-09-26 13:23:19 +0200214 * \param[in] arfcn GSM ARFCN (Channel Number)
215 * \param[in] ts GSM time slot
216 * \param[in] chan_type Channel Type
217 * \param[in] ss Sub-slot
218 * \param[in] fn GSM Frame Number
219 * \param[in] signal_dbm Signal Strength (dBm)
220 * \param[in] snr Signal/Noise Ratio (SNR)
221 * \param[in] data Pointer to data buffer
222 * \param[in] len Length of \ref data
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200223 * \return message buffer or NULL in case of error
Sylvain Munautabf66e72011-09-26 13:23:19 +0200224 *
225 * This function will allocate a new msgb and fill it with a GSMTAP
226 * header containing the information
227 */
Sylvain Munaut15ae7152011-09-26 13:05:07 +0200228struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
229 uint8_t ss, uint32_t fn, int8_t signal_dbm,
230 uint8_t snr, const uint8_t *data, unsigned int len)
231{
232 return gsmtap_makemsg_ex(GSMTAP_TYPE_UM, arfcn, ts, chan_type,
233 ss, fn, signal_dbm, snr, data, len);
234}
235
Harald Weltee4764422011-05-22 12:25:57 +0200236#ifdef HAVE_SYS_SOCKET_H
237
238#include <sys/socket.h>
239#include <netinet/in.h>
240
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200241/*! Create a new (sending) GSMTAP source socket
Harald Welte47379ca2011-08-17 16:35:24 +0200242 * \param[in] host host name or IP address in string format
243 * \param[in] port UDP port number in host byte order
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200244 * \return file descriptor of the new socket
Harald Welte47379ca2011-08-17 16:35:24 +0200245 *
246 * Opens a GSMTAP source (sending) socket, conncet it to host/port and
247 * return resulting fd. If \a host is NULL, the destination address
248 * will be localhost. If \a port is 0, the default \ref
249 * GSMTAP_UDP_PORT will be used.
250 * */
Harald Welte33cb71a2011-05-21 18:54:32 +0200251int gsmtap_source_init_fd(const char *host, uint16_t port)
252{
253 if (port == 0)
254 port = GSMTAP_UDP_PORT;
255 if (host == NULL)
256 host = "localhost";
257
Pablo Neira Ayuso0849c9a2011-06-09 15:04:30 +0200258 return osmo_sock_init(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, host, port,
259 OSMO_SOCK_F_CONNECT);
Harald Welte33cb71a2011-05-21 18:54:32 +0200260}
261
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200262/*! Add a local sink to an existing GSMTAP source and return fd
Harald Weltede6e4982012-12-06 21:25:27 +0100263 * \param[in] gsmtap_fd file descriptor of the gsmtap socket
264 * \returns file descriptor of locally bound receive socket
265 *
266 * In case the GSMTAP socket is connected to a local destination
267 * IP/port, this function creates a corresponding receiving socket
268 * bound to that destination IP + port.
269 *
270 * In case the gsmtap socket is not connected to a local IP/port, or
271 * creation of the receiving socket fails, a negative error code is
272 * returned.
273 */
Harald Welte33cb71a2011-05-21 18:54:32 +0200274int gsmtap_source_add_sink_fd(int gsmtap_fd)
275{
276 struct sockaddr_storage ss;
277 socklen_t ss_len = sizeof(ss);
278 int rc;
279
280 rc = getpeername(gsmtap_fd, (struct sockaddr *)&ss, &ss_len);
281 if (rc < 0)
282 return rc;
283
284 if (osmo_sockaddr_is_local((struct sockaddr *)&ss, ss_len) == 1) {
Pablo Neira Ayuso0849c9a2011-06-09 15:04:30 +0200285 rc = osmo_sock_init_sa((struct sockaddr *)&ss, SOCK_DGRAM,
Philipp Maierb8a91622018-08-23 20:18:55 +0200286 IPPROTO_UDP,
287 OSMO_SOCK_F_BIND |
288 OSMO_SOCK_F_UDP_REUSEADDR);
Harald Welte33cb71a2011-05-21 18:54:32 +0200289 if (rc >= 0)
290 return rc;
291 }
292
293 return -ENODEV;
294}
295
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200296/*! Send a \ref msgb through a GSMTAP source
Harald Welte47379ca2011-08-17 16:35:24 +0200297 * \param[in] gti GSMTAP instance
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100298 * \param[in] msg message buffer
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200299 * \return 0 in case of success; negative in case of error
Neels Hofmeyrc9a4ce62018-02-16 01:23:29 +0100300 * NOTE: in case of nonzero return value, the *caller* must free the msg!
301 * (This enables the caller to attempt re-sending the message.)
302 * If 0 is returned, the msgb was freed by this function.
Harald Welte47379ca2011-08-17 16:35:24 +0200303 */
Harald Welte33cb71a2011-05-21 18:54:32 +0200304int gsmtap_sendmsg(struct gsmtap_inst *gti, struct msgb *msg)
305{
Harald Welte13692a62011-05-22 20:06:11 +0200306 if (!gti)
307 return -ENODEV;
308
Harald Welte33cb71a2011-05-21 18:54:32 +0200309 if (gti->ofd_wq_mode)
310 return osmo_wqueue_enqueue(&gti->wq, msg);
311 else {
312 /* try immediate send and return error if any */
313 int rc;
314
315 rc = write(gsmtap_inst_fd(gti), msg->data, msg->len);
Neels Hofmeyr90539ac2018-02-16 01:24:03 +0100316 if (rc < 0) {
Harald Welte33cb71a2011-05-21 18:54:32 +0200317 return rc;
318 } else if (rc >= msg->len) {
319 msgb_free(msg);
320 return 0;
321 } else {
322 /* short write */
323 return -EIO;
324 }
325 }
326}
327
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200328/*! send an arbitrary type through GSMTAP.
Sylvain Munautabf66e72011-09-26 13:23:19 +0200329 * See \ref gsmtap_makemsg_ex for arguments
330 */
Sylvain Munaut15ae7152011-09-26 13:05:07 +0200331int gsmtap_send_ex(struct gsmtap_inst *gti, uint8_t type, uint16_t arfcn, uint8_t ts,
Harald Welte33cb71a2011-05-21 18:54:32 +0200332 uint8_t chan_type, uint8_t ss, uint32_t fn,
333 int8_t signal_dbm, uint8_t snr, const uint8_t *data,
334 unsigned int len)
Harald Weltee34a9402010-06-29 22:31:21 +0200335{
336 struct msgb *msg;
Neels Hofmeyra4952aa2018-02-16 01:26:00 +0100337 int rc;
Harald Weltee34a9402010-06-29 22:31:21 +0200338
Harald Welte13692a62011-05-22 20:06:11 +0200339 if (!gti)
340 return -ENODEV;
341
Sylvain Munaut15ae7152011-09-26 13:05:07 +0200342 msg = gsmtap_makemsg_ex(type, arfcn, ts, chan_type, ss, fn, signal_dbm,
Harald Weltee34a9402010-06-29 22:31:21 +0200343 snr, data, len);
344 if (!msg)
345 return -ENOMEM;
346
Neels Hofmeyra4952aa2018-02-16 01:26:00 +0100347 rc = gsmtap_sendmsg(gti, msg);
348 if (rc)
349 msgb_free(msg);
350 return rc;
Harald Weltee779c362010-06-29 20:51:13 +0200351}
352
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200353/*! send a message from L1/L2 through GSMTAP.
Sylvain Munautabf66e72011-09-26 13:23:19 +0200354 * See \ref gsmtap_makemsg for arguments
355 */
Sylvain Munaut15ae7152011-09-26 13:05:07 +0200356int gsmtap_send(struct gsmtap_inst *gti, uint16_t arfcn, uint8_t ts,
357 uint8_t chan_type, uint8_t ss, uint32_t fn,
358 int8_t signal_dbm, uint8_t snr, const uint8_t *data,
359 unsigned int len)
360{
361 return gsmtap_send_ex(gti, GSMTAP_TYPE_UM, arfcn, ts, chan_type, ss, fn,
362 signal_dbm, snr, data, len);
363}
364
Harald Weltee779c362010-06-29 20:51:13 +0200365/* Callback from select layer if we can write to the socket */
Harald Welte33cb71a2011-05-21 18:54:32 +0200366static int gsmtap_wq_w_cb(struct osmo_fd *ofd, struct msgb *msg)
Harald Weltee779c362010-06-29 20:51:13 +0200367{
Harald Weltee779c362010-06-29 20:51:13 +0200368 int rc;
369
Harald Welte33cb71a2011-05-21 18:54:32 +0200370 rc = write(ofd->fd, msg->data, msg->len);
Harald Weltee779c362010-06-29 20:51:13 +0200371 if (rc < 0) {
Harald Weltee779c362010-06-29 20:51:13 +0200372 return rc;
373 }
374 if (rc != msg->len) {
Harald Weltee779c362010-06-29 20:51:13 +0200375 return -EIO;
376 }
377
Harald Weltee779c362010-06-29 20:51:13 +0200378 return 0;
379}
380
Harald Welted58ba462011-04-27 10:57:49 +0200381/* Callback from select layer if we can read from the sink socket */
Pablo Neira Ayusof7f89d02011-05-07 12:42:40 +0200382static int gsmtap_sink_fd_cb(struct osmo_fd *fd, unsigned int flags)
Harald Welted58ba462011-04-27 10:57:49 +0200383{
384 int rc;
385 uint8_t buf[4096];
386
Harald Welte16886992019-03-20 10:26:39 +0100387 if (!(flags & OSMO_FD_READ))
Harald Welted58ba462011-04-27 10:57:49 +0200388 return 0;
389
390 rc = read(fd->fd, buf, sizeof(buf));
391 if (rc < 0) {
Harald Welted58ba462011-04-27 10:57:49 +0200392 return rc;
393 }
394 /* simply discard any data arriving on the socket */
395
396 return 0;
397}
398
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200399/*! Add a local sink to an existing GSMTAP source and return fd
Vadim Yanitskiy2f65bb12019-03-25 15:57:09 +0700400 * \param[in] gti existing GSMTAP source
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200401 * \returns file descriptor of locally bound receive socket
402 *
403 * In case the GSMTAP socket is connected to a local destination
404 * IP/port, this function creates a corresponding receiving socket
405 * bound to that destination IP + port.
406 *
407 * In case the gsmtap socket is not connected to a local IP/port, or
408 * creation of the receiving socket fails, a negative error code is
409 * returned.
410 *
411 * The file descriptor of the receiving socket is automatically added
412 * to the libosmocore select() handling.
413 */
Harald Welte33cb71a2011-05-21 18:54:32 +0200414int gsmtap_source_add_sink(struct gsmtap_inst *gti)
Harald Welted58ba462011-04-27 10:57:49 +0200415{
Harald Welte9d862c82016-11-26 00:10:07 +0100416 int fd, rc;
Harald Welted58ba462011-04-27 10:57:49 +0200417
Harald Welte33cb71a2011-05-21 18:54:32 +0200418 fd = gsmtap_source_add_sink_fd(gsmtap_inst_fd(gti));
419 if (fd < 0)
420 return fd;
Harald Welted58ba462011-04-27 10:57:49 +0200421
Harald Welte33cb71a2011-05-21 18:54:32 +0200422 if (gti->ofd_wq_mode) {
423 struct osmo_fd *sink_ofd;
424
425 sink_ofd = &gti->sink_ofd;
426 sink_ofd->fd = fd;
Harald Welte16886992019-03-20 10:26:39 +0100427 sink_ofd->when = OSMO_FD_READ;
Harald Welte33cb71a2011-05-21 18:54:32 +0200428 sink_ofd->cb = gsmtap_sink_fd_cb;
429
Harald Welte9d862c82016-11-26 00:10:07 +0100430 rc = osmo_fd_register(sink_ofd);
431 if (rc < 0) {
432 close(fd);
433 return rc;
434 }
Harald Welted58ba462011-04-27 10:57:49 +0200435 }
436
Harald Welte33cb71a2011-05-21 18:54:32 +0200437 return fd;
438}
Harald Welted58ba462011-04-27 10:57:49 +0200439
Harald Welte47379ca2011-08-17 16:35:24 +0200440
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200441/*! Open GSMTAP source socket, connect and register osmo_fd
Harald Welte47379ca2011-08-17 16:35:24 +0200442 * \param[in] host host name or IP address in string format
443 * \param[in] port UDP port number in host byte order
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100444 * \param[in] ofd_wq_mode Register \ref osmo_wqueue (1) or not (0)
Harald Welte2d2e2cc2016-04-25 12:11:20 +0200445 * \return callee-allocated \ref gsmtap_inst
Harald Welte47379ca2011-08-17 16:35:24 +0200446 *
447 * Open GSMTAP source (sending) socket, connect it to host/port,
448 * allocate 'struct gsmtap_inst' and optionally osmo_fd/osmo_wqueue
Vadim Yanitskiy2f65bb12019-03-25 15:57:09 +0700449 * registration.
450 */
Harald Welte33cb71a2011-05-21 18:54:32 +0200451struct gsmtap_inst *gsmtap_source_init(const char *host, uint16_t port,
452 int ofd_wq_mode)
453{
454 struct gsmtap_inst *gti;
Harald Welte9d862c82016-11-26 00:10:07 +0100455 int fd, rc;
Harald Welted58ba462011-04-27 10:57:49 +0200456
Harald Welte33cb71a2011-05-21 18:54:32 +0200457 fd = gsmtap_source_init_fd(host, port);
458 if (fd < 0)
459 return NULL;
460
461 gti = talloc_zero(NULL, struct gsmtap_inst);
462 gti->ofd_wq_mode = ofd_wq_mode;
463 gti->wq.bfd.fd = fd;
464 gti->sink_ofd.fd = -1;
465
466 if (ofd_wq_mode) {
467 osmo_wqueue_init(&gti->wq, 64);
468 gti->wq.write_cb = &gsmtap_wq_w_cb;
469
Harald Welte9d862c82016-11-26 00:10:07 +0100470 rc = osmo_fd_register(&gti->wq.bfd);
471 if (rc < 0) {
Vadim Yanitskiyb9baf022019-03-24 00:01:27 +0700472 talloc_free(gti);
Harald Welte9d862c82016-11-26 00:10:07 +0100473 close(fd);
474 return NULL;
475 }
Harald Welte33cb71a2011-05-21 18:54:32 +0200476 }
477
478 return gti;
Harald Welted58ba462011-04-27 10:57:49 +0200479}
480
Harald Weltee4764422011-05-22 12:25:57 +0200481#endif /* HAVE_SYS_SOCKET_H */
Harald Weltede6e4982012-12-06 21:25:27 +0100482
Harald Welteaa3ba462017-07-13 00:01:02 +0200483const struct value_string gsmtap_gsm_channel_names[] = {
484 { GSMTAP_CHANNEL_UNKNOWN, "UNKNOWN" },
485 { GSMTAP_CHANNEL_BCCH, "BCCH" },
486 { GSMTAP_CHANNEL_CCCH, "CCCH" },
487 { GSMTAP_CHANNEL_RACH, "RACH" },
488 { GSMTAP_CHANNEL_AGCH, "AGCH" },
489 { GSMTAP_CHANNEL_PCH, "PCH" },
490 { GSMTAP_CHANNEL_SDCCH, "SDCCH" },
491 { GSMTAP_CHANNEL_SDCCH4, "SDCCH/4" },
492 { GSMTAP_CHANNEL_SDCCH8, "SDCCH/8" },
Harald Welte67733042020-03-08 17:21:29 +0100493 { GSMTAP_CHANNEL_FACCH_F, "FACCH/F" },
494 { GSMTAP_CHANNEL_FACCH_H, "FACCH/H" },
Harald Welteaa3ba462017-07-13 00:01:02 +0200495 { GSMTAP_CHANNEL_PACCH, "PACCH" },
496 { GSMTAP_CHANNEL_CBCH52, "CBCH" },
497 { GSMTAP_CHANNEL_PDCH, "PDCH" } ,
498 { GSMTAP_CHANNEL_PTCCH, "PTTCH" },
499 { GSMTAP_CHANNEL_CBCH51, "CBCH" },
500 { GSMTAP_CHANNEL_ACCH | GSMTAP_CHANNEL_SDCCH, "LSACCH" },
501 { GSMTAP_CHANNEL_ACCH | GSMTAP_CHANNEL_SDCCH4, "SACCH/4" },
502 { GSMTAP_CHANNEL_ACCH | GSMTAP_CHANNEL_SDCCH8, "SACCH/8" },
Harald Welte67733042020-03-08 17:21:29 +0100503 { GSMTAP_CHANNEL_ACCH | GSMTAP_CHANNEL_FACCH_F, "SACCH/F" },
504 { GSMTAP_CHANNEL_ACCH | GSMTAP_CHANNEL_FACCH_H, "SACCH/H" },
505 { GSMTAP_CHANNEL_VOICE_F, "TCH/F" },
506 { GSMTAP_CHANNEL_VOICE_H, "TCH/H" },
Harald Welteaa3ba462017-07-13 00:01:02 +0200507 { 0, NULL }
508};
509
510/* for debugging */
511const struct value_string gsmtap_type_names[] = {
512 { GSMTAP_TYPE_UM, "GSM Um (MS<->BTS)" },
513 { GSMTAP_TYPE_ABIS, "GSM Abis (BTS<->BSC)" },
514 { GSMTAP_TYPE_UM_BURST, "GSM Um burst (MS<->BTS)" },
515 { GSMTAP_TYPE_SIM, "SIM Card" },
516 { GSMTAP_TYPE_TETRA_I1, "TETRA V+D" },
517 { GSMTAP_TYPE_TETRA_I1_BURST, "TETRA bursts" },
518 { GSMTAP_TYPE_WMX_BURST, "WiMAX burst" },
519 { GSMTAP_TYPE_GMR1_UM, "GMR-1 air interfeace (MES-MS<->GTS)"},
520 { GSMTAP_TYPE_UMTS_RLC_MAC, "UMTS RLC/MAC" },
521 { GSMTAP_TYPE_UMTS_RRC, "UMTS RRC" },
522 { GSMTAP_TYPE_LTE_RRC, "LTE RRC" },
523 { GSMTAP_TYPE_LTE_MAC, "LTE MAC" },
524 { GSMTAP_TYPE_LTE_MAC_FRAMED, "LTE MAC with context hdr" },
525 { GSMTAP_TYPE_OSMOCORE_LOG, "libosmocore logging" },
526 { GSMTAP_TYPE_QC_DIAG, "Qualcomm DIAG" },
527 { 0, NULL }
528};
529
Harald Weltede6e4982012-12-06 21:25:27 +0100530/*! @} */