linux/net/irda/irias_object.c
<<
>>
Prefs
   1/*********************************************************************
   2 *
   3 * Filename:      irias_object.c
   4 * Version:       0.3
   5 * Description:   IAS object database and functions
   6 * Status:        Experimental.
   7 * Author:        Dag Brattli <dagb@cs.uit.no>
   8 * Created at:    Thu Oct  1 22:50:04 1998
   9 * Modified at:   Wed Dec 15 11:23:16 1999
  10 * Modified by:   Dag Brattli <dagb@cs.uit.no>
  11 *
  12 *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  13 *
  14 *     This program is free software; you can redistribute it and/or
  15 *     modify it under the terms of the GNU General Public License as
  16 *     published by the Free Software Foundation; either version 2 of
  17 *     the License, or (at your option) any later version.
  18 *
  19 *     Neither Dag Brattli nor University of Tromsø admit liability nor
  20 *     provide warranty for any of this software. This material is
  21 *     provided "AS-IS" and at no charge.
  22 *
  23 ********************************************************************/
  24
  25#include <linux/slab.h>
  26#include <linux/string.h>
  27#include <linux/socket.h>
  28#include <linux/module.h>
  29
  30#include <net/irda/irda.h>
  31#include <net/irda/irias_object.h>
  32
  33hashbin_t *irias_objects;
  34
  35/*
  36 *  Used when a missing value needs to be returned
  37 */
  38struct ias_value irias_missing = { IAS_MISSING, 0, 0, 0, {0}};
  39
  40
  41/*
  42 * Function ias_new_object (name, id)
  43 *
  44 *    Create a new IAS object
  45 *
  46 */
  47struct ias_object *irias_new_object( char *name, int id)
  48{
  49        struct ias_object *obj;
  50
  51        obj = kzalloc(sizeof(struct ias_object), GFP_ATOMIC);
  52        if (obj == NULL) {
  53                net_warn_ratelimited("%s(), Unable to allocate object!\n",
  54                                     __func__);
  55                return NULL;
  56        }
  57
  58        obj->magic = IAS_OBJECT_MAGIC;
  59        obj->name = kstrndup(name, IAS_MAX_CLASSNAME, GFP_ATOMIC);
  60        if (!obj->name) {
  61                net_warn_ratelimited("%s(), Unable to allocate name!\n",
  62                                     __func__);
  63                kfree(obj);
  64                return NULL;
  65        }
  66        obj->id = id;
  67
  68        /* Locking notes : the attrib spinlock has lower precendence
  69         * than the objects spinlock. Never grap the objects spinlock
  70         * while holding any attrib spinlock (risk of deadlock). Jean II */
  71        obj->attribs = hashbin_new(HB_LOCK);
  72
  73        if (obj->attribs == NULL) {
  74                net_warn_ratelimited("%s(), Unable to allocate attribs!\n",
  75                                     __func__);
  76                kfree(obj->name);
  77                kfree(obj);
  78                return NULL;
  79        }
  80
  81        return obj;
  82}
  83EXPORT_SYMBOL(irias_new_object);
  84
  85/*
  86 * Function irias_delete_attrib (attrib)
  87 *
  88 *    Delete given attribute and deallocate all its memory
  89 *
  90 */
  91static void __irias_delete_attrib(struct ias_attrib *attrib)
  92{
  93        IRDA_ASSERT(attrib != NULL, return;);
  94        IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
  95
  96        kfree(attrib->name);
  97
  98        irias_delete_value(attrib->value);
  99        attrib->magic = ~IAS_ATTRIB_MAGIC;
 100
 101        kfree(attrib);
 102}
 103
 104void __irias_delete_object(struct ias_object *obj)
 105{
 106        IRDA_ASSERT(obj != NULL, return;);
 107        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 108
 109        kfree(obj->name);
 110
 111        hashbin_delete(obj->attribs, (FREE_FUNC) __irias_delete_attrib);
 112
 113        obj->magic = ~IAS_OBJECT_MAGIC;
 114
 115        kfree(obj);
 116}
 117
 118/*
 119 * Function irias_delete_object (obj)
 120 *
 121 *    Remove object from hashbin and deallocate all attributes associated with
 122 *    with this object and the object itself
 123 *
 124 */
 125int irias_delete_object(struct ias_object *obj)
 126{
 127        struct ias_object *node;
 128
 129        IRDA_ASSERT(obj != NULL, return -1;);
 130        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
 131
 132        /* Remove from list */
 133        node = hashbin_remove_this(irias_objects, (irda_queue_t *) obj);
 134        if (!node)
 135                pr_debug("%s(), object already removed!\n",
 136                         __func__);
 137
 138        /* Destroy */
 139        __irias_delete_object(obj);
 140
 141        return 0;
 142}
 143EXPORT_SYMBOL(irias_delete_object);
 144
 145/*
 146 * Function irias_delete_attrib (obj)
 147 *
 148 *    Remove attribute from hashbin and, if it was the last attribute of
 149 *    the object, remove the object as well.
 150 *
 151 */
 152int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib,
 153                        int cleanobject)
 154{
 155        struct ias_attrib *node;
 156
 157        IRDA_ASSERT(obj != NULL, return -1;);
 158        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
 159        IRDA_ASSERT(attrib != NULL, return -1;);
 160
 161        /* Remove attribute from object */
 162        node = hashbin_remove_this(obj->attribs, (irda_queue_t *) attrib);
 163        if (!node)
 164                return 0; /* Already removed or non-existent */
 165
 166        /* Deallocate attribute */
 167        __irias_delete_attrib(node);
 168
 169        /* Check if object has still some attributes, destroy it if none.
 170         * At first glance, this look dangerous, as the kernel reference
 171         * various IAS objects. However, we only use this function on
 172         * user attributes, not kernel attributes, so there is no risk
 173         * of deleting a kernel object this way. Jean II */
 174        node = (struct ias_attrib *) hashbin_get_first(obj->attribs);
 175        if (cleanobject && !node)
 176                irias_delete_object(obj);
 177
 178        return 0;
 179}
 180
 181/*
 182 * Function irias_insert_object (obj)
 183 *
 184 *    Insert an object into the LM-IAS database
 185 *
 186 */
 187void irias_insert_object(struct ias_object *obj)
 188{
 189        IRDA_ASSERT(obj != NULL, return;);
 190        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 191
 192        hashbin_insert(irias_objects, (irda_queue_t *) obj, 0, obj->name);
 193}
 194EXPORT_SYMBOL(irias_insert_object);
 195
 196/*
 197 * Function irias_find_object (name)
 198 *
 199 *    Find object with given name
 200 *
 201 */
 202struct ias_object *irias_find_object(char *name)
 203{
 204        IRDA_ASSERT(name != NULL, return NULL;);
 205
 206        /* Unsafe (locking), object might change */
 207        return hashbin_lock_find(irias_objects, 0, name);
 208}
 209EXPORT_SYMBOL(irias_find_object);
 210
 211/*
 212 * Function irias_find_attrib (obj, name)
 213 *
 214 *    Find named attribute in object
 215 *
 216 */
 217struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name)
 218{
 219        struct ias_attrib *attrib;
 220
 221        IRDA_ASSERT(obj != NULL, return NULL;);
 222        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;);
 223        IRDA_ASSERT(name != NULL, return NULL;);
 224
 225        attrib = hashbin_lock_find(obj->attribs, 0, name);
 226        if (attrib == NULL)
 227                return NULL;
 228
 229        /* Unsafe (locking), attrib might change */
 230        return attrib;
 231}
 232
 233/*
 234 * Function irias_add_attribute (obj, attrib)
 235 *
 236 *    Add attribute to object
 237 *
 238 */
 239static void irias_add_attrib(struct ias_object *obj, struct ias_attrib *attrib,
 240                             int owner)
 241{
 242        IRDA_ASSERT(obj != NULL, return;);
 243        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 244
 245        IRDA_ASSERT(attrib != NULL, return;);
 246        IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
 247
 248        /* Set if attrib is owned by kernel or user space */
 249        attrib->value->owner = owner;
 250
 251        hashbin_insert(obj->attribs, (irda_queue_t *) attrib, 0, attrib->name);
 252}
 253
 254/*
 255 * Function irias_object_change_attribute (obj_name, attrib_name, new_value)
 256 *
 257 *    Change the value of an objects attribute.
 258 *
 259 */
 260int irias_object_change_attribute(char *obj_name, char *attrib_name,
 261                                  struct ias_value *new_value)
 262{
 263        struct ias_object *obj;
 264        struct ias_attrib *attrib;
 265        unsigned long flags;
 266
 267        /* Find object */
 268        obj = hashbin_lock_find(irias_objects, 0, obj_name);
 269        if (obj == NULL) {
 270                net_warn_ratelimited("%s: Unable to find object: %s\n",
 271                                     __func__, obj_name);
 272                return -1;
 273        }
 274
 275        /* Slightly unsafe (obj might get removed under us) */
 276        spin_lock_irqsave(&obj->attribs->hb_spinlock, flags);
 277
 278        /* Find attribute */
 279        attrib = hashbin_find(obj->attribs, 0, attrib_name);
 280        if (attrib == NULL) {
 281                net_warn_ratelimited("%s: Unable to find attribute: %s\n",
 282                                     __func__, attrib_name);
 283                spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
 284                return -1;
 285        }
 286
 287        if ( attrib->value->type != new_value->type) {
 288                pr_debug("%s(), changing value type not allowed!\n",
 289                         __func__);
 290                spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
 291                return -1;
 292        }
 293
 294        /* Delete old value */
 295        irias_delete_value(attrib->value);
 296
 297        /* Insert new value */
 298        attrib->value = new_value;
 299
 300        /* Success */
 301        spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
 302        return 0;
 303}
 304EXPORT_SYMBOL(irias_object_change_attribute);
 305
 306/*
 307 * Function irias_object_add_integer_attrib (obj, name, value)
 308 *
 309 *    Add an integer attribute to an LM-IAS object
 310 *
 311 */
 312void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
 313                              int owner)
 314{
 315        struct ias_attrib *attrib;
 316
 317        IRDA_ASSERT(obj != NULL, return;);
 318        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 319        IRDA_ASSERT(name != NULL, return;);
 320
 321        attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
 322        if (attrib == NULL) {
 323                net_warn_ratelimited("%s: Unable to allocate attribute!\n",
 324                                     __func__);
 325                return;
 326        }
 327
 328        attrib->magic = IAS_ATTRIB_MAGIC;
 329        attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
 330
 331        /* Insert value */
 332        attrib->value = irias_new_integer_value(value);
 333        if (!attrib->name || !attrib->value) {
 334                net_warn_ratelimited("%s: Unable to allocate attribute!\n",
 335                                     __func__);
 336                if (attrib->value)
 337                        irias_delete_value(attrib->value);
 338                kfree(attrib->name);
 339                kfree(attrib);
 340                return;
 341        }
 342
 343        irias_add_attrib(obj, attrib, owner);
 344}
 345EXPORT_SYMBOL(irias_add_integer_attrib);
 346
 347 /*
 348 * Function irias_add_octseq_attrib (obj, name, octet_seq, len)
 349 *
 350 *    Add a octet sequence attribute to an LM-IAS object
 351 *
 352 */
 353
 354void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
 355                             int len, int owner)
 356{
 357        struct ias_attrib *attrib;
 358
 359        IRDA_ASSERT(obj != NULL, return;);
 360        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 361
 362        IRDA_ASSERT(name != NULL, return;);
 363        IRDA_ASSERT(octets != NULL, return;);
 364
 365        attrib = kzalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
 366        if (attrib == NULL) {
 367                net_warn_ratelimited("%s: Unable to allocate attribute!\n",
 368                                     __func__);
 369                return;
 370        }
 371
 372        attrib->magic = IAS_ATTRIB_MAGIC;
 373        attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
 374
 375        attrib->value = irias_new_octseq_value( octets, len);
 376        if (!attrib->name || !attrib->value) {
 377                net_warn_ratelimited("%s: Unable to allocate attribute!\n",
 378                                     __func__);
 379                if (attrib->value)
 380                        irias_delete_value(attrib->value);
 381                kfree(attrib->name);
 382                kfree(attrib);
 383                return;
 384        }
 385
 386        irias_add_attrib(obj, attrib, owner);
 387}
 388EXPORT_SYMBOL(irias_add_octseq_attrib);
 389
 390/*
 391 * Function irias_object_add_string_attrib (obj, string)
 392 *
 393 *    Add a string attribute to an LM-IAS object
 394 *
 395 */
 396void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
 397                             int owner)
 398{
 399        struct ias_attrib *attrib;
 400
 401        IRDA_ASSERT(obj != NULL, return;);
 402        IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 403
 404        IRDA_ASSERT(name != NULL, return;);
 405        IRDA_ASSERT(value != NULL, return;);
 406
 407        attrib = kzalloc(sizeof( struct ias_attrib), GFP_ATOMIC);
 408        if (attrib == NULL) {
 409                net_warn_ratelimited("%s: Unable to allocate attribute!\n",
 410                                     __func__);
 411                return;
 412        }
 413
 414        attrib->magic = IAS_ATTRIB_MAGIC;
 415        attrib->name = kstrndup(name, IAS_MAX_ATTRIBNAME, GFP_ATOMIC);
 416
 417        attrib->value = irias_new_string_value(value);
 418        if (!attrib->name || !attrib->value) {
 419                net_warn_ratelimited("%s: Unable to allocate attribute!\n",
 420                                     __func__);
 421                if (attrib->value)
 422                        irias_delete_value(attrib->value);
 423                kfree(attrib->name);
 424                kfree(attrib);
 425                return;
 426        }
 427
 428        irias_add_attrib(obj, attrib, owner);
 429}
 430EXPORT_SYMBOL(irias_add_string_attrib);
 431
 432/*
 433 * Function irias_new_integer_value (integer)
 434 *
 435 *    Create new IAS integer value
 436 *
 437 */
 438struct ias_value *irias_new_integer_value(int integer)
 439{
 440        struct ias_value *value;
 441
 442        value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
 443        if (value == NULL)
 444                return NULL;
 445
 446        value->type = IAS_INTEGER;
 447        value->len = 4;
 448        value->t.integer = integer;
 449
 450        return value;
 451}
 452EXPORT_SYMBOL(irias_new_integer_value);
 453
 454/*
 455 * Function irias_new_string_value (string)
 456 *
 457 *    Create new IAS string value
 458 *
 459 * Per IrLMP 1.1, 4.3.3.2, strings are up to 256 chars - Jean II
 460 */
 461struct ias_value *irias_new_string_value(char *string)
 462{
 463        struct ias_value *value;
 464
 465        value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
 466        if (value == NULL)
 467                return NULL;
 468
 469        value->type = IAS_STRING;
 470        value->charset = CS_ASCII;
 471        value->t.string = kstrndup(string, IAS_MAX_STRING, GFP_ATOMIC);
 472        if (!value->t.string) {
 473                net_warn_ratelimited("%s: Unable to kmalloc!\n", __func__);
 474                kfree(value);
 475                return NULL;
 476        }
 477
 478        value->len = strlen(value->t.string);
 479
 480        return value;
 481}
 482
 483/*
 484 * Function irias_new_octseq_value (octets, len)
 485 *
 486 *    Create new IAS octet-sequence value
 487 *
 488 * Per IrLMP 1.1, 4.3.3.2, octet-sequence are up to 1024 bytes - Jean II
 489 */
 490struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
 491{
 492        struct ias_value *value;
 493
 494        value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
 495        if (value == NULL)
 496                return NULL;
 497
 498        value->type = IAS_OCT_SEQ;
 499        /* Check length */
 500        if(len > IAS_MAX_OCTET_STRING)
 501                len = IAS_MAX_OCTET_STRING;
 502        value->len = len;
 503
 504        value->t.oct_seq = kmemdup(octseq, len, GFP_ATOMIC);
 505        if (value->t.oct_seq == NULL){
 506                net_warn_ratelimited("%s: Unable to kmalloc!\n", __func__);
 507                kfree(value);
 508                return NULL;
 509        }
 510        return value;
 511}
 512
 513struct ias_value *irias_new_missing_value(void)
 514{
 515        struct ias_value *value;
 516
 517        value = kzalloc(sizeof(struct ias_value), GFP_ATOMIC);
 518        if (value == NULL)
 519                return NULL;
 520
 521        value->type = IAS_MISSING;
 522
 523        return value;
 524}
 525
 526/*
 527 * Function irias_delete_value (value)
 528 *
 529 *    Delete IAS value
 530 *
 531 */
 532void irias_delete_value(struct ias_value *value)
 533{
 534        IRDA_ASSERT(value != NULL, return;);
 535
 536        switch (value->type) {
 537        case IAS_INTEGER: /* Fallthrough */
 538        case IAS_MISSING:
 539                /* No need to deallocate */
 540                break;
 541        case IAS_STRING:
 542                /* Deallocate string */
 543                kfree(value->t.string);
 544                break;
 545        case IAS_OCT_SEQ:
 546                /* Deallocate byte stream */
 547                 kfree(value->t.oct_seq);
 548                 break;
 549        default:
 550                pr_debug("%s(), Unknown value type!\n", __func__);
 551                break;
 552        }
 553        kfree(value);
 554}
 555EXPORT_SYMBOL(irias_delete_value);
 556