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 33 hashbin_t *irias_objects; 34 35 /* 36 * Used when a missing value needs to be returned 37 */ 38 struct 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 */ 47 struct 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 } 83 EXPORT_SYMBOL(irias_new_object); 84 85 /* 86 * Function irias_delete_attrib (attrib) 87 * 88 * Delete given attribute and deallocate all its memory 89 * 90 */ 91 static 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 104 void __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 */ 125 int 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 } 143 EXPORT_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 */ 152 int 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 */ 187 void 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 } 194 EXPORT_SYMBOL(irias_insert_object); 195 196 /* 197 * Function irias_find_object (name) 198 * 199 * Find object with given name 200 * 201 */ 202 struct 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 } 209 EXPORT_SYMBOL(irias_find_object); 210 211 /* 212 * Function irias_find_attrib (obj, name) 213 * 214 * Find named attribute in object 215 * 216 */ 217 struct 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 */ 239 static 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 */ 260 int 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 } 304 EXPORT_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 */ 312 void 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 } 345 EXPORT_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 354 void 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 } 388 EXPORT_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 */ 396 void 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 } 430 EXPORT_SYMBOL(irias_add_string_attrib); 431 432 /* 433 * Function irias_new_integer_value (integer) 434 * 435 * Create new IAS integer value 436 * 437 */ 438 struct 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 } 452 EXPORT_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 */ 461 struct 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 */ 490 struct 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 513 struct 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 */ 532 void 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 } 555 EXPORT_SYMBOL(irias_delete_value); 556
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.