Merge commit 'f2699501bc20a1dc5ee965ca1cbb8f18a3471ff8'
authorSylvain Munaut <tnt@246tNt.com>
Sun, 29 May 2011 13:53:59 +0000 (15:53 +0200)
committerSylvain Munaut <tnt@246tNt.com>
Sun, 29 May 2011 13:53:59 +0000 (15:53 +0200)
1  2 
src/shared/libosmocore/include/osmocom/core/bitvec.h
src/shared/libosmocore/src/gsm/sysinfo.c
src/shared/libosmocore/src/socket.c

index bbe1641,0000000..7cb8a87
mode 100644,000000..100644
--- /dev/null
@@@ -1,77 -1,0 +1,78 @@@
 +#ifndef _BITVEC_H
 +#define _BITVEC_H
 +
 +/* bit vector utility routines */
 +
 +/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
 + *
 + * 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 <stdint.h>
 +
 +/* In GSM mac blocks, every bit can be 0 or 1, or L or H.  L/H are
 + * defined relative to the 0x2b padding pattern */
 +enum bit_value {
 +      ZERO    = 0,
 +      ONE     = 1,
 +      L       = 2,
 +      H       = 3,
 +};
 +
 +struct bitvec {
 +      unsigned int cur_bit;   /* curser to the next unused bit */
 +      unsigned int data_len;  /* length of data array in bytes */
 +      uint8_t *data;          /* pointer to data array */
 +};
 +
 +/* check if the bit is 0 or 1 for a given position inside a bitvec */
 +enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr);
 +
 +/* check if the bit is L or H for a given position inside a bitvec */
 +enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv,
 +                                      unsigned int bitnr);
 +
 +/* get the Nth set bit inside the bit vector */
 +unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n);
 +
 +/* Set a bit at given position */
 +int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum,
 +                      enum bit_value bit);
 +
 +/* Set the next bit in the vector */
 +int bitvec_set_bit(struct bitvec *bv, enum bit_value bit);
 +
 +/* get the next bit (low/high) inside a bitvec */
 +int bitvec_get_bit_high(struct bitvec *bv);
 +
 +/* Set multiple bits at the current position */
 +int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count);
 +
 +/* Add an unsigned integer (of length count bits) to current position */
 +int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count);
 +
 +/* get multiple bits (based on numeric value) from current pos */
 +int bitvec_get_uint(struct bitvec *bv, int num_bits);
 +
 +/* find the first bit set in bit vector */
 +int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val);
 +
 +/* Pad the bit vector up to a certain bit position */
 +int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
 +
 +#endif /* _BITVEC_H */
index 0dbff3a,0000000..9df1887
mode 100644,000000..100644
--- /dev/null
@@@ -1,131 -1,0 +1,130 @@@
- #include <netinet/in.h>
 +/* GSM 04.08 System Information (SI) encoding and decoding
 + * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
 +
 +/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
 + *
 + * 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, see <http://www.gnu.org/licenses/>.
 + *
 + */
 +
 +#include <errno.h>
 +#include <string.h>
 +#include <stdio.h>
