blob: b9a21ab65b785351d37445c0fc608287bc899029 [file] [log] [blame]
Harald Weltee72cf552016-04-28 07:18:49 +02001#include <errno.h>
2
3#include <osmocom/core/msgb.h>
4#include <osmocom/core/logging.h>
5#include <osmocom/core/linuxlist.h>
6#include <osmocom/abis/ipa.h>
7#include <osmocom/abis/ipaccess.h>
8
9#include "gsup_server.h"
10
11static void osmo_gsup_server_send(struct osmo_gsup_conn *conn,
12 int proto_ext, struct msgb *msg_tx)
13{
14 ipa_prepend_header_ext(msg_tx, proto_ext);
15 ipa_msg_push_header(msg_tx, IPAC_PROTO_OSMO);
16 ipa_server_conn_send(conn->conn, msg_tx);
17}
18
19int osmo_gsup_conn_send(struct osmo_gsup_conn *conn, struct msgb *msg)
20{
21 if (!conn) {
22 msgb_free(msg);
23 return -ENOTCONN;
24 }
25
26 osmo_gsup_server_send(conn, IPAC_PROTO_EXT_GSUP, msg);
27
28 return 0;
29}
30
31static int osmo_gsup_conn_oap_handle(struct osmo_gsup_conn *conn,
32 struct msgb *msg_rx)
33{
34 int rc;
35 struct msgb *msg_tx;
36#if 0
37 rc = oap_handle(&conn->oap_state, msg_rx, &msg_tx);
38 msgb_free(msg_rx);
39 if (rc < 0)
40 return rc;
41
42 if (msg_tx)
43 osmo_gsup_conn_send(conn, IPAC_PROTO_EXT_OAP, msg_tx);
44#endif
45 return 0;
46}
47
Harald Weltee72cf552016-04-28 07:18:49 +020048/* Data from a given client has arrived over the socket */
49static int osmo_gsup_server_read_cb(struct ipa_server_conn *conn,
50 struct msgb *msg)
51{
52 struct ipaccess_head *hh = (struct ipaccess_head *) msg->data;
53 struct ipaccess_head_ext *he = (struct ipaccess_head_ext *) msgb_l2(msg);
54 struct osmo_gsup_conn *clnt = (struct osmo_gsup_conn *)conn->data;
55 int rc;
Harald Weltee72cf552016-04-28 07:18:49 +020056
57 msg->l2h = &hh->data[0];
58
Harald Welte173afdb2016-04-28 08:53:25 +020059 if (hh->proto == IPAC_PROTO_IPACCESS) {
60 rc = ipa_server_conn_ccm(conn, msg);
61 if (rc < 0) {
62 /* conn is already invalid here! */
Harald Welte173afdb2016-04-28 08:53:25 +020063 return -1;
Harald Weltee72cf552016-04-28 07:18:49 +020064 }
Harald Welte5341b5d2016-04-28 12:48:39 +020065 msgb_free(msg);
Harald Weltee72cf552016-04-28 07:18:49 +020066 return 0;
67 }
Harald Weltee72cf552016-04-28 07:18:49 +020068
Harald Weltef2d96da2016-04-28 11:13:15 +020069 if (hh->proto != IPAC_PROTO_OSMO) {
70 LOGP(DLGSUP, LOGL_NOTICE, "Unsupported IPA stream ID 0x%02x\n",
71 hh->proto);
Harald Weltee72cf552016-04-28 07:18:49 +020072 goto invalid;
Harald Weltef2d96da2016-04-28 11:13:15 +020073 }
Harald Weltee72cf552016-04-28 07:18:49 +020074
Harald Weltef2d96da2016-04-28 11:13:15 +020075 if (!he || msgb_l2len(msg) < sizeof(*he)) {
76 LOGP(DLGSUP, LOGL_NOTICE, "short IPA message\n");
Harald Weltee72cf552016-04-28 07:18:49 +020077 goto invalid;
Harald Weltef2d96da2016-04-28 11:13:15 +020078 }
Harald Weltee72cf552016-04-28 07:18:49 +020079
80 msg->l2h = &he->data[0];
81
82 if (he->proto == IPAC_PROTO_EXT_GSUP) {
83 OSMO_ASSERT(clnt->server->read_cb != NULL);
84 clnt->server->read_cb(clnt, msg);
85 /* expecting read_cb() to free msg */
86 } else if (he->proto == IPAC_PROTO_EXT_OAP) {
87 return osmo_gsup_conn_oap_handle(clnt, msg);
88 /* osmo_gsup_client_oap_handle frees msg */
Harald Weltef2d96da2016-04-28 11:13:15 +020089 } else {
90 LOGP(DLGSUP, LOGL_NOTICE, "Unsupported IPA Osmo Proto 0x%02x\n",
91 hh->proto);
Harald Weltee72cf552016-04-28 07:18:49 +020092 goto invalid;
Harald Weltef2d96da2016-04-28 11:13:15 +020093 }
Harald Weltee72cf552016-04-28 07:18:49 +020094
95 return 0;
96
97invalid:
98 LOGP(DLGSUP, LOGL_NOTICE,
Harald Weltef2d96da2016-04-28 11:13:15 +020099 "GSUP received an invalid IPA message from %s:%d: %s\n",
100 conn->addr, conn->port, osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
Harald Weltee72cf552016-04-28 07:18:49 +0200101 msgb_free(msg);
102 return -1;
103
104}
105
Harald Welte173afdb2016-04-28 08:53:25 +0200106static int osmo_gsup_server_ccm_cb(struct ipa_server_conn *conn,
107 struct msgb *msg, struct tlv_parsed *tlvp,
108 struct ipaccess_unit *unit)
109{
110 LOGP(DLGSUP, LOGL_INFO, "CCM Callback\n");
111 /* TODO: ? */
112 return 0;
113}
114
Harald Weltee72cf552016-04-28 07:18:49 +0200115static int osmo_gsup_server_closed_cb(struct ipa_server_conn *conn)
116{
117 struct osmo_gsup_conn *clnt = (struct osmo_gsup_conn *)conn->data;
118
119 LOGP(DLGSUP, LOGL_INFO, "Lost GSUP client %s:%d\n",
120 conn->addr, conn->port);
121
122 llist_del(&clnt->list);
Harald Weltea7617e92016-04-28 12:57:10 +0200123 talloc_free(clnt);
Harald Weltee72cf552016-04-28 07:18:49 +0200124
125 return 0;
126}
127
128/* a client has connected to the server socket and we have accept()ed it */
129static int osmo_gsup_server_accept_cb(struct ipa_server_link *link, int fd)
130{
131 struct osmo_gsup_conn *conn;
132 struct osmo_gsup_server *gsups =
133 (struct osmo_gsup_server *) link->data;
Harald Welte173afdb2016-04-28 08:53:25 +0200134 int rc;
Harald Weltee72cf552016-04-28 07:18:49 +0200135
Harald Weltea7617e92016-04-28 12:57:10 +0200136 conn = talloc_zero(gsups, struct osmo_gsup_conn);
Harald Weltee72cf552016-04-28 07:18:49 +0200137 OSMO_ASSERT(conn);
138
Harald Weltea7617e92016-04-28 12:57:10 +0200139 conn->conn = ipa_server_conn_create(gsups, link, fd,
Harald Weltee72cf552016-04-28 07:18:49 +0200140 osmo_gsup_server_read_cb,
141 osmo_gsup_server_closed_cb, conn);
Harald Welte173afdb2016-04-28 08:53:25 +0200142 conn->conn->ccm_cb = osmo_gsup_server_ccm_cb;
Harald Weltee72cf552016-04-28 07:18:49 +0200143 OSMO_ASSERT(conn->conn);
144
145 /* link data structure with server structure */
146 conn->server = gsups;
147 llist_add_tail(&conn->list, &gsups->clients);
148
149 LOGP(DLGSUP, LOGL_INFO, "New GSUP client %s:%d\n",
150 conn->conn->addr, conn->conn->port);
Harald Welte173afdb2016-04-28 08:53:25 +0200151
152 /* request the identity of the client */
153 rc = ipa_ccm_send_id_req(fd);
154 if (rc < 0)
155 goto failed;
Harald Weltee72cf552016-04-28 07:18:49 +0200156#if 0
157 rc = oap_init(&gsups->oap_config, &conn->oap_state);
158 if (rc != 0)
159 goto failed;
Harald Weltee72cf552016-04-28 07:18:49 +0200160#endif
161 return 0;
Harald Welte173afdb2016-04-28 08:53:25 +0200162failed:
163 ipa_server_conn_destroy(conn->conn);
164 return -1;
Harald Weltee72cf552016-04-28 07:18:49 +0200165}
166
167struct osmo_gsup_server *
168osmo_gsup_server_create(void *ctx, const char *ip_addr,
169 uint16_t tcp_port,
170 osmo_gsup_read_cb_t read_cb)
171{
172 struct osmo_gsup_server *gsups;
173 int rc;
174
175 gsups = talloc_zero(ctx, struct osmo_gsup_server);
176 OSMO_ASSERT(gsups);
177
178 INIT_LLIST_HEAD(&gsups->clients);
179
180 gsups->link = ipa_server_link_create(gsups,
181 /* no e1inp */ NULL,
182 ip_addr, tcp_port,
183 osmo_gsup_server_accept_cb,
184 gsups);
185 if (!gsups->link)
186 goto failed;
187
188 gsups->read_cb = read_cb;
189
190 rc = ipa_server_link_open(gsups->link);
191 if (rc < 0)
192 goto failed;
193
194 return gsups;
195
196failed:
197 osmo_gsup_server_destroy(gsups);
198 return NULL;
199}
200
201void osmo_gsup_server_destroy(struct osmo_gsup_server *gsups)
202{
203 if (gsups->link) {
204 ipa_server_link_close(gsups->link);
205 ipa_server_link_destroy(gsups->link);
206 gsups->link = NULL;
207 }
208 talloc_free(gsups);
209}