| .. | .. |
|---|
| 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 | |
|---|