.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * IUCV protocol stack for Linux on zSeries |
---|
3 | 4 | * |
---|
.. | .. |
---|
15 | 16 | #include <linux/module.h> |
---|
16 | 17 | #include <linux/netdevice.h> |
---|
17 | 18 | #include <linux/types.h> |
---|
| 19 | +#include <linux/limits.h> |
---|
18 | 20 | #include <linux/list.h> |
---|
19 | 21 | #include <linux/errno.h> |
---|
20 | 22 | #include <linux/kernel.h> |
---|
.. | .. |
---|
35 | 37 | |
---|
36 | 38 | static char iucv_userid[80]; |
---|
37 | 39 | |
---|
38 | | -static const struct proto_ops iucv_sock_ops; |
---|
39 | | - |
---|
40 | 40 | static struct proto iucv_proto = { |
---|
41 | 41 | .name = "AF_IUCV", |
---|
42 | 42 | .owner = THIS_MODULE, |
---|
.. | .. |
---|
49 | 49 | static const u8 iprm_shutdown[8] = |
---|
50 | 50 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; |
---|
51 | 51 | |
---|
52 | | -#define TRGCLS_SIZE (sizeof(((struct iucv_message *)0)->class)) |
---|
| 52 | +#define TRGCLS_SIZE sizeof_field(struct iucv_message, class) |
---|
53 | 53 | |
---|
54 | 54 | #define __iucv_sock_wait(sk, condition, timeo, ret) \ |
---|
55 | 55 | do { \ |
---|
.. | .. |
---|
84 | 84 | __ret; \ |
---|
85 | 85 | }) |
---|
86 | 86 | |
---|
| 87 | +static struct sock *iucv_accept_dequeue(struct sock *parent, |
---|
| 88 | + struct socket *newsock); |
---|
87 | 89 | static void iucv_sock_kill(struct sock *sk); |
---|
88 | 90 | static void iucv_sock_close(struct sock *sk); |
---|
89 | | -static void iucv_sever_path(struct sock *, int); |
---|
90 | 91 | |
---|
91 | | -static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, |
---|
92 | | - struct packet_type *pt, struct net_device *orig_dev); |
---|
93 | | -static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock, |
---|
94 | | - struct sk_buff *skb, u8 flags); |
---|
95 | 92 | static void afiucv_hs_callback_txnotify(struct sk_buff *, enum iucv_tx_notify); |
---|
96 | 93 | |
---|
97 | 94 | /* Call Back functions */ |
---|
.. | .. |
---|
125 | 122 | { |
---|
126 | 123 | memcpy(&dst[8], src, 8); |
---|
127 | 124 | } |
---|
128 | | - |
---|
129 | | -static int afiucv_pm_prepare(struct device *dev) |
---|
130 | | -{ |
---|
131 | | -#ifdef CONFIG_PM_DEBUG |
---|
132 | | - printk(KERN_WARNING "afiucv_pm_prepare\n"); |
---|
133 | | -#endif |
---|
134 | | - return 0; |
---|
135 | | -} |
---|
136 | | - |
---|
137 | | -static void afiucv_pm_complete(struct device *dev) |
---|
138 | | -{ |
---|
139 | | -#ifdef CONFIG_PM_DEBUG |
---|
140 | | - printk(KERN_WARNING "afiucv_pm_complete\n"); |
---|
141 | | -#endif |
---|
142 | | -} |
---|
143 | | - |
---|
144 | | -/** |
---|
145 | | - * afiucv_pm_freeze() - Freeze PM callback |
---|
146 | | - * @dev: AFIUCV dummy device |
---|
147 | | - * |
---|
148 | | - * Sever all established IUCV communication pathes |
---|
149 | | - */ |
---|
150 | | -static int afiucv_pm_freeze(struct device *dev) |
---|
151 | | -{ |
---|
152 | | - struct iucv_sock *iucv; |
---|
153 | | - struct sock *sk; |
---|
154 | | - |
---|
155 | | -#ifdef CONFIG_PM_DEBUG |
---|
156 | | - printk(KERN_WARNING "afiucv_pm_freeze\n"); |
---|
157 | | -#endif |
---|
158 | | - read_lock(&iucv_sk_list.lock); |
---|
159 | | - sk_for_each(sk, &iucv_sk_list.head) { |
---|
160 | | - iucv = iucv_sk(sk); |
---|
161 | | - switch (sk->sk_state) { |
---|
162 | | - case IUCV_DISCONN: |
---|
163 | | - case IUCV_CLOSING: |
---|
164 | | - case IUCV_CONNECTED: |
---|
165 | | - iucv_sever_path(sk, 0); |
---|
166 | | - break; |
---|
167 | | - case IUCV_OPEN: |
---|
168 | | - case IUCV_BOUND: |
---|
169 | | - case IUCV_LISTEN: |
---|
170 | | - case IUCV_CLOSED: |
---|
171 | | - default: |
---|
172 | | - break; |
---|
173 | | - } |
---|
174 | | - skb_queue_purge(&iucv->send_skb_q); |
---|
175 | | - skb_queue_purge(&iucv->backlog_skb_q); |
---|
176 | | - } |
---|
177 | | - read_unlock(&iucv_sk_list.lock); |
---|
178 | | - return 0; |
---|
179 | | -} |
---|
180 | | - |
---|
181 | | -/** |
---|
182 | | - * afiucv_pm_restore_thaw() - Thaw and restore PM callback |
---|
183 | | - * @dev: AFIUCV dummy device |
---|
184 | | - * |
---|
185 | | - * socket clean up after freeze |
---|
186 | | - */ |
---|
187 | | -static int afiucv_pm_restore_thaw(struct device *dev) |
---|
188 | | -{ |
---|
189 | | - struct sock *sk; |
---|
190 | | - |
---|
191 | | -#ifdef CONFIG_PM_DEBUG |
---|
192 | | - printk(KERN_WARNING "afiucv_pm_restore_thaw\n"); |
---|
193 | | -#endif |
---|
194 | | - read_lock(&iucv_sk_list.lock); |
---|
195 | | - sk_for_each(sk, &iucv_sk_list.head) { |
---|
196 | | - switch (sk->sk_state) { |
---|
197 | | - case IUCV_CONNECTED: |
---|
198 | | - sk->sk_err = EPIPE; |
---|
199 | | - sk->sk_state = IUCV_DISCONN; |
---|
200 | | - sk->sk_state_change(sk); |
---|
201 | | - break; |
---|
202 | | - case IUCV_DISCONN: |
---|
203 | | - case IUCV_CLOSING: |
---|
204 | | - case IUCV_LISTEN: |
---|
205 | | - case IUCV_BOUND: |
---|
206 | | - case IUCV_OPEN: |
---|
207 | | - default: |
---|
208 | | - break; |
---|
209 | | - } |
---|
210 | | - } |
---|
211 | | - read_unlock(&iucv_sk_list.lock); |
---|
212 | | - return 0; |
---|
213 | | -} |
---|
214 | | - |
---|
215 | | -static const struct dev_pm_ops afiucv_pm_ops = { |
---|
216 | | - .prepare = afiucv_pm_prepare, |
---|
217 | | - .complete = afiucv_pm_complete, |
---|
218 | | - .freeze = afiucv_pm_freeze, |
---|
219 | | - .thaw = afiucv_pm_restore_thaw, |
---|
220 | | - .restore = afiucv_pm_restore_thaw, |
---|
221 | | -}; |
---|
222 | | - |
---|
223 | | -static struct device_driver af_iucv_driver = { |
---|
224 | | - .owner = THIS_MODULE, |
---|
225 | | - .name = "afiucv", |
---|
226 | | - .bus = NULL, |
---|
227 | | - .pm = &afiucv_pm_ops, |
---|
228 | | -}; |
---|
229 | | - |
---|
230 | | -/* dummy device used as trigger for PM functions */ |
---|
231 | | -static struct device *af_iucv_dev; |
---|
232 | 125 | |
---|
233 | 126 | /** |
---|
234 | 127 | * iucv_msg_length() - Returns the length of an iucv message. |
---|
.. | .. |
---|
321 | 214 | struct sk_buff *nskb; |
---|
322 | 215 | int err, confirm_recv = 0; |
---|
323 | 216 | |
---|
324 | | - memset(skb->head, 0, ETH_HLEN); |
---|
325 | | - phs_hdr = skb_push(skb, sizeof(struct af_iucv_trans_hdr)); |
---|
326 | | - skb_reset_mac_header(skb); |
---|
| 217 | + phs_hdr = skb_push(skb, sizeof(*phs_hdr)); |
---|
| 218 | + memset(phs_hdr, 0, sizeof(*phs_hdr)); |
---|
327 | 219 | skb_reset_network_header(skb); |
---|
328 | | - skb_push(skb, ETH_HLEN); |
---|
329 | | - skb_reset_mac_header(skb); |
---|
330 | | - memset(phs_hdr, 0, sizeof(struct af_iucv_trans_hdr)); |
---|
331 | 220 | |
---|
332 | 221 | phs_hdr->magic = ETH_P_AF_IUCV; |
---|
333 | 222 | phs_hdr->version = 1; |
---|
.. | .. |
---|
438 | 327 | parent->sk_state = IUCV_CLOSED; |
---|
439 | 328 | } |
---|
440 | 329 | |
---|
| 330 | +static void iucv_sock_link(struct iucv_sock_list *l, struct sock *sk) |
---|
| 331 | +{ |
---|
| 332 | + write_lock_bh(&l->lock); |
---|
| 333 | + sk_add_node(sk, &l->head); |
---|
| 334 | + write_unlock_bh(&l->lock); |
---|
| 335 | +} |
---|
| 336 | + |
---|
| 337 | +static void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *sk) |
---|
| 338 | +{ |
---|
| 339 | + write_lock_bh(&l->lock); |
---|
| 340 | + sk_del_node_init(sk); |
---|
| 341 | + write_unlock_bh(&l->lock); |
---|
| 342 | +} |
---|
| 343 | + |
---|
441 | 344 | /* Kill socket (only if zapped and orphaned) */ |
---|
442 | 345 | static void iucv_sock_kill(struct sock *sk) |
---|
443 | 346 | { |
---|
.. | .. |
---|
515 | 418 | sk->sk_state = IUCV_DISCONN; |
---|
516 | 419 | sk->sk_state_change(sk); |
---|
517 | 420 | } |
---|
518 | | - case IUCV_DISCONN: /* fall through */ |
---|
| 421 | + fallthrough; |
---|
| 422 | + |
---|
| 423 | + case IUCV_DISCONN: |
---|
519 | 424 | sk->sk_state = IUCV_CLOSING; |
---|
520 | 425 | sk->sk_state_change(sk); |
---|
521 | 426 | |
---|
.. | .. |
---|
528 | 433 | iucv_sock_in_state(sk, IUCV_CLOSED, 0), |
---|
529 | 434 | timeo); |
---|
530 | 435 | } |
---|
| 436 | + fallthrough; |
---|
531 | 437 | |
---|
532 | | - case IUCV_CLOSING: /* fall through */ |
---|
| 438 | + case IUCV_CLOSING: |
---|
533 | 439 | sk->sk_state = IUCV_CLOSED; |
---|
534 | 440 | sk->sk_state_change(sk); |
---|
535 | 441 | |
---|
.. | .. |
---|
538 | 444 | |
---|
539 | 445 | skb_queue_purge(&iucv->send_skb_q); |
---|
540 | 446 | skb_queue_purge(&iucv->backlog_skb_q); |
---|
| 447 | + fallthrough; |
---|
541 | 448 | |
---|
542 | | - default: /* fall through */ |
---|
| 449 | + default: |
---|
543 | 450 | iucv_sever_path(sk, 1); |
---|
544 | 451 | } |
---|
545 | 452 | |
---|
.. | .. |
---|
596 | 503 | |
---|
597 | 504 | sk->sk_destruct = iucv_sock_destruct; |
---|
598 | 505 | sk->sk_sndtimeo = IUCV_CONN_TIMEOUT; |
---|
599 | | - sk->sk_allocation = GFP_DMA; |
---|
600 | 506 | |
---|
601 | 507 | sock_reset_flag(sk, SOCK_ZAPPED); |
---|
602 | 508 | |
---|
.. | .. |
---|
607 | 513 | return sk; |
---|
608 | 514 | } |
---|
609 | 515 | |
---|
610 | | -/* Create an IUCV socket */ |
---|
611 | | -static int iucv_sock_create(struct net *net, struct socket *sock, int protocol, |
---|
612 | | - int kern) |
---|
613 | | -{ |
---|
614 | | - struct sock *sk; |
---|
615 | | - |
---|
616 | | - if (protocol && protocol != PF_IUCV) |
---|
617 | | - return -EPROTONOSUPPORT; |
---|
618 | | - |
---|
619 | | - sock->state = SS_UNCONNECTED; |
---|
620 | | - |
---|
621 | | - switch (sock->type) { |
---|
622 | | - case SOCK_STREAM: |
---|
623 | | - sock->ops = &iucv_sock_ops; |
---|
624 | | - break; |
---|
625 | | - case SOCK_SEQPACKET: |
---|
626 | | - /* currently, proto ops can handle both sk types */ |
---|
627 | | - sock->ops = &iucv_sock_ops; |
---|
628 | | - break; |
---|
629 | | - default: |
---|
630 | | - return -ESOCKTNOSUPPORT; |
---|
631 | | - } |
---|
632 | | - |
---|
633 | | - sk = iucv_sock_alloc(sock, protocol, GFP_KERNEL, kern); |
---|
634 | | - if (!sk) |
---|
635 | | - return -ENOMEM; |
---|
636 | | - |
---|
637 | | - iucv_sock_init(sk, NULL); |
---|
638 | | - |
---|
639 | | - return 0; |
---|
640 | | -} |
---|
641 | | - |
---|
642 | | -void iucv_sock_link(struct iucv_sock_list *l, struct sock *sk) |
---|
643 | | -{ |
---|
644 | | - write_lock_bh(&l->lock); |
---|
645 | | - sk_add_node(sk, &l->head); |
---|
646 | | - write_unlock_bh(&l->lock); |
---|
647 | | -} |
---|
648 | | - |
---|
649 | | -void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *sk) |
---|
650 | | -{ |
---|
651 | | - write_lock_bh(&l->lock); |
---|
652 | | - sk_del_node_init(sk); |
---|
653 | | - write_unlock_bh(&l->lock); |
---|
654 | | -} |
---|
655 | | - |
---|
656 | | -void iucv_accept_enqueue(struct sock *parent, struct sock *sk) |
---|
| 516 | +static void iucv_accept_enqueue(struct sock *parent, struct sock *sk) |
---|
657 | 517 | { |
---|
658 | 518 | unsigned long flags; |
---|
659 | 519 | struct iucv_sock *par = iucv_sk(parent); |
---|
.. | .. |
---|
666 | 526 | sk_acceptq_added(parent); |
---|
667 | 527 | } |
---|
668 | 528 | |
---|
669 | | -void iucv_accept_unlink(struct sock *sk) |
---|
| 529 | +static void iucv_accept_unlink(struct sock *sk) |
---|
670 | 530 | { |
---|
671 | 531 | unsigned long flags; |
---|
672 | 532 | struct iucv_sock *par = iucv_sk(iucv_sk(sk)->parent); |
---|
.. | .. |
---|
679 | 539 | sock_put(sk); |
---|
680 | 540 | } |
---|
681 | 541 | |
---|
682 | | -struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock) |
---|
| 542 | +static struct sock *iucv_accept_dequeue(struct sock *parent, |
---|
| 543 | + struct socket *newsock) |
---|
683 | 544 | { |
---|
684 | 545 | struct iucv_sock *isk, *n; |
---|
685 | 546 | struct sock *sk; |
---|
.. | .. |
---|
727 | 588 | int addr_len) |
---|
728 | 589 | { |
---|
729 | 590 | struct sockaddr_iucv *sa = (struct sockaddr_iucv *) addr; |
---|
| 591 | + char uid[sizeof(sa->siucv_user_id)]; |
---|
730 | 592 | struct sock *sk = sock->sk; |
---|
731 | 593 | struct iucv_sock *iucv; |
---|
732 | 594 | int err = 0; |
---|
733 | 595 | struct net_device *dev; |
---|
734 | | - char uid[9]; |
---|
735 | 596 | |
---|
736 | 597 | /* Verify the input sockaddr */ |
---|
737 | 598 | if (addr_len < sizeof(struct sockaddr_iucv) || |
---|
.. | .. |
---|
790 | 651 | memcpy(iucv->src_user_id, iucv_userid, 8); |
---|
791 | 652 | sk->sk_state = IUCV_BOUND; |
---|
792 | 653 | iucv->transport = AF_IUCV_TRANS_IUCV; |
---|
| 654 | + sk->sk_allocation |= GFP_DMA; |
---|
793 | 655 | if (!iucv->msglimit) |
---|
794 | 656 | iucv->msglimit = IUCV_QUEUELEN_DEFAULT; |
---|
795 | 657 | goto done_unlock; |
---|
.. | .. |
---|
814 | 676 | return -EPROTO; |
---|
815 | 677 | |
---|
816 | 678 | memcpy(iucv->src_user_id, iucv_userid, 8); |
---|
| 679 | + iucv->transport = AF_IUCV_TRANS_IUCV; |
---|
| 680 | + sk->sk_allocation |= GFP_DMA; |
---|
817 | 681 | |
---|
818 | 682 | write_lock_bh(&iucv_sk_list.lock); |
---|
819 | 683 | __iucv_auto_name(iucv); |
---|
.. | .. |
---|
1097 | 961 | |
---|
1098 | 962 | /* initialize defaults */ |
---|
1099 | 963 | cmsg_done = 0; /* check for duplicate headers */ |
---|
1100 | | - txmsg.class = 0; |
---|
1101 | 964 | |
---|
1102 | 965 | /* iterate over control messages */ |
---|
1103 | 966 | for_each_cmsghdr(cmsg, msg) { |
---|
.. | .. |
---|
1508 | 1371 | return 0; |
---|
1509 | 1372 | } |
---|
1510 | 1373 | |
---|
1511 | | -__poll_t iucv_sock_poll(struct file *file, struct socket *sock, |
---|
1512 | | - poll_table *wait) |
---|
| 1374 | +static __poll_t iucv_sock_poll(struct file *file, struct socket *sock, |
---|
| 1375 | + poll_table *wait) |
---|
1513 | 1376 | { |
---|
1514 | 1377 | struct sock *sk = sock->sk; |
---|
1515 | 1378 | __poll_t mask = 0; |
---|
.. | .. |
---|
1632 | 1495 | |
---|
1633 | 1496 | /* getsockopt and setsockopt */ |
---|
1634 | 1497 | static int iucv_sock_setsockopt(struct socket *sock, int level, int optname, |
---|
1635 | | - char __user *optval, unsigned int optlen) |
---|
| 1498 | + sockptr_t optval, unsigned int optlen) |
---|
1636 | 1499 | { |
---|
1637 | 1500 | struct sock *sk = sock->sk; |
---|
1638 | 1501 | struct iucv_sock *iucv = iucv_sk(sk); |
---|
.. | .. |
---|
1645 | 1508 | if (optlen < sizeof(int)) |
---|
1646 | 1509 | return -EINVAL; |
---|
1647 | 1510 | |
---|
1648 | | - if (get_user(val, (int __user *) optval)) |
---|
| 1511 | + if (copy_from_sockptr(&val, optval, sizeof(int))) |
---|
1649 | 1512 | return -EFAULT; |
---|
1650 | 1513 | |
---|
1651 | 1514 | rc = 0; |
---|
.. | .. |
---|
1662 | 1525 | switch (sk->sk_state) { |
---|
1663 | 1526 | case IUCV_OPEN: |
---|
1664 | 1527 | case IUCV_BOUND: |
---|
1665 | | - if (val < 1 || val > (u16)(~0)) |
---|
| 1528 | + if (val < 1 || val > U16_MAX) |
---|
1666 | 1529 | rc = -EINVAL; |
---|
1667 | 1530 | else |
---|
1668 | 1531 | iucv->msglimit = val; |
---|
.. | .. |
---|
1791 | 1654 | |
---|
1792 | 1655 | niucv = iucv_sk(nsk); |
---|
1793 | 1656 | iucv_sock_init(nsk, sk); |
---|
| 1657 | + niucv->transport = AF_IUCV_TRANS_IUCV; |
---|
| 1658 | + nsk->sk_allocation |= GFP_DMA; |
---|
1794 | 1659 | |
---|
1795 | 1660 | /* Set the new iucv_sock */ |
---|
1796 | 1661 | memcpy(niucv->dst_name, ipuser + 8, 8); |
---|
.. | .. |
---|
1884 | 1749 | struct sock *sk = path->private; |
---|
1885 | 1750 | struct sk_buff *this = NULL; |
---|
1886 | 1751 | struct sk_buff_head *list = &iucv_sk(sk)->send_skb_q; |
---|
1887 | | - struct sk_buff *list_skb = list->next; |
---|
| 1752 | + struct sk_buff *list_skb; |
---|
1888 | 1753 | unsigned long flags; |
---|
1889 | 1754 | |
---|
1890 | 1755 | bh_lock_sock(sk); |
---|
1891 | | - if (!skb_queue_empty(list)) { |
---|
1892 | | - spin_lock_irqsave(&list->lock, flags); |
---|
1893 | 1756 | |
---|
1894 | | - while (list_skb != (struct sk_buff *)list) { |
---|
1895 | | - if (msg->tag == IUCV_SKB_CB(list_skb)->tag) { |
---|
1896 | | - this = list_skb; |
---|
1897 | | - break; |
---|
1898 | | - } |
---|
1899 | | - list_skb = list_skb->next; |
---|
| 1757 | + spin_lock_irqsave(&list->lock, flags); |
---|
| 1758 | + skb_queue_walk(list, list_skb) { |
---|
| 1759 | + if (msg->tag == IUCV_SKB_CB(list_skb)->tag) { |
---|
| 1760 | + this = list_skb; |
---|
| 1761 | + break; |
---|
1900 | 1762 | } |
---|
1901 | | - if (this) |
---|
1902 | | - __skb_unlink(this, list); |
---|
| 1763 | + } |
---|
| 1764 | + if (this) |
---|
| 1765 | + __skb_unlink(this, list); |
---|
| 1766 | + spin_unlock_irqrestore(&list->lock, flags); |
---|
1903 | 1767 | |
---|
1904 | | - spin_unlock_irqrestore(&list->lock, flags); |
---|
1905 | | - |
---|
1906 | | - if (this) { |
---|
1907 | | - kfree_skb(this); |
---|
1908 | | - /* wake up any process waiting for sending */ |
---|
1909 | | - iucv_sock_wake_msglim(sk); |
---|
1910 | | - } |
---|
| 1768 | + if (this) { |
---|
| 1769 | + kfree_skb(this); |
---|
| 1770 | + /* wake up any process waiting for sending */ |
---|
| 1771 | + iucv_sock_wake_msglim(sk); |
---|
1911 | 1772 | } |
---|
1912 | 1773 | |
---|
1913 | 1774 | if (sk->sk_state == IUCV_CLOSING) { |
---|
.. | .. |
---|
1953 | 1814 | /***************** HiperSockets transport callbacks ********************/ |
---|
1954 | 1815 | static void afiucv_swap_src_dest(struct sk_buff *skb) |
---|
1955 | 1816 | { |
---|
1956 | | - struct af_iucv_trans_hdr *trans_hdr = |
---|
1957 | | - (struct af_iucv_trans_hdr *)skb->data; |
---|
| 1817 | + struct af_iucv_trans_hdr *trans_hdr = iucv_trans_hdr(skb); |
---|
1958 | 1818 | char tmpID[8]; |
---|
1959 | 1819 | char tmpName[8]; |
---|
1960 | 1820 | |
---|
.. | .. |
---|
1977 | 1837 | **/ |
---|
1978 | 1838 | static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb) |
---|
1979 | 1839 | { |
---|
| 1840 | + struct af_iucv_trans_hdr *trans_hdr = iucv_trans_hdr(skb); |
---|
1980 | 1841 | struct sock *nsk; |
---|
1981 | 1842 | struct iucv_sock *iucv, *niucv; |
---|
1982 | | - struct af_iucv_trans_hdr *trans_hdr; |
---|
1983 | 1843 | int err; |
---|
1984 | 1844 | |
---|
1985 | 1845 | iucv = iucv_sk(sk); |
---|
1986 | | - trans_hdr = (struct af_iucv_trans_hdr *)skb->data; |
---|
1987 | 1846 | if (!iucv) { |
---|
1988 | 1847 | /* no sock - connection refused */ |
---|
1989 | 1848 | afiucv_swap_src_dest(skb); |
---|
.. | .. |
---|
2044 | 1903 | static int afiucv_hs_callback_synack(struct sock *sk, struct sk_buff *skb) |
---|
2045 | 1904 | { |
---|
2046 | 1905 | struct iucv_sock *iucv = iucv_sk(sk); |
---|
2047 | | - struct af_iucv_trans_hdr *trans_hdr = |
---|
2048 | | - (struct af_iucv_trans_hdr *)skb->data; |
---|
2049 | 1906 | |
---|
2050 | 1907 | if (!iucv) |
---|
2051 | 1908 | goto out; |
---|
2052 | 1909 | if (sk->sk_state != IUCV_BOUND) |
---|
2053 | 1910 | goto out; |
---|
2054 | 1911 | bh_lock_sock(sk); |
---|
2055 | | - iucv->msglimit_peer = trans_hdr->window; |
---|
| 1912 | + iucv->msglimit_peer = iucv_trans_hdr(skb)->window; |
---|
2056 | 1913 | sk->sk_state = IUCV_CONNECTED; |
---|
2057 | 1914 | sk->sk_state_change(sk); |
---|
2058 | 1915 | bh_unlock_sock(sk); |
---|
.. | .. |
---|
2108 | 1965 | static int afiucv_hs_callback_win(struct sock *sk, struct sk_buff *skb) |
---|
2109 | 1966 | { |
---|
2110 | 1967 | struct iucv_sock *iucv = iucv_sk(sk); |
---|
2111 | | - struct af_iucv_trans_hdr *trans_hdr = |
---|
2112 | | - (struct af_iucv_trans_hdr *)skb->data; |
---|
2113 | 1968 | |
---|
2114 | 1969 | if (!iucv) |
---|
2115 | 1970 | return NET_RX_SUCCESS; |
---|
.. | .. |
---|
2117 | 1972 | if (sk->sk_state != IUCV_CONNECTED) |
---|
2118 | 1973 | return NET_RX_SUCCESS; |
---|
2119 | 1974 | |
---|
2120 | | - atomic_sub(trans_hdr->window, &iucv->msg_sent); |
---|
| 1975 | + atomic_sub(iucv_trans_hdr(skb)->window, &iucv->msg_sent); |
---|
2121 | 1976 | iucv_sock_wake_msglim(sk); |
---|
2122 | 1977 | return NET_RX_SUCCESS; |
---|
2123 | 1978 | } |
---|
.. | .. |
---|
2180 | 2035 | int err = NET_RX_SUCCESS; |
---|
2181 | 2036 | char nullstring[8]; |
---|
2182 | 2037 | |
---|
2183 | | - if (skb->len < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) { |
---|
2184 | | - WARN_ONCE(1, "AF_IUCV too short skb, len=%d, min=%d", |
---|
2185 | | - (int)skb->len, |
---|
2186 | | - (int)(ETH_HLEN + sizeof(struct af_iucv_trans_hdr))); |
---|
| 2038 | + if (!pskb_may_pull(skb, sizeof(*trans_hdr))) { |
---|
2187 | 2039 | kfree_skb(skb); |
---|
2188 | 2040 | return NET_RX_SUCCESS; |
---|
2189 | 2041 | } |
---|
2190 | | - if (skb_headlen(skb) < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) |
---|
2191 | | - if (skb_linearize(skb)) { |
---|
2192 | | - WARN_ONCE(1, "AF_IUCV skb_linearize failed, len=%d", |
---|
2193 | | - (int)skb->len); |
---|
2194 | | - kfree_skb(skb); |
---|
2195 | | - return NET_RX_SUCCESS; |
---|
2196 | | - } |
---|
2197 | | - skb_pull(skb, ETH_HLEN); |
---|
2198 | | - trans_hdr = (struct af_iucv_trans_hdr *)skb->data; |
---|
| 2042 | + |
---|
| 2043 | + trans_hdr = iucv_trans_hdr(skb); |
---|
2199 | 2044 | EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName)); |
---|
2200 | 2045 | EBCASC(trans_hdr->destUserID, sizeof(trans_hdr->destUserID)); |
---|
2201 | 2046 | EBCASC(trans_hdr->srcAppName, sizeof(trans_hdr->srcAppName)); |
---|
.. | .. |
---|
2266 | 2111 | kfree_skb(skb); |
---|
2267 | 2112 | break; |
---|
2268 | 2113 | } |
---|
2269 | | - /* fall through and receive non-zero length data */ |
---|
| 2114 | + fallthrough; /* and receive non-zero length data */ |
---|
2270 | 2115 | case (AF_IUCV_FLAG_SHT): |
---|
2271 | 2116 | /* shutdown request */ |
---|
2272 | | - /* fall through and receive zero length data */ |
---|
| 2117 | + fallthrough; /* and receive zero length data */ |
---|
2273 | 2118 | case 0: |
---|
2274 | 2119 | /* plain data frame */ |
---|
2275 | 2120 | IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class; |
---|
.. | .. |
---|
2310 | 2155 | |
---|
2311 | 2156 | list = &iucv->send_skb_q; |
---|
2312 | 2157 | spin_lock_irqsave(&list->lock, flags); |
---|
2313 | | - if (skb_queue_empty(list)) |
---|
2314 | | - goto out_unlock; |
---|
2315 | | - list_skb = list->next; |
---|
2316 | | - nskb = list_skb->next; |
---|
2317 | | - while (list_skb != (struct sk_buff *)list) { |
---|
| 2158 | + skb_queue_walk_safe(list, list_skb, nskb) { |
---|
2318 | 2159 | if (skb_shinfo(list_skb) == skb_shinfo(skb)) { |
---|
2319 | 2160 | switch (n) { |
---|
2320 | 2161 | case TX_NOTIFY_OK: |
---|
.. | .. |
---|
2347 | 2188 | } |
---|
2348 | 2189 | break; |
---|
2349 | 2190 | } |
---|
2350 | | - list_skb = nskb; |
---|
2351 | | - nskb = nskb->next; |
---|
2352 | 2191 | } |
---|
2353 | | -out_unlock: |
---|
2354 | 2192 | spin_unlock_irqrestore(&list->lock, flags); |
---|
2355 | 2193 | |
---|
2356 | 2194 | if (sk->sk_state == IUCV_CLOSING) { |
---|
.. | .. |
---|
2418 | 2256 | .getsockopt = iucv_sock_getsockopt, |
---|
2419 | 2257 | }; |
---|
2420 | 2258 | |
---|
| 2259 | +static int iucv_sock_create(struct net *net, struct socket *sock, int protocol, |
---|
| 2260 | + int kern) |
---|
| 2261 | +{ |
---|
| 2262 | + struct sock *sk; |
---|
| 2263 | + |
---|
| 2264 | + if (protocol && protocol != PF_IUCV) |
---|
| 2265 | + return -EPROTONOSUPPORT; |
---|
| 2266 | + |
---|
| 2267 | + sock->state = SS_UNCONNECTED; |
---|
| 2268 | + |
---|
| 2269 | + switch (sock->type) { |
---|
| 2270 | + case SOCK_STREAM: |
---|
| 2271 | + case SOCK_SEQPACKET: |
---|
| 2272 | + /* currently, proto ops can handle both sk types */ |
---|
| 2273 | + sock->ops = &iucv_sock_ops; |
---|
| 2274 | + break; |
---|
| 2275 | + default: |
---|
| 2276 | + return -ESOCKTNOSUPPORT; |
---|
| 2277 | + } |
---|
| 2278 | + |
---|
| 2279 | + sk = iucv_sock_alloc(sock, protocol, GFP_KERNEL, kern); |
---|
| 2280 | + if (!sk) |
---|
| 2281 | + return -ENOMEM; |
---|
| 2282 | + |
---|
| 2283 | + iucv_sock_init(sk, NULL); |
---|
| 2284 | + |
---|
| 2285 | + return 0; |
---|
| 2286 | +} |
---|
| 2287 | + |
---|
2421 | 2288 | static const struct net_proto_family iucv_sock_family_ops = { |
---|
2422 | 2289 | .family = AF_IUCV, |
---|
2423 | 2290 | .owner = THIS_MODULE, |
---|
.. | .. |
---|
2431 | 2298 | |
---|
2432 | 2299 | static int afiucv_iucv_init(void) |
---|
2433 | 2300 | { |
---|
2434 | | - int err; |
---|
2435 | | - |
---|
2436 | | - err = pr_iucv->iucv_register(&af_iucv_handler, 0); |
---|
2437 | | - if (err) |
---|
2438 | | - goto out; |
---|
2439 | | - /* establish dummy device */ |
---|
2440 | | - af_iucv_driver.bus = pr_iucv->bus; |
---|
2441 | | - err = driver_register(&af_iucv_driver); |
---|
2442 | | - if (err) |
---|
2443 | | - goto out_iucv; |
---|
2444 | | - af_iucv_dev = kzalloc(sizeof(struct device), GFP_KERNEL); |
---|
2445 | | - if (!af_iucv_dev) { |
---|
2446 | | - err = -ENOMEM; |
---|
2447 | | - goto out_driver; |
---|
2448 | | - } |
---|
2449 | | - dev_set_name(af_iucv_dev, "af_iucv"); |
---|
2450 | | - af_iucv_dev->bus = pr_iucv->bus; |
---|
2451 | | - af_iucv_dev->parent = pr_iucv->root; |
---|
2452 | | - af_iucv_dev->release = (void (*)(struct device *))kfree; |
---|
2453 | | - af_iucv_dev->driver = &af_iucv_driver; |
---|
2454 | | - err = device_register(af_iucv_dev); |
---|
2455 | | - if (err) |
---|
2456 | | - goto out_iucv_dev; |
---|
2457 | | - return 0; |
---|
2458 | | - |
---|
2459 | | -out_iucv_dev: |
---|
2460 | | - put_device(af_iucv_dev); |
---|
2461 | | -out_driver: |
---|
2462 | | - driver_unregister(&af_iucv_driver); |
---|
2463 | | -out_iucv: |
---|
2464 | | - pr_iucv->iucv_unregister(&af_iucv_handler, 0); |
---|
2465 | | -out: |
---|
2466 | | - return err; |
---|
| 2301 | + return pr_iucv->iucv_register(&af_iucv_handler, 0); |
---|
2467 | 2302 | } |
---|
2468 | 2303 | |
---|
2469 | 2304 | static void afiucv_iucv_exit(void) |
---|
2470 | 2305 | { |
---|
2471 | | - device_unregister(af_iucv_dev); |
---|
2472 | | - driver_unregister(&af_iucv_driver); |
---|
2473 | 2306 | pr_iucv->iucv_unregister(&af_iucv_handler, 0); |
---|
2474 | 2307 | } |
---|
2475 | 2308 | |
---|