From e779c364ac7eb1f6bcf42e507972bc3322e6f908 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 29 Jun 2010 20:51:13 +0200 Subject: Add gsmtap utility functions to libosmocore This is imported from OsmocomBB/Layer23 --- src/Makefile.am | 2 +- src/gsmtap_util.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 src/gsmtap_util.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 1a7d87f3..dc2309a0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,7 @@ lib_LTLIBRARIES = libosmocore.la libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \ tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ - logging.c gsm0808.c rate_ctr.c + logging.c gsm0808.c rate_ctr.c gsmtap_util.c if ENABLE_TALLOC libosmocore_la_SOURCES += talloc.c diff --git a/src/gsmtap_util.c b/src/gsmtap_util.c new file mode 100644 index 00000000..5da43690 --- /dev/null +++ b/src/gsmtap_util.c @@ -0,0 +1,185 @@ +/* GSMTAP output for Osmocom Layer2 (will only work on the host PC) */ +/* + * (C) 2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "../config.h" + +#ifdef HAVE_SYS_SELECT_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +static struct bsc_fd gsmtap_bfd = { .fd = -1 }; +static LLIST_HEAD(gsmtap_txqueue); + +uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t link_id) +{ + uint8_t ret = GSMTAP_CHANNEL_UNKNOWN; + + switch (rsl_chantype) { + case RSL_CHAN_Bm_ACCHs: + ret = GSMTAP_CHANNEL_TCH_F; + break; + case RSL_CHAN_Lm_ACCHs: + ret = GSMTAP_CHANNEL_TCH_H; + break; + case RSL_CHAN_SDCCH4_ACCH: + ret = GSMTAP_CHANNEL_SDCCH4; + break; + case RSL_CHAN_SDCCH8_ACCH: + ret = GSMTAP_CHANNEL_SDCCH8; + break; + case RSL_CHAN_BCCH: + ret = GSMTAP_CHANNEL_BCCH; + break; + case RSL_CHAN_RACH: + ret = GSMTAP_CHANNEL_RACH; + break; + case RSL_CHAN_PCH_AGCH: + /* it could also be AGCH... */ + ret = GSMTAP_CHANNEL_PCH; + break; + } + + if (link_id & 0x40) + ret |= GSMTAP_CHANNEL_ACCH; + + return ret; +} + +/* receive a message from L1/L2 and put it in GSMTAP */ +int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss, + uint32_t fn, int8_t signal_dbm, uint8_t snr, + const uint8_t *data, unsigned int len) +{ + struct msgb *msg; + struct gsmtap_hdr *gh; + uint8_t *dst; + + /* gsmtap was never initialized, so don't try to send anything */ + if (gsmtap_bfd.fd == -1) + return 0; + + msg = msgb_alloc(sizeof(*gh) + len, "gsmtap_tx"); + if (!msg) + return -ENOMEM; + + gh = (struct gsmtap_hdr *) msgb_put(msg, sizeof(*gh)); + + gh->version = GSMTAP_VERSION; + gh->hdr_len = sizeof(*gh)/4; + gh->type = GSMTAP_TYPE_UM; + gh->timeslot = ts; + gh->sub_slot = ss; + gh->arfcn = htons(arfcn); + gh->snr_db = snr; + gh->signal_dbm = signal_dbm; + gh->frame_number = htonl(fn); + gh->sub_type = chan_type; + gh->antenna_nr = 0; + + dst = msgb_put(msg, len); + memcpy(dst, data, len); + + msgb_enqueue(&gsmtap_txqueue, msg); + gsmtap_bfd.when |= BSC_FD_WRITE; + + return 0; +} + +/* Callback from select layer if we can write to the socket */ +static int gsmtap_fd_cb(struct bsc_fd *fd, unsigned int flags) +{ + struct msgb *msg; + int rc; + + if (!(flags & BSC_FD_WRITE)) + return 0; + + msg = msgb_dequeue(&gsmtap_txqueue); + if (!msg) { + /* no more messages in the queue, disable READ cb */ + gsmtap_bfd.when = 0; + return 0; + } + rc = write(gsmtap_bfd.fd, msg->data, msg->len); + if (rc < 0) { + perror("writing msgb to gsmtap fd"); + msgb_free(msg); + return rc; + } + if (rc != msg->len) { + perror("short write to gsmtap fd"); + msgb_free(msg); + return -EIO; + } + + msgb_free(msg); + return 0; +} + +int gsmtap_init(uint32_t dst_ip) +{ + int rc; + struct sockaddr_in sin; + + sin.sin_family = AF_INET; + sin.sin_port = htons(GSMTAP_UDP_PORT); + sin.sin_addr.s_addr = htonl(dst_ip); + + /* FIXME: create socket */ + rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (rc < 0) { + perror("creating UDP socket"); + return rc; + } + gsmtap_bfd.fd = rc; + rc = connect(rc, (struct sockaddr *)&sin, sizeof(sin)); + if (rc < 0) { + perror("connecting UDP socket"); + close(gsmtap_bfd.fd); + gsmtap_bfd.fd = 0; + return rc; + } + + gsmtap_bfd.when = BSC_FD_WRITE; + gsmtap_bfd.cb = gsmtap_fd_cb; + gsmtap_bfd.data = NULL; + + return bsc_register_fd(&gsmtap_bfd); +} + +#endif /* HAVE_SYS_SELECT_H */ -- cgit v1.2.3 From e34a94054227bb8b21a6082f7954fea980e2fead Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 29 Jun 2010 22:31:21 +0200 Subject: [gsmtap] add new gsmtap_makemsg() function This generates a gsmtap message without actually enqueueing to a bsc_select style queue. --- src/gsmtap_util.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/gsmtap_util.c b/src/gsmtap_util.c index 5da43690..abee4dac 100644 --- a/src/gsmtap_util.c +++ b/src/gsmtap_util.c @@ -81,21 +81,17 @@ uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t link_id) } /* receive a message from L1/L2 and put it in GSMTAP */ -int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss, - uint32_t fn, int8_t signal_dbm, uint8_t snr, - const uint8_t *data, unsigned int len) +struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, + uint8_t ss, uint32_t fn, int8_t signal_dbm, + uint8_t snr, const uint8_t *data, unsigned int len) { struct msgb *msg; struct gsmtap_hdr *gh; uint8_t *dst; - /* gsmtap was never initialized, so don't try to send anything */ - if (gsmtap_bfd.fd == -1) - return 0; - msg = msgb_alloc(sizeof(*gh) + len, "gsmtap_tx"); if (!msg) - return -ENOMEM; + return NULL; gh = (struct gsmtap_hdr *) msgb_put(msg, sizeof(*gh)); @@ -114,6 +110,25 @@ int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss, dst = msgb_put(msg, len); memcpy(dst, data, len); + return msg; +} + +/* receive a message from L1/L2 and put it in GSMTAP */ +int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss, + uint32_t fn, int8_t signal_dbm, uint8_t snr, + const uint8_t *data, unsigned int len) +{ + struct msgb *msg; + + /* gsmtap was never initialized, so don't try to send anything */ + if (gsmtap_bfd.fd == -1) + return 0; + + msg = gsmtap_makemsg(arfcn, ts, chan_type, ss, fn, signal_dbm, + snr, data, len); + if (!msg) + return -ENOMEM; + msgb_enqueue(&gsmtap_txqueue, msg); gsmtap_bfd.when |= BSC_FD_WRITE; -- cgit v1.2.3 From b9ce51c5fd9773694856802a175efdd9b37a2242 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 30 Jun 2010 19:43:11 +0200 Subject: Add support for plugins (and specifically GPRS encryption plugins) --- src/Makefile.am | 8 ++++- src/gprs_cipher_core.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/plugin.c | 62 ++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 src/gprs_cipher_core.c create mode 100644 src/plugin.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index dc2309a0..a7d450b1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,13 @@ lib_LTLIBRARIES = libosmocore.la libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \ tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ - logging.c gsm0808.c rate_ctr.c gsmtap_util.c + logging.c gsm0808.c rate_ctr.c gsmtap_util.c \ + gprs_cipher_core.c + +if ENABLE_PLUGIN +libosmocore_la_SOURCES += plugin.c +libosmocore_la_LDFLAGS = -ldl +endif if ENABLE_TALLOC libosmocore_la_SOURCES += talloc.c diff --git a/src/gprs_cipher_core.c b/src/gprs_cipher_core.c new file mode 100644 index 00000000..a72dda84 --- /dev/null +++ b/src/gprs_cipher_core.c @@ -0,0 +1,85 @@ +/* GPRS LLC cipher core infrastructure */ + +/* (C) 2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include +#include +#include + +#include + +static LLIST_HEAD(gprs_ciphers); + +static struct gprs_cipher_impl *selected_ciphers[_GPRS_ALGO_NUM]; + +/* register a cipher with the core */ +int gprs_cipher_register(struct gprs_cipher_impl *ciph) +{ + if (ciph->algo > ARRAY_SIZE(selected_ciphers)) + return -ERANGE; + + llist_add_tail(&ciph->list, &gprs_ciphers); + + /* check if we want to select this implementation over others */ + if (!selected_ciphers[ciph->algo] || + (selected_ciphers[ciph->algo]->priority > ciph->priority)) + selected_ciphers[ciph->algo] = ciph; + + return 0; +} + +/* load all available GPRS cipher plugins */ +int gprs_cipher_load(const char *path) +{ + /* load all plugins available from path */ + return plugin_load_all(path); +} + +/* function to be called by core code */ +int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo, + uint64_t kc, uint32_t iv, enum gprs_cipher_direction dir) +{ + if (algo > ARRAY_SIZE(selected_ciphers)) + return -ERANGE; + + if (!selected_ciphers[algo]) + return -EINVAL; + + if (len > GSM0464_CIPH_MAX_BLOCK) + return -ERANGE; + + /* run the actual cipher from the plugin */ + return selected_ciphers[algo]->run(out, len, kc, iv, dir); +} + +int gprs_cipher_supported(enum gprs_ciph_algo algo) +{ + if (algo > ARRAY_SIZE(selected_ciphers)) + return -ERANGE; + + if (selected_ciphers[algo]) + return 1; + + return 0; +} diff --git a/src/plugin.c b/src/plugin.c new file mode 100644 index 00000000..e953508a --- /dev/null +++ b/src/plugin.c @@ -0,0 +1,62 @@ +/* plugin infrastructure */ + +/* (C) 2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "../config.h" + +#if HAVE_DLFCN_H + +#include +#include +#include +#include +#include + +#include + +int plugin_load_all(const char *directory) +{ + unsigned int num = 0; + char fname[PATH_MAX]; + DIR *dir; + struct dirent *entry; + + dir = opendir(directory); + if (!dir) + return -errno; + + while ((entry = readdir(dir))) { + snprintf(fname, sizeof(fname), "%s/%s", directory, + entry->d_name); + if (dlopen(fname, RTLD_NOW)) + num++; + } + + closedir(dir); + + return num; +} +#else +int plugin_load_all(const char *directory) +{ + return 0; +} +#endif /* HAVE_DLFCN_H */ -- cgit v1.2.3 From e335b91ccd6175f43d8bb0c2ea4811e49cb4d95b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 30 Jun 2010 19:50:14 +0200 Subject: GPRS: Add 'input' generator functions for GPRS cipher algorithm --- src/gprs_cipher_core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/gprs_cipher_core.c b/src/gprs_cipher_core.c index a72dda84..6174bd72 100644 --- a/src/gprs_cipher_core.c +++ b/src/gprs_cipher_core.c @@ -83,3 +83,17 @@ int gprs_cipher_supported(enum gprs_ciph_algo algo) return 0; } + +/* GSM TS 04.64 / Section A.2.1 : Generation of 'input' */ +uint32_t gprs_cipher_gen_input_ui(uint32_t iov_ui, uint8_t sapi, uint32_t lfn, uint32_t oc) +{ + uint32_t sx = ((1<<27) * sapi) + (1<<31); + + return (iov_ui ^ sx) + lfn + oc; +} + +/* GSM TS 04.64 / Section A.2.1 : Generation of 'input' */ +uint32_t gprs_cipher_gen_input_i(uint32_t iov_i, uint32_t lfn, uint32_t oc) +{ + return iov_i + lfn + oc; +} -- cgit v1.2.3 From e10ae5b083fee8c91b7c8275aab72061280753e9 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sun, 4 Jul 2010 11:41:36 +0200 Subject: gsm_utils: Fix typo in gsm band name thanks to horizon for noticing :p Signed-off-by: Sylvain Munaut --- src/gsm_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gsm_utils.c b/src/gsm_utils.c index 913946ed..dc97ceff 100644 --- a/src/gsm_utils.c +++ b/src/gsm_utils.c @@ -199,7 +199,7 @@ const char *gsm_band_name(enum gsm_band band) case GSM_BAND_450: return "GSM450"; case GSM_BAND_480: - return "GSM450"; + return "GSM480"; case GSM_BAND_750: return "GSM750"; case GSM_BAND_810: -- cgit v1.2.3 From cd2a74bd43883e98c6a4f54bbf43a1915c83d483 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 12 Jul 2010 08:55:14 +0200 Subject: Added single octet TV (type + value) to libosmocore. In case of a single octet, the upper nibble is the type, the lower nibble carries the value. [import from accidentially committed changes to osmocom-bb.git] diff --git a/src/shared/libosmocore/include/osmocore/tlv.h b/src/shared/libosmocore/include/osmocore/tlv.h index c733dbc..4cfce87 100644 --- a/src/shared/libosmocore/include/osmocore/tlv.h +++ b/src/shared/libosmocore/include/osmocore/tlv.h @@ -212,6 +212,7 @@ enum tlv_type { TLV_TYPE_TLV, TLV_TYPE_TL16V, TLV_TYPE_TvLV, + TLV_TYPE_SINGLE_TV }; struct tlv_def { diff --git a/src/shared/libosmocore/src/tlv_parser.c b/src/shared/libosmocore/src/tlv_parser.c index 407e57a..bbef7a9 100644 --- a/src/shared/libosmocore/src/tlv_parser.c +++ b/src/shared/libosmocore/src/tlv_parser.c @@ -36,6 +36,14 @@ int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val, tag = *buf; *o_tag = tag; + /* single octet TV IE */ + if (def->def[tag & 0xf0].type == TLV_TYPE_SINGLE_TV) { + *o_tag = tag & 0xf0; + *o_val = buf; + *o_len = 1; + return 1; + } + /* FIXME: use tables for knwon IEI */ switch (def->def[tag].type) { case TLV_TYPE_T: --- src/tlv_parser.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/tlv_parser.c b/src/tlv_parser.c index 407e57aa..bbef7a9a 100644 --- a/src/tlv_parser.c +++ b/src/tlv_parser.c @@ -36,6 +36,14 @@ int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val, tag = *buf; *o_tag = tag; + /* single octet TV IE */ + if (def->def[tag & 0xf0].type == TLV_TYPE_SINGLE_TV) { + *o_tag = tag & 0xf0; + *o_val = buf; + *o_len = 1; + return 1; + } + /* FIXME: use tables for knwon IEI */ switch (def->def[tag].type) { case TLV_TYPE_T: -- cgit v1.2.3 From 014cb8725cd4ef58e6ef4be830a58bbf59d4aa03 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 12 Jul 2010 09:11:00 +0200 Subject: Added new IE definitions to gsm_04_08.h of libosmocore. Also added RR and MM TLV tables to gsm48.c [import from accidential commit to osmocom-bb.git] --- src/gsm48.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gsm48.c b/src/gsm48.c index d957aef6..756a1825 100644 --- a/src/gsm48.c +++ b/src/gsm48.c @@ -75,6 +75,68 @@ const struct tlv_definition gsm48_att_tlvdef = { }, }; +/* RR elements */ +const struct tlv_definition gsm48_rr_att_tlvdef = { + .def = { + /* NOTE: Don't add IE 17 = MOBILE_ID here, it already used. */ + [GSM48_IE_VGCS_TARGET] = { TLV_TYPE_TLV }, + [GSM48_IE_FRQSHORT_AFTER] = { TLV_TYPE_FIXED, 9 }, + [GSM48_IE_MUL_RATE_CFG] = { TLV_TYPE_TLV }, + [GSM48_IE_FREQ_L_AFTER] = { TLV_TYPE_TLV }, + [GSM48_IE_MSLOT_DESC] = { TLV_TYPE_TLV }, + [GSM48_IE_CHANMODE_2] = { TLV_TYPE_TV }, + [GSM48_IE_FRQSHORT_BEFORE] = { TLV_TYPE_FIXED, 9 }, + [GSM48_IE_CHANMODE_3] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_4] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_5] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_6] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_7] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_8] = { TLV_TYPE_TV }, + [GSM48_IE_FREQ_L_BEFORE] = { TLV_TYPE_TLV }, + [GSM48_IE_CH_DESC_1_BEFORE] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_CH_DESC_2_BEFORE] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_F_CH_SEQ_BEFORE] = { TLV_TYPE_FIXED, 9 }, + [GSM48_IE_CLASSMARK3] = { TLV_TYPE_TLV }, + [GSM48_IE_MA_BEFORE] = { TLV_TYPE_TLV }, + [GSM48_IE_RR_PACKET_UL] = { TLV_TYPE_TLV }, + [GSM48_IE_RR_PACKET_DL] = { TLV_TYPE_TLV }, + [GSM48_IE_CELL_CH_DESC] = { TLV_TYPE_FIXED, 16 }, + [GSM48_IE_CHANMODE_1] = { TLV_TYPE_TV }, + [GSM48_IE_CHDES_2_AFTER] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_MODE_SEC_CH] = { TLV_TYPE_TV }, + [GSM48_IE_F_CH_SEQ_AFTER] = { TLV_TYPE_FIXED, 9 }, + [GSM48_IE_MA_AFTER] = { TLV_TYPE_TLV }, + [GSM48_IE_BA_RANGE] = { TLV_TYPE_TLV }, + [GSM48_IE_GROUP_CHDES] = { TLV_TYPE_TLV }, + [GSM48_IE_BA_LIST_PREF] = { TLV_TYPE_TLV }, + [GSM48_IE_MOB_OVSERV_DIF] = { TLV_TYPE_TLV }, + [GSM48_IE_REALTIME_DIFF] = { TLV_TYPE_TLV }, + [GSM48_IE_START_TIME] = { TLV_TYPE_FIXED, 2 }, + [GSM48_IE_TIMING_ADVANCE] = { TLV_TYPE_TV }, + [GSM48_IE_GROUP_CIP_SEQ] = { TLV_TYPE_SINGLE_TV }, + [GSM48_IE_CIP_MODE_SET] = { TLV_TYPE_SINGLE_TV }, + [GSM48_IE_GPRS_RESUMPT] = { TLV_TYPE_SINGLE_TV }, + [GSM48_IE_SYNC_IND] = { TLV_TYPE_SINGLE_TV }, + }, +}; + +/* MM elements */ +const struct tlv_definition gsm48_mm_att_tlvdef = { + .def = { + [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV }, + [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV }, + [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV }, + [GSM48_IE_UTC] = { TLV_TYPE_TV }, + [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 }, + [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV }, + + [GSM48_IE_LOCATION_AREA] = { TLV_TYPE_FIXED, 5 }, + [GSM48_IE_PRIORITY_LEV] = { TLV_TYPE_SINGLE_TV }, + [GSM48_IE_FOLLOW_ON_PROC] = { TLV_TYPE_T }, + [GSM48_IE_CTS_PERMISSION] = { TLV_TYPE_T }, + }, +}; + static const struct value_string rr_cause_names[] = { { GSM48_RR_CAUSE_NORMAL, "Normal event" }, { GSM48_RR_CAUSE_ABNORMAL_UNSPEC, "Abnormal release, unspecified" }, @@ -97,7 +159,7 @@ static const struct value_string rr_cause_names[] = { }; /* FIXME: convert to value_string */ -static const char *cc_state_names[33] = { +static const char *cc_state_names[32] = { "NULL", "INITIATED", "MM_CONNECTION_PEND", -- cgit v1.2.3 From ed00fe4449ac2309ad80c32f0ba7aa80b2b8895a Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Mon, 12 Jul 2010 09:12:46 +0200 Subject: Add 3-digit MNC support to gsm48_generate_lai() --- src/gsm48.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/gsm48.c b/src/gsm48.c index 756a1825..daec4f39 100644 --- a/src/gsm48.c +++ b/src/gsm48.c @@ -272,13 +272,13 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc, to_bcd(bcd, mnc); /* FIXME: do we need three-digit MNC? See Table 10.5.3 */ -#if 0 - lai48->digits[1] |= bcd[2] << 4; - lai48->digits[2] = bcd[0] | (bcd[1] << 4); -#else - lai48->digits[1] |= 0xf << 4; - lai48->digits[2] = bcd[1] | (bcd[2] << 4); -#endif + if (mnc > 99) { + lai48->digits[1] |= bcd[2] << 4; + lai48->digits[2] = bcd[0] | (bcd[1] << 4); + } else { + lai48->digits[1] |= 0xf << 4; + lai48->digits[2] = bcd[1] | (bcd[2] << 4); + } lai48->lac = htons(lac); } -- cgit v1.2.3