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