aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2016-04-28 07:54:31 +0200
committerHarald Welte <laforge@gnumonks.org>2016-04-29 12:59:27 +0200
commit12814b96367ca4ef7e94fb5fb18609d5fabd33a1 (patch)
treec289b01d84e55bdb82bda5ae65b9a81caa474176
parentb2d727a10256ed133f0db7f6760bfef73f8b9f6e (diff)
ipa_server_conn: Add server-side CCM handling
An ipa_server implementation may call ipa_server_conn_ccm for the CCM processing on the server side of the connection. This function in turn will call a conn->ccm_cb() function for messages to be handled by the server implementation, such as the ID_RESP message, which contains the Unit ID of the client that has just connected.
-rw-r--r--include/osmocom/abis/ipa.h3
-rw-r--r--src/input/ipa.c67
2 files changed, 70 insertions, 0 deletions
diff --git a/include/osmocom/abis/ipa.h b/include/osmocom/abis/ipa.h
index 6447ccd..a157889 100644
--- a/include/osmocom/abis/ipa.h
+++ b/include/osmocom/abis/ipa.h
@@ -35,6 +35,8 @@ struct ipa_server_conn {
struct osmo_fd ofd;
struct llist_head tx_queue;
int (*closed_cb)(struct ipa_server_conn *peer);
+ int (*ccm_cb)(struct ipa_server_conn *peer, struct msgb *msg,
+ struct tlv_parsed *tlvp, struct ipaccess_unit *ud);
int (*cb)(struct ipa_server_conn *peer, struct msgb *msg);
void *data;
struct msgb *pending_msg;
@@ -51,6 +53,7 @@ ipa_server_conn_create(void *ctx, struct ipa_server_link *link, int fd,
void ipa_server_conn_destroy(struct ipa_server_conn *peer);
void ipa_server_conn_send(struct ipa_server_conn *peer, struct msgb *msg);
+int ipa_server_conn_ccm(struct ipa_server_conn *conn, struct msgb *msg);
enum ipa_client_conn_state {
IPA_CLIENT_LINK_STATE_NONE = 0,
diff --git a/src/input/ipa.c b/src/input/ipa.c
index bd1671b..f90d62c 100644
--- a/src/input/ipa.c
+++ b/src/input/ipa.c
@@ -434,6 +434,73 @@ ipa_server_conn_create(void *ctx, struct ipa_server_link *link, int fd,
return conn;
}
+int ipa_server_conn_ccm(struct ipa_server_conn *conn, struct msgb *msg)
+{
+ struct tlv_parsed tlvp;
+ uint8_t msg_type = *(msg->l2h);
+ struct ipaccess_unit unit_data = {};
+ char *unitid;
+ int len, rc;
+
+ /* shared CCM handling on both server and client */
+ rc = ipa_ccm_rcvmsg_base(msg, &conn->ofd);
+ switch (rc) {
+ case -1:
+ /* error in IPA CCM processing */
+ goto err;
+ case 1:
+ /* IPA CCM message that was handled in _base */
+ return 0;
+ case 0:
+ /* IPA CCM message that we need to handle */
+ break;
+ default:
+ /* Error */
+ LOGP(DLINP, LOGL_ERROR, "Unexpected return from "
+ "ipa_ccm_rcvmsg_base: %d\n", rc);
+ goto err;
+ }
+
+ switch (msg_type) {
+ case IPAC_MSGT_ID_RESP:
+ rc = ipa_ccm_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2,
+ msgb_l2len(msg)-2);
+ if (rc < 0) {
+ LOGP(DLINP, LOGL_ERROR, "IPA CCM RESPonse with "
+ "malformed TLVs\n");
+ goto err;
+ }
+ if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT)) {
+ LOGP(DLINP, LOGL_ERROR, "IPA CCM RESP without "
+ "unit ID\n");
+ goto err;
+ }
+ len = TLVP_LEN(&tlvp, IPAC_IDTAG_UNIT);
+ if (len < 1) {
+ LOGP(DLINP, LOGL_ERROR, "IPA CCM RESP with short"
+ "unit ID\n");
+ goto err;
+ }
+ unitid = (char *) TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT);
+ unitid[len-1] = '\0';
+ ipa_parse_unitid(unitid, &unit_data);
+
+ /* FIXME */
+ rc = conn->ccm_cb(conn, msg, &tlvp, &unit_data);
+ if (rc < 0)
+ goto err;
+ break;
+ default:
+ LOGP(DLINP, LOGL_ERROR, "Unknown IPA message type\n");
+ break;
+ }
+ return 0;
+err:
+ /* in case of any error, we close the connection */
+ ipa_server_conn_destroy(conn);
+ return -1;
+}
+
void ipa_server_conn_destroy(struct ipa_server_conn *conn)
{
close(conn->ofd.fd);