blob: f5515e384caae50b49f791f5e116090d37250af1 [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);
123
124 return 0;
125}
126
127/* a client has connected to the server socket and we have accept()ed it */
128static int osmo_gsup_server_accept_cb(struct ipa_server_link *link, int fd)
129{
130 struct osmo_gsup_conn *conn;
131 struct osmo_gsup_server *gsups =
132 (struct osmo_gsup_server *) link->data;
Harald Welte173afdb2016-04-28 08:53:25 +0200133 int rc;
Harald Weltee72cf552016-04-28 07:18:49 +0200134
135 conn = talloc_zero(link->data, struct osmo_gsup_conn);
136 OSMO_ASSERT(conn);
137
138 conn->conn = ipa_server_conn_create(conn, link, fd,
139 osmo_gsup_server_read_cb,
140 osmo_gsup_server_closed_cb, conn);
Harald Welte173afdb2016-04-28 08:53:25 +0200141 conn->conn->ccm_cb = osmo_gsup_server_ccm_cb;
Harald Weltee72cf552016-04-28 07:18:49 +0200142 OSMO_ASSERT(conn->conn);
143
144 /* link data structure with server structure */
145 conn->server = gsups;
146 llist_add_tail(&conn->list, &gsups->clients);
147
148 LOGP(DLGSUP, LOGL_INFO, "New GSUP client %s:%d\n",
149 conn->conn->addr, conn->conn->port);
Harald Welte173afdb2016-04-28 08:53:25 +0200150
151 /* request the identity of the client */
152 rc = ipa_ccm_send_id_req(fd);
153 if (rc < 0)
154 goto failed;
Harald Weltee72cf552016-04-28 07:18:49 +0200155#if 0
156 rc = oap_init(&gsups->oap_config, &conn->oap_state);
157 if (rc != 0)
158 goto failed;
Harald Weltee72cf552016-04-28 07:18:49 +0200159#endif
160 return 0;
Harald Welte173afdb2016-04-28 08:53:25 +0200161failed:
162 ipa_server_conn_destroy(conn->conn);
163 return -1;
Harald Weltee72cf552016-04-28 07:18:49 +0200164}
165
166struct osmo_gsup_server *
167osmo_gsup_server_create(void *ctx, const char *ip_addr,
168 uint16_t tcp_port,
169 osmo_gsup_read_cb_t read_cb)
170{
171 struct osmo_gsup_server *gsups;
172 int rc;
173
174 gsups = talloc_zero(ctx, struct osmo_gsup_server);
175 OSMO_ASSERT(gsups);
176
177 INIT_LLIST_HEAD(&gsups->clients);
178
179 gsups->link = ipa_server_link_create(gsups,
180 /* no e1inp */ NULL,
181 ip_addr, tcp_port,
182 osmo_gsup_server_accept_cb,
183 gsups);
184 if (!gsups->link)
185 goto failed;
186
187 gsups->read_cb = read_cb;
188
189 rc = ipa_server_link_open(gsups->link);
190 if (rc < 0)
191 goto failed;
192
193 return gsups;
194
195failed:
196 osmo_gsup_server_destroy(gsups);
197 return NULL;
198}
199
200void osmo_gsup_server_destroy(struct osmo_gsup_server *gsups)
201{
202 if (gsups->link) {
203 ipa_server_link_close(gsups->link);
204 ipa_server_link_destroy(gsups->link);
205 gsups->link = NULL;
206 }
207 talloc_free(gsups);
208}