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