diff options
author | Harald Welte <laforge@gnumonks.org> | 2016-04-28 07:54:31 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2016-04-29 12:59:27 +0200 |
commit | 12814b96367ca4ef7e94fb5fb18609d5fabd33a1 (patch) | |
tree | c289b01d84e55bdb82bda5ae65b9a81caa474176 | |
parent | b2d727a10256ed133f0db7f6760bfef73f8b9f6e (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.h | 3 | ||||
-rw-r--r-- | src/input/ipa.c | 67 |
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); |