1 /* Socket based Layer1 <-> Layer23 communication over L1CTL primitives. */
3 /* (C) 2016 by Sebastian Stumpf <sebastian.stumpf87@googlemail.com>
4 * (C) 2017 by Harald Welte <laforge@gnumonks.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
36 #include <arpa/inet.h>
38 #include <osmocom/core/linuxlist.h>
39 #include <osmocom/core/select.h>
40 #include <osmocom/core/talloc.h>
41 #include <osmocom/core/socket.h>
43 #include <virtphy/l1ctl_sock.h>
44 #include <virtphy/logging.h>
46 #define L1CTL_SOCK_MSGB_SIZE 256
48 static void l1ctl_client_destroy(struct l1ctl_sock_client
*lsc
)
50 struct l1ctl_sock_inst
*lsi
= lsc
->l1ctl_sock
;
53 osmo_fd_close(&lsc
->ofd
);
54 llist_del(&lsc
->list
);
59 * @brief L1CTL socket file descriptor callback function.
61 * @param ofd The osmocom file descriptor.
62 * @param what Indicates if the fd has a read, write or exception request. See select.h.
64 * Will be called by osmo_select_main() if data on fd is pending.
66 static int l1ctl_sock_data_cb(struct osmo_fd
*ofd
, unsigned int what
)
68 struct l1ctl_sock_client
*lsc
= ofd
->data
;
69 struct l1ctl_hdr
*l1h
;
74 /* Check if request is really read request */
75 if (!(what
& BSC_FD_READ
))
78 msg
= msgb_alloc(L1CTL_SOCK_MSGB_SIZE
, "L1CTL sock rx");
80 /* read length of the message first and convert to host byte order */
81 rc
= read(ofd
->fd
, &len
, sizeof(len
));
85 /* convert to host byte order */
87 if (len
<= 0 || len
> L1CTL_SOCK_MSGB_SIZE
)
90 rc
= read(ofd
->fd
, msgb_data(msg
), len
);
93 l1h
= (void *) msgb_data(msg
);
94 msg
->l1h
= (void *) l1h
;
95 lsc
->l1ctl_sock
->recv_cb(lsc
, msg
);
99 LOGP(DL1C
, LOGL_ERROR
, "Failed to receive msg from l2. Connection will be closed.\n");
100 l1ctl_client_destroy(lsc
);
106 /* called for the master (listening) socket of the instance, allocates a new client */
107 static int l1ctl_sock_accept_cb(struct osmo_fd
*ofd
, unsigned int what
)
110 struct l1ctl_sock_inst
*lsi
= ofd
->data
;
111 struct l1ctl_sock_client
*lsc
;
114 fd
= accept(ofd
->fd
, NULL
, NULL
);
116 LOGP(DL1C
, LOGL_ERROR
, "Failed to accept connection to l2.\n");
120 lsc
= talloc_zero(lsi
, struct l1ctl_sock_client
);
123 LOGP(DL1C
, LOGL_ERROR
, "Failed to allocate L1CTL client\n");
127 lsc
->l1ctl_sock
= lsi
;
129 lsc
->ofd
.when
= BSC_FD_READ
;
130 lsc
->ofd
.cb
= l1ctl_sock_data_cb
;
132 if (lsi
->accept_cb
) {
133 rc
= lsi
->accept_cb(lsc
);
141 LOGP(DL1C
, LOGL_INFO
, "Accepted client (fd=%u) from server (fd=%u)\n", fd
, ofd
->fd
);
142 if (osmo_fd_register(&lsc
->ofd
) != 0) {
143 LOGP(DL1C
, LOGL_ERROR
, "Failed to register the l2 connection fd.\n");
147 llist_add_tail(&lsc
->list
, &lsi
->clients
);
151 struct l1ctl_sock_inst
*l1ctl_sock_init(
153 void (*recv_cb
)(struct l1ctl_sock_client
*lsc
, struct msgb
*msg
),
154 int (*accept_cb
)(struct l1ctl_sock_client
*lsc
),
155 void (*close_cb
)(struct l1ctl_sock_client
*lsc
),
158 struct l1ctl_sock_inst
*lsi
;
162 path
= L1CTL_SOCK_PATH
;
164 lsi
= talloc_zero(ctx
, struct l1ctl_sock_inst
);
167 lsi
->ofd
.when
= BSC_FD_READ
;
168 lsi
->ofd
.cb
= l1ctl_sock_accept_cb
;
170 rc
= osmo_sock_unix_init_ofd(&lsi
->ofd
, SOCK_STREAM
, 0, path
, OSMO_SOCK_F_BIND
);
172 LOGP(DL1C
, LOGL_ERROR
, "Error creating L1CTL listening socket\n");
177 lsi
->recv_cb
= recv_cb
;
178 lsi
->accept_cb
= accept_cb
;
179 lsi
->close_cb
= close_cb
;
180 lsi
->l1ctl_sock_path
= path
;
181 INIT_LLIST_HEAD(&lsi
->clients
);
186 void l1ctl_sock_destroy(struct l1ctl_sock_inst
*lsi
)
188 struct l1ctl_sock_client
*lsc
, *lsc2
;
190 llist_for_each_entry_safe(lsc
, lsc2
, &lsi
->clients
, list
)
191 l1ctl_client_destroy(lsc
);
193 osmo_fd_close(&lsi
->ofd
);
197 int l1ctl_sock_write_msg(struct l1ctl_sock_client
*lsc
, struct msgb
*msg
)
200 rc
= write(lsc
->ofd
.fd
, msgb_data(msg
), msgb_length(msg
));