From bc4b0bbe123c673880be370162c25aabebbae15a Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 23 Mar 2015 17:02:12 +0100 Subject: [PATCH 1/8] mtp: Clean-up and remove the unused start routine --- include/mtp_data.h | 1 - src/link_udp.c | 7 ------- src/mtp_link.c | 1 - src/sctp_m2ua.c | 9 --------- 4 files changed, 18 deletions(-) diff --git a/include/mtp_data.h b/include/mtp_data.h index 69db8f7..b6d031c 100644 --- a/include/mtp_data.h +++ b/include/mtp_data.h @@ -139,7 +139,6 @@ struct mtp_link { struct rate_ctr_group *ctrg; /* callback's to implement */ - int (*start)(struct mtp_link *); int (*write)(struct mtp_link *, struct msgb *msg); int (*shutdown)(struct mtp_link *); int (*reset)(struct mtp_link *data); diff --git a/src/link_udp.c b/src/link_udp.c index bc9cf2f..13d338f 100644 --- a/src/link_udp.c +++ b/src/link_udp.c @@ -223,12 +223,6 @@ static int udp_link_write(struct mtp_link *link, struct msgb *msg) return 0; } -static int udp_link_start(struct mtp_link *link) -{ - do_start(link); - return 0; -} - int link_udp_init(struct mtp_udp_link *link, char *remote, int port) { /* prepare the remote */ @@ -383,7 +377,6 @@ struct mtp_udp_link *mtp_udp_link_init(struct mtp_link *blnk) lnk->base->clear_queue = udp_link_dummy; lnk->base->reset = udp_link_reset; - lnk->base->start = udp_link_start; lnk->base->write = udp_link_write; /* prepare the remote */ diff --git a/src/mtp_link.c b/src/mtp_link.c index b48f0d5..3a2683a 100644 --- a/src/mtp_link.c +++ b/src/mtp_link.c @@ -224,7 +224,6 @@ struct mtp_link *mtp_link_alloc(struct mtp_link_set *set) } /* make sure a unconfigured link does not crash */ - link->start = dummy_arg1; link->write = dummy_arg2; link->shutdown = dummy_arg1; link->reset = dummy_arg1; diff --git a/src/sctp_m2ua.c b/src/sctp_m2ua.c index 55ecdfa..f1a6219 100644 --- a/src/sctp_m2ua.c +++ b/src/sctp_m2ua.c @@ -734,14 +734,6 @@ static int sctp_m2ua_dummy(struct mtp_link *link) return 0; } -static int sctp_m2ua_start(struct mtp_link *_link) -{ - struct mtp_m2ua_link *link = (struct mtp_m2ua_link *) _link->data; - - link->transport->started = 1; - return 0; -} - static int sctp_m2ua_reset(struct mtp_link *_link) { struct mtp_m2ua_link *link = (struct mtp_m2ua_link *) _link->data; @@ -843,7 +835,6 @@ struct mtp_m2ua_link *mtp_m2ua_link_init(struct mtp_link *blnk) lnk->base->shutdown = sctp_m2ua_reset; lnk->base->clear_queue = sctp_m2ua_dummy; lnk->base->reset = sctp_m2ua_reset; - lnk->base->start = sctp_m2ua_start; lnk->base->write = sctp_m2ua_write; lnk->transport = trans; From 679a8d0b75fe2db44cacdcd56b11aec3803ca521 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 24 Mar 2015 18:36:24 +0100 Subject: [PATCH 2/8] mtp: Allow to skip SLTM on links (e.g. m3ua) For M3UA links we can't send SLTM messages but we can assume that the link is fine. Add a flag that a link can set in case SLTM should be skipped. The linkset will then directly wait for routable DPCs and bring the SCCP part up. --- include/mtp_data.h | 6 ++++++ src/mtp_layer3.c | 4 ++-- src/mtp_link.c | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/mtp_data.h b/include/mtp_data.h index b6d031c..9d53f24 100644 --- a/include/mtp_data.h +++ b/include/mtp_data.h @@ -144,6 +144,9 @@ struct mtp_link { int (*reset)(struct mtp_link *data); int (*clear_queue)(struct mtp_link *data); + /* for M3UA and others.. */ + int skip_link_test; + /* private data */ enum ss7_link_type type; void *data; @@ -190,4 +193,7 @@ struct mtp_link_set *mtp_link_set_num(struct bsc_data *bsc, int num); struct mtp_link *mtp_link_alloc(struct mtp_link_set *set); struct mtp_link *mtp_link_num(struct mtp_link_set *set, int num); +/* linkset handling */ +int mtp_link_verified(struct mtp_link *link); + #endif diff --git a/src/mtp_layer3.c b/src/mtp_layer3.c index 92e8f41..238a3f1 100644 --- a/src/mtp_layer3.c +++ b/src/mtp_layer3.c @@ -231,7 +231,7 @@ static int send_tfa(struct mtp_link *link, int opc) return 0; } -static int linkset_up(struct mtp_link *link) +int mtp_link_verified(struct mtp_link *link) { struct mtp_link_set *set = link->set; @@ -394,7 +394,7 @@ static int mtp_link_regular_msg(struct mtp_link *link, struct mtp_level_3_hdr *h case MTP_TST_MSG_SLTA: /* If this link is proven set it up */ if (mtp_link_slta(link, l3_len, mng) == 0) - linkset_up(link); + mtp_link_verified(link); break; } break; diff --git a/src/mtp_link.c b/src/mtp_link.c index 3a2683a..9b84e63 100644 --- a/src/mtp_link.c +++ b/src/mtp_link.c @@ -132,6 +132,15 @@ void mtp_link_start_link_test(struct mtp_link *link) return; } + if (link->skip_link_test) { + LOGP(DINP, LOGL_ERROR, "Skipping starting linktest on %d/%s of %d/%s.\n", + link->nr, link->name, link->set->nr, link->set->name); + link->sltm_pending = 0; + link->was_up = 1; + mtp_link_verified(link); + return; + } + mtp_sltm_t2_timeout(link); } From d2f21e079613a7c0ed4f245fb14a6b3d20eefdfc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 23 Mar 2015 16:19:37 +0100 Subject: [PATCH 3/8] m3ua: Begin to create a m3ua client connection Implement a basic M3UA state machine on a SCTP connection. --- include/mtp_data.h | 1 + include/sctp_m3ua.h | 22 ++++++ src/Makefile.am | 2 +- src/sctp_m3ua_client.c | 75 +++++++++++++++++++ src/vty_interface.c | 158 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 include/sctp_m3ua.h create mode 100644 src/sctp_m3ua_client.c diff --git a/include/mtp_data.h b/include/mtp_data.h index 9d53f24..74e0864 100644 --- a/include/mtp_data.h +++ b/include/mtp_data.h @@ -41,6 +41,7 @@ enum ss7_link_type { SS7_LTYPE_NONE, SS7_LTYPE_UDP, SS7_LTYPE_M2UA, + SS7_LTYPE_M3UA_CLIENT, }; /** diff --git a/include/sctp_m3ua.h b/include/sctp_m3ua.h new file mode 100644 index 0000000..c7918be --- /dev/null +++ b/include/sctp_m3ua.h @@ -0,0 +1,22 @@ +/* + * Represet M3UA client (and later server) links + */ +#pragma once + +#include "mtp_data.h" + +#include + +struct mtp_m3ua_client_link { + struct mtp_link *base; + + char *source; + struct sockaddr_in local; + + char *dest; + struct sockaddr_in remote; + int link_index; + int routing_context; +}; + +struct mtp_m3ua_client_link *mtp_m3ua_client_link_init(struct mtp_link *link); diff --git a/src/Makefile.am b/src/Makefile.am index b7044a4..b4fe733 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ osmo_stp_SOURCES = main_stp.c mtp_layer3.c thread.c pcap.c link_udp.c snmp_mtp.c bss_patch.c bssap_sccp.c bsc_sccp.c bsc_ussd.c input/ipaccess.c \ mtp_link.c counter.c bsc.c ss7_application.c \ vty_interface.c vty_interface_cmds.c mgcp_patch.c \ - mgcp_callagent.c isup_filter.c + mgcp_callagent.c isup_filter.c sctp_m3ua_client.c osmo_stp_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \ $(LIBOSMOSCCP_LIBS) $(NEXUSWARE_C7_LIBS) \ -lpthread -lnetsnmp -lcrypto -lxua -lsctp diff --git a/src/sctp_m3ua_client.c b/src/sctp_m3ua_client.c new file mode 100644 index 0000000..0c87f2f --- /dev/null +++ b/src/sctp_m3ua_client.c @@ -0,0 +1,75 @@ +/* Run M3UA over SCTP here */ +/* (C) 2015 by Holger Hans Peter Freyther + * + * 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 . + */ + +#include +#include + +#include + +#define SCTP_PPID_M3UA 3 + +#define notImplemented \ + LOGP(DINP, LOGL_NOTICE, "%s:%s not implemented.\n", \ + __FILE__, __func__); + +static int m3ua_write(struct mtp_link *mtp_link, struct msgb *msg) +{ + msgb_free(msg); + return 0; +} + +static int m3ua_shutdown(struct mtp_link *mtp_link) +{ + return 0; +} + +static int m3ua_reset(struct mtp_link *mtp_link) +{ + /* let the framework call start again */ + return m3ua_shutdown(mtp_link); +} + +static int m3ua_clear_queue(struct mtp_link *mtp_link) +{ + /* nothing */ + return 0; +} + +struct mtp_m3ua_client_link *mtp_m3ua_client_link_init(struct mtp_link *blnk) +{ + struct mtp_m3ua_client_link *lnk; + + lnk = talloc_zero(blnk, struct mtp_m3ua_client_link); + if (!lnk) { + LOGP(DINP, LOGL_ERROR, "Failed to allocate.\n"); + return NULL; + } + + /* make sure we can resolve it both ways */ + lnk->base = blnk; + blnk->data = lnk; + blnk->type = SS7_LTYPE_M3UA_CLIENT; + + /* do some checks for lower layer handling */ + blnk->skip_link_test = 1; + + lnk->base->write = m3ua_write; + lnk->base->shutdown = m3ua_shutdown; + lnk->base->reset = m3ua_reset; + lnk->base->clear_queue = m3ua_clear_queue; + return lnk; +} diff --git a/src/vty_interface.c b/src/vty_interface.c index 93ebc6a..dd4412b 100644 --- a/src/vty_interface.c +++ b/src/vty_interface.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -157,6 +158,7 @@ static void write_link(struct vty *vty, struct mtp_link *link) const char *name = link->name ? link->name : ""; struct mtp_udp_link *ulnk; struct mtp_m2ua_link *m2ua; + struct mtp_m3ua_client_link *m3ua_client; vty_out(vty, " link %d%s", link->nr, VTY_NEWLINE); vty_out(vty, " description %s%s", name, VTY_NEWLINE); @@ -179,11 +181,27 @@ static void write_link(struct vty *vty, struct mtp_link *link) vty_out(vty, " ss7-transport m2ua%s", VTY_NEWLINE); if (m2ua->as) - vty_out(vty, " m2ua application-server %s%s", + vty_out(vty, " m2ua application-server-index %s%s", m2ua->as, VTY_NEWLINE); vty_out(vty, " m2ua link-index %d%s", m2ua->link_index, VTY_NEWLINE); break; + case SS7_LTYPE_M3UA_CLIENT: + m3ua_client = (struct mtp_m3ua_client_link *) link->data; + vty_out(vty, " ss7-transport m3ua-client%s", VTY_NEWLINE); + vty_out(vty, " m3ua-client source ip %s%s", + inet_ntoa(m3ua_client->local.sin_addr), VTY_NEWLINE); + vty_out(vty, " m3ua-client source port %d%s", + ntohs(m3ua_client->local.sin_port), VTY_NEWLINE); + vty_out(vty, " m3ua-client dest ip %s%s", + inet_ntoa(m3ua_client->remote.sin_addr), VTY_NEWLINE); + vty_out(vty, " m3ua-client dest port %d%s", + ntohs(m3ua_client->remote.sin_port), VTY_NEWLINE); + vty_out(vty, " m3ua-client link-index %d%s", + m3ua_client->link_index, VTY_NEWLINE); + vty_out(vty, " m3ua-client routing-context %d%s", + m3ua_client->routing_context, VTY_NEWLINE); + break; case SS7_LTYPE_NONE: break; } @@ -573,7 +591,7 @@ DEFUN(cfg_linkset_link, cfg_linkset_link_cmd, } DEFUN(cfg_link_ss7_transport, cfg_link_ss7_transport_cmd, - "ss7-transport (none|udp|m2ua)", + "ss7-transport (none|udp|m2ua|m3ua-client)", "SS7 transport for the link\n" "No transport\n" "MTP over UDP\n" "SCTP M2UA\n") { @@ -586,6 +604,8 @@ DEFUN(cfg_link_ss7_transport, cfg_link_ss7_transport_cmd, wanted = SS7_LTYPE_UDP; else if (strcmp("m2ua", argv[0]) == 0) wanted = SS7_LTYPE_M2UA; + else if (strcmp("m3ua-client", argv[0]) == 0) + wanted = SS7_LTYPE_M3UA_CLIENT; if (link->type != wanted && link->type != SS7_LTYPE_NONE) { vty_out(vty, "%%Can not change the type of a link.\n"); @@ -599,6 +619,9 @@ DEFUN(cfg_link_ss7_transport, cfg_link_ss7_transport_cmd, case SS7_LTYPE_M2UA: link->data = mtp_m2ua_link_init(link); break; + case SS7_LTYPE_M3UA_CLIENT: + link->data = mtp_m3ua_client_link_init(link); + break; case SS7_LTYPE_NONE: /* nothing */ break; @@ -735,6 +758,131 @@ DEFUN(cfg_link_m2ua_link_index, cfg_link_m2ua_link_index_cmd, return CMD_SUCCESS; } + +DEFUN(cfg_link_m3ua_client_source_ip, cfg_link_m3ua_client_source_ip_cmd, + "m3ua-client source ip HOST_NAME", + "M3UA Client\n" "Source Address\n" "IP\n" "Hostname or IPv4 address\n") +{ + struct hostent *hosts; + + struct mtp_link *link = vty->index; + struct mtp_m3ua_client_link *m3ua_link; + + if (link->type != SS7_LTYPE_M3UA_CLIENT) { + vty_out(vty, "%%This only applies to UDP links.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + m3ua_link = link->data; + + talloc_free(m3ua_link->source); + m3ua_link->source = talloc_strdup(m3ua_link, argv[0]); + + hosts = gethostbyname(m3ua_link->source); + if (!hosts || hosts->h_length < 1 || hosts->h_addrtype != AF_INET) { + vty_out(vty, "Failed to resolve '%s'%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + m3ua_link->local.sin_addr = * (struct in_addr *) hosts->h_addr_list[0]; + return CMD_SUCCESS; +} + +DEFUN(cfg_link_m3ua_client_source_port, cfg_link_m3ua_client_source_port_cmd, + "m3ua-client source port <1-65535>", + "M3UA Client\n" "Source Address\n" "Port\n" "Number\n") +{ + struct mtp_link *link = vty->index; + struct mtp_m3ua_client_link *m3ua_link; + + if (link->type != SS7_LTYPE_M3UA_CLIENT) { + vty_out(vty, "%%This only applies to UDP links.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + m3ua_link = link->data; + m3ua_link->local.sin_port = htons(atoi(argv[0])); + return CMD_SUCCESS; +} + +DEFUN(cfg_link_m3ua_client_dest_ip, cfg_link_m3ua_client_dest_ip_cmd, + "m3ua-client dest ip HOST_NAME", + "M3UA Client\n" "Destination Address\n" "IP\n" "Hostname or IPv4 address\n") +{ + struct hostent *hosts; + + struct mtp_link *link = vty->index; + struct mtp_m3ua_client_link *m3ua_link; + + if (link->type != SS7_LTYPE_M3UA_CLIENT) { + vty_out(vty, "%%This only applies to M3UA client links.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + m3ua_link = link->data; + + talloc_free(m3ua_link->dest); + m3ua_link->dest = talloc_strdup(m3ua_link, argv[0]); + + hosts = gethostbyname(m3ua_link->dest); + if (!hosts || hosts->h_length < 1 || hosts->h_addrtype != AF_INET) { + vty_out(vty, "Failed to resolve '%s'%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + m3ua_link->remote.sin_addr = * (struct in_addr *) hosts->h_addr_list[0]; + return CMD_SUCCESS; +} + +DEFUN(cfg_link_m3ua_client_dest_port, cfg_link_m3ua_client_dest_port_cmd, + "m3ua-client dest port <1-65535>", + "M3UA Client\n" "Destination Address\n" "Port\n" "Number\n") +{ + struct mtp_link *link = vty->index; + struct mtp_m3ua_client_link *m3ua_link; + + if (link->type != SS7_LTYPE_M3UA_CLIENT) { + vty_out(vty, "%%This only applies to M3UA client links.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + m3ua_link = link->data; + m3ua_link->remote.sin_port = htons(atoi(argv[0])); + return CMD_SUCCESS; +} + +DEFUN(cfg_link_m3ua_client_link_index, cfg_link_m3ua_client_link_index_cmd, + "m3ua-client link-index <0-65535>", + "M3UA Client\n" "Link index\n" "Index\n") +{ + struct mtp_link *link = vty->index; + struct mtp_m3ua_client_link *m3ua_link; + + if (link->type != SS7_LTYPE_M3UA_CLIENT) { + vty_out(vty, "%%This only applies to M3UA client links.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + m3ua_link = link->data; + m3ua_link->link_index = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_link_m3ua_client_routing_ctx, cfg_link_m3ua_client_routing_ctx_cmd, + "m3ua-client routing-context <0-65535>", + "M3UA Client\n" "Routing Context\n" "Nunber\n") +{ + struct mtp_link *link = vty->index; + struct mtp_m3ua_client_link *m3ua_link; + + if (link->type != SS7_LTYPE_M3UA_CLIENT) { + vty_out(vty, "%%This only applies to M3UA client links.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + m3ua_link = link->data; + m3ua_link->routing_context = atoi(argv[0]); + return CMD_SUCCESS; +} + DEFUN(cfg_ss7_msc, cfg_ss7_msc_cmd, "msc <0-100>", "MSC Connection\n" "MSC Number\n") @@ -1151,6 +1299,12 @@ void cell_vty_init(void) install_element(LINK_NODE, &cfg_link_udp_link_index_cmd); install_element(LINK_NODE, &cfg_link_m2ua_as_cmd); install_element(LINK_NODE, &cfg_link_m2ua_link_index_cmd); + install_element(LINK_NODE, &cfg_link_m3ua_client_source_ip_cmd); + install_element(LINK_NODE, &cfg_link_m3ua_client_source_port_cmd); + install_element(LINK_NODE, &cfg_link_m3ua_client_dest_ip_cmd); + install_element(LINK_NODE, &cfg_link_m3ua_client_dest_port_cmd); + install_element(LINK_NODE, &cfg_link_m3ua_client_link_index_cmd); + install_element(LINK_NODE, &cfg_link_m3ua_client_routing_ctx_cmd); install_element(SS7_NODE, &cfg_ss7_msc_cmd); install_node(&msc_node, config_write_msc); From 6a20bae1f9adee67829ade0f20d9626deb98eee6 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 23 Mar 2015 16:59:18 +0100 Subject: [PATCH 4/8] m3ua: Implement connect and re-connect handling --- include/sctp_m3ua.h | 5 ++ src/sctp_m3ua_client.c | 166 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 165 insertions(+), 6 deletions(-) diff --git a/include/sctp_m3ua.h b/include/sctp_m3ua.h index c7918be..f59b5de 100644 --- a/include/sctp_m3ua.h +++ b/include/sctp_m3ua.h @@ -5,11 +5,16 @@ #include "mtp_data.h" +#include + #include struct mtp_m3ua_client_link { struct mtp_link *base; + struct osmo_wqueue queue; + struct osmo_timer_list connect_timer; + char *source; struct sockaddr_in local; diff --git a/src/sctp_m3ua_client.c b/src/sctp_m3ua_client.c index 0c87f2f..0cef103 100644 --- a/src/sctp_m3ua_client.c +++ b/src/sctp_m3ua_client.c @@ -17,35 +17,186 @@ #include #include +#include #include +#include + +#include + #define SCTP_PPID_M3UA 3 -#define notImplemented \ - LOGP(DINP, LOGL_NOTICE, "%s:%s not implemented.\n", \ - __FILE__, __func__); +#define notImplemented() \ + LOGP(DINP, LOGL_NOTICE, "%s not implemented.\n", __func__) + +static int m3ua_shutdown(struct mtp_link *mtp_link); +static void m3ua_start(void *data); + +static void schedule_restart(struct mtp_m3ua_client_link *link) +{ + link->connect_timer.data = link; + link->connect_timer.cb = m3ua_start; + osmo_timer_schedule(&link->connect_timer, 1, 0); +} + +static void fail_link(struct mtp_m3ua_client_link *link) +{ + /* We need to fail the link */ + m3ua_shutdown(link->base); + mtp_link_down(link->base); + schedule_restart(link); +} + +static int m3ua_conn_handle(struct mtp_m3ua_client_link *link, + struct msgb *msg, struct sctp_sndrcvinfo *info) +{ + notImplemented(); + return 0; +} + +static int m3ua_conn_write(struct osmo_fd *fd, struct msgb *msg) +{ + int ret; + struct sctp_sndrcvinfo info; + memcpy(&info, msg->data, sizeof(info)); + + ret = sctp_send(fd->fd, msg->l2h, msgb_l2len(msg), + &info, 0); + + if (ret != msgb_l2len(msg)) + LOGP(DINP, LOGL_ERROR, "Failed to send %d.\n", ret); + + return 0; +} + +static int m3ua_conn_read(struct osmo_fd *fd) +{ + struct sockaddr_in addr; + struct sctp_sndrcvinfo info; + socklen_t len = sizeof(addr); + struct mtp_m3ua_client_link *link = fd->data; + struct msgb *msg; + int rc; + + msg = msgb_alloc(2048, "m3ua buffer"); + if (!msg) { + LOGP(DINP, LOGL_ERROR, "Failed to allocate buffer.\n"); + fail_link(link); + return -1; + } + + memset(&info, 0, sizeof(info)); + memset(&addr, 0, sizeof(addr)); + rc = sctp_recvmsg(fd->fd, msg->data, msg->data_len, + (struct sockaddr *) &addr, &len, &info, NULL); + if (rc <= 0) { + LOGP(DINP, LOGL_ERROR, "Failed to read.\n"); + msgb_free(msg); + fail_link(link); + return -1; + } + + if (ntohl(info.sinfo_ppid) != SCTP_PPID_M3UA) { + LOGP(DINP, LOGL_ERROR, "Only M3UA is allowed on this socket: %d\n", + ntohl(info.sinfo_ppid)); + msgb_free(msg); + return -1; + } + + msgb_put(msg, rc); + LOGP(DINP, LOGL_DEBUG, "Read %d on stream: %d ssn: %d assoc: %d\n", + rc, info.sinfo_stream, info.sinfo_ssn, info.sinfo_assoc_id); + m3ua_conn_handle(link, msg, &info); + msgb_free(msg); + return 0; +} + +static void m3ua_start(void *data) +{ + int sctp, ret; + struct sockaddr_in loc_addr, rem_addr; + struct mtp_m3ua_client_link *link = data; + struct sctp_event_subscribe events; + + sctp = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP); + if (!sctp) { + LOGP(DINP, LOGL_ERROR, "Failed to create socket.\n"); + return fail_link(link); + } + + memset(&events, 0, sizeof(events)); + events.sctp_data_io_event = 1; + ret = setsockopt(sctp, SOL_SCTP, SCTP_EVENTS, &events, sizeof(events)); + if (ret != 0) { + LOGP(DINP, LOGL_ERROR, "Failed to enable SCTP Events. Closing socket.\n"); + close(sctp); + return fail_link(link); + } + + loc_addr = link->local; + loc_addr.sin_family = AF_INET; + if (bind(sctp, (struct sockaddr *) &loc_addr, sizeof(loc_addr)) != 0) { + LOGP(DINP, LOGL_ERROR, "Failed to bind.\n"); + close(sctp); + return fail_link(link); + } + + rem_addr = link->remote; + rem_addr.sin_family = AF_INET; + if (connect(sctp, (struct sockaddr *) &rem_addr, sizeof(rem_addr)) != 0) { + LOGP(DINP, LOGL_ERROR, "Failed to connect\n"); + close(sctp); + return fail_link(link); + } + + link->queue.bfd.fd = sctp; + link->queue.bfd.data = link; + link->queue.bfd.when = BSC_FD_READ; + link->queue.read_cb = m3ua_conn_read; + link->queue.write_cb = m3ua_conn_write; + + if (osmo_fd_register(&link->queue.bfd) != 0) { + LOGP(DINP, LOGL_ERROR, "Failed to register fd\n"); + close(sctp); + return fail_link(link); + } +} static int m3ua_write(struct mtp_link *mtp_link, struct msgb *msg) { + notImplemented(); msgb_free(msg); return 0; } static int m3ua_shutdown(struct mtp_link *mtp_link) { + struct mtp_m3ua_client_link *link = mtp_link->data; + + if (link->queue.bfd.fd >= 0) { + osmo_fd_unregister(&link->queue.bfd); + close(link->queue.bfd.fd); + link->queue.bfd.fd = -1; + } + osmo_wqueue_clear(&link->queue); return 0; } static int m3ua_reset(struct mtp_link *mtp_link) { - /* let the framework call start again */ - return m3ua_shutdown(mtp_link); + struct mtp_m3ua_client_link *link = mtp_link->data; + + /* stop things in case they run.. */ + m3ua_shutdown(mtp_link); + schedule_restart(link); + return 0; } static int m3ua_clear_queue(struct mtp_link *mtp_link) { - /* nothing */ + struct mtp_m3ua_client_link *link = mtp_link->data; + osmo_wqueue_clear(&link->queue); return 0; } @@ -71,5 +222,8 @@ struct mtp_m3ua_client_link *mtp_m3ua_client_link_init(struct mtp_link *blnk) lnk->base->shutdown = m3ua_shutdown; lnk->base->reset = m3ua_reset; lnk->base->clear_queue = m3ua_clear_queue; + + osmo_wqueue_init(&lnk->queue, 10); + lnk->queue.bfd.fd = -1; return lnk; } From d1df399a972ce2b96b0d3ef9e90d17a7c16a93b5 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 24 Mar 2015 18:51:02 +0100 Subject: [PATCH 5/8] m3ua: Implement link bring-up and sending/receiving of data the opc/dpc for ISUP is currently wrong. The send/recv path for actual SCCP data is not tested. --- include/sctp_m3ua.h | 5 + src/sctp_m3ua_client.c | 343 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 346 insertions(+), 2 deletions(-) diff --git a/include/sctp_m3ua.h b/include/sctp_m3ua.h index f59b5de..0cc405f 100644 --- a/include/sctp_m3ua.h +++ b/include/sctp_m3ua.h @@ -22,6 +22,11 @@ struct mtp_m3ua_client_link { struct sockaddr_in remote; int link_index; int routing_context; + + + /* state of the link */ + int aspsm_active; + int asptm_active; }; struct mtp_m3ua_client_link *mtp_m3ua_client_link_init(struct mtp_link *link); diff --git a/src/sctp_m3ua_client.c b/src/sctp_m3ua_client.c index 0cef103..dd378bb 100644 --- a/src/sctp_m3ua_client.c +++ b/src/sctp_m3ua_client.c @@ -18,6 +18,11 @@ #include #include #include +#include +#include + +#include +#include #include @@ -30,6 +35,20 @@ #define notImplemented() \ LOGP(DINP, LOGL_NOTICE, "%s not implemented.\n", __func__) + +/* + * State machine code + */ +static void m3ua_handle_aspsm(struct mtp_m3ua_client_link *link, struct xua_msg *msg); +static void m3ua_handle_asptm(struct mtp_m3ua_client_link *link, struct xua_msg *msg); +static void m3ua_handle_trans(struct mtp_m3ua_client_link *link, struct xua_msg *msg); +static void m3ua_send_daud(struct mtp_m3ua_client_link *link, uint32_t pc); +static void m3ua_send_aspup(struct mtp_m3ua_client_link *link); +static void m3ua_send_aspac(struct mtp_m3ua_client_link *link); + +/* + * boilerplate + */ static int m3ua_shutdown(struct mtp_link *mtp_link); static void m3ua_start(void *data); @@ -51,7 +70,30 @@ static void fail_link(struct mtp_m3ua_client_link *link) static int m3ua_conn_handle(struct mtp_m3ua_client_link *link, struct msgb *msg, struct sctp_sndrcvinfo *info) { - notImplemented(); + struct xua_msg *m3ua; + m3ua = xua_from_msg(M3UA_VERSION, msg->len, msg->data); + if (!m3ua) { + LOGP(DINP, LOGL_ERROR, "Failed to parse the message.\n"); + return -1; + } + + switch (m3ua->hdr.msg_class) { + case M3UA_CLS_ASPSM: + m3ua_handle_aspsm(link, m3ua); + break; + case M3UA_CLS_ASPTM: + m3ua_handle_asptm(link, m3ua); + break; + case M3UA_CLS_TRANS: + m3ua_handle_trans(link, m3ua); + break; + default: + LOGP(DINP, LOGL_ERROR, "Unhandled msg_class %d\n", + m3ua->hdr.msg_class); + break; + } + + xua_msg_free(m3ua); return 0; } @@ -70,6 +112,29 @@ static int m3ua_conn_write(struct osmo_fd *fd, struct msgb *msg) return 0; } +static int m3ua_conn_send(struct mtp_m3ua_client_link *link, + struct xua_msg *m3ua, + struct sctp_sndrcvinfo *info) +{ + struct msgb *msg; + msg = xua_to_msg(M3UA_VERSION, m3ua); + if (!msg) + return -1; + + /* save the OOB data in front of the message */ + msg->l2h = msg->data; + msgb_push(msg, sizeof(*info)); + memcpy(msg->data, info, sizeof(*info)); + + if (osmo_wqueue_enqueue(&link->queue, msg) != 0) { + LOGP(DINP, LOGL_ERROR, "Failed to enqueue.\n"); + msgb_free(msg); + return -1; + } + + return 0; +} + static int m3ua_conn_read(struct osmo_fd *fd) { struct sockaddr_in addr; @@ -161,11 +226,89 @@ static void m3ua_start(void *data) close(sctp); return fail_link(link); } + + /* begin the messages for bring-up */ + m3ua_send_aspup(link); } static int m3ua_write(struct mtp_link *mtp_link, struct msgb *msg) { - notImplemented(); + struct mtp_m3ua_client_link *link = mtp_link->data; + struct sctp_sndrcvinfo info; + struct xua_msg *m3ua; + struct mtp_level_3_hdr *mtp_hdr; + struct m3ua_protocol_data proto_data; + uint8_t *proto_start; + + if (!link->asptm_active) { + LOGP(DINP, LOGL_ERROR, "ASP not ready for %d/%s of %d/%s.\n", + mtp_link->nr, mtp_link->name, mtp_link->set->nr, + mtp_link->set->name); + goto clean; + } + + /* + * TODO.. we could enhance the structure of mtp_link to + * have function pointers for operations like SLTM instead + * of doing what we do here. + * The entire m3ua episode (code + reading the spec) had a + * budget of < 2 man days so the amount of architecture changes + * we can do. + */ + + /* TODO.. need to terminate MTPL3 locally... */ + + /* TODO.. extract MTP information.. */ + mtp_hdr = (struct mtp_level_3_hdr *) msg->l2h; + switch (mtp_hdr->ser_ind) { + case MTP_SI_MNT_SNM_MSG: + case MTP_SI_MNT_REG_MSG: + LOGP(DINP, LOGL_ERROR, + "Dropping SNM/REG/ISUP/??? message %d\n", mtp_hdr->ser_ind); + goto clean; + break; + case MTP_SI_MNT_ISUP: + case MTP_SI_MNT_SCCP: + default: + /* TODO... read OPC/DPC from message.. */ + memset(&proto_data, 0, sizeof(proto_data)); + proto_data.opc = htonl(mtp_link->set->sccp_opc); + proto_data.dpc = htonl(mtp_link->set->sccp_dpc == -1 ? + mtp_link->set->sccp_dpc : mtp_link->set->dpc); + proto_data.sls = MTP_LINK_SLS(mtp_hdr->addr); + proto_data.si = mtp_hdr->ser_ind; + proto_data.ni = mtp_link->set->ni; + + msg->l3h = mtp_hdr->data; + msgb_pull_to_l3(msg); + proto_start = msgb_push(msg, sizeof(proto_data)); + memcpy(proto_start, &proto_data, sizeof(proto_data)); + break; + }; + + m3ua = xua_msg_alloc(); + if (!m3ua) + goto clean; + + mtp_handle_pcap(mtp_link, NET_OUT, msg->data, msg->len); + + m3ua->hdr.msg_class = M3UA_CLS_TRANS; + m3ua->hdr.msg_type = M3UA_TRANS_DATA; + + /* + * Modify the data...to create a true protocol data.. + */ + xua_msg_add_data(m3ua, M3UA_TAG_PROTO_DATA, msg->len, msg->data); + + memset(&info, 0, sizeof(info)); + info.sinfo_stream = 0; + info.sinfo_assoc_id = 1; + info.sinfo_ppid = htonl(SCTP_PPID_M3UA); + + m3ua_conn_send(link, m3ua, &info); + xua_msg_free(m3ua); + +clean: msgb_free(msg); return 0; } @@ -180,6 +323,8 @@ static int m3ua_shutdown(struct mtp_link *mtp_link) link->queue.bfd.fd = -1; } osmo_wqueue_clear(&link->queue); + link->aspsm_active = 0; + link->asptm_active = 0; return 0; } @@ -227,3 +372,197 @@ struct mtp_m3ua_client_link *mtp_m3ua_client_link_init(struct mtp_link *blnk) lnk->queue.bfd.fd = -1; return lnk; } + + +/* + * asp handling + */ +static void m3ua_send_aspup(struct mtp_m3ua_client_link *link) +{ + struct sctp_sndrcvinfo info; + struct xua_msg *aspup; + uint32_t asp_ident; + + aspup = xua_msg_alloc(); + if (!aspup) { + fail_link(link); + return; + } + + memset(&info, 0, sizeof(info)); + info.sinfo_stream = 0; + info.sinfo_assoc_id = 1; + info.sinfo_ppid = htonl(SCTP_PPID_M3UA); + + aspup->hdr.msg_class = M3UA_CLS_ASPSM; + aspup->hdr.msg_type = M3UA_ASPSM_UP; + + asp_ident = htonl(link->link_index); + xua_msg_add_data(aspup, MUA_TAG_ASP_IDENT, 4, (uint8_t *) &asp_ident); + + m3ua_conn_send(link, aspup, &info); + xua_msg_free(aspup); +} + +static void m3ua_send_aspac(struct mtp_m3ua_client_link *link) +{ + struct sctp_sndrcvinfo info; + struct xua_msg *aspac; + uint32_t routing_ctx; + uint32_t traffic_mode; + + aspac = xua_msg_alloc(); + if (!aspac) { + fail_link(link); + return; + } + + memset(&info, 0, sizeof(info)); + info.sinfo_stream = 0; + info.sinfo_assoc_id = 1; + info.sinfo_ppid = htonl(SCTP_PPID_M3UA); + + aspac->hdr.msg_class = M3UA_CLS_ASPTM; + aspac->hdr.msg_type = M3UA_ASPTM_ACTIV; + + traffic_mode = htonl(2); + xua_msg_add_data(aspac, 11, 4, (uint8_t *) &traffic_mode); + + routing_ctx = htonl(link->routing_context); + xua_msg_add_data(aspac, MUA_TAG_ROUTING_CTX, 4, (uint8_t *) &routing_ctx); + + m3ua_conn_send(link, aspac, &info); + xua_msg_free(aspac); +} + +static void m3ua_send_daud(struct mtp_m3ua_client_link *link, uint32_t dpc) +{ + struct sctp_sndrcvinfo info; + struct xua_msg *daud; + uint32_t routing_ctx; + + daud = xua_msg_alloc(); + if (!daud) { + fail_link(link); + return; + } + + memset(&info, 0, sizeof(info)); + info.sinfo_stream = 0; + info.sinfo_assoc_id = 1; + info.sinfo_ppid = htonl(SCTP_PPID_M3UA); + + daud->hdr.msg_class = M3UA_CLS_SSNM; + daud->hdr.msg_type = M3UA_SSNM_DAUD; + + routing_ctx = htonl(link->routing_context); + xua_msg_add_data(daud, MUA_TAG_ROUTING_CTX, 4, (uint8_t *) &routing_ctx); + + dpc = htonl(dpc); + xua_msg_add_data(daud, MUA_TAG_AFF_PC, 4, (uint8_t *) &dpc); + + m3ua_conn_send(link, daud, &info); + xua_msg_free(daud); +} + +static void m3ua_handle_aspsm(struct mtp_m3ua_client_link *link, struct xua_msg *m3ua) +{ + switch (m3ua->hdr.msg_type) { + case M3UA_ASPSM_UP_ACK: + LOGP(DINP, LOGL_NOTICE, "Received ASP_UP_ACK.. sending ASPAC\n"); + link->aspsm_active = 1; + m3ua_send_aspac(link); + break; + default: + LOGP(DINP, LOGL_ERROR, "Unhandled msg_type %d\n", + m3ua->hdr.msg_type); + break; + } +} + +static void m3ua_handle_asptm(struct mtp_m3ua_client_link *link, struct xua_msg *m3ua) +{ + switch (m3ua->hdr.msg_type) { + case M3UA_ASPTM_ACTIV_ACK: + LOGP(DINP, LOGL_NOTICE, "Received ASPAC_ACK.. taking link up\n"); + link->asptm_active = 1; + mtp_link_up(link->base); + m3ua_send_daud(link, link->base->set->dpc); + if (link->base->set->sccp_dpc != -1) + m3ua_send_daud(link, link->base->set->sccp_dpc); + break; + default: + LOGP(DINP, LOGL_ERROR, "Unhandled msg_type %d\n", + m3ua->hdr.msg_type); + break; + } +} + +static void m3ua_handle_trans(struct mtp_m3ua_client_link *link, struct xua_msg *m3ua) +{ + struct msgb *msg; + struct xua_msg_part *data; + struct mtp_link *mtp_link; + struct m3ua_protocol_data *proto; + struct mtp_level_3_hdr *mtp_hdr; + uint32_t opc, dpc; + uint8_t sls, si; + + mtp_link = link->base; + + /* ignore everything if the link is blocked */ + if (mtp_link->blocked) + return; + + if (m3ua->hdr.msg_type != M3UA_TRANS_DATA) { + LOGP(DINP, LOGL_ERROR, "msg_type(%d) is not known. Ignoring\n", + m3ua->hdr.msg_type); + return; + } + + data = xua_msg_find_tag(m3ua, M3UA_TAG_PROTO_DATA); + if (!data) { + LOGP(DINP, LOGL_ERROR, "No PROTO_DATA in DATA message.\n"); + return; + } + + if (data->len > 2048) { + LOGP(DINP, LOGL_ERROR, "TOO much data for us to handle.\n"); + return; + } + + if (data->len < sizeof(struct m3ua_protocol_data)) { + LOGP(DINP, LOGL_ERROR, "Too little data..\n"); + return; + } + + msg = msgb_alloc(2048, "m3ua-data"); + if (!msg) { + LOGP(DINP, LOGL_ERROR, "Failed to allocate storage.\n"); + return; + } + + msg->l2h = msgb_put(msg, data->len); + memcpy(msg->l2h, data->dat, data->len); + + proto = (struct m3ua_protocol_data *) msg->l2h; + opc = ntohl(proto->opc); + dpc = ntohl(proto->dpc); + sls = proto->sls; + si = proto->si; + LOGP(DINP, LOGL_DEBUG, "Got data for OPC(%d)/DPC(%d)/SLS(%d) len(%d)\n", + opc, dpc, sls, msgb_l2len(msg) - sizeof(*proto)); + + + /* put a MTP3 header in front */ + msg->l3h = proto->data; + msgb_pull_to_l3(msg); + msg->l2h = msgb_push(msg, sizeof(*mtp_hdr)); + mtp_hdr = (struct mtp_level_3_hdr *) msg->l2h; + mtp_hdr->ser_ind = si; + mtp_hdr->addr = MTP_ADDR(sls % 16, dpc, opc); + + mtp_handle_pcap(mtp_link, NET_IN, msg->l2h, msgb_l2len(msg)); + mtp_link_set_data(mtp_link, msg); + msgb_free(msg); +} From ebdbc1140388255b27479f752d0813d986ca1c03 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 24 Mar 2015 19:21:01 +0100 Subject: [PATCH 6/8] m3ua: Use the MTP_READ_DPC/MTP_READ_OPC for using the right PC Make the code work for both ISUP and SCCP and let the address handling still be part of the linkset/mtp3 code. --- src/sctp_m3ua_client.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sctp_m3ua_client.c b/src/sctp_m3ua_client.c index dd378bb..cb9fab3 100644 --- a/src/sctp_m3ua_client.c +++ b/src/sctp_m3ua_client.c @@ -23,6 +23,7 @@ #include #include +#include #include @@ -264,17 +265,15 @@ static int m3ua_write(struct mtp_link *mtp_link, struct msgb *msg) case MTP_SI_MNT_SNM_MSG: case MTP_SI_MNT_REG_MSG: LOGP(DINP, LOGL_ERROR, - "Dropping SNM/REG/ISUP/??? message %d\n", mtp_hdr->ser_ind); + "Dropping SNM/REG message %d\n", mtp_hdr->ser_ind); goto clean; break; case MTP_SI_MNT_ISUP: case MTP_SI_MNT_SCCP: default: - /* TODO... read OPC/DPC from message.. */ memset(&proto_data, 0, sizeof(proto_data)); - proto_data.opc = htonl(mtp_link->set->sccp_opc); - proto_data.dpc = htonl(mtp_link->set->sccp_dpc == -1 ? - mtp_link->set->sccp_dpc : mtp_link->set->dpc); + proto_data.opc = htonl(MTP_READ_OPC(mtp_hdr->addr)); + proto_data.dpc = htonl(MTP_READ_DPC(mtp_hdr->addr)); proto_data.sls = MTP_LINK_SLS(mtp_hdr->addr); proto_data.si = mtp_hdr->ser_ind; proto_data.ni = mtp_link->set->ni; From 316168249f25e46d802edcfed2461845000a066d Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 24 Mar 2015 19:24:22 +0100 Subject: [PATCH 7/8] all: Use the libosmo-sccp version of mtp_level3.h --- include/Makefile.am | 2 +- include/mtp_level3.h | 180 ------------------------------------- src/isup.c | 2 +- src/links.c | 2 +- src/main.c | 2 +- src/main_stp.c | 2 +- src/mtp_layer3.c | 6 +- src/mtp_link.c | 2 +- src/sccp_state.c | 2 +- src/sctp_m3ua_client.c | 1 - tests/mtp/Makefile.am | 2 +- tests/mtp/mtp_parse_test.c | 10 +-- 12 files changed, 16 insertions(+), 197 deletions(-) delete mode 100644 include/mtp_level3.h diff --git a/include/Makefile.am b/include/Makefile.am index aff4e37..db4f76d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,4 +1,4 @@ -noinst_HEADERS = mtp_level3.h mtp_data.h ipaccess.h thread.h mtp_pcap.h \ +noinst_HEADERS = mtp_data.h ipaccess.h thread.h mtp_pcap.h \ mgcp_ss7.h bss_patch.h bssap_sccp.h bsc_data.h udp_input.h \ snmp_mtp.h cellmgr_debug.h bsc_sccp.h bsc_ussd.h sctp_m2ua.h \ isup_types.h counter.h msc_connection.h ss7_application.h \ diff --git a/include/mtp_level3.h b/include/mtp_level3.h deleted file mode 100644 index f311ad5..0000000 --- a/include/mtp_level3.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Q.701-Q.704, Q.706, Q.707 handling code */ -/* - * (C) 2010 by Holger Hans Peter Freyther - * (C) 2010 by On-Waves - * All Rights Reserved - * - * 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 . - * - */ - -#ifndef mtp_level3_h -#define mtp_level3_h - -#include -#include -#include - - -/* - * pssible service information octets.. - */ -#define MTP_NI_NATION_NET 0x02 - -#define MTP_SI_MNT_SNM_MSG 0x00 -#define MTP_SI_MNT_REG_MSG 0x01 -#define MTP_SI_MNT_SCCP 0x03 -#define MTP_SI_MNT_ISUP 0x05 - -/* - * h0 contains the group, h1 the semantic of it - */ - -#define MTP_TST_MSG_GRP 0x01 -#define MTP_PROHIBIT_MSG_GRP 0x04 -#define MTP_SROUTE_MSG_GRP 0x05 -#define MTP_TRF_RESTR_MSG_GRP 0x07 - -/* h1 values for different groups */ -#define MTP_TST_MSG_SLTM 0x01 -#define MTP_TST_MSG_SLTA 0x02 - -#define MTP_RESTR_MSG_ALLWED 0x01 - -/* For the prohibit group */ -#define MTP_PROHIBIT_MSG_SIG 0x01 -#define MTP_PROHIBIT_MSG_TFA 0x05 - -/* For the Signalling-route-set-test */ -#define MTP_SROUTE_MSG_TEST 0x01 - - -#define SCCP_SST 0x03 -#define SCCP_SSP 0x02 -#define SCCP_SSA 0x01 - -#define MTP_LINK_MASK 0x0F -#define MTP_ADDR_MASK 0x3FFF -#define MTP_APOC_MASK 0x3f - - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define MTP_LINK_SLS(addr) ((addr >>28) & MTP_LINK_MASK) -#define MTP_ADDR(link, dpc, opc) \ - (((dpc) & MTP_ADDR_MASK) << 0 | \ - ((opc) & MTP_ADDR_MASK) << 14| \ - ((link) & MTP_LINK_MASK) << 28) -#define MTP_MAKE_APOC(apoc) \ - (apoc & 0x3fff) -#define MTP_ADDR_DPC(addr) \ - (addr & MTP_ADDR_MASK) -#define MTP_ADDR_OPC(addr) \ - ((addr >> 14) & MTP_ADDR_MASK) -#elif __BYTE_ORDER == __BIG_ENDIAN -static inline uint32_t c_swap_32(uint32_t in) -{ - return (((in & 0x000000ff) << 24) | - ((in & 0x0000ff00) << 8) | - ((in & 0x00ff0000) >> 8) | - ((in & 0xff000000) >> 24)); -} -static inline uint16_t c_swap_16(uint16_t in) -{ - return (((in & 0x00ff) << 8) | - (in & 0xff00) >> 8); -} -#define MTP_LINK_SLS(addr) ((c_swap_32(addr)>>28) & MTP_LINK_MASK) -#define MTP_ADDR(link, dpc, opc) \ - c_swap_32(((dpc) & MTP_ADDR_MASK) << 0 | \ - ((opc) & MTP_ADDR_MASK) << 14| \ - ((link) & MTP_LINK_MASK) << 28) -#define MTP_MAKE_APOC(apoc) \ - c_swap_16((apoc & 0x3fff)) -#define MTP_ADDR_DPC(addr) \ - (c_swap_32(addr) & MTP_ADDR_MASK) -#define MTP_ADDR_OPC(addr) \ - ((c_swap_32(addr) >> 14) & MTP_ADDR_MASK) -#endif - - - -/* - * not the on wire address... - */ -struct mtp_addr { - uint16_t dpc; - uint16_t opc; - uint8_t link; -} __attribute__((packed)); - -/* - * the struct is defined in Q.704 and can be seen in the - * wireshark dissectors too - */ -struct mtp_level_3_hdr { -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint8_t ser_ind : 4, - spare : 2, - ni : 2; -#elif __BYTE_ORDER == __BIG_ENDIAN - uint8_t ni : 2, - spare : 2, - ser_ind : 4; -#endif - uint32_t addr; - uint8_t data[0]; -} __attribute__((packed)); - -struct mtp_level_3_cmn { -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint8_t h0 : 4, - h1 : 4; -#elif __BYTE_ORDER == __BIG_ENDIAN - uint8_t h1 : 4, - h0 : 4; -#endif -} __attribute__((packed)); - -struct mtp_level_3_mng { - struct mtp_level_3_cmn cmn; -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint8_t spare : 4, - length : 4; -#elif __BYTE_ORDER == __BIG_ENDIAN - uint8_t length : 4, - spare : 4; -#endif - uint8_t data[0]; -} __attribute__((packed)); - -struct mtp_level_3_prohib { - struct mtp_level_3_cmn cmn; - - uint16_t apoc; -} __attribute__((packed)); - -struct sccp_con_ctrl_prt_mgt { - uint8_t sst; - uint8_t assn; /* affected sub system number */ - uint16_t apoc; -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint8_t mul_ind : 2, - spare : 6; -#elif __BYTE_ORDER == __BIG_ENDIAN - uint8_t spare : 6, - mul_ind : 2; -#endif -} __attribute__((packed)); - -#endif diff --git a/src/isup.c b/src/isup.c index 2827f21..7fe9e23 100644 --- a/src/isup.c +++ b/src/isup.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/links.c b/src/links.c index 1b97e58..febfa56 100644 --- a/src/links.c +++ b/src/links.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/main.c b/src/main.c index 5f5611b..bafdc39 100644 --- a/src/main.c +++ b/src/main.c @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/main_stp.c b/src/main_stp.c index 0cd7824..8a9e10e 100644 --- a/src/main_stp.c +++ b/src/main_stp.c @@ -21,7 +21,7 @@ */ #include -#include +#include #include #include #include diff --git a/src/mtp_layer3.c b/src/mtp_layer3.c index 238a3f1..c4bbab4 100644 --- a/src/mtp_layer3.c +++ b/src/mtp_layer3.c @@ -19,7 +19,7 @@ * */ #include -#include +#include #include #include #include @@ -368,9 +368,9 @@ static int mtp_link_regular_msg(struct mtp_link *link, struct mtp_level_3_hdr *h return -1; } - if (MTP_ADDR_DPC(hdr->addr) != link->set->opc) { + if (MTP_READ_DPC(hdr->addr) != link->set->opc) { LOGP(DINP, LOGL_ERROR, "MSG for OPC %d not handled on %d/%s\n", - MTP_ADDR_DPC(hdr->addr), link->set->nr, link->set->name); + MTP_READ_DPC(hdr->addr), link->set->nr, link->set->name); return -1; } diff --git a/src/mtp_link.c b/src/mtp_link.c index 9b84e63..858bf4a 100644 --- a/src/mtp_link.c +++ b/src/mtp_link.c @@ -20,7 +20,7 @@ */ #include -#include +#include #include #include diff --git a/src/sccp_state.c b/src/sccp_state.c index a788580..49cf49a 100644 --- a/src/sccp_state.c +++ b/src/sccp_state.c @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/sctp_m3ua_client.c b/src/sctp_m3ua_client.c index cb9fab3..972738c 100644 --- a/src/sctp_m3ua_client.c +++ b/src/sctp_m3ua_client.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/tests/mtp/Makefile.am b/tests/mtp/Makefile.am index 3490641..21cc2c0 100644 --- a/tests/mtp/Makefile.am +++ b/tests/mtp/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -Wall +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include $(LIBOSMOCORE_CFLAGS) -Wall noinst_PROGRAMS = mtp_parse_test EXTRA_DIST = mtp_parse_test.ok diff --git a/tests/mtp/mtp_parse_test.c b/tests/mtp/mtp_parse_test.c index e21baed..c13d295 100644 --- a/tests/mtp/mtp_parse_test.c +++ b/tests/mtp/mtp_parse_test.c @@ -1,5 +1,5 @@ /* MTP Layer3 parsing tests */ -#include +#include #include @@ -590,14 +590,14 @@ int main(int argc, char **argv) tests[2].prohib.apoc = MTP_MAKE_APOC(86); addr = MTP_ADDR(0x00, 0x2AAA, 0x1555); - if (MTP_ADDR_OPC(addr) != 0x1555) { + if (MTP_READ_OPC(addr) != 0x1555) { fprintf(stderr, "Failed to extract OPC: %d\n", - MTP_ADDR_OPC(addr)); + MTP_READ_OPC(addr)); abort(); } - if (MTP_ADDR_DPC(addr) != 0x2AAA) { + if (MTP_READ_DPC(addr) != 0x2AAA) { fprintf(stderr, "Failed to extract DPC: %d\n", - MTP_ADDR_DPC(addr)); + MTP_READ_DPC(addr)); abort(); } From 71477e134214750b6dad8232f993d4843516c8fb Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 24 Mar 2015 21:14:18 +0100 Subject: [PATCH 8/8] m3ua: Send data on stream != 0 RFC4666: The DATA message MUST NOT be sent on stream 0 --- src/sctp_m3ua_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sctp_m3ua_client.c b/src/sctp_m3ua_client.c index 972738c..26a63f1 100644 --- a/src/sctp_m3ua_client.c +++ b/src/sctp_m3ua_client.c @@ -299,7 +299,7 @@ static int m3ua_write(struct mtp_link *mtp_link, struct msgb *msg) xua_msg_add_data(m3ua, M3UA_TAG_PROTO_DATA, msg->len, msg->data); memset(&info, 0, sizeof(info)); - info.sinfo_stream = 0; + info.sinfo_stream = 1; info.sinfo_assoc_id = 1; info.sinfo_ppid = htonl(SCTP_PPID_M3UA);