Hi again,
This patch add the possibility to set a new IAS
object/attribute from a program in user space. This patch has been
tested and all the standard caveats of this type of procedure (moving
data user->kernel) have been taken care of.
Jean
linux/include/linux/irda.f2.h linux/include/linux/irda.h
--- linux/include/linux/irda.f2.h Thu Dec 9 13:09:00 1999
+++ linux/include/linux/irda.h Thu Dec 9 13:35:09 1999
@@ -97,6 +97,11 @@ typedef enum {
#define IAS_MAX_CLASSNAME 64
#define IAS_MAX_ATTRIBNAME 256
+#define IAS_MISSING 0
+#define IAS_INTEGER 1
+#define IAS_OCT_SEQ 2
+#define IAS_STRING 3
+
#define LSAP_ANY 0xff
struct sockaddr_irda {
@@ -132,7 +137,7 @@ struct irda_ias_set {
struct {
unsigned char len;
unsigned char charset;
- unsigned char string[IAS_MAX_STRING];
+ unsigned char string[IAS_MAX_STRING + 1];
} irda_attrib_string;
} attribute;
};
diff -u -p linux/net/irda/af_irda.f2.c linux/net/irda/af_irda.c
--- linux/net/irda/af_irda.f2.c Thu Dec 9 13:00:32 1999
+++ linux/net/irda/af_irda.c Thu Dec 9 14:09:04 1999
@@ -1578,6 +1578,8 @@ static int irda_setsockopt(struct socket
struct sock *sk = sock->sk;
struct irda_sock *self;
int opt;
+ struct irda_ias_set ias_opt;
+ struct ias_object * ias_obj;
self = sk->protinfo.irda;
ASSERT(self != NULL, return -1;);
@@ -1585,17 +1587,74 @@ static int irda_setsockopt(struct socket
if (level != SOL_IRLMP)
return -ENOPROTOOPT;
- if (optlen < sizeof(int))
- return -EINVAL;
-
- if (get_user(opt, (int *)optval))
- return -EFAULT;
-
switch (optname) {
case IRLMP_IAS_SET:
+ if (optlen != sizeof(struct irda_ias_set))
+ return -EINVAL;
+
+ /* Copy query to the driver. */
+ if (copy_from_user(&ias_opt, (char *)optval, optlen))
+ return -EFAULT;
+
+ /* Find the object we target */
+ ias_obj = irias_find_object(ias_opt.irda_class_name);
+ if(ias_obj == (struct ias_object *) NULL) {
+ /* Create a new object */
+ ias_obj = irias_new_object(ias_opt.irda_class_name,
+ jiffies);
+ }
+
+ /* Do we have it already ? */
+ if(irias_find_attrib(ias_obj, ias_opt.irda_attrib_name))
+ return -EINVAL;
+
+ /* Look at the type */
+ switch(ias_opt.irda_attrib_type) {
+ case IAS_INTEGER:
+ /* Add an integer attribute */
+ irias_add_integer_attrib(ias_obj,
+ ias_opt.irda_attrib_name,
+ ias_opt.attribute.irda_attrib_int);
+ break;
+ case IAS_OCT_SEQ:
+ /* Check length */
+ if(ias_opt.attribute.irda_attrib_octet_seq.len >
+ IAS_MAX_OCTET_STRING)
+ return -EINVAL;
+ /* Add an octet sequence attribute */
+ irias_add_octseq_attrib(ias_obj,
+ ias_opt.irda_attrib_name,
+ ias_opt.attribute.irda_attrib_octet_seq.OctetSeq,
+ ias_opt.attribute.irda_attrib_octet_seq.len);
+ break;
+ case IAS_STRING:
+ /* Should check charset & co */
+ /* Check length */
+ if(ias_opt.attribute.irda_attrib_string.len >
+ IAS_MAX_STRING)
+ return -EINVAL;
+ /* NULL terminate the string (avoid troubles) */
+
+ias_opt.attribute.irda_attrib_string.string[ias_opt.attribute.irda_attrib_string.len]
+= '\0';
+ /* Add a string attribute */
+ irias_add_string_attrib(ias_obj,
+ ias_opt.irda_attrib_name,
+ ias_opt.attribute.irda_attrib_string.string);
+ break;
+ default :
+ return -EINVAL;
+ }
+ irias_insert_object(ias_obj);
+ break;
+
IRDA_DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n");
return -ENOPROTOOPT;
case IRTTP_MAX_SDU_SIZE:
+ if (optlen < sizeof(int))
+ return -EINVAL;
+
+ if (get_user(opt, (int *)optval))
+ return -EFAULT;
+
/* Only possible for a seqpacket service (TTP with SAR) */
if (sk->type != SOCK_SEQPACKET) {
IRDA_DEBUG(2, __FUNCTION__
@@ -1609,6 +1668,12 @@ static int irda_setsockopt(struct socket
}
break;
case IRLMP_HINTS_SET:
+ if (optlen < sizeof(int))
+ return -EINVAL;
+
+ if (get_user(opt, (int *)optval))
+ return -EFAULT;
+
/* Unregister any old registration */
if (self->skey)
irlmp_unregister_service(self->skey);
@@ -1721,6 +1786,10 @@ static int irda_getsockopt(struct socket
if (copy_to_user(optval, &val, len))
return -EFAULT;
break;
+ /*
+ if (copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv)))
+ ret = -EFAULT;
+ */
default:
return -ENOPROTOOPT;
}