1 // SPDX-License-Identifier: GPL-2.0-only
5 * Datagram (ISI) Phonet sockets
7 * Copyright (C) 2008 Nokia Corporation.
9 * Authors: Sakari Ailus <sakari.ailus@nokia.com>
10 * RĂ©mi Denis-Courmont
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/socket.h>
16 #include <asm/ioctls.h>
19 #include <linux/phonet.h>
20 #include <linux/export.h>
21 #include <net/phonet/phonet.h>
23 static int pn_backlog_rcv(struct sock
*sk
, struct sk_buff
*skb
);
25 /* associated socket ceases to exist */
26 static void pn_sock_close(struct sock
*sk
, long timeout
)
28 sk_common_release(sk
);
31 static int pn_ioctl(struct sock
*sk
, int cmd
, unsigned long arg
)
39 skb
= skb_peek(&sk
->sk_receive_queue
);
40 answ
= skb
? skb
->len
: 0;
42 return put_user(answ
, (int __user
*)arg
);
44 case SIOCPNADDRESOURCE
:
45 case SIOCPNDELRESOURCE
: {
47 if (get_user(res
, (u32 __user
*)arg
))
51 if (cmd
== SIOCPNADDRESOURCE
)
52 return pn_sock_bind_res(sk
, res
);
54 return pn_sock_unbind_res(sk
, res
);
61 /* Destroy socket. All references are gone. */
62 static void pn_destruct(struct sock
*sk
)
64 skb_queue_purge(&sk
->sk_receive_queue
);
67 static int pn_init(struct sock
*sk
)
69 sk
->sk_destruct
= pn_destruct
;
73 static int pn_sendmsg(struct sock
*sk
, struct msghdr
*msg
, size_t len
)
75 DECLARE_SOCKADDR(struct sockaddr_pn
*, target
, msg
->msg_name
);
79 if (msg
->msg_flags
& ~(MSG_DONTWAIT
|MSG_EOR
|MSG_NOSIGNAL
|
86 if (msg
->msg_namelen
< sizeof(struct sockaddr_pn
))
89 if (target
->spn_family
!= AF_PHONET
)
92 skb
= sock_alloc_send_skb(sk
, MAX_PHONET_HEADER
+ len
,
93 msg
->msg_flags
& MSG_DONTWAIT
, &err
);
96 skb_reserve(skb
, MAX_PHONET_HEADER
);
98 err
= memcpy_from_msg((void *)skb_put(skb
, len
), msg
, len
);
105 * Fill in the Phonet header and
106 * finally pass the packet forwards.
108 err
= pn_skb_send(sk
, skb
, target
);
110 /* If ok, return len. */
111 return (err
>= 0) ? len
: err
;
114 static int pn_recvmsg(struct sock
*sk
, struct msghdr
*msg
, size_t len
,
115 int noblock
, int flags
, int *addr_len
)
117 struct sk_buff
*skb
= NULL
;
118 struct sockaddr_pn sa
;
119 int rval
= -EOPNOTSUPP
;
122 if (flags
& ~(MSG_PEEK
|MSG_TRUNC
|MSG_DONTWAIT
|MSG_NOSIGNAL
|
126 skb
= skb_recv_datagram(sk
, flags
, noblock
, &rval
);
130 pn_skb_get_src_sockaddr(skb
, &sa
);
134 msg
->msg_flags
|= MSG_TRUNC
;
138 rval
= skb_copy_datagram_msg(skb
, 0, msg
, copylen
);
144 rval
= (flags
& MSG_TRUNC
) ? skb
->len
: copylen
;
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
);
153 skb_free_datagram(sk
, skb
);
159 /* Queue an skb for a sock. */
160 static int pn_backlog_rcv(struct sock
*sk
, struct sk_buff
*skb
)
162 int err
= sock_queue_rcv_skb(sk
, skb
);
166 return err
? NET_RX_DROP
: NET_RX_SUCCESS
;
169 /* Module registration */
170 static struct proto pn_proto
= {
171 .close
= pn_sock_close
,
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
,
185 static const struct phonet_protocol pn_dgram_proto
= {
186 .ops
= &phonet_dgram_ops
,
188 .sock_type
= SOCK_DGRAM
,
191 int __init
isi_register(void)
193 return phonet_proto_register(PN_PROTO_PHONET
, &pn_dgram_proto
);
196 void __exit
isi_unregister(void)
198 phonet_proto_unregister(PN_PROTO_PHONET
, &pn_dgram_proto
);