vserver 1.9.5.x5
[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 static 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         /* Remove from list */
163         node = hashbin_remove_this(irias_objects, (irda_queue_t *) obj);
164         if (!node)
165                 IRDA_DEBUG( 0, "%s(), object already removed!\n",
166                             __FUNCTION__);
167
168         /* Destroy */
169         __irias_delete_object(obj);
170
171         return 0;
172 }
173 EXPORT_SYMBOL(irias_delete_object);
174
175 /*
176  * Function irias_delete_attrib (obj)
177  *
178  *    Remove attribute from hashbin and, if it was the last attribute of
179  *    the object, remove the object as well.
180  *
181  */
182 int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib,
183                         int cleanobject)
184 {
185         struct ias_attrib *node;
186
187         ASSERT(obj != NULL, return -1;);
188         ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
189         ASSERT(attrib != NULL, return -1;);
190
191         /* Remove attribute from object */
192         node = hashbin_remove_this(obj->attribs, (irda_queue_t *) attrib);
193         if (!node)
194                 return 0; /* Already removed or non-existent */
195
196         /* Deallocate attribute */
197         __irias_delete_attrib(node);
198
199         /* Check if object has still some attributes, destroy it if none.
200          * At first glance, this look dangerous, as the kernel reference
201          * various IAS objects. However, we only use this function on
202          * user attributes, not kernel attributes, so there is no risk
203          * of deleting a kernel object this way. Jean II */
204         node = (struct ias_attrib *) hashbin_get_first(obj->attribs);
205         if (cleanobject && !node)
206                 irias_delete_object(obj);
207
208         return 0;
209 }
210
211 /*
212  * Function irias_insert_object (obj)
213  *
214  *    Insert an object into the LM-IAS database
215  *
216  */
217 void irias_insert_object(struct ias_object *obj)
218 {
219         ASSERT(obj != NULL, return;);
220         ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
221
222         hashbin_insert(irias_objects, (irda_queue_t *) obj, 0, obj->name);
223 }
224 EXPORT_SYMBOL(irias_insert_object);
225
226 /*
227  * Function irias_find_object (name)
228  *
229  *    Find object with given name
230  *
231  */
232 struct ias_object *irias_find_object(char *name)
233 {
234         ASSERT(name != NULL, return NULL;);
235
236         /* Unsafe (locking), object might change */
237         return hashbin_lock_find(irias_objects, 0, name);
238 }
239 EXPORT_SYMBOL(irias_find_object);
240
241 /*
242  * Function irias_find_attrib (obj, name)
243  *
244  *    Find named attribute in object
245  *
246  */
247 struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name)
248 {
249         struct ias_attrib *attrib;
250
251         ASSERT(obj != NULL, return NULL;);
252         ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;);
253         ASSERT(name != NULL, return NULL;);
254
255         attrib = hashbin_lock_find(obj->attribs, 0, name);
256         if (attrib == NULL)
257                 return NULL;
258
259         /* Unsafe (locking), attrib might change */
260         return attrib;
261 }
262 EXPORT_SYMBOL(irias_find_attrib);
263
264 /*
265  * Function irias_add_attribute (obj, attrib)
266  *
267  *    Add attribute to object
268  *
269  */
270 static void irias_add_attrib(struct ias_object *obj, struct ias_attrib *attrib,
271                              int owner)
272 {
273         ASSERT(obj != NULL, return;);
274         ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
275
276         ASSERT(attrib != NULL, return;);
277         ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
278
279         /* Set if attrib is owned by kernel or user space */
280         attrib->value->owner = owner;
281
282         hashbin_insert(obj->attribs, (irda_queue_t *) attrib, 0, attrib->name);
283 }
284
285 /*
286  * Function irias_object_change_attribute (obj_name, attrib_name, new_value)
287  *
288  *    Change the value of an objects attribute.
289  *
290  */
291 int irias_object_change_attribute(char *obj_name, char *attrib_name,
292                                   struct ias_value *new_value)
293 {
294         struct ias_object *obj;
295         struct ias_attrib *attrib;
296         unsigned long flags;
297
298         /* Find object */
299         obj = hashbin_lock_find(irias_objects, 0, obj_name);
300         if (obj == NULL) {
301                 WARNING("%s: Unable to find object: %s\n", __FUNCTION__,
302                         obj_name);
303                 return -1;
304         }
305
306         /* Slightly unsafe (obj might get removed under us) */
307         spin_lock_irqsave(&obj->attribs->hb_spinlock, flags);
308
309         /* Find attribute */
310         attrib = hashbin_find(obj->attribs, 0, attrib_name);
311         if (attrib == NULL) {
312                 WARNING("%s: Unable to find attribute: %s\n", __FUNCTION__,
313                         attrib_name);
314                 spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
315                 return -1;
316         }
317
318         if ( attrib->value->type != new_value->type) {
319                 IRDA_DEBUG( 0, "%s(), changing value type not allowed!\n",
320                             __FUNCTION__);
321                 spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
322                 return -1;
323         }
324
325         /* Delete old value */
326         irias_delete_value(attrib->value);
327
328         /* Insert new value */
329         attrib->value = new_value;
330
331         /* Success */
332         spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
333         return 0;
334 }
335 EXPORT_SYMBOL(irias_object_change_attribute);
336
337 /*
338  * Function irias_object_add_integer_attrib (obj, name, value)
339  *
340  *    Add an integer attribute to an LM-IAS object
341  *
342  */
343 void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
344                               int owner)
345 {
346         struct ias_attrib *attrib;
347
348         ASSERT(obj != NULL, return;);
349         ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
350         ASSERT(name != NULL, return;);
351
352         attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib),
353                                                GFP_ATOMIC);
354         if (attrib == NULL) {
355                 WARNING("%s: Unable to allocate attribute!\n", __FUNCTION__);
356                 return;
357         }
358         memset(attrib, 0, sizeof( struct ias_attrib));
359
360         attrib->magic = IAS_ATTRIB_MAGIC;
361         attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
362
363         /* Insert value */
364         attrib->value = irias_new_integer_value(value);
365
366         irias_add_attrib(obj, attrib, owner);
367 }
368 EXPORT_SYMBOL(irias_add_integer_attrib);
369
370  /*
371  * Function irias_add_octseq_attrib (obj, name, octet_seq, len)
372  *
373  *    Add a octet sequence attribute to an LM-IAS object
374  *
375  */
376
377 void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
378                              int len, int owner)
379 {
380         struct ias_attrib *attrib;
381
382         ASSERT(obj != NULL, return;);
383         ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
384
385         ASSERT(name != NULL, return;);
386         ASSERT(octets != NULL, return;);
387
388         attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib),
389                                                GFP_ATOMIC);
390         if (attrib == NULL) {
391                 WARNING("%s: Unable to allocate attribute!\n", __FUNCTION__);
392                 return;
393         }
394         memset(attrib, 0, sizeof( struct ias_attrib));
395
396         attrib->magic = IAS_ATTRIB_MAGIC;
397         attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
398
399         attrib->value = irias_new_octseq_value( octets, len);
400
401         irias_add_attrib(obj, attrib, owner);
402 }
403 EXPORT_SYMBOL(irias_add_octseq_attrib);
404
405 /*
406  * Function irias_object_add_string_attrib (obj, string)
407  *
408  *    Add a string attribute to an LM-IAS object
409  *
410  */
411 void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
412                              int owner)
413 {
414         struct ias_attrib *attrib;
415
416         ASSERT(obj != NULL, return;);
417         ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
418
419         ASSERT(name != NULL, return;);
420         ASSERT(value != NULL, return;);
421
422         attrib = (struct ias_attrib *) kmalloc(sizeof( struct ias_attrib),
423                                                GFP_ATOMIC);
424         if (attrib == NULL) {
425                 WARNING("%s: Unable to allocate attribute!\n", __FUNCTION__);
426                 return;
427         }
428         memset(attrib, 0, sizeof( struct ias_attrib));
429
430         attrib->magic = IAS_ATTRIB_MAGIC;
431         attrib->name = strndup(name, IAS_MAX_ATTRIBNAME);
432
433         attrib->value = irias_new_string_value(value);
434
435         irias_add_attrib(obj, attrib, owner);
436 }
437 EXPORT_SYMBOL(irias_add_string_attrib);
438
439 /*
440  * Function irias_new_integer_value (integer)
441  *
442  *    Create new IAS integer value
443  *
444  */
445 struct ias_value *irias_new_integer_value(int integer)
446 {
447         struct ias_value *value;
448
449         value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
450         if (value == NULL) {
451                 WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
452                 return NULL;
453         }
454         memset(value, 0, sizeof(struct ias_value));
455
456         value->type = IAS_INTEGER;
457         value->len = 4;
458         value->t.integer = integer;
459
460         return value;
461 }
462 EXPORT_SYMBOL(irias_new_integer_value);
463
464 /*
465  * Function irias_new_string_value (string)
466  *
467  *    Create new IAS string value
468  *
469  * Per IrLMP 1.1, 4.3.3.2, strings are up to 256 chars - Jean II
470  */
471 struct ias_value *irias_new_string_value(char *string)
472 {
473         struct ias_value *value;
474
475         value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
476         if (value == NULL) {
477                 WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
478                 return NULL;
479         }
480         memset( value, 0, sizeof( struct ias_value));
481
482         value->type = IAS_STRING;
483         value->charset = CS_ASCII;
484         value->t.string = strndup(string, IAS_MAX_STRING);
485         value->len = strlen(value->t.string);
486
487         return value;
488 }
489 EXPORT_SYMBOL(irias_new_string_value);
490
491 /*
492  * Function irias_new_octseq_value (octets, len)
493  *
494  *    Create new IAS octet-sequence value
495  *
496  * Per IrLMP 1.1, 4.3.3.2, octet-sequence are up to 1024 bytes - Jean II
497  */
498 struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
499 {
500         struct ias_value *value;
501
502         value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
503         if (value == NULL) {
504                 WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
505                 return NULL;
506         }
507         memset(value, 0, sizeof(struct ias_value));
508
509         value->type = IAS_OCT_SEQ;
510         /* Check length */
511         if(len > IAS_MAX_OCTET_STRING)
512                 len = IAS_MAX_OCTET_STRING;
513         value->len = len;
514
515         value->t.oct_seq = kmalloc(len, GFP_ATOMIC);
516         if (value->t.oct_seq == NULL){
517                 WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
518                 kfree(value);
519                 return NULL;
520         }
521         memcpy(value->t.oct_seq, octseq , len);
522         return value;
523 }
524 EXPORT_SYMBOL(irias_new_octseq_value);
525
526 struct ias_value *irias_new_missing_value(void)
527 {
528         struct ias_value *value;
529
530         value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
531         if (value == NULL) {
532                 WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
533                 return NULL;
534         }
535         memset(value, 0, sizeof(struct ias_value));
536
537         value->type = IAS_MISSING;
538         value->len = 0;
539
540         return value;
541 }
542
543 /*
544  * Function irias_delete_value (value)
545  *
546  *    Delete IAS value
547  *
548  */
549 void irias_delete_value(struct ias_value *value)
550 {
551         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
552
553         ASSERT(value != NULL, return;);
554
555         switch (value->type) {
556         case IAS_INTEGER: /* Fallthrough */
557         case IAS_MISSING:
558                 /* No need to deallocate */
559                 break;
560         case IAS_STRING:
561                 /* If string, deallocate string */
562                 if (value->t.string != NULL)
563                         kfree(value->t.string);
564                 break;
565         case IAS_OCT_SEQ:
566                 /* If byte stream, deallocate byte stream */
567                  if (value->t.oct_seq != NULL)
568                          kfree(value->t.oct_seq);
569                  break;
570         default:
571                 IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
572                 break;
573         }
574         kfree(value);
575 }
576 EXPORT_SYMBOL(irias_delete_value);