aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-01-17 08:33:29 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-01-17 09:32:05 +0100
commit5899b2d3467e59463606edca9c7407126ebd3218 (patch)
tree3e28bc78feefc79168e50178f2395f5424333552 /src/osmo-bts-sysmo/misc/sysmobts_mgr.c
parent1881e46cb9b7006ddaa66943bc95444766817abb (diff)
sysmobts-mgr: Respond to ipaccess-find broadcast messages
Bind to port 3006 and listen to incoming IPA requests. Currently we unconditionally respond with the MAC and IP Address of the unit. To determine the IP Address the kernel is asked for thesource address of the route for the destination. In contrast to a nanoBTS we will reply to the port the initial request came from.
Diffstat (limited to 'src/osmo-bts-sysmo/misc/sysmobts_mgr.c')
-rw-r--r--src/osmo-bts-sysmo/misc/sysmobts_mgr.c143
1 files changed, 136 insertions, 7 deletions
diff --git a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
index b5bbc311..2e031f3c 100644
--- a/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
+++ b/src/osmo-bts-sysmo/misc/sysmobts_mgr.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <getopt.h>
#include <limits.h>
+#include <arpa/inet.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -39,6 +40,8 @@
#include "misc/sysmobts_misc.h"
#include "misc/sysmobts_mgr.h"
+#include "misc/sysmobts_nl.h"
+#include "misc/sysmobts_par.h"
static int no_eeprom_write = 0;
static int daemonize = 0;
@@ -127,6 +130,10 @@ static void signal_handler(int signal)
#include <osmocom/core/logging.h>
#include <osmocom/core/application.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/socket.h>
+
+#include <osmocom/gsm/protocol/ipaccess.h>
+#include <osmocom/gsm/tlv.h>
#include <osmo-bts/bts.h>
#include <osmo-bts/logging.h>
@@ -144,6 +151,12 @@ static struct log_info_cat mgr_log_info_cat[] = {
.color = "\033[1;36m",
.enabled = 1, .loglevel = LOGL_INFO,
},
+ [DFIND] = {
+ .name = "DFIND",
+ .description = "ipaccess-find handling",
+ .color = "\033[1;37m",
+ .enabled = 1, .loglevel = LOGL_INFO,
+ },
};
static const struct log_info mgr_log_info = {
@@ -157,8 +170,114 @@ static int mgr_log_init(void)
return 0;
}
+/*
+ * The TLV structure in IPA messages in UDP packages is a bit
+ * weird. First the header appears to have an extra NULL byte
+ * and second the L16 of the L16TV needs to include +1 for the
+ * tag. The default msgb/tlv and libosmo-abis routines do not
+ * provide this.
+ */
+
+static void ipaccess_prepend_header_quirk(struct msgb *msg, int proto)
+{
+ struct ipaccess_head *hh;
+
+ /* prepend the ip.access header */
+ hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh) + 1);
+ hh->len = htons(msg->len - sizeof(*hh) - 1);
+ hh->proto = proto;
+}
+
+static void quirk_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag,
+ const uint8_t *val)
+{
+ uint8_t *buf = msgb_put(msg, len + 2 + 1);
+
+ *buf++ = (len + 1) >> 8;
+ *buf++ = (len + 1) & 0xff;
+ *buf++ = tag;
+ memcpy(buf, val, len);
+}
+
+/*
+ * We don't look at the content of the request yet and lie
+ * about most of the responses.
+ */
+static void respond_to(struct sockaddr_in *src, struct osmo_fd *fd,
+ uint8_t *data, size_t len)
+{
+ static int fetched_info = 0;
+ static char mac_str[20] = { };
+
+ struct sockaddr_in loc_addr;
+ char loc_ip[INET_ADDRSTRLEN];
+ struct msgb *msg = msgb_alloc_headroom(512, 128, "ipa get response");
+ if (!msg) {
+ LOGP(DFIND, LOGL_ERROR, "Failed to allocate msgb\n");
+ return;
+ }
+
+ if (!fetched_info) {
+ uint8_t mac[6];
+ sysmobts_par_get_buf(SYSMOBTS_PAR_MAC, mac, sizeof(mac));
+ snprintf(mac_str, sizeof(mac_str), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+ mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+ fetched_info = 1;
+ }
+
+ if (source_for_dest(&src->sin_addr, &loc_addr.sin_addr) != 0) {
+ LOGP(DFIND, LOGL_ERROR, "Failed to determine local source\n");
+ return;
+ }
+
+ msgb_put_u8(msg, IPAC_MSGT_ID_RESP);
+
+ /* append MAC addr */
+ quirk_l16tv_put(msg, strlen(mac_str) + 1, IPAC_IDTAG_MACADDR, (uint8_t *) mac_str);
+
+ /* append ip address */
+ inet_ntop(AF_INET, &loc_addr.sin_addr, loc_ip, sizeof(loc_ip));
+ quirk_l16tv_put(msg, strlen(loc_ip) + 1, IPAC_IDTAG_IPADDR, (uint8_t *) loc_ip);
+
+ /* ip.access nanoBTS would reply to port==3006 */
+ ipaccess_prepend_header_quirk(msg, IPAC_PROTO_IPACCESS);
+ sendto(fd->fd, msg->data, msg->len, 0, (struct sockaddr *)src, sizeof(*src));
+}
+
+static int ipaccess_bcast(struct osmo_fd *fd, unsigned int what)
+{
+ uint8_t data[2048];
+ char src[INET_ADDRSTRLEN];
+ struct sockaddr_in addr = {};
+ socklen_t len = sizeof(addr);
+ int rc;
+
+ rc = recvfrom(fd->fd, data, sizeof(data), 0,
+ (struct sockaddr *) &addr, &len);
+ if (rc <= 0) {
+ LOGP(DFIND, LOGL_ERROR,
+ "Failed to read from socket errno(%d)\n", errno);
+ return -1;
+ }
+
+ LOGP(DFIND, LOGL_DEBUG,
+ "Received request from: %s size %d\n",
+ inet_ntop(AF_INET, &addr.sin_addr, src, sizeof(src)), rc);
+
+ if (rc < 6)
+ return 0;
+
+ if (data[2] != IPAC_PROTO_IPACCESS || data[4] != IPAC_MSGT_ID_GET)
+ return 0;
+
+ respond_to(&addr, fd, data + 6, rc - 6);
+ return 0;
+}
+
int main(int argc, char **argv)
{
+ struct osmo_fd fd;
void *tall_msgb_ctx;
int rc;
@@ -178,6 +297,23 @@ int main(int argc, char **argv)
if (rc < 0)
exit(2);
+ /* start temperature check timer */
+ temp_timer.cb = check_temp_timer_cb;
+ check_temp_timer_cb(NULL);
+
+ /* start operational hours timer */
+ hours_timer.cb = hours_timer_cb;
+ hours_timer_cb(NULL);
+
+ /* handle broadcast messages for ipaccess-find */
+ fd.cb = ipaccess_bcast;
+ rc = osmo_sock_init_ofd(&fd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
+ "0.0.0.0", 3006, OSMO_SOCK_F_BIND);
+ if (rc < 0) {
+ perror("Socket creation");
+ exit(3);
+ }
+
if (daemonize) {
rc = osmo_daemonize();
if (rc < 0) {
@@ -186,13 +322,6 @@ int main(int argc, char **argv)
}
}
- /* start temperature check timer */
- temp_timer.cb = check_temp_timer_cb;
- check_temp_timer_cb(NULL);
-
- /* start operational hours timer */
- hours_timer.cb = hours_timer_cb;
- hours_timer_cb(NULL);
while (1) {
log_reset_context();