This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
dexter gerrit-no-reply at lists.osmocom.orgAdded llc-xid encoder / decoder Change-Id: Ia06e4cb08bf9b48c2a4682606d1b1a91d19a9d37 --- M openbsc/include/openbsc/Makefile.am A openbsc/include/openbsc/gprs_llc_xid.h M openbsc/src/gprs/Makefile.am A openbsc/src/gprs/gprs_llc_xid.c 4 files changed, 316 insertions(+), 2 deletions(-) git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/38/638/2 diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 9ef8a15..9e8c554 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -18,7 +18,7 @@ gprs_gb_parse.h smpp.h meas_feed.h \ gprs_gsup_client.h bsc_msg_filter.h \ oap.h oap_messages.h \ - gtphub.h gprs_sndcp.h slhc.h + gtphub.h gprs_sndcp.h slhc.h gprs_llc_xid.h openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/gprs_llc_xid.h b/openbsc/include/openbsc/gprs_llc_xid.h new file mode 100644 index 0000000..c840edb --- /dev/null +++ b/openbsc/include/openbsc/gprs_llc_xid.h @@ -0,0 +1,58 @@ +/* GPRS LLC XID field encoding/decoding as per 3GPP TS 04.64 */ + +/* (C) 2016 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _GPRS_LLC_XID_H +#define _GPRS_LLC_XID_H + +#include <stdint.h> +#include <osmocom/core/linuxlist.h> + +/* TS 101 351 6.4.1.6 Exchange Identification (XID) + command/response parameter field */ +struct gprs_llc_xid_field { + struct llist_head list; + uint8_t type; /* See also Table 6: LLC layer parameter + negotiation */ + uint8_t *data; /* Payload data (octets) */ + unsigned int data_len; /* Payload length */ +}; + +/* Transform a list with XID fields into a XID message (bytes) */ +int gprs_llc_compile_xid(struct llist_head *xid_fields, uint8_t * bytes, + int bytes_maxlen); + +/* Transform a XID message (bytes) into a list of XID fields */ +int gprs_llc_parse_xid(struct llist_head *xid_fields, uint8_t * bytes, + int bytes_len); + +/* Free llist with xid fields */ +void gprs_llc_free_xid(struct llist_head *xid_fields); + +/* Create a duplicate of an XID-Field */ +struct gprs_llc_xid_field *gprs_llc_duplicate_xid_field(struct + gprs_llc_xid_field + *xid_field); + +/* Dump a list with XID fields (Debug) */ +void gprs_llc_dump_xid_fields(struct llist_head *xid_fields); + +#endif diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index a118a19..b3a5137 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -23,7 +23,8 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ slhc.c \ sgsn_main.c sgsn_vty.c sgsn_libgtp.c \ - gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c crc24.c \ + gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c \ + gprs_llc_xid.c crc24.c \ sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \ gprs_utils.c gprs_gsup_client.c \ sgsn_cdr.c sgsn_ares.c \ diff --git a/openbsc/src/gprs/gprs_llc_xid.c b/openbsc/src/gprs/gprs_llc_xid.c new file mode 100644 index 0000000..d8c5339 --- /dev/null +++ b/openbsc/src/gprs/gprs_llc_xid.c @@ -0,0 +1,255 @@ +/* GPRS LLC XID field encoding/decoding as per 3GPP TS 04.64 */ + +/* (C) 2016 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <errno.h> + +#include <osmocom/core/utils.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/talloc.h> + +#include <openbsc/debug.h> +#include <openbsc/gprs_llc.h> +#include <openbsc/sgsn.h> +#include <openbsc/gprs_llc_xid.h> + + +/* Parse XID parameter field */ +static int +decode_xid_field(uint8_t *bytes, uint8_t bytes_len, + struct gprs_llc_xid_field *xid_field) +{ + uint8_t xl; + uint8_t type; + uint8_t len; + int bytes_counter = 0; + + /* Exit immediately if it is clear that no + parseable data is present */ + if ((bytes_len < 1) || (!(bytes))) + return -EINVAL; + + /* Exit immediately if no result can be stored */ + if (!xid_field) + return -EINVAL; + + /* Extract header info */ + xl = (*bytes >> 7) & 1; + type = (*bytes >> 2) & 0x1F; + + /* Extract length field */ + len = (*bytes) & 0x3; + bytes++; + bytes_counter++; + if (xl) { + if (bytes_len < 2) + return -EINVAL; + len = (len << 6) & 0xC0; + len |= ((*bytes) >> 2) & 0x3F; + bytes++; + bytes_counter++; + } + + /* Fill out struct */ + xid_field->type = type; + xid_field->data_len = len; + if (len > 0) { + if (bytes_len < bytes_counter + len) + return -EINVAL; + + xid_field->data = + talloc_zero_size(NULL, xid_field->data_len); + memcpy(xid_field->data, bytes, xid_field->data_len); + } else + xid_field->data = NULL; + + /* Return consumed length */ + return bytes_counter + len; +} + + +/* Encode XID parameter field */ +static int +encode_xid_field(uint8_t *bytes, int bytes_maxlen, + struct gprs_llc_xid_field *xid_field) +{ + int xl = 0; + + /* Exit immediately if no source struct is available */ + if (!xid_field) + return -EINVAL; + + /* When the length does not fit into 2 bits, + we need extended length fields */ + if (xid_field->data_len > 3) + xl = 1; + + /* Exit immediately if it is clear that no + encoding result can be stored */ + if (bytes_maxlen < xid_field->data_len + 1 + xl) + return -EINVAL; + + /* There are only 5 bits reserved for the type, exit on exceed */ + if (xid_field->type > 31) + return -EINVAL; + + /* Encode header */ + memset(bytes, 0, bytes_maxlen); + if (xl) + bytes[0] |= 0x80; + bytes[0] |= (((xid_field->type) & 0x1F) << 2); + + if (xl) { + bytes[0] |= (((xid_field->data_len) >> 6) & 0x03); + bytes[1] = ((xid_field->data_len) << 2) & 0xFC; + } else + bytes[0] |= ((xid_field->data_len) & 0x03); + + /* Append payload data */ + if ((xid_field->data) && (xid_field->data_len)) + memcpy(bytes + 1 + xl, xid_field->data, + xid_field->data_len); + + /* Return generated length */ + return xid_field->data_len + 1 + xl; +} + + +/* Transform a list with XID fields into a XID message (bytes) */ +int +gprs_llc_compile_xid(struct llist_head *xid_fields, uint8_t * bytes, + int bytes_maxlen) +{ + struct gprs_llc_xid_field *xid_field; + int rc; + int byte_counter = 0; + + memset(bytes, 0, bytes_maxlen); + + llist_for_each_entry(xid_field, xid_fields, list) { + /* Encode XID-Field */ + rc = encode_xid_field(bytes, bytes_maxlen, xid_field); + + /* Immediately stop on error */ + if (rc < 0) + return rc; + + /* Advance pointer and lower maxlen for the + next encoding round */ + bytes += rc; + byte_counter += rc; + bytes_maxlen -= rc; + } + + /* Return generated length */ + return byte_counter; +} + + +/* Transform a XID message (bytes) into a list of XID fields */ +int +gprs_llc_parse_xid(struct llist_head *xid_fields, uint8_t * bytes, + int bytes_len) +{ + struct gprs_llc_xid_field *xid_field; + int rc; + + while (1) { + /* Decode XID field */ + xid_field = talloc_zero(NULL, struct gprs_llc_xid_field); + rc = decode_xid_field(bytes, bytes_len, xid_field); + + /* Immediately stop on error */ + if (rc < 0) + return rc; + + /* Add parsed XID field to list */ + llist_add(&xid_field->list, xid_fields); + + /* Advance pointer and lower bytes_len for the next + decoding round */ + bytes += rc; + bytes_len -= rc; + + /* We are (scuccessfully) done when no further byes are left */ + if (bytes_len == 0) + return 0; + } +} + + +/* Free llist with xid fields */ +void gprs_llc_free_xid(struct llist_head *xid_fields) +{ + struct gprs_llc_xid_field *xid_field; + + llist_for_each_entry(xid_field, xid_fields, list) { + if ((xid_field->data) && (xid_field->data_len)) + talloc_free(xid_field->data); + talloc_free(xid_field); + } + +} + + +/* Create a duplicate of an XID-Field */ +struct gprs_llc_xid_field *gprs_llc_duplicate_xid_field(struct + gprs_llc_xid_field + *xid_field) +{ + struct gprs_llc_xid_field *duplicate_of_xid_field; + + /* Create a copy of the XID field in memory */ + duplicate_of_xid_field = + talloc_zero(NULL, struct gprs_llc_xid_field); + memcpy(duplicate_of_xid_field, xid_field, + sizeof(struct gprs_llc_xid_field)); + duplicate_of_xid_field->data = + talloc_zero_size(NULL, xid_field->data_len); + memcpy(duplicate_of_xid_field->data, xid_field->data, + xid_field->data_len); + + /* Wipeout all llist information in the duplicate (just to be sure) */ + memset(&duplicate_of_xid_field->list, 0, + sizeof(struct llist_head)); + + return duplicate_of_xid_field; +} + + +/* Dump a list with XID fields (Debug) */ +void gprs_llc_dump_xid_fields(struct llist_head *xid_fields) +{ + struct gprs_llc_xid_field *xid_field; + + llist_for_each_entry(xid_field, xid_fields, list) { + LOGP(DSNDCP, LOGL_DEBUG, + "XID: type=%i, data_len=%i, data=%s\n", + xid_field->type, xid_field->data_len, + osmo_hexdump_nospc(xid_field->data, + xid_field->data_len)); + } +} -- To view, visit https://gerrit.osmocom.org/638 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newpatchset Gerrit-Change-Id: Ia06e4cb08bf9b48c2a4682606d1b1a91d19a9d37 Gerrit-PatchSet: 2 Gerrit-Project: openbsc Gerrit-Branch: master Gerrit-Owner: dexter <pmaier at sysmocom.de> Gerrit-Reviewer: Jenkins Builder