********************************************************************/
#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <asm/uaccess.h>
#include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
#include <net/irda/af_irda.h>
static int irda_create(struct socket *sock, int protocol);
-static struct proto_ops irda_stream_ops;
-static struct proto_ops irda_seqpacket_ops;
-static struct proto_ops irda_dgram_ops;
+static const struct proto_ops irda_stream_ops;
+static const struct proto_ops irda_seqpacket_ops;
+static const struct proto_ops irda_dgram_ops;
#ifdef CONFIG_IRDA_ULTRA
-static struct proto_ops irda_ultra_ops;
+static const struct proto_ops irda_ultra_ops;
#define ULTRA_MAX_DATA 382
#endif /* CONFIG_IRDA_ULTRA */
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- self = (struct irda_sock *) instance;
- ASSERT(self != NULL, return -1;);
-
- sk = self->sk;
- ASSERT(sk != NULL, return -1;);
+ self = instance;
+ sk = instance;
+ IRDA_ASSERT(sk != NULL, return -1;);
err = sock_queue_rcv_skb(sk, skb);
if (err) {
struct irda_sock *self;
struct sock *sk;
- self = (struct irda_sock *) instance;
+ self = instance;
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
if(skb)
dev_kfree_skb(skb);
- sk = self->sk;
+ sk = instance;
if (sk == NULL) {
IRDA_DEBUG(0, "%s(%p) : BUG : sk is NULL\n",
__FUNCTION__, self);
struct irda_sock *self;
struct sock *sk;
- self = (struct irda_sock *) instance;
+ self = instance;
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
- sk = self->sk;
+ sk = instance;
if (sk == NULL) {
dev_kfree_skb(skb);
return;
switch (sk->sk_type) {
case SOCK_STREAM:
if (max_sdu_size != 0) {
- ERROR("%s: max_sdu_size must be 0\n", __FUNCTION__);
+ IRDA_ERROR("%s: max_sdu_size must be 0\n",
+ __FUNCTION__);
return;
}
self->max_data_size = irttp_get_max_seg_size(self->tsap);
break;
case SOCK_SEQPACKET:
if (max_sdu_size == 0) {
- ERROR("%s: max_sdu_size cannot be 0\n", __FUNCTION__);
+ IRDA_ERROR("%s: max_sdu_size cannot be 0\n",
+ __FUNCTION__);
return;
}
self->max_data_size = max_sdu_size;
struct irda_sock *self;
struct sock *sk;
- self = (struct irda_sock *) instance;
+ self = instance;
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
- sk = self->sk;
+ sk = instance;
if (sk == NULL) {
dev_kfree_skb(skb);
return;
switch (sk->sk_type) {
case SOCK_STREAM:
if (max_sdu_size != 0) {
- ERROR("%s: max_sdu_size must be 0\n", __FUNCTION__);
+ IRDA_ERROR("%s: max_sdu_size must be 0\n",
+ __FUNCTION__);
kfree_skb(skb);
return;
}
break;
case SOCK_SEQPACKET:
if (max_sdu_size == 0) {
- ERROR("%s: max_sdu_size cannot be 0\n", __FUNCTION__);
+ IRDA_ERROR("%s: max_sdu_size cannot be 0\n",
+ __FUNCTION__);
kfree_skb(skb);
return;
}
* Accept incoming connection
*
*/
-void irda_connect_response(struct irda_sock *self)
+static void irda_connect_response(struct irda_sock *self)
{
struct sk_buff *skb;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
skb = dev_alloc_skb(64);
if (skb == NULL) {
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- self = (struct irda_sock *) instance;
- ASSERT(self != NULL, return;);
-
- sk = self->sk;
- ASSERT(sk != NULL, return;);
+ self = instance;
+ sk = instance;
+ IRDA_ASSERT(sk != NULL, return;);
switch (flow) {
case FLOW_STOP:
self = (struct irda_sock *) priv;
if (!self) {
- WARNING("%s: lost myself!\n", __FUNCTION__);
+ IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);
return;
}
self = (struct irda_sock *) priv;
if (!self) {
- WARNING("%s: lost myself!\n", __FUNCTION__);
+ IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);
return;
}
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
self = (struct irda_sock *) priv;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
/* Nothing for the caller */
self->cachelog = NULL;
notify_t notify;
if (self->tsap) {
- WARNING("%s: busy!\n", __FUNCTION__);
+ IRDA_WARNING("%s: busy!\n", __FUNCTION__);
return -EBUSY;
}
notify_t notify;
if (self->lsap) {
- WARNING("%s(), busy!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), busy!\n", __FUNCTION__);
return -EBUSY;
}
{
IRDA_DEBUG(2, "%s(%p, %s)\n", __FUNCTION__, self, name);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
if (self->iriap) {
- WARNING("%s(): busy with a previous query\n", __FUNCTION__);
+ IRDA_WARNING("%s(): busy with a previous query\n",
+ __FUNCTION__);
return -EBUSY;
}
IRDA_DEBUG(2, "%s(), name=%s\n", __FUNCTION__, name);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Ask lmp for the current discovery log
* Note : we have to use irlmp_get_discoveries(), as opposed
struct irda_sock *self = irda_sk(sk);
int err;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
err = irda_create(newsock, sk->sk_protocol);
if (err)
newsk->sk_state = TCP_ESTABLISHED;
new = irda_sk(newsk);
- ASSERT(new != NULL, return -1;);
+ IRDA_ASSERT(new != NULL, return -1;);
/* Now attach up the new socket */
new->tsap = irttp_dup(self->tsap, new);
self->daddr = addr->sir_addr;
IRDA_DEBUG(1, "%s(), daddr = %08x\n", __FUNCTION__, self->daddr);
- /* Query remote LM-IAS */
- err = irda_find_lsap_sel(self, addr->sir_name);
- if (err) {
- IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
- return err;
+ /* If we don't have a valid service name, we assume the
+ * user want to connect on a specific LSAP. Prevent
+ * the use of invalid LSAPs (IrLMP 1.1 p10). Jean II */
+ if((addr->sir_name[0] != '\0') ||
+ (addr->sir_lsap_sel >= 0x70)) {
+ /* Query remote LM-IAS using service name */
+ err = irda_find_lsap_sel(self, addr->sir_name);
+ if (err) {
+ IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
+ return err;
+ }
+ } else {
+ /* Directly connect to the remote LSAP
+ * specified by the sir_lsap field.
+ * Please use with caution, in IrDA LSAPs are
+ * dynamic and there is no "well-known" LSAP. */
+ self->dtsap_sel = addr->sir_lsap_sel;
}
}
return 0;
}
+static struct proto irda_proto = {
+ .name = "IRDA",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct irda_sock),
+};
+
/*
* Function irda_create (sock, protocol)
*
}
/* Allocate networking socket */
- if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1, NULL)) == NULL)
- return -ENOMEM;
-
- /* Allocate IrDA socket */
- self = sk->sk_protinfo = kmalloc(sizeof(struct irda_sock), GFP_ATOMIC);
- if (self == NULL) {
- sk_free(sk);
+ sk = sk_alloc(PF_IRDA, GFP_ATOMIC, &irda_proto, 1);
+ if (sk == NULL)
return -ENOMEM;
- }
- memset(self, 0, sizeof(struct irda_sock));
+ self = irda_sk(sk);
IRDA_DEBUG(2, "%s() : self is %p\n", __FUNCTION__, self);
init_waitqueue_head(&self->query_wait);
/* Initialise networking socket struct */
sock_init_data(sock, sk); /* Note : set sk->sk_refcnt to 1 */
- sk_set_owner(sk, THIS_MODULE);
sk->sk_family = PF_IRDA;
sk->sk_protocol = protocol;
- /* Link networking socket and IrDA socket structs together */
- self->sk = sk;
switch (sock->type) {
case SOCK_STREAM:
self->max_sdu_size_rx = TTP_SAR_UNBOUND;
break;
default:
- ERROR("%s: protocol not supported!\n", __FUNCTION__);
+ IRDA_ERROR("%s: protocol not supported!\n",
+ __FUNCTION__);
return -ESOCKTNOSUPPORT;
}
break;
* Destroy socket
*
*/
-void irda_destroy_socket(struct irda_sock *self)
+static void irda_destroy_socket(struct irda_sock *self)
{
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
/* Unregister with IrLMP */
irlmp_unregister_client(self->ckey);
self->lsap = NULL;
}
#endif /* CONFIG_IRDA_ULTRA */
- kfree(self);
}
/*
/* Destroy IrDA socket */
irda_destroy_socket(irda_sk(sk));
- /* Prevent sock_def_destruct() to create havoc */
- sk->sk_protinfo = NULL;
sock_orphan(sk);
sock->sk = NULL;
return -ENOTCONN;
self = irda_sk(sk);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Check if IrTTP is wants us to slow down */
if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN;
- /* Check that we don't send out to big frames */
+ /* Check that we don't send out too big frames */
if (len > self->max_data_size) {
IRDA_DEBUG(2, "%s(), Chopping frame from %zd to %d bytes!\n",
__FUNCTION__, len, self->max_data_size);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err);
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
if (sock->flags & __SO_ACCEPTCON)
return(-EINVAL);
/*
* POSIX 1003.1g mandates this order.
*/
- if (sk->sk_err)
- ret = sock_error(sk);
+ ret = sock_error(sk);
+ if (ret)
+ break;
else if (sk->sk_shutdown & RCV_SHUTDOWN)
;
else if (noblock)
return -ENOTCONN;
self = irda_sk(sk);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/*
- * Check that we don't send out to big frames. This is an unreliable
+ * Check that we don't send out too big frames. This is an unreliable
* service, so we have no fragmentation and no coalescence
*/
if (len > self->max_data_size) {
}
self = irda_sk(sk);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Check if an address was specified with sendto. Jean II */
if (msg->msg_name) {
}
/*
- * Check that we don't send out to big frames. This is an unreliable
+ * Check that we don't send out too big frames. This is an unreliable
* service, so we have no fragmentation and no coalescence
*/
if (len > self->max_data_size) {
struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(1, "%s(%p)\n", __FUNCTION__, self);
return -EINVAL;
default:
IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __FUNCTION__);
- return dev_ioctl(cmd, (void __user *) arg);
+ return -ENOIOCTLCMD;
}
/*NOTREACHED*/
return 0;
}
+#ifdef CONFIG_COMPAT
+/*
+ * Function irda_ioctl (sock, cmd, arg)
+ */
+static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ /*
+ * All IRDA's ioctl are standard ones.
+ */
+ return -ENOIOCTLCMD;
+}
+#endif
+
/*
* Function irda_setsockopt (sock, level, optname, optval, optlen)
*
struct ias_attrib * ias_attr; /* Attribute in IAS object */
int opt;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
}
/* Remove the attribute (and maybe the object) */
- irias_delete_attrib(ias_obj, ias_attr);
+ irias_delete_attrib(ias_obj, ias_attr, 1);
kfree(ias_opt);
break;
case IRLMP_MAX_SDU_SIZE:
__FUNCTION__, opt);
self->max_sdu_size_rx = opt;
} else {
- WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n",
+ __FUNCTION__);
return -ENOPROTOOPT;
}
break;
/* Check that we can proceed with IAP */
if (self->iriap) {
- WARNING("%s: busy with a previous query\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: busy with a previous query\n",
+ __FUNCTION__);
kfree(ias_opt);
return -EBUSY;
}
.owner = THIS_MODULE,
};
-static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
.getname = irda_getname,
.poll = irda_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
.sendpage = sock_no_sendpage,
};
-static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
.sendpage = sock_no_sendpage,
};
-static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
};
#ifdef CONFIG_IRDA_ULTRA
-static struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
*/
int __init irsock_init(void)
{
- sock_register(&irda_family_ops);
+ int rc = proto_register(&irda_proto, 0);
- return 0;
+ if (rc == 0)
+ rc = sock_register(&irda_family_ops);
+
+ return rc;
}
/*
void __exit irsock_cleanup(void)
{
sock_unregister(PF_IRDA);
-
- return;
+ proto_unregister(&irda_proto);
}