root/net/phonet/datagram.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pn_sock_close
  2. pn_ioctl
  3. pn_destruct
  4. pn_init
  5. pn_sendmsg
  6. pn_recvmsg
  7. pn_backlog_rcv
  8. isi_register
  9. isi_unregister

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * File: datagram.c
   4  *
   5  * Datagram (ISI) Phonet sockets
   6  *
   7  * Copyright (C) 2008 Nokia Corporation.
   8  *
   9  * Authors: Sakari Ailus <sakari.ailus@nokia.com>
  10  *          RĂ©mi Denis-Courmont
  11  */
  12 
  13 #include <linux/kernel.h>
  14 #include <linux/slab.h>
  15 #include <linux/socket.h>
  16 #include <asm/ioctls.h>
  17 #include <net/sock.h>
  18 
  19 #include <linux/phonet.h>
  20 #include <linux/export.h>
  21 #include <net/phonet/phonet.h>
  22 
  23 static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb);
  24 
  25 /* associated socket ceases to exist */
  26 static void pn_sock_close(struct sock *sk, long timeout)
  27 {
  28         sk_common_release(sk);
  29 }
  30 
  31 static int pn_ioctl(struct sock *sk, int cmd, unsigned long arg)
  32 {
  33         struct sk_buff *skb;
  34         int answ;
  35 
  36         switch (cmd) {
  37         case SIOCINQ:
  38                 lock_sock(sk);
  39                 skb = skb_peek(&sk->sk_receive_queue);
  40                 answ = skb ? skb->len : 0;
  41                 release_sock(sk);
  42                 return put_user(answ, (int __user *)arg);
  43 
  44         case SIOCPNADDRESOURCE:
  45         case SIOCPNDELRESOURCE: {
  46                         u32 res;
  47                         if (get_user(res, (u32 __user *)arg))
  48                                 return -EFAULT;
  49                         if (res >= 256)
  50                                 return -EINVAL;
  51                         if (cmd == SIOCPNADDRESOURCE)
  52                                 return pn_sock_bind_res(sk, res);
  53                         else
  54                                 return pn_sock_unbind_res(sk, res);
  55                 }
  56         }
  57 
  58         return -ENOIOCTLCMD;
  59 }
  60 
  61 /* Destroy socket. All references are gone. */
  62 static void pn_destruct(struct sock *sk)
  63 {
  64         skb_queue_purge(&sk->sk_receive_queue);
  65 }
  66 
  67 static int pn_init(struct sock *sk)
  68 {
  69         sk->sk_destruct = pn_destruct;
  70         return 0;
  71 }
  72 
  73 static int pn_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
  74 {
  75         DECLARE_SOCKADDR(struct sockaddr_pn *, target, msg->msg_name);
  76         struct sk_buff *skb;
  77         int err;
  78 
  79         if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|
  80                                 MSG_CMSG_COMPAT))
  81                 return -EOPNOTSUPP;
  82 
  83         if (target == NULL)
  84                 return -EDESTADDRREQ;
  85 
  86         if (msg->msg_namelen < sizeof(struct sockaddr_pn))
  87                 return -EINVAL;
  88 
  89         if (target->spn_family != AF_PHONET)
  90                 return -EAFNOSUPPORT;
  91 
  92         skb = sock_alloc_send_skb(sk, MAX_PHONET_HEADER + len,
  93                                         msg->msg_flags & MSG_DONTWAIT, &err);
  94         if (skb == NULL)
  95                 return err;
  96         skb_reserve(skb, MAX_PHONET_HEADER);
  97 
  98         err = memcpy_from_msg((void *)skb_put(skb, len), msg, len);
  99         if (err < 0) {
 100                 kfree_skb(skb);
 101                 return err;
 102         }
 103 
 104         /*
 105          * Fill in the Phonet header and
 106          * finally pass the packet forwards.
 107          */
 108         err = pn_skb_send(sk, skb, target);
 109 
 110         /* If ok, return len. */
 111         return (err >= 0) ? len : err;
 112 }
 113 
 114 static int pn_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
 115                       int noblock, int flags, int *addr_len)
 116 {
 117         struct sk_buff *skb = NULL;
 118         struct sockaddr_pn sa;
 119         int rval = -EOPNOTSUPP;
 120         int copylen;
 121 
 122         if (flags & ~(MSG_PEEK|MSG_TRUNC|MSG_DONTWAIT|MSG_NOSIGNAL|
 123                         MSG_CMSG_COMPAT))
 124                 goto out_nofree;
 125 
 126         skb = skb_recv_datagram(sk, flags, noblock, &rval);
 127         if (skb == NULL)
 128                 goto out_nofree;
 129 
 130         pn_skb_get_src_sockaddr(skb, &sa);
 131 
 132         copylen = skb->len;
 133         if (len < copylen) {
 134                 msg->msg_flags |= MSG_TRUNC;
 135                 copylen = len;
 136         }
 137 
 138         rval = skb_copy_datagram_msg(skb, 0, msg, copylen);
 139         if (rval) {
 140                 rval = -EFAULT;
 141                 goto out;
 142         }
 143 
 144         rval = (flags & MSG_TRUNC) ? skb->len : copylen;
 145 
 146         if (msg->msg_name != NULL) {
 147                 __sockaddr_check_size(sizeof(sa));
 148                 memcpy(msg->msg_name, &sa, sizeof(sa));
 149                 *addr_len = sizeof(sa);
 150         }
 151 
 152 out:
 153         skb_free_datagram(sk, skb);
 154 
 155 out_nofree:
 156         return rval;
 157 }
 158 
 159 /* Queue an skb for a sock. */
 160 static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 161 {
 162         int err = sock_queue_rcv_skb(sk, skb);
 163 
 164         if (err < 0)
 165                 kfree_skb(skb);
 166         return err ? NET_RX_DROP : NET_RX_SUCCESS;
 167 }
 168 
 169 /* Module registration */
 170 static struct proto pn_proto = {
 171         .close          = pn_sock_close,
 172         .ioctl          = pn_ioctl,
 173         .init           = pn_init,
 174         .sendmsg        = pn_sendmsg,
 175         .recvmsg        = pn_recvmsg,
 176         .backlog_rcv    = pn_backlog_rcv,
 177         .hash           = pn_sock_hash,
 178         .unhash         = pn_sock_unhash,
 179         .get_port       = pn_sock_get_port,
 180         .obj_size       = sizeof(struct pn_sock),
 181         .owner          = THIS_MODULE,
 182         .name           = "PHONET",
 183 };
 184 
 185 static const struct phonet_protocol pn_dgram_proto = {
 186         .ops            = &phonet_dgram_ops,
 187         .prot           = &pn_proto,
 188         .sock_type      = SOCK_DGRAM,
 189 };
 190 
 191 int __init isi_register(void)
 192 {
 193         return phonet_proto_register(PN_PROTO_PHONET, &pn_dgram_proto);
 194 }
 195 
 196 void __exit isi_unregister(void)
 197 {
 198         phonet_proto_unregister(PN_PROTO_PHONET, &pn_dgram_proto);
 199 }

/* [<][>][^][v][top][bottom][index][help] */