o af_pppox: create module infrastructure for protocol modules

With this the pppox module is protected by the networking core and
the pppox "core" protects modules for specific pppox protocols (pppoe,
for instance), while doing it removed some not needed struct sock
member initializations in pppoe_create that are done by sock_init_data.
parent 427375ed
......@@ -471,16 +471,15 @@ struct packet_type pppoed_ptype = {
/***********************************************************************
*
* Really kill the socket. (Called from sock_put if refcnt == 0.)
* Really kill the socket. (Called from pppox_sk_free if refcnt == 0.)
*
**********************************************************************/
void pppoe_sock_destruct(struct sock *sk)
static void pppoe_sk_free(struct sock *sk)
{
struct pppox_opt *po = pppox_sk(sk);
if (po)
kfree(po);
MOD_DEC_USE_COUNT;
}
......@@ -495,26 +494,16 @@ static int pppoe_create(struct socket *sock)
struct sock *sk;
struct pppox_opt *po;
MOD_INC_USE_COUNT;
sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1, NULL);
sk = pppox_sk_alloc(sock, PX_PROTO_OE, GFP_KERNEL, 1, NULL);
if (!sk)
goto decmod;
sock_init_data(sock, sk);
goto out;
sock->state = SS_UNCONNECTED;
sock->ops = &pppoe_ops;
sk->protocol = PX_PROTO_OE;
sk->family = PF_PPPOX;
sk->backlog_rcv = pppoe_rcv_core;
sk->next = NULL;
sk->pprev = NULL;
sk->state = PPPOX_NONE;
sk->type = SOCK_STREAM;
sk->destruct = pppoe_sock_destruct;
po = pppox_sk(sk) = kmalloc(sizeof(*po), GFP_KERNEL);
if (!po)
......@@ -522,10 +511,8 @@ static int pppoe_create(struct socket *sock)
memset(po, 0, sizeof(*po));
po->sk = sk;
error = 0;
sock->sk = sk;
out: return error;
frees: sk_free(sk);
decmod: MOD_DEC_USE_COUNT;
goto out;
}
......@@ -1075,16 +1062,16 @@ static struct file_operations pppoe_seq_fops = {
};
#endif /* CONFIG_PROC_FS */
/* ->release and ->ioctl are set at pppox_create */
struct proto_ops pppoe_ops = {
.family = AF_PPPOX,
.release = pppoe_release,
.bind = sock_no_bind,
.connect = pppoe_connect,
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = pppoe_getname,
.poll = datagram_poll,
.ioctl = pppoe_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
......@@ -1096,7 +1083,10 @@ struct proto_ops pppoe_ops = {
struct pppox_proto pppoe_proto = {
.create = pppoe_create,
.ioctl = pppoe_ioctl
.ioctl = pppoe_ioctl,
.release = pppoe_release,
.sk_free = pppoe_sk_free,
.owner = THIS_MODULE,
};
......
......@@ -64,9 +64,45 @@ void pppox_unbind_sock(struct sock *sk)
}
}
static int pppox_release(struct socket *sock)
{
struct sock *sk = sock->sk;
int rc = pppox_protos[sk->protocol]->release(sock);
module_put(pppox_protos[sk->protocol]->owner);
return rc;
}
static void pppox_sk_free(struct sock *sk)
{
pppox_protos[sk->protocol]->sk_free(sk);
module_put(pppox_protos[sk->protocol]->owner);
}
struct sock *pppox_sk_alloc(struct socket *sock, int protocol, int priority,
int zero_it, kmem_cache_t *slab)
{
struct sock *sk = NULL;
if (!try_module_get(pppox_protos[protocol]->owner))
goto out;
sk = sk_alloc(PF_PPPOX, priority, zero_it, slab);
if (sk) {
sock_init_data(sock, sk);
sk->family = PF_PPPOX;
sk->protocol = protocol;
sk->destruct = pppox_sk_free;
} else
module_put(pppox_protos[protocol]->owner);
out:
return sk;
}
EXPORT_SYMBOL(register_pppox_proto);
EXPORT_SYMBOL(unregister_pppox_proto);
EXPORT_SYMBOL(pppox_unbind_sock);
EXPORT_SYMBOL(pppox_sk_alloc);
static int pppox_ioctl(struct socket* sock, unsigned int cmd,
unsigned long arg)
......@@ -116,11 +152,19 @@ static int pppox_create(struct socket *sock, int protocol)
if (!pppox_protos[protocol])
goto out;
rc = -EBUSY;
if (!try_module_get(pppox_protos[protocol]->owner))
goto out;
rc = pppox_protos[protocol]->create(sock);
if (!rc)
if (!rc) {
/* We get to set the ioctl handler. */
/* And the release handler, for module refcounting */
/* For everything else, pppox is just a shell. */
sock->ops->ioctl = pppox_ioctl;
sock->ops->release = pppox_release;
} else
module_put(pppox_protos[protocol]->owner);
out:
return rc;
}
......@@ -128,6 +172,7 @@ static int pppox_create(struct socket *sock, int protocol)
static struct net_proto_family pppox_proto_family = {
.family = PF_PPPOX,
.create = pppox_create,
.owner = THIS_MODULE,
};
static int __init pppox_init(void)
......
......@@ -134,10 +134,15 @@ struct pppox_opt {
#define pppox_sk(__sk) ((struct pppox_opt *)(__sk)->protinfo)
struct module;
struct pppox_proto {
int (*create)(struct socket *sock);
int (*ioctl)(struct socket *sock, unsigned int cmd,
unsigned long arg);
int (*create)(struct socket *sock);
int (*ioctl)(struct socket *sock, unsigned int cmd,
unsigned long arg);
int (*release)(struct socket *sock);
void (*sk_free)(struct sock *sk);
struct module *owner;
};
extern int register_pppox_proto(int proto_num, struct pppox_proto *pp);
......@@ -145,6 +150,9 @@ extern void unregister_pppox_proto(int proto_num);
extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
extern int pppox_channel_ioctl(struct ppp_channel *pc, unsigned int cmd,
unsigned long arg);
extern struct sock *pppox_sk_alloc(struct socket *sock, int protocol,
int priority, int zero_it,
kmem_cache_t *slab);
/* PPPoX socket states */
enum {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment