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