- static const uint8_t rsl2sitype[0xff] = {
 +
 +#include <osmocom/core/bitvec.h>
 +#include <osmocom/core/utils.h>
 +#include <osmocom/gsm/sysinfo.h>
 +#include <osmocom/gsm/protocol/gsm_04_08.h>
 +#include <osmocom/gsm/protocol/gsm_08_58.h>
 +
 +/* verify the sizes of the system information type structs */
 +
 +/* rest octets are not part of the struct */
 +osmo_static_assert(sizeof(struct gsm48_system_information_type_header) == 3, _si_header_size);
 +osmo_static_assert(sizeof(struct gsm48_rach_control) == 3, _si_rach_control);
 +osmo_static_assert(sizeof(struct gsm48_system_information_type_1) == 22, _si1_size);
 +osmo_static_assert(sizeof(struct gsm48_system_information_type_2) == 23, _si2_size);
 +osmo_static_assert(sizeof(struct gsm48_system_information_type_3) == 19, _si3_size);
 +osmo_static_assert(sizeof(struct gsm48_system_information_type_4) == 13, _si4_size);
 +
 +/* bs11 forgot the l2 len, 0-6 rest octets */
 +osmo_static_assert(sizeof(struct gsm48_system_information_type_5) == 18, _si5_size);
 +osmo_static_assert(sizeof(struct gsm48_system_information_type_6) == 11, _si6_size);
 +
 +osmo_static_assert(sizeof(struct gsm48_system_information_type_13) == 3, _si13_size);
 +
 +static const uint8_t sitype2rsl[_MAX_SYSINFO_TYPE] = {
 +      [SYSINFO_TYPE_1]        = RSL_SYSTEM_INFO_1,
 +      [SYSINFO_TYPE_2]        = RSL_SYSTEM_INFO_2,
 +      [SYSINFO_TYPE_3]        = RSL_SYSTEM_INFO_3,
 +      [SYSINFO_TYPE_4]        = RSL_SYSTEM_INFO_4,
 +      [SYSINFO_TYPE_5]        = RSL_SYSTEM_INFO_5,
 +      [SYSINFO_TYPE_6]        = RSL_SYSTEM_INFO_6,
 +      [SYSINFO_TYPE_7]        = RSL_SYSTEM_INFO_7,
 +      [SYSINFO_TYPE_8]        = RSL_SYSTEM_INFO_8,
 +      [SYSINFO_TYPE_9]        = RSL_SYSTEM_INFO_9,
 +      [SYSINFO_TYPE_10]       = RSL_SYSTEM_INFO_10,
 +      [SYSINFO_TYPE_13]       = RSL_SYSTEM_INFO_13,
 +      [SYSINFO_TYPE_16]       = RSL_SYSTEM_INFO_16,
 +      [SYSINFO_TYPE_17]       = RSL_SYSTEM_INFO_17,
 +      [SYSINFO_TYPE_18]       = RSL_SYSTEM_INFO_18,
 +      [SYSINFO_TYPE_19]       = RSL_SYSTEM_INFO_19,
 +      [SYSINFO_TYPE_20]       = RSL_SYSTEM_INFO_20,
 +      [SYSINFO_TYPE_2bis]     = RSL_SYSTEM_INFO_2bis,
 +      [SYSINFO_TYPE_2ter]     = RSL_SYSTEM_INFO_2ter,
 +      [SYSINFO_TYPE_2quater]  = RSL_SYSTEM_INFO_2quater,
 +      [SYSINFO_TYPE_5bis]     = RSL_SYSTEM_INFO_5bis,
 +      [SYSINFO_TYPE_5ter]     = RSL_SYSTEM_INFO_5ter,
 +};
 +
++static const uint8_t rsl2sitype[256] = {
 +      [RSL_SYSTEM_INFO_1] = SYSINFO_TYPE_1,
 +      [RSL_SYSTEM_INFO_2] = SYSINFO_TYPE_2,
 +      [RSL_SYSTEM_INFO_3] = SYSINFO_TYPE_3,
 +      [RSL_SYSTEM_INFO_4] = SYSINFO_TYPE_4,
 +      [RSL_SYSTEM_INFO_5] = SYSINFO_TYPE_5,
 +      [RSL_SYSTEM_INFO_6] = SYSINFO_TYPE_6,
 +      [RSL_SYSTEM_INFO_7] = SYSINFO_TYPE_7,
 +      [RSL_SYSTEM_INFO_8] = SYSINFO_TYPE_8,
 +      [RSL_SYSTEM_INFO_9] = SYSINFO_TYPE_9,
 +      [RSL_SYSTEM_INFO_10] = SYSINFO_TYPE_10,
 +      [RSL_SYSTEM_INFO_13] = SYSINFO_TYPE_13,
 +      [RSL_SYSTEM_INFO_16] = SYSINFO_TYPE_16,
 +      [RSL_SYSTEM_INFO_17] = SYSINFO_TYPE_17,
 +      [RSL_SYSTEM_INFO_18] = SYSINFO_TYPE_18,
 +      [RSL_SYSTEM_INFO_19] = SYSINFO_TYPE_19,
 +      [RSL_SYSTEM_INFO_20] = SYSINFO_TYPE_20,
 +      [RSL_SYSTEM_INFO_2bis] = SYSINFO_TYPE_2bis,
 +      [RSL_SYSTEM_INFO_2ter] = SYSINFO_TYPE_2ter,
 +      [RSL_SYSTEM_INFO_2quater] = SYSINFO_TYPE_2quater,
 +      [RSL_SYSTEM_INFO_5bis] = SYSINFO_TYPE_5bis,
 +      [RSL_SYSTEM_INFO_5ter] = SYSINFO_TYPE_5ter,
 +};
 +
 +const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE] = {
 +      { SYSINFO_TYPE_1,       "1" },
 +      { SYSINFO_TYPE_2,       "2" },
 +      { SYSINFO_TYPE_3,       "3" },
 +      { SYSINFO_TYPE_4,       "4" },
 +      { SYSINFO_TYPE_5,       "5" },
 +      { SYSINFO_TYPE_6,       "6" },
 +      { SYSINFO_TYPE_7,       "7" },
 +      { SYSINFO_TYPE_8,       "8" },
 +      { SYSINFO_TYPE_9,       "9" },
 +      { SYSINFO_TYPE_10,      "10" },
 +      { SYSINFO_TYPE_13,      "13" },
 +      { SYSINFO_TYPE_16,      "16" },
 +      { SYSINFO_TYPE_17,      "17" },
 +      { SYSINFO_TYPE_18,      "18" },
 +      { SYSINFO_TYPE_19,      "19" },
 +      { SYSINFO_TYPE_20,      "20" },
 +      { SYSINFO_TYPE_2bis,    "2bis" },
 +      { SYSINFO_TYPE_2ter,    "2ter" },
 +      { SYSINFO_TYPE_2quater, "2quater" },
 +      { SYSINFO_TYPE_5bis,    "5bis" },
 +      { SYSINFO_TYPE_5ter,    "5ter" },
 +      { 0, NULL }
 +};
 +
 +uint8_t osmo_sitype2rsl(enum osmo_sysinfo_type si_type)
 +{
 +      return sitype2rsl[si_type];
 +}
 +
 +enum osmo_sysinfo_type osmo_rsl2sitype(uint8_t rsl_si)
 +{
 +      return rsl2sitype[rsl_si];
 +}
