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;
        }

Reply via email to