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