2 * IEEE802154.4 socket interface
4 * Copyright 2007, 2008 Siemens AG
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * Sergey Lapin <slapin@ossfans.org>
21 * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
24 #include <linux/net.h>
25 #include <linux/capability.h>
26 #include <linux/module.h>
27 #include <linux/if_arp.h>
29 #include <linux/termios.h> /* For TIOCOUTQ/INQ */
30 #include <linux/list.h>
31 #include <linux/slab.h>
32 #include <net/datalink.h>
33 #include <net/psnap.h>
35 #include <net/tcp_states.h>
36 #include <net/route.h>
38 #include <net/af_ieee802154.h>
39 #include <net/ieee802154_netdev.h>
44 * Utility function for families
47 ieee802154_get_dev(struct net
*net
, const struct ieee802154_addr
*addr
)
49 struct net_device
*dev
= NULL
;
50 struct net_device
*tmp
;
51 __le16 pan_id
, short_addr
;
52 u8 hwaddr
[IEEE802154_ADDR_LEN
];
55 case IEEE802154_ADDR_LONG
:
56 ieee802154_devaddr_to_raw(hwaddr
, addr
->extended_addr
);
58 dev
= dev_getbyhwaddr_rcu(net
, ARPHRD_IEEE802154
, hwaddr
);
63 case IEEE802154_ADDR_SHORT
:
64 if (addr
->pan_id
== cpu_to_le16(IEEE802154_PANID_BROADCAST
) ||
65 addr
->short_addr
== cpu_to_le16(IEEE802154_ADDR_UNDEF
) ||
66 addr
->short_addr
== cpu_to_le16(IEEE802154_ADDR_BROADCAST
))
71 for_each_netdev(net
, tmp
) {
72 if (tmp
->type
!= ARPHRD_IEEE802154
)
75 pan_id
= ieee802154_mlme_ops(tmp
)->get_pan_id(tmp
);
77 ieee802154_mlme_ops(tmp
)->get_short_addr(tmp
);
79 if (pan_id
== addr
->pan_id
&&
80 short_addr
== addr
->short_addr
) {
90 pr_warning("Unsupported ieee802154 address type: %d\n",
98 static int ieee802154_sock_release(struct socket
*sock
)
100 struct sock
*sk
= sock
->sk
;
104 sk
->sk_prot
->close(sk
, 0);
108 static int ieee802154_sock_sendmsg(struct kiocb
*iocb
, struct socket
*sock
,
109 struct msghdr
*msg
, size_t len
)
111 struct sock
*sk
= sock
->sk
;
113 return sk
->sk_prot
->sendmsg(iocb
, sk
, msg
, len
);
116 static int ieee802154_sock_bind(struct socket
*sock
, struct sockaddr
*uaddr
,
119 struct sock
*sk
= sock
->sk
;
121 if (sk
->sk_prot
->bind
)
122 return sk
->sk_prot
->bind(sk
, uaddr
, addr_len
);
124 return sock_no_bind(sock
, uaddr
, addr_len
);
127 static int ieee802154_sock_connect(struct socket
*sock
, struct sockaddr
*uaddr
,
128 int addr_len
, int flags
)
130 struct sock
*sk
= sock
->sk
;
132 if (addr_len
< sizeof(uaddr
->sa_family
))
135 if (uaddr
->sa_family
== AF_UNSPEC
)
136 return sk
->sk_prot
->disconnect(sk
, flags
);
138 return sk
->sk_prot
->connect(sk
, uaddr
, addr_len
);
141 static int ieee802154_dev_ioctl(struct sock
*sk
, struct ifreq __user
*arg
,
145 int ret
= -ENOIOCTLCMD
;
146 struct net_device
*dev
;
148 if (copy_from_user(&ifr
, arg
, sizeof(struct ifreq
)))
151 ifr
.ifr_name
[IFNAMSIZ
-1] = 0;
153 dev_load(sock_net(sk
), ifr
.ifr_name
);
154 dev
= dev_get_by_name(sock_net(sk
), ifr
.ifr_name
);
159 if (dev
->type
== ARPHRD_IEEE802154
&& dev
->netdev_ops
->ndo_do_ioctl
)
160 ret
= dev
->netdev_ops
->ndo_do_ioctl(dev
, &ifr
, cmd
);
162 if (!ret
&& copy_to_user(arg
, &ifr
, sizeof(struct ifreq
)))
169 static int ieee802154_sock_ioctl(struct socket
*sock
, unsigned int cmd
,
172 struct sock
*sk
= sock
->sk
;
176 return sock_get_timestamp(sk
, (struct timeval __user
*)arg
);
178 return sock_get_timestampns(sk
, (struct timespec __user
*)arg
);
181 return ieee802154_dev_ioctl(sk
, (struct ifreq __user
*)arg
,
184 if (!sk
->sk_prot
->ioctl
)
186 return sk
->sk_prot
->ioctl(sk
, cmd
, arg
);
190 static const struct proto_ops ieee802154_raw_ops
= {
191 .family
= PF_IEEE802154
,
192 .owner
= THIS_MODULE
,
193 .release
= ieee802154_sock_release
,
194 .bind
= ieee802154_sock_bind
,
195 .connect
= ieee802154_sock_connect
,
196 .socketpair
= sock_no_socketpair
,
197 .accept
= sock_no_accept
,
198 .getname
= sock_no_getname
,
199 .poll
= datagram_poll
,
200 .ioctl
= ieee802154_sock_ioctl
,
201 .listen
= sock_no_listen
,
202 .shutdown
= sock_no_shutdown
,
203 .setsockopt
= sock_common_setsockopt
,
204 .getsockopt
= sock_common_getsockopt
,
205 .sendmsg
= ieee802154_sock_sendmsg
,
206 .recvmsg
= sock_common_recvmsg
,
207 .mmap
= sock_no_mmap
,
208 .sendpage
= sock_no_sendpage
,
210 .compat_setsockopt
= compat_sock_common_setsockopt
,
211 .compat_getsockopt
= compat_sock_common_getsockopt
,
215 static const struct proto_ops ieee802154_dgram_ops
= {
216 .family
= PF_IEEE802154
,
217 .owner
= THIS_MODULE
,
218 .release
= ieee802154_sock_release
,
219 .bind
= ieee802154_sock_bind
,
220 .connect
= ieee802154_sock_connect
,
221 .socketpair
= sock_no_socketpair
,
222 .accept
= sock_no_accept
,
223 .getname
= sock_no_getname
,
224 .poll
= datagram_poll
,
225 .ioctl
= ieee802154_sock_ioctl
,
226 .listen
= sock_no_listen
,
227 .shutdown
= sock_no_shutdown
,
228 .setsockopt
= sock_common_setsockopt
,
229 .getsockopt
= sock_common_getsockopt
,
230 .sendmsg
= ieee802154_sock_sendmsg
,
231 .recvmsg
= sock_common_recvmsg
,
232 .mmap
= sock_no_mmap
,
233 .sendpage
= sock_no_sendpage
,
235 .compat_setsockopt
= compat_sock_common_setsockopt
,
236 .compat_getsockopt
= compat_sock_common_getsockopt
,
242 * Create a socket. Initialise the socket, blank the addresses
245 static int ieee802154_create(struct net
*net
, struct socket
*sock
,
246 int protocol
, int kern
)
251 const struct proto_ops
*ops
;
253 if (!net_eq(net
, &init_net
))
254 return -EAFNOSUPPORT
;
256 switch (sock
->type
) {
258 proto
= &ieee802154_raw_prot
;
259 ops
= &ieee802154_raw_ops
;
262 proto
= &ieee802154_dgram_prot
;
263 ops
= &ieee802154_dgram_ops
;
266 rc
= -ESOCKTNOSUPPORT
;
271 sk
= sk_alloc(net
, PF_IEEE802154
, GFP_KERNEL
, proto
);
278 sock_init_data(sock
, sk
);
279 /* FIXME: sk->sk_destruct */
280 sk
->sk_family
= PF_IEEE802154
;
282 /* Checksums on by default */
283 sock_set_flag(sk
, SOCK_ZAPPED
);
285 if (sk
->sk_prot
->hash
)
286 sk
->sk_prot
->hash(sk
);
288 if (sk
->sk_prot
->init
) {
289 rc
= sk
->sk_prot
->init(sk
);
291 sk_common_release(sk
);
297 static const struct net_proto_family ieee802154_family_ops
= {
298 .family
= PF_IEEE802154
,
299 .create
= ieee802154_create
,
300 .owner
= THIS_MODULE
,
303 static int ieee802154_rcv(struct sk_buff
*skb
, struct net_device
*dev
,
304 struct packet_type
*pt
, struct net_device
*orig_dev
)
306 if (!netif_running(dev
))
308 pr_debug("got frame, type %d, dev %p\n", dev
->type
, dev
);
310 print_hex_dump_bytes("ieee802154_rcv ", DUMP_PREFIX_NONE
, skb
->data
, skb
->len
);
313 if (!net_eq(dev_net(dev
), &init_net
))
316 ieee802154_raw_deliver(dev
, skb
);
318 if (dev
->type
!= ARPHRD_IEEE802154
)
321 if (skb
->pkt_type
!= PACKET_OTHERHOST
)
322 return ieee802154_dgram_deliver(dev
, skb
);
330 static struct packet_type ieee802154_packet_type
= {
331 .type
= htons(ETH_P_IEEE802154
),
332 .func
= ieee802154_rcv
,
335 static int __init
af_ieee802154_init(void)
339 rc
= proto_register(&ieee802154_raw_prot
, 1);
343 rc
= proto_register(&ieee802154_dgram_prot
, 1);
347 /* Tell SOCKET that we are alive */
348 rc
= sock_register(&ieee802154_family_ops
);
351 dev_add_pack(&ieee802154_packet_type
);
357 proto_unregister(&ieee802154_dgram_prot
);
359 proto_unregister(&ieee802154_raw_prot
);
363 static void __exit
af_ieee802154_remove(void)
365 dev_remove_pack(&ieee802154_packet_type
);
366 sock_unregister(PF_IEEE802154
);
367 proto_unregister(&ieee802154_dgram_prot
);
368 proto_unregister(&ieee802154_raw_prot
);
371 module_init(af_ieee802154_init
);
372 module_exit(af_ieee802154_remove
);
374 MODULE_LICENSE("GPL");
375 MODULE_ALIAS_NETPROTO(PF_IEEE802154
);