diff options
Diffstat (limited to 'drivers/isdn/mISDN/l1oip_core.c')
| -rw-r--r-- | drivers/isdn/mISDN/l1oip_core.c | 104 |
1 files changed, 42 insertions, 62 deletions
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 6be2041248d3..6ab036e4a35f 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * l1oip.c low level driver for tunneling layer 1 over IP @@ -5,21 +6,6 @@ * NOTE: It is not compatible with TDMoIP nor "ISDN over IP". * * Author Andreas Eversberg (jolly@eversberg.eu) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * */ /* module parameters: @@ -214,7 +200,7 @@ The complete socket opening and closing is done by a thread. When the thread opened a socket, the hc->socket descriptor is set. Whenever a - packet shall be sent to the socket, the hc->socket must be checked wheter not + packet shall be sent to the socket, the hc->socket must be checked whether not NULL. To prevent change in socket descriptor, the hc->socket_lock must be used. To change the socket, a recall of l1oip_socket_open() will safely kill the socket process and create a new one. @@ -243,8 +229,8 @@ static const char *l1oip_revision = "2.00"; static int l1oip_cnt; -static spinlock_t l1oip_lock; -static struct list_head l1oip_ilist; +static DEFINE_SPINLOCK(l1oip_lock); +static LIST_HEAD(l1oip_ilist); #define MAX_CARDS 16 static u_int type[MAX_CARDS]; @@ -259,6 +245,7 @@ static int debug; static int ulaw; MODULE_AUTHOR("Andreas Eversberg"); +MODULE_DESCRIPTION("mISDN driver for tunneling layer 1 over IP"); MODULE_LICENSE("GPL"); module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR); module_param_array(codec, uint, NULL, S_IRUGO | S_IWUSR); @@ -279,7 +266,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask, u16 timebase, u8 *buf, int len) { u8 *p; - u8 frame[len + 32]; + u8 frame[MAX_DFRAME_LEN_L1 + 32]; struct socket *socket = NULL; if (debug & DEBUG_L1OIP_MSG) @@ -289,7 +276,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask, p = frame; /* restart timer */ - if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ)) + if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ) && !hc->shutdown) mod_timer(&hc->keep_tl, jiffies + L1OIP_KEEPALIVE * HZ); else hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE * HZ; @@ -440,14 +427,8 @@ l1oip_socket_recv(struct l1oip *hc, u8 remotecodec, u8 channel, u16 timebase, #ifdef REORDER_DEBUG if (hc->chan[channel].disorder_flag) { - struct sk_buff *skb; - int cnt; - skb = hc->chan[channel].disorder_skb; - hc->chan[channel].disorder_skb = nskb; - nskb = skb; - cnt = hc->chan[channel].disorder_cnt; - hc->chan[channel].disorder_cnt = rx_counter; - rx_counter = cnt; + swap(hc->chan[channel].disorder_skb, nskb); + swap(hc->chan[channel].disorder_cnt, rx_counter); } hc->chan[channel].disorder_flag ^= 1; if (nskb) @@ -621,7 +602,9 @@ multiframe: goto multiframe; /* restart timer */ - if (time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) || !hc->timeout_on) { + if ((time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) || + !hc->timeout_on) && + !hc->shutdown) { hc->timeout_on = 1; mod_timer(&hc->timeout_tl, jiffies + L1OIP_TIMEOUT * HZ); } else /* only adjust timer */ @@ -651,8 +634,10 @@ l1oip_socket_thread(void *data) { struct l1oip *hc = (struct l1oip *)data; int ret = 0; - struct msghdr msg; struct sockaddr_in sin_rx; + struct kvec iov; + struct msghdr msg = {.msg_name = &sin_rx, + .msg_namelen = sizeof(sin_rx)}; unsigned char *recvbuf; size_t recvbuf_size = 1500; int recvlen; @@ -667,6 +652,9 @@ l1oip_socket_thread(void *data) goto fail; } + iov.iov_base = recvbuf; + iov.iov_len = recvbuf_size; + /* make daemon */ allow_signal(SIGTERM); @@ -688,7 +676,7 @@ l1oip_socket_thread(void *data) hc->sin_remote.sin_port = htons((unsigned short)hc->remoteport); /* bind to incoming port */ - if (socket->ops->bind(socket, (struct sockaddr *)&hc->sin_local, + if (socket->ops->bind(socket, (struct sockaddr_unsized *)&hc->sin_local, sizeof(hc->sin_local))) { printk(KERN_ERR "%s: Failed to bind socket to port %d.\n", __func__, hc->localport); @@ -703,12 +691,6 @@ l1oip_socket_thread(void *data) goto fail; } - /* build receive message */ - msg.msg_name = &sin_rx; - msg.msg_namelen = sizeof(sin_rx); - msg.msg_control = NULL; - msg.msg_controllen = 0; - /* build send message */ hc->sendmsg.msg_name = &hc->sin_remote; hc->sendmsg.msg_namelen = sizeof(hc->sin_remote); @@ -725,12 +707,8 @@ l1oip_socket_thread(void *data) printk(KERN_DEBUG "%s: socket created and open\n", __func__); while (!signal_pending(current)) { - struct kvec iov = { - .iov_base = recvbuf, - .iov_len = recvbuf_size, - }; - recvlen = kernel_recvmsg(socket, &msg, &iov, 1, - recvbuf_size, 0); + iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, recvbuf_size); + recvlen = sock_recvmsg(socket, &msg, 0); if (recvlen > 0) { l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen); } else { @@ -842,17 +820,18 @@ l1oip_send_bh(struct work_struct *work) * timer stuff */ static void -l1oip_keepalive(void *data) +l1oip_keepalive(struct timer_list *t) { - struct l1oip *hc = (struct l1oip *)data; + struct l1oip *hc = timer_container_of(hc, t, keep_tl); schedule_work(&hc->workq); } static void -l1oip_timeout(void *data) +l1oip_timeout(struct timer_list *t) { - struct l1oip *hc = (struct l1oip *)data; + struct l1oip *hc = timer_container_of(hc, t, + timeout_tl); struct dchannel *dch = hc->chan[hc->d_idx].dch; if (debug & DEBUG_L1OIP_MSG) @@ -911,7 +890,11 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) p = skb->data; l = skb->len; while (l) { - ll = (l < L1OIP_MAX_PERFRAME) ? l : L1OIP_MAX_PERFRAME; + /* + * This is technically bounded by L1OIP_MAX_PERFRAME but + * MAX_DFRAME_LEN_L1 < L1OIP_MAX_PERFRAME + */ + ll = (l < MAX_DFRAME_LEN_L1) ? l : MAX_DFRAME_LEN_L1; l1oip_socket_send(hc, 0, dch->slot, 0, hc->chan[dch->slot].tx_counter++, p, ll); p += ll; @@ -1149,7 +1132,11 @@ handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb) p = skb->data; l = skb->len; while (l) { - ll = (l < L1OIP_MAX_PERFRAME) ? l : L1OIP_MAX_PERFRAME; + /* + * This is technically bounded by L1OIP_MAX_PERFRAME but + * MAX_DFRAME_LEN_L1 < L1OIP_MAX_PERFRAME + */ + ll = (l < MAX_DFRAME_LEN_L1) ? l : MAX_DFRAME_LEN_L1; l1oip_socket_send(hc, hc->codec, bch->slot, 0, hc->chan[bch->slot].tx_counter, p, ll); hc->chan[bch->slot].tx_counter += ll; @@ -1248,11 +1235,10 @@ release_card(struct l1oip *hc) { int ch; - if (timer_pending(&hc->keep_tl)) - del_timer(&hc->keep_tl); + hc->shutdown = true; - if (timer_pending(&hc->timeout_tl)) - del_timer(&hc->timeout_tl); + timer_shutdown_sync(&hc->keep_tl); + timer_shutdown_sync(&hc->timeout_tl); cancel_work_sync(&hc->workq); @@ -1270,8 +1256,7 @@ release_card(struct l1oip *hc) mISDN_freebchannel(hc->chan[ch].bch); kfree(hc->chan[ch].bch); #ifdef REORDER_DEBUG - if (hc->chan[ch].disorder_skb) - dev_kfree_skb(hc->chan[ch].disorder_skb); + dev_kfree_skb(hc->chan[ch].disorder_skb); #endif } } @@ -1437,13 +1422,11 @@ init_card(struct l1oip *hc, int pri, int bundle) if (ret) return ret; - hc->keep_tl.function = (void *)l1oip_keepalive; - hc->keep_tl.data = (ulong)hc; - init_timer(&hc->keep_tl); + timer_setup(&hc->keep_tl, l1oip_keepalive, 0); hc->keep_tl.expires = jiffies + 2 * HZ; /* two seconds first time */ add_timer(&hc->keep_tl); - setup_timer(&hc->timeout_tl, (void *)l1oip_timeout, (ulong)hc); + timer_setup(&hc->timeout_tl, l1oip_timeout, 0); hc->timeout_on = 0; /* state that we have timer off */ return 0; @@ -1459,9 +1442,6 @@ l1oip_init(void) printk(KERN_INFO "mISDN: Layer-1-over-IP driver Rev. %s\n", l1oip_revision); - INIT_LIST_HEAD(&l1oip_ilist); - spin_lock_init(&l1oip_lock); - if (l1oip_4bit_alloc(ulaw)) return -ENOMEM; |
