0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/slab.h>
0015 #include <linux/socket.h>
0016 #include <asm/ioctls.h>
0017 #include <net/sock.h>
0018
0019 #include <linux/phonet.h>
0020 #include <linux/export.h>
0021 #include <net/phonet/phonet.h>
0022
0023 static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb);
0024
0025
0026 static void pn_sock_close(struct sock *sk, long timeout)
0027 {
0028 sk_common_release(sk);
0029 }
0030
0031 static int pn_ioctl(struct sock *sk, int cmd, unsigned long arg)
0032 {
0033 struct sk_buff *skb;
0034 int answ;
0035
0036 switch (cmd) {
0037 case SIOCINQ:
0038 lock_sock(sk);
0039 skb = skb_peek(&sk->sk_receive_queue);
0040 answ = skb ? skb->len : 0;
0041 release_sock(sk);
0042 return put_user(answ, (int __user *)arg);
0043
0044 case SIOCPNADDRESOURCE:
0045 case SIOCPNDELRESOURCE: {
0046 u32 res;
0047 if (get_user(res, (u32 __user *)arg))
0048 return -EFAULT;
0049 if (res >= 256)
0050 return -EINVAL;
0051 if (cmd == SIOCPNADDRESOURCE)
0052 return pn_sock_bind_res(sk, res);
0053 else
0054 return pn_sock_unbind_res(sk, res);
0055 }
0056 }
0057
0058 return -ENOIOCTLCMD;
0059 }
0060
0061
0062 static void pn_destruct(struct sock *sk)
0063 {
0064 skb_queue_purge(&sk->sk_receive_queue);
0065 }
0066
0067 static int pn_init(struct sock *sk)
0068 {
0069 sk->sk_destruct = pn_destruct;
0070 return 0;
0071 }
0072
0073 static int pn_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
0074 {
0075 DECLARE_SOCKADDR(struct sockaddr_pn *, target, msg->msg_name);
0076 struct sk_buff *skb;
0077 int err;
0078
0079 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|
0080 MSG_CMSG_COMPAT))
0081 return -EOPNOTSUPP;
0082
0083 if (target == NULL)
0084 return -EDESTADDRREQ;
0085
0086 if (msg->msg_namelen < sizeof(struct sockaddr_pn))
0087 return -EINVAL;
0088
0089 if (target->spn_family != AF_PHONET)
0090 return -EAFNOSUPPORT;
0091
0092 skb = sock_alloc_send_skb(sk, MAX_PHONET_HEADER + len,
0093 msg->msg_flags & MSG_DONTWAIT, &err);
0094 if (skb == NULL)
0095 return err;
0096 skb_reserve(skb, MAX_PHONET_HEADER);
0097
0098 err = memcpy_from_msg((void *)skb_put(skb, len), msg, len);
0099 if (err < 0) {
0100 kfree_skb(skb);
0101 return err;
0102 }
0103
0104
0105
0106
0107
0108 err = pn_skb_send(sk, skb, target);
0109
0110
0111 return (err >= 0) ? len : err;
0112 }
0113
0114 static int pn_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
0115 int flags, int *addr_len)
0116 {
0117 struct sk_buff *skb = NULL;
0118 struct sockaddr_pn sa;
0119 int rval = -EOPNOTSUPP;
0120 int copylen;
0121
0122 if (flags & ~(MSG_PEEK|MSG_TRUNC|MSG_DONTWAIT|MSG_NOSIGNAL|
0123 MSG_CMSG_COMPAT))
0124 goto out_nofree;
0125
0126 skb = skb_recv_datagram(sk, flags, &rval);
0127 if (skb == NULL)
0128 goto out_nofree;
0129
0130 pn_skb_get_src_sockaddr(skb, &sa);
0131
0132 copylen = skb->len;
0133 if (len < copylen) {
0134 msg->msg_flags |= MSG_TRUNC;
0135 copylen = len;
0136 }
0137
0138 rval = skb_copy_datagram_msg(skb, 0, msg, copylen);
0139 if (rval) {
0140 rval = -EFAULT;
0141 goto out;
0142 }
0143
0144 rval = (flags & MSG_TRUNC) ? skb->len : copylen;
0145
0146 if (msg->msg_name != NULL) {
0147 __sockaddr_check_size(sizeof(sa));
0148 memcpy(msg->msg_name, &sa, sizeof(sa));
0149 *addr_len = sizeof(sa);
0150 }
0151
0152 out:
0153 skb_free_datagram(sk, skb);
0154
0155 out_nofree:
0156 return rval;
0157 }
0158
0159
0160 static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb)
0161 {
0162 int err = sock_queue_rcv_skb(sk, skb);
0163
0164 if (err < 0)
0165 kfree_skb(skb);
0166 return err ? NET_RX_DROP : NET_RX_SUCCESS;
0167 }
0168
0169
0170 static struct proto pn_proto = {
0171 .close = pn_sock_close,
0172 .ioctl = pn_ioctl,
0173 .init = pn_init,
0174 .sendmsg = pn_sendmsg,
0175 .recvmsg = pn_recvmsg,
0176 .backlog_rcv = pn_backlog_rcv,
0177 .hash = pn_sock_hash,
0178 .unhash = pn_sock_unhash,
0179 .get_port = pn_sock_get_port,
0180 .obj_size = sizeof(struct pn_sock),
0181 .owner = THIS_MODULE,
0182 .name = "PHONET",
0183 };
0184
0185 static const struct phonet_protocol pn_dgram_proto = {
0186 .ops = &phonet_dgram_ops,
0187 .prot = &pn_proto,
0188 .sock_type = SOCK_DGRAM,
0189 };
0190
0191 int __init isi_register(void)
0192 {
0193 return phonet_proto_register(PN_PROTO_PHONET, &pn_dgram_proto);
0194 }
0195
0196 void __exit isi_unregister(void)
0197 {
0198 phonet_proto_unregister(PN_PROTO_PHONET, &pn_dgram_proto);
0199 }