Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
net
phonet
datagram.c
Go to the documentation of this file.
1
/*
2
* File: datagram.c
3
*
4
* Datagram (ISI) Phonet sockets
5
*
6
* Copyright (C) 2008 Nokia Corporation.
7
*
8
* Authors: Sakari Ailus <
[email protected]
>
9
* RĂ©mi Denis-Courmont
10
*
11
* This program is free software; you can redistribute it and/or
12
* modify it under the terms of the GNU General Public License
13
* version 2 as published by the Free Software Foundation.
14
*
15
* This program is distributed in the hope that it will be useful, but
16
* WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
* General Public License for more details.
19
*
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23
* 02110-1301 USA
24
*/
25
26
#include <linux/kernel.h>
27
#include <linux/slab.h>
28
#include <linux/socket.h>
29
#include <asm/ioctls.h>
30
#include <
net/sock.h
>
31
32
#include <linux/phonet.h>
33
#include <linux/export.h>
34
#include <
net/phonet/phonet.h
>
35
36
static
int
pn_backlog_rcv(
struct
sock
*
sk
,
struct
sk_buff
*
skb
);
37
38
/* associated socket ceases to exist */
39
static
void
pn_sock_close(
struct
sock
*
sk
,
long
timeout)
40
{
41
sk_common_release
(sk);
42
}
43
44
static
int
pn_ioctl(
struct
sock
*
sk
,
int
cmd
,
unsigned
long
arg
)
45
{
46
struct
sk_buff
*
skb
;
47
int
answ;
48
49
switch
(cmd) {
50
case
SIOCINQ
:
51
lock_sock(sk);
52
skb = skb_peek(&sk->
sk_receive_queue
);
53
answ = skb ? skb->
len
: 0;
54
release_sock
(sk);
55
return
put_user
(answ, (
int
__user *)arg);
56
57
case
SIOCPNADDRESOURCE
:
58
case
SIOCPNDELRESOURCE
: {
59
u32
res
;
60
if
(
get_user
(res, (
u32
__user *)arg))
61
return
-
EFAULT
;
62
if
(res >= 256)
63
return
-
EINVAL
;
64
if
(cmd ==
SIOCPNADDRESOURCE
)
65
return
pn_sock_bind_res
(sk, res);
66
else
67
return
pn_sock_unbind_res
(sk, res);
68
}
69
}
70
71
return
-
ENOIOCTLCMD
;
72
}
73
74
/* Destroy socket. All references are gone. */
75
static
void
pn_destruct(
struct
sock
*sk)
76
{
77
skb_queue_purge
(&sk->
sk_receive_queue
);
78
}
79
80
static
int
pn_init(
struct
sock
*sk)
81
{
82
sk->
sk_destruct
= pn_destruct;
83
return
0;
84
}
85
86
static
int
pn_sendmsg(
struct
kiocb
*
iocb
,
struct
sock
*sk,
87
struct
msghdr
*
msg
,
size_t
len
)
88
{
89
struct
sockaddr_pn
*
target
;
90
struct
sk_buff
*
skb
;
91
int
err
;
92
93
if
(msg->
msg_flags
& ~(
MSG_DONTWAIT
|
MSG_EOR
|
MSG_NOSIGNAL
|
94
MSG_CMSG_COMPAT
))
95
return
-
EOPNOTSUPP
;
96
97
if
(msg->
msg_name
==
NULL
)
98
return
-
EDESTADDRREQ
;
99
100
if
(msg->
msg_namelen
<
sizeof
(
struct
sockaddr_pn
))
101
return
-
EINVAL
;
102
103
target = (
struct
sockaddr_pn
*)msg->
msg_name
;
104
if
(target->
spn_family
!=
AF_PHONET
)
105
return
-
EAFNOSUPPORT
;
106
107
skb =
sock_alloc_send_skb
(sk,
MAX_PHONET_HEADER
+ len,
108
msg->
msg_flags
&
MSG_DONTWAIT
, &err);
109
if
(skb ==
NULL
)
110
return
err
;
111
skb_reserve(skb,
MAX_PHONET_HEADER
);
112
113
err =
memcpy_fromiovec
((
void
*)
skb_put
(skb, len), msg->
msg_iov
, len);
114
if
(err < 0) {
115
kfree_skb
(skb);
116
return
err
;
117
}
118
119
/*
120
* Fill in the Phonet header and
121
* finally pass the packet forwards.
122
*/
123
err =
pn_skb_send
(sk, skb, target);
124
125
/* If ok, return len. */
126
return
(err >= 0) ? len :
err
;
127
}
128
129
static
int
pn_recvmsg(
struct
kiocb
*iocb,
struct
sock
*sk,
130
struct
msghdr
*msg,
size_t
len,
int
noblock,
131
int
flags
,
int
*addr_len)
132
{
133
struct
sk_buff
*skb =
NULL
;
134
struct
sockaddr_pn
sa
;
135
int
rval = -
EOPNOTSUPP
;
136
int
copylen;
137
138
if
(flags & ~(
MSG_PEEK
|
MSG_TRUNC
|
MSG_DONTWAIT
|
MSG_NOSIGNAL
|
139
MSG_CMSG_COMPAT
))
140
goto
out_nofree;
141
142
if
(addr_len)
143
*addr_len =
sizeof
(
sa
);
144
145
skb =
skb_recv_datagram
(sk, flags, noblock, &rval);
146
if
(skb ==
NULL
)
147
goto
out_nofree;
148
149
pn_skb_get_src_sockaddr(skb, &
sa
);
150
151
copylen = skb->
len
;
152
if
(len < copylen) {
153
msg->
msg_flags
|=
MSG_TRUNC
;
154
copylen = len;
155
}
156
157
rval =
skb_copy_datagram_iovec
(skb, 0, msg->
msg_iov
, copylen);
158
if
(rval) {
159
rval = -
EFAULT
;
160
goto
out
;
161
}
162
163
rval = (flags &
MSG_TRUNC
) ? skb->
len
: copylen;
164
165
if
(msg->
msg_name
!=
NULL
)
166
memcpy
(msg->
msg_name
, &
sa
,
sizeof
(
struct
sockaddr_pn
));
167
168
out
:
169
skb_free_datagram
(sk, skb);
170
171
out_nofree:
172
return
rval;
173
}
174
175
/* Queue an skb for a sock. */
176
static
int
pn_backlog_rcv(
struct
sock
*sk,
struct
sk_buff
*skb)
177
{
178
int
err =
sock_queue_rcv_skb
(sk, skb);
179
180
if
(err < 0)
181
kfree_skb
(skb);
182
return
err ?
NET_RX_DROP
:
NET_RX_SUCCESS
;
183
}
184
185
/* Module registration */
186
static
struct
proto
pn_proto = {
187
.close = pn_sock_close,
188
.ioctl = pn_ioctl,
189
.init = pn_init,
190
.sendmsg = pn_sendmsg,
191
.recvmsg = pn_recvmsg,
192
.backlog_rcv = pn_backlog_rcv,
193
.hash =
pn_sock_hash
,
194
.unhash =
pn_sock_unhash
,
195
.get_port =
pn_sock_get_port
,
196
.obj_size =
sizeof
(
struct
pn_sock
),
197
.
owner
=
THIS_MODULE
,
198
.name =
"PHONET"
,
199
};
200
201
static
struct
phonet_protocol
pn_dgram_proto = {
202
.ops = &
phonet_dgram_ops
,
203
.prot = &pn_proto,
204
.sock_type =
SOCK_DGRAM
,
205
};
206
207
int
__init
isi_register
(
void
)
208
{
209
return
phonet_proto_register
(
PN_PROTO_PHONET
, &pn_dgram_proto);
210
}
211
212
void
__exit
isi_unregister
(
void
)
213
{
214
phonet_proto_unregister
(
PN_PROTO_PHONET
, &pn_dgram_proto);
215
}
Generated on Thu Jan 10 2013 14:57:30 for Linux Kernel by
1.8.2