index 901b8cd,0000000..014bbaa
mode 100644,000000..100644
--- /dev/null
@@@ -1,181 -1,0 +1,179 @@@
- #include <arpa/inet.h>
 +#include "../config.h"
 +
 +#ifdef HAVE_SYS_SOCKET_H
 +
 +#include <osmocom/core/logging.h>
 +#include <osmocom/core/select.h>
 +#include <osmocom/core/socket.h>
 +
- #include <netinet/in.h>
 +#include <sys/socket.h>
 +#include <sys/types.h>
 +
 +#include <stdio.h>
 +#include <unistd.h>
 +#include <stdint.h>
 +#include <string.h>
 +#include <errno.h>
 +#include <netdb.h>
 +#include <ifaddrs.h>
 +
 +int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
 +                 const char *host, uint16_t port, int connect0_bind1)
 +{
 +      struct addrinfo hints, *result, *rp;
 +      int sfd, rc, on = 1;
 +      char portbuf[16];
 +
 +      sprintf(portbuf, "%u", port);
 +      memset(&hints, 0, sizeof(struct addrinfo));
 +      hints.ai_family = family;
 +      hints.ai_socktype = type;
 +      hints.ai_flags = 0;
 +      hints.ai_protocol = proto;
 +
 +      rc = getaddrinfo(host, portbuf, &hints, &result);
 +      if (rc != 0) {
 +              perror("getaddrinfo returned NULL");
 +              return -EINVAL;
 +      }
 +
 +      for (rp = result; rp != NULL; rp = rp->ai_next) {
 +              sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
 +              if (sfd == -1)
 +                      continue;
 +              if (connect0_bind1 == 0) {
 +                      if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
 +                              break;
 +              } else {
 +                      if (bind(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
 +                              break;
 +              }
 +              close(sfd);
 +      }
 +      freeaddrinfo(result);
 +
 +      if (rp == NULL) {
 +              perror("unable to connect/bind socket");
 +              return -ENODEV;
 +      }
 +
 +      setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
 +
 +      /* Make sure to call 'listen' on a bound, connection-oriented sock */
 +      if (connect0_bind1 == 1) {
 +              switch (type) {
 +              case SOCK_STREAM:
 +              case SOCK_SEQPACKET:
 +                      listen(sfd, 10);
 +                      break;
 +              }
 +      }
 +      return sfd;
 +}
 +
 +int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
 +                      const char *host, uint16_t port, int connect0_bind1)
 +{
 +      int sfd, rc;
 +
 +      sfd = osmo_sock_init(family, type, proto, host, port, connect0_bind1);
 +      if (sfd < 0)
 +              return sfd;
 +
 +      ofd->fd = sfd;
 +      ofd->when = BSC_FD_READ;
 +
 +      rc = osmo_fd_register(ofd);
 +      if (rc < 0) {
 +              close(sfd);
 +              return rc;
 +      }
 +
 +      return sfd;
 +}
 +
 +int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
 +                    uint8_t proto, int connect0_bind1)
 +{
 +      char host[NI_MAXHOST];
 +      uint16_t port;
 +      struct sockaddr_in *sin;
 +      struct sockaddr_in6 *sin6;
 +      int s, sa_len;
 +
 +      /* determine port and host from ss */
 +      switch (ss->sa_family) {
 +      case AF_INET:
 +              sin = (struct sockaddr_in *) ss;
 +              sa_len = sizeof(struct sockaddr_in);
 +              port = ntohs(sin->sin_port);
 +              break;
 +      case AF_INET6:
 +              sin6 = (struct sockaddr_in6 *) ss;
 +              sa_len = sizeof(struct sockaddr_in6);
 +              port = ntohs(sin6->sin6_port);
 +              break;
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      s = getnameinfo(ss, sa_len, host, NI_MAXHOST,
 +                      NULL, 0, NI_NUMERICHOST);
 +      if (s != 0) {
 +              perror("getnameinfo failed");
 +              return s;
 +      }
 +
 +      return osmo_sock_init(ss->sa_family, type, proto, host,
 +                            port, connect0_bind1);
 +}
 +
 +static int sockaddr_equal(const struct sockaddr *a,
 +                        const struct sockaddr *b, unsigned int len)
 +{
 +      struct sockaddr_in *sin_a, *sin_b;
 +      struct sockaddr_in6 *sin6_a, *sin6_b;
 +
 +      if (a->sa_family != b->sa_family)
 +              return 0;
 +
 +      switch (a->sa_family) {
 +      case AF_INET:
 +              sin_a = (struct sockaddr_in *)a;
 +              sin_b = (struct sockaddr_in *)b;
 +              if (!memcmp(&sin_a->sin_addr, &sin_b->sin_addr,
 +                          sizeof(struct in_addr)))
 +                      return 1;
 +              break;
 +      case AF_INET6:
 +              sin6_a = (struct sockaddr_in6 *)a;
 +              sin6_b = (struct sockaddr_in6 *)b;
 +              if (!memcmp(&sin6_a->sin6_addr, &sin6_b->sin6_addr,
 +                          sizeof(struct in6_addr)))
 +                      return 1;
 +              break;
 +      }
 +      return 0;
 +}
 +
 +/* determine if the given address is a local address */
 +int osmo_sockaddr_is_local(struct sockaddr *addr, socklen_t addrlen)
 +{
 +      struct ifaddrs *ifaddr, *ifa;
 +
 +      if (getifaddrs(&ifaddr) == -1) {
 +              perror("getifaddrs");
 +              return -EIO;
 +      }
 +
 +      for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
 +              if (!ifa->ifa_addr)
 +                      continue;
 +              if (sockaddr_equal(ifa->ifa_addr, addr, addrlen))
 +                      return 1;
 +      }
 +
 +      return 0;
 +}
 +
 +#endif /* HAVE_SYS_SOCKET_H */