18e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   BNEP implementation for Linux Bluetooth stack (BlueZ).
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Copyright (C) 2001-2002 Inventel Systemes
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Written 2001-2002 by
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	David Libault  <david.libault@inventel.fr>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   This program is free software; you can redistribute it and/or modify
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   it under the terms of the GNU General Public License version 2 as
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   published by the Free Software Foundation;
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
178e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
188e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
198e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
228e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
238e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   SOFTWARE IS DISCLAIMED.
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
278c520a59927a5600973782505dbb750d985057c4Gustavo Padovan#include <linux/export.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/file.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "bnep.h"
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3277cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATOstatic struct bt_sock_list bnep_sk_list = {
3377cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	.lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock)
3477cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO};
3577cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnep_sock_release(struct socket *sock)
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sock *sk = sock->sk;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BT_DBG("sock %p sk %p", sock, sk);
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!sk)
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4577cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	bt_sock_unlink(&bnep_sk_list, sk);
4677cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sock_orphan(sk);
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sock_put(sk);
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnep_connlist_req cl;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnep_connadd_req  ca;
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnep_conndel_req  cd;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnep_conninfo ci;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct socket *nsock;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __user *argp = (void __user *)arg;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BT_DBG("cmd %x arg %lx", cmd, arg);
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cmd) {
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case BNEPCONNADD:
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_NET_ADMIN))
67bf5b30b8a4416de04f1ac1196281ddb318669464Zhao Hongjiang			return -EPERM;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_from_user(&ca, argp, sizeof(ca)))
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
718e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nsock = sockfd_lookup(ca.sock, &err);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!nsock)
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return err;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (nsock->sk->sk_state != BT_CONNECTED) {
7767b23219ce2f78352b0c566a472ff16c1b0fea9aJulia Lawall			sockfd_put(nsock);
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EBADFD;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8043629f8f5ea32a998d06d1bb41eefa0e821ff573Vasiliy Kulikov		ca.device[sizeof(ca.device)-1] = 0;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = bnep_add_connection(&ca, nsock);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!err) {
848e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki			if (copy_to_user(argp, &ca, sizeof(ca)))
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				err = -EFAULT;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
8767b23219ce2f78352b0c566a472ff16c1b0fea9aJulia Lawall			sockfd_put(nsock);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
908e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case BNEPCONNDEL:
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!capable(CAP_NET_ADMIN))
93bf5b30b8a4416de04f1ac1196281ddb318669464Zhao Hongjiang			return -EPERM;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_from_user(&cd, argp, sizeof(cd)))
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
978e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return bnep_del_connection(&cd);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case BNEPGETCONNLIST:
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_from_user(&cl, argp, sizeof(cl)))
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cl.cnum <= 0)
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
1068e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = bnep_get_connlist(&cl);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!err && copy_to_user(argp, &cl, sizeof(cl)))
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case BNEPGETCONNINFO:
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (copy_from_user(&ci, argp, sizeof(ci)))
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = bnep_get_conninfo(&ci);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!err && copy_to_user(argp, &ci, sizeof(ci)))
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
130e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann#ifdef CONFIG_COMPAT
131e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmannstatic int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
132e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann{
133e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	if (cmd == BNEPGETCONNLIST) {
134e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann		struct bnep_connlist_req cl;
135816a11d5ced501d368fabe09172f3d62744e8b53Johan Hedberg		u32 uci;
136e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann		int err;
137e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann
138816a11d5ced501d368fabe09172f3d62744e8b53Johan Hedberg		if (get_user(cl.cnum, (u32 __user *) arg) ||
139e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann				get_user(uci, (u32 __user *) (arg + 4)))
140e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann			return -EFAULT;
141e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann
142e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann		cl.ci = compat_ptr(uci);
143e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann
144e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann		if (cl.cnum <= 0)
145e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann			return -EINVAL;
1468e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki
147e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann		err = bnep_get_connlist(&cl);
148e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann
149816a11d5ced501d368fabe09172f3d62744e8b53Johan Hedberg		if (!err && put_user(cl.cnum, (u32 __user *) arg))
150e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann			err = -EFAULT;
151e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann
152e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann		return err;
153e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	}
154e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann
155e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	return bnep_sock_ioctl(sock, cmd, arg);
156e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann}
157e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann#endif
158e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann
15990ddc4f0470427df306f308ad03db6b6b21644b8Eric Dumazetstatic const struct proto_ops bnep_sock_ops = {
160e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.family		= PF_BLUETOOTH,
161e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.owner		= THIS_MODULE,
162e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.release	= bnep_sock_release,
163e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.ioctl		= bnep_sock_ioctl,
164e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann#ifdef CONFIG_COMPAT
165e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.compat_ioctl	= bnep_sock_compat_ioctl,
166e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann#endif
167e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.bind		= sock_no_bind,
168e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.getname	= sock_no_getname,
169e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.sendmsg	= sock_no_sendmsg,
170e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.recvmsg	= sock_no_recvmsg,
171e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.poll		= sock_no_poll,
172e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.listen		= sock_no_listen,
173e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.shutdown	= sock_no_shutdown,
174e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.setsockopt	= sock_no_setsockopt,
175e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.getsockopt	= sock_no_getsockopt,
176e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.connect	= sock_no_connect,
177e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.socketpair	= sock_no_socketpair,
178e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.accept		= sock_no_accept,
179e9c5702e3c5558dade169949abd730173e87ef9cMarcel Holtmann	.mmap		= sock_no_mmap
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct proto bnep_proto = {
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "BNEP",
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner		= THIS_MODULE,
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.obj_size	= sizeof(struct bt_sock)
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1883f378b684453f2a028eda463ce383370545d9cc9Eric Parisstatic int bnep_sock_create(struct net *net, struct socket *sock, int protocol,
1893f378b684453f2a028eda463ce383370545d9cc9Eric Paris			    int kern)
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sock *sk;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BT_DBG("sock %p", sock);
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sock->type != SOCK_RAW)
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ESOCKTNOSUPPORT;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1986257ff2177ff02d7f260a7a501876aa41cb9a9f6Pavel Emelyanov	sk = sk_alloc(net, PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!sk)
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sock_init_data(sock, sk);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sock->ops = &bnep_sock_ops;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sock->state = SS_UNCONNECTED;
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sock_reset_flag(sk, SOCK_ZAPPED);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sk->sk_protocol = protocol;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sk->sk_state	= BT_OPEN;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21377cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	bt_sock_link(&bnep_sk_list, sk);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
217ec1b4cf74c81bfd0fbe5bf62bafc86c45917e72fStephen Hemmingerstatic const struct net_proto_family bnep_sock_family_ops = {
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.family = PF_BLUETOOTH,
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner	= THIS_MODULE,
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.create = bnep_sock_create
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init bnep_sock_init(void)
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = proto_register(&bnep_proto, 0);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err < 0)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
23277cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	if (err < 0) {
23377cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO		BT_ERR("Can't register BNEP socket");
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto error;
23577cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	}
23677cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO
237b03166152f6da91cec8b66837b309dd3923ea536Al Viro	err = bt_procfs_init(&init_net, "bnep", &bnep_sk_list, NULL);
23877cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	if (err < 0) {
23977cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO		BT_ERR("Failed to create BNEP proc file");
24077cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO		bt_sock_unregister(BTPROTO_BNEP);
24177cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO		goto error;
24277cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	}
24377cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO
24477cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	BT_INFO("BNEP socket layer initialized");
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror:
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	proto_unregister(&bnep_proto);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
253a4e2acf01a7e5fcd960fc332335ca10313641f4bTobias Klauservoid __exit bnep_sock_cleanup(void)
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25577cf5585a31fdad48c16ddae9be154f5afe22c1cMasatake YAMATO	bt_procfs_cleanup(&init_net, "bnep");
2565e9d7f868f04106139a58212b860dcdc268ad3afDavid Herrmann	bt_sock_unregister(BTPROTO_BNEP);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	proto_unregister(&bnep_proto);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
259