Showing error 1505

User: Jiri Slaby
Error type: Leaving function in locked state
Error type description: Some lock is not unlocked on all paths of a function, so it is leaked
File location: net/irda/iriap.c
Line in file: 993
Project: Linux Kernel
Project version: 2.6.28
Tools: Stanse (1.2)
Entered: 2012-05-21 20:30:05 UTC


Source:

   1/*********************************************************************
   2 *
   3 * Filename:      iriap.c
   4 * Version:       0.8
   5 * Description:   Information Access Protocol (IAP)
   6 * Status:        Experimental.
   7 * Author:        Dag Brattli <dagb@cs.uit.no>
   8 * Created at:    Thu Aug 21 00:02:07 1997
   9 * Modified at:   Sat Dec 25 16:42:42 1999
  10 * Modified by:   Dag Brattli <dagb@cs.uit.no>
  11 *
  12 *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
  13 *     All Rights Reserved.
  14 *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
  15 *
  16 *     This program is free software; you can redistribute it and/or
  17 *     modify it under the terms of the GNU General Public License as
  18 *     published by the Free Software Foundation; either version 2 of
  19 *     the License, or (at your option) any later version.
  20 *
  21 *     Neither Dag Brattli nor University of Troms�� admit liability nor
  22 *     provide warranty for any of this software. This material is
  23 *     provided "AS-IS" and at no charge.
  24 *
  25 ********************************************************************/
  26
  27#include <linux/module.h>
  28#include <linux/types.h>
  29#include <linux/skbuff.h>
  30#include <linux/fs.h>
  31#include <linux/string.h>
  32#include <linux/init.h>
  33#include <linux/seq_file.h>
  34
  35#include <asm/byteorder.h>
  36#include <asm/unaligned.h>
  37
  38#include <net/irda/irda.h>
  39#include <net/irda/irttp.h>
  40#include <net/irda/irlmp.h>
  41#include <net/irda/irias_object.h>
  42#include <net/irda/iriap_event.h>
  43#include <net/irda/iriap.h>
  44
  45#ifdef CONFIG_IRDA_DEBUG
  46/* FIXME: This one should go in irlmp.c */
  47static const char *ias_charset_types[] = {
  48        "CS_ASCII",
  49        "CS_ISO_8859_1",
  50        "CS_ISO_8859_2",
  51        "CS_ISO_8859_3",
  52        "CS_ISO_8859_4",
  53        "CS_ISO_8859_5",
  54        "CS_ISO_8859_6",
  55        "CS_ISO_8859_7",
  56        "CS_ISO_8859_8",
  57        "CS_ISO_8859_9",
  58        "CS_UNICODE"
  59};
  60#endif        /* CONFIG_IRDA_DEBUG */
  61
  62static hashbin_t *iriap = NULL;
  63static void *service_handle;
  64
  65static void __iriap_close(struct iriap_cb *self);
  66static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode);
  67static void iriap_disconnect_indication(void *instance, void *sap,
  68                                        LM_REASON reason, struct sk_buff *skb);
  69static void iriap_connect_indication(void *instance, void *sap,
  70                                     struct qos_info *qos, __u32 max_sdu_size,
  71                                     __u8 max_header_size,
  72                                     struct sk_buff *skb);
  73static void iriap_connect_confirm(void *instance, void *sap,
  74                                  struct qos_info *qos,
  75                                  __u32 max_sdu_size, __u8 max_header_size,
  76                                  struct sk_buff *skb);
  77static int iriap_data_indication(void *instance, void *sap,
  78                                 struct sk_buff *skb);
  79
  80static void iriap_watchdog_timer_expired(void *data);
  81
  82static inline void iriap_start_watchdog_timer(struct iriap_cb *self,
  83                                              int timeout)
  84{
  85        irda_start_timer(&self->watchdog_timer, timeout, self,
  86                         iriap_watchdog_timer_expired);
  87}
  88
  89/*
  90 * Function iriap_init (void)
  91 *
  92 *    Initializes the IrIAP layer, called by the module initialization code
  93 *    in irmod.c
  94 */
  95int __init iriap_init(void)
  96{
  97        struct ias_object *obj;
  98        struct iriap_cb *server;
  99        __u8 oct_seq[6];
 100        __u16 hints;
 101
 102        /* Allocate master array */
 103        iriap = hashbin_new(HB_LOCK);
 104        if (!iriap)
 105                return -ENOMEM;
 106
 107        /* Object repository - defined in irias_object.c */
 108        irias_objects = hashbin_new(HB_LOCK);
 109        if (!irias_objects) {
 110                IRDA_WARNING("%s: Can't allocate irias_objects hashbin!\n",
 111                             __func__);
 112                hashbin_delete(iriap, NULL);
 113                return -ENOMEM;
 114        }
 115
 116        /*
 117         *  Register some default services for IrLMP
 118         */
 119        hints  = irlmp_service_to_hint(S_COMPUTER);
 120        service_handle = irlmp_register_service(hints);
 121
 122        /* Register the Device object with LM-IAS */
 123        obj = irias_new_object("Device", IAS_DEVICE_ID);
 124        irias_add_string_attrib(obj, "DeviceName", "Linux", IAS_KERNEL_ATTR);
 125
 126        oct_seq[0] = 0x01;  /* Version 1 */
 127        oct_seq[1] = 0x00;  /* IAS support bits */
 128        oct_seq[2] = 0x00;  /* LM-MUX support bits */
 129#ifdef CONFIG_IRDA_ULTRA
 130        oct_seq[2] |= 0x04; /* Connectionless Data support */
 131#endif
 132        irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3,
 133                                IAS_KERNEL_ATTR);
 134        irias_insert_object(obj);
 135
 136        /*
 137         *  Register server support with IrLMP so we can accept incoming
 138         *  connections
 139         */
 140        server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
 141        if (!server) {
 142                IRDA_DEBUG(0, "%s(), unable to open server\n", __func__);
 143                return -1;
 144        }
 145        iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
 146
 147        return 0;
 148}
 149
 150/*
 151 * Function iriap_cleanup (void)
 152 *
 153 *    Initializes the IrIAP layer, called by the module cleanup code in
 154 *    irmod.c
 155 */
 156void iriap_cleanup(void)
 157{
 158        irlmp_unregister_service(service_handle);
 159
 160        hashbin_delete(iriap, (FREE_FUNC) __iriap_close);
 161        hashbin_delete(irias_objects, (FREE_FUNC) __irias_delete_object);
 162}
 163
 164/*
 165 * Function iriap_open (void)
 166 *
 167 *    Opens an instance of the IrIAP layer, and registers with IrLMP
 168 */
 169struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
 170                            CONFIRM_CALLBACK callback)
 171{
 172        struct iriap_cb *self;
 173
 174        IRDA_DEBUG(2, "%s()\n", __func__);
 175
 176        self = kzalloc(sizeof(*self), GFP_ATOMIC);
 177        if (!self) {
 178                IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
 179                return NULL;
 180        }
 181
 182        /*
 183         *  Initialize instance
 184         */
 185
 186        self->magic = IAS_MAGIC;
 187        self->mode = mode;
 188        if (mode == IAS_CLIENT)
 189                iriap_register_lsap(self, slsap_sel, mode);
 190
 191        self->confirm = callback;
 192        self->priv = priv;
 193
 194        /* iriap_getvaluebyclass_request() will construct packets before
 195         * we connect, so this must have a sane value... Jean II */
 196        self->max_header_size = LMP_MAX_HEADER;
 197
 198        init_timer(&self->watchdog_timer);
 199
 200        hashbin_insert(iriap, (irda_queue_t *) self, (long) self, NULL);
 201
 202        /* Initialize state machines */
 203        iriap_next_client_state(self, S_DISCONNECT);
 204        iriap_next_call_state(self, S_MAKE_CALL);
 205        iriap_next_server_state(self, R_DISCONNECT);
 206        iriap_next_r_connect_state(self, R_WAITING);
 207
 208        return self;
 209}
 210EXPORT_SYMBOL(iriap_open);
 211
 212/*
 213 * Function __iriap_close (self)
 214 *
 215 *    Removes (deallocates) the IrIAP instance
 216 *
 217 */
 218static void __iriap_close(struct iriap_cb *self)
 219{
 220        IRDA_DEBUG(4, "%s()\n", __func__);
 221
 222        IRDA_ASSERT(self != NULL, return;);
 223        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 224
 225        del_timer(&self->watchdog_timer);
 226
 227        if (self->request_skb)
 228                dev_kfree_skb(self->request_skb);
 229
 230        self->magic = 0;
 231
 232        kfree(self);
 233}
 234
 235/*
 236 * Function iriap_close (void)
 237 *
 238 *    Closes IrIAP and deregisters with IrLMP
 239 */
 240void iriap_close(struct iriap_cb *self)
 241{
 242        struct iriap_cb *entry;
 243
 244        IRDA_DEBUG(2, "%s()\n", __func__);
 245
 246        IRDA_ASSERT(self != NULL, return;);
 247        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 248
 249        if (self->lsap) {
 250                irlmp_close_lsap(self->lsap);
 251                self->lsap = NULL;
 252        }
 253
 254        entry = (struct iriap_cb *) hashbin_remove(iriap, (long) self, NULL);
 255        IRDA_ASSERT(entry == self, return;);
 256
 257        __iriap_close(self);
 258}
 259EXPORT_SYMBOL(iriap_close);
 260
 261static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
 262{
 263        notify_t notify;
 264
 265        IRDA_DEBUG(2, "%s()\n", __func__);
 266
 267        irda_notify_init(&notify);
 268        notify.connect_confirm       = iriap_connect_confirm;
 269        notify.connect_indication    = iriap_connect_indication;
 270        notify.disconnect_indication = iriap_disconnect_indication;
 271        notify.data_indication       = iriap_data_indication;
 272        notify.instance = self;
 273        if (mode == IAS_CLIENT)
 274                strcpy(notify.name, "IrIAS cli");
 275        else
 276                strcpy(notify.name, "IrIAS srv");
 277
 278        self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
 279        if (self->lsap == NULL) {
 280                IRDA_ERROR("%s: Unable to allocated LSAP!\n", __func__);
 281                return -1;
 282        }
 283        self->slsap_sel = self->lsap->slsap_sel;
 284
 285        return 0;
 286}
 287
 288/*
 289 * Function iriap_disconnect_indication (handle, reason)
 290 *
 291 *    Got disconnect, so clean up everything associated with this connection
 292 *
 293 */
 294static void iriap_disconnect_indication(void *instance, void *sap,
 295                                        LM_REASON reason,
 296                                        struct sk_buff *skb)
 297{
 298        struct iriap_cb *self;
 299
 300        IRDA_DEBUG(4, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
 301
 302        self = (struct iriap_cb *) instance;
 303
 304        IRDA_ASSERT(self != NULL, return;);
 305        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 306
 307        IRDA_ASSERT(iriap != NULL, return;);
 308
 309        del_timer(&self->watchdog_timer);
 310
 311        /* Not needed */
 312        if (skb)
 313                dev_kfree_skb(skb);
 314
 315        if (self->mode == IAS_CLIENT) {
 316                IRDA_DEBUG(4, "%s(), disconnect as client\n", __func__);
 317
 318
 319                iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
 320                                      NULL);
 321                /*
 322                 * Inform service user that the request failed by sending
 323                 * it a NULL value. Warning, the client might close us, so
 324                 * remember no to use self anymore after calling confirm
 325                 */
 326                if (self->confirm)
 327                        self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
 328        } else {
 329                IRDA_DEBUG(4, "%s(), disconnect as server\n", __func__);
 330                iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
 331                                      NULL);
 332                iriap_close(self);
 333        }
 334}
 335
 336/*
 337 * Function iriap_disconnect_request (handle)
 338 */
 339static void iriap_disconnect_request(struct iriap_cb *self)
 340{
 341        struct sk_buff *tx_skb;
 342
 343        IRDA_DEBUG(4, "%s()\n", __func__);
 344
 345        IRDA_ASSERT(self != NULL, return;);
 346        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 347
 348        tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
 349        if (tx_skb == NULL) {
 350                IRDA_DEBUG(0,
 351                           "%s(), Could not allocate an sk_buff of length %d\n",
 352                           __func__, LMP_MAX_HEADER);
 353                return;
 354        }
 355
 356        /*
 357         *  Reserve space for MUX control and LAP header
 358         */
 359        skb_reserve(tx_skb, LMP_MAX_HEADER);
 360
 361        irlmp_disconnect_request(self->lsap, tx_skb);
 362}
 363
 364/*
 365 * Function iriap_getvaluebyclass (addr, name, attr)
 366 *
 367 *    Retrieve all values from attribute in all objects with given class
 368 *    name
 369 */
 370int iriap_getvaluebyclass_request(struct iriap_cb *self,
 371                                  __u32 saddr, __u32 daddr,
 372                                  char *name, char *attr)
 373{
 374        struct sk_buff *tx_skb;
 375        int name_len, attr_len, skb_len;
 376        __u8 *frame;
 377
 378        IRDA_ASSERT(self != NULL, return -1;);
 379        IRDA_ASSERT(self->magic == IAS_MAGIC, return -1;);
 380
 381        /* Client must supply the destination device address */
 382        if (!daddr)
 383                return -1;
 384
 385        self->daddr = daddr;
 386        self->saddr = saddr;
 387
 388        /*
 389         *  Save operation, so we know what the later indication is about
 390         */
 391        self->operation = GET_VALUE_BY_CLASS;
 392
 393        /* Give ourselves 10 secs to finish this operation */
 394        iriap_start_watchdog_timer(self, 10*HZ);
 395
 396        name_len = strlen(name);        /* Up to IAS_MAX_CLASSNAME = 60 */
 397        attr_len = strlen(attr);        /* Up to IAS_MAX_ATTRIBNAME = 60 */
 398
 399        skb_len = self->max_header_size+2+name_len+1+attr_len+4;
 400        tx_skb = alloc_skb(skb_len, GFP_ATOMIC);
 401        if (!tx_skb)
 402                return -ENOMEM;
 403
 404        /* Reserve space for MUX and LAP header */
 405        skb_reserve(tx_skb, self->max_header_size);
 406        skb_put(tx_skb, 3+name_len+attr_len);
 407        frame = tx_skb->data;
 408
 409        /* Build frame */
 410        frame[0] = IAP_LST | GET_VALUE_BY_CLASS;
 411        frame[1] = name_len;                       /* Insert length of name */
 412        memcpy(frame+2, name, name_len);           /* Insert name */
 413        frame[2+name_len] = attr_len;              /* Insert length of attr */
 414        memcpy(frame+3+name_len, attr, attr_len);  /* Insert attr */
 415
 416        iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, tx_skb);
 417
 418        /* Drop reference count - see state_s_disconnect(). */
 419        dev_kfree_skb(tx_skb);
 420
 421        return 0;
 422}
 423EXPORT_SYMBOL(iriap_getvaluebyclass_request);
 424
 425/*
 426 * Function iriap_getvaluebyclass_confirm (self, skb)
 427 *
 428 *    Got result from GetValueByClass command. Parse it and return result
 429 *    to service user.
 430 *
 431 */
 432static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
 433                                          struct sk_buff *skb)
 434{
 435        struct ias_value *value;
 436        int charset;
 437        __u32 value_len;
 438        __u32 tmp_cpu32;
 439        __u16 obj_id;
 440        __u16 len;
 441        __u8  type;
 442        __u8 *fp;
 443        int n;
 444
 445        IRDA_ASSERT(self != NULL, return;);
 446        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 447        IRDA_ASSERT(skb != NULL, return;);
 448
 449        /* Initialize variables */
 450        fp = skb->data;
 451        n = 2;
 452
 453        /* Get length, MSB first */
 454        len = get_unaligned_be16(fp + n);
 455        n += 2;
 456
 457        IRDA_DEBUG(4, "%s(), len=%d\n", __func__, len);
 458
 459        /* Get object ID, MSB first */
 460        obj_id = get_unaligned_be16(fp + n);
 461        n += 2;
 462
 463        type = fp[n++];
 464        IRDA_DEBUG(4, "%s(), Value type = %d\n", __func__, type);
 465
 466        switch (type) {
 467        case IAS_INTEGER:
 468                memcpy(&tmp_cpu32, fp+n, 4); n += 4;
 469                be32_to_cpus(&tmp_cpu32);
 470                value = irias_new_integer_value(tmp_cpu32);
 471
 472                /*  Legal values restricted to 0x01-0x6f, page 15 irttp */
 473                IRDA_DEBUG(4, "%s(), lsap=%d\n", __func__, value->t.integer);
 474                break;
 475        case IAS_STRING:
 476                charset = fp[n++];
 477
 478                switch (charset) {
 479                case CS_ASCII:
 480                        break;
 481/*                case CS_ISO_8859_1: */
 482/*                case CS_ISO_8859_2: */
 483/*                case CS_ISO_8859_3: */
 484/*                case CS_ISO_8859_4: */
 485/*                case CS_ISO_8859_5: */
 486/*                case CS_ISO_8859_6: */
 487/*                case CS_ISO_8859_7: */
 488/*                case CS_ISO_8859_8: */
 489/*                case CS_ISO_8859_9: */
 490/*                case CS_UNICODE: */
 491                default:
 492                        IRDA_DEBUG(0, "%s(), charset %s, not supported\n",
 493                                   __func__, ias_charset_types[charset]);
 494
 495                        /* Aborting, close connection! */
 496                        iriap_disconnect_request(self);
 497                        return;
 498                        /* break; */
 499                }
 500                value_len = fp[n++];
 501                IRDA_DEBUG(4, "%s(), strlen=%d\n", __func__, value_len);
 502
 503                /* Make sure the string is null-terminated */
 504                fp[n+value_len] = 0x00;
 505                IRDA_DEBUG(4, "Got string %s\n", fp+n);
 506
 507                /* Will truncate to IAS_MAX_STRING bytes */
 508                value = irias_new_string_value(fp+n);
 509                break;
 510        case IAS_OCT_SEQ:
 511                value_len = get_unaligned_be16(fp + n);
 512                n += 2;
 513
 514                /* Will truncate to IAS_MAX_OCTET_STRING bytes */
 515                value = irias_new_octseq_value(fp+n, value_len);
 516                break;
 517        default:
 518                value = irias_new_missing_value();
 519                break;
 520        }
 521
 522        /* Finished, close connection! */
 523        iriap_disconnect_request(self);
 524
 525        /* Warning, the client might close us, so remember no to use self
 526         * anymore after calling confirm
 527         */
 528        if (self->confirm)
 529                self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
 530        else {
 531                IRDA_DEBUG(0, "%s(), missing handler!\n", __func__);
 532                irias_delete_value(value);
 533        }
 534}
 535
 536/*
 537 * Function iriap_getvaluebyclass_response ()
 538 *
 539 *    Send answer back to remote LM-IAS
 540 *
 541 */
 542static void iriap_getvaluebyclass_response(struct iriap_cb *self,
 543                                           __u16 obj_id,
 544                                           __u8 ret_code,
 545                                           struct ias_value *value)
 546{
 547        struct sk_buff *tx_skb;
 548        int n;
 549        __be32 tmp_be32;
 550        __be16 tmp_be16;
 551        __u8 *fp;
 552
 553        IRDA_DEBUG(4, "%s()\n", __func__);
 554
 555        IRDA_ASSERT(self != NULL, return;);
 556        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 557        IRDA_ASSERT(value != NULL, return;);
 558        IRDA_ASSERT(value->len <= 1024, return;);
 559
 560        /* Initialize variables */
 561        n = 0;
 562
 563        /*
 564         *  We must adjust the size of the response after the length of the
 565         *  value. We add 32 bytes because of the 6 bytes for the frame and
 566         *  max 5 bytes for the value coding.
 567         */
 568        tx_skb = alloc_skb(value->len + self->max_header_size + 32,
 569                           GFP_ATOMIC);
 570        if (!tx_skb)
 571                return;
 572
 573        /* Reserve space for MUX and LAP header */
 574        skb_reserve(tx_skb, self->max_header_size);
 575        skb_put(tx_skb, 6);
 576
 577        fp = tx_skb->data;
 578
 579        /* Build frame */
 580        fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
 581        fp[n++] = ret_code;
 582
 583        /* Insert list length (MSB first) */
 584        tmp_be16 = htons(0x0001);
 585        memcpy(fp+n, &tmp_be16, 2);  n += 2;
 586
 587        /* Insert object identifier ( MSB first) */
 588        tmp_be16 = cpu_to_be16(obj_id);
 589        memcpy(fp+n, &tmp_be16, 2); n += 2;
 590
 591        switch (value->type) {
 592        case IAS_STRING:
 593                skb_put(tx_skb, 3 + value->len);
 594                fp[n++] = value->type;
 595                fp[n++] = 0; /* ASCII */
 596                fp[n++] = (__u8) value->len;
 597                memcpy(fp+n, value->t.string, value->len); n+=value->len;
 598                break;
 599        case IAS_INTEGER:
 600                skb_put(tx_skb, 5);
 601                fp[n++] = value->type;
 602
 603                tmp_be32 = cpu_to_be32(value->t.integer);
 604                memcpy(fp+n, &tmp_be32, 4); n += 4;
 605                break;
 606        case IAS_OCT_SEQ:
 607                skb_put(tx_skb, 3 + value->len);
 608                fp[n++] = value->type;
 609
 610                tmp_be16 = cpu_to_be16(value->len);
 611                memcpy(fp+n, &tmp_be16, 2); n += 2;
 612                memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
 613                break;
 614        case IAS_MISSING:
 615                IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __func__);
 616                skb_put(tx_skb, 1);
 617                fp[n++] = value->type;
 618                break;
 619        default:
 620                IRDA_DEBUG(0, "%s(), type not implemented!\n", __func__);
 621                break;
 622        }
 623        iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, tx_skb);
 624
 625        /* Drop reference count - see state_r_execute(). */
 626        dev_kfree_skb(tx_skb);
 627}
 628
 629/*
 630 * Function iriap_getvaluebyclass_indication (self, skb)
 631 *
 632 *    getvaluebyclass is requested from peer LM-IAS
 633 *
 634 */
 635static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
 636                                             struct sk_buff *skb)
 637{
 638        struct ias_object *obj;
 639        struct ias_attrib *attrib;
 640        int name_len;
 641        int attr_len;
 642        char name[IAS_MAX_CLASSNAME + 1];        /* 60 bytes */
 643        char attr[IAS_MAX_ATTRIBNAME + 1];        /* 60 bytes */
 644        __u8 *fp;
 645        int n;
 646
 647        IRDA_DEBUG(4, "%s()\n", __func__);
 648
 649        IRDA_ASSERT(self != NULL, return;);
 650        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 651        IRDA_ASSERT(skb != NULL, return;);
 652
 653        fp = skb->data;
 654        n = 1;
 655
 656        name_len = fp[n++];
 657        memcpy(name, fp+n, name_len); n+=name_len;
 658        name[name_len] = '\0';
 659
 660        attr_len = fp[n++];
 661        memcpy(attr, fp+n, attr_len); n+=attr_len;
 662        attr[attr_len] = '\0';
 663
 664        IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
 665        obj = irias_find_object(name);
 666
 667        if (obj == NULL) {
 668                IRDA_DEBUG(2, "LM-IAS: Object %s not found\n", name);
 669                iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
 670                                               &irias_missing);
 671                return;
 672        }
 673        IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
 674
 675        attrib = irias_find_attrib(obj, attr);
 676        if (attrib == NULL) {
 677                IRDA_DEBUG(2, "LM-IAS: Attribute %s not found\n", attr);
 678                iriap_getvaluebyclass_response(self, obj->id,
 679                                               IAS_ATTRIB_UNKNOWN,
 680                                               &irias_missing);
 681                return;
 682        }
 683
 684        /* We have a match; send the value.  */
 685        iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS,
 686                                       attrib->value);
 687
 688        return;
 689}
 690
 691/*
 692 * Function iriap_send_ack (void)
 693 *
 694 *    Currently not used
 695 *
 696 */
 697void iriap_send_ack(struct iriap_cb *self)
 698{
 699        struct sk_buff *tx_skb;
 700        __u8 *frame;
 701
 702        IRDA_DEBUG(2, "%s()\n", __func__);
 703
 704        IRDA_ASSERT(self != NULL, return;);
 705        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 706
 707        tx_skb = alloc_skb(LMP_MAX_HEADER + 1, GFP_ATOMIC);
 708        if (!tx_skb)
 709                return;
 710
 711        /* Reserve space for MUX and LAP header */
 712        skb_reserve(tx_skb, self->max_header_size);
 713        skb_put(tx_skb, 1);
 714        frame = tx_skb->data;
 715
 716        /* Build frame */
 717        frame[0] = IAP_LST | IAP_ACK | self->operation;
 718
 719        irlmp_data_request(self->lsap, tx_skb);
 720}
 721
 722void iriap_connect_request(struct iriap_cb *self)
 723{
 724        int ret;
 725
 726        IRDA_ASSERT(self != NULL, return;);
 727        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 728
 729        ret = irlmp_connect_request(self->lsap, LSAP_IAS,
 730                                    self->saddr, self->daddr,
 731                                    NULL, NULL);
 732        if (ret < 0) {
 733                IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
 734                self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
 735        }
 736}
 737
 738/*
 739 * Function iriap_connect_confirm (handle, skb)
 740 *
 741 *    LSAP connection confirmed!
 742 *
 743 */
 744static void iriap_connect_confirm(void *instance, void *sap,
 745                                  struct qos_info *qos, __u32 max_seg_size,
 746                                  __u8 max_header_size,
 747                                  struct sk_buff *skb)
 748{
 749        struct iriap_cb *self;
 750
 751        self = (struct iriap_cb *) instance;
 752
 753        IRDA_ASSERT(self != NULL, return;);
 754        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 755        IRDA_ASSERT(skb != NULL, return;);
 756
 757        self->max_data_size = max_seg_size;
 758        self->max_header_size = max_header_size;
 759
 760        del_timer(&self->watchdog_timer);
 761
 762        iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, skb);
 763
 764        /* Drop reference count - see state_s_make_call(). */
 765        dev_kfree_skb(skb);
 766}
 767
 768/*
 769 * Function iriap_connect_indication ( handle, skb)
 770 *
 771 *    Remote LM-IAS is requesting connection
 772 *
 773 */
 774static void iriap_connect_indication(void *instance, void *sap,
 775                                     struct qos_info *qos, __u32 max_seg_size,
 776                                     __u8 max_header_size,
 777                                     struct sk_buff *skb)
 778{
 779        struct iriap_cb *self, *new;
 780
 781        IRDA_DEBUG(1, "%s()\n", __func__);
 782
 783        self = (struct iriap_cb *) instance;
 784
 785        IRDA_ASSERT(skb != NULL, return;);
 786        IRDA_ASSERT(self != NULL, goto out;);
 787        IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;);
 788
 789        /* Start new server */
 790        new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
 791        if (!new) {
 792                IRDA_DEBUG(0, "%s(), open failed\n", __func__);
 793                goto out;
 794        }
 795
 796        /* Now attach up the new "socket" */
 797        new->lsap = irlmp_dup(self->lsap, new);
 798        if (!new->lsap) {
 799                IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
 800                goto out;
 801        }
 802
 803        new->max_data_size = max_seg_size;
 804        new->max_header_size = max_header_size;
 805
 806        /* Clean up the original one to keep it in listen state */
 807        irlmp_listen(self->lsap);
 808
 809        iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, skb);
 810
 811out:
 812        /* Drop reference count - see state_r_disconnect(). */
 813        dev_kfree_skb(skb);
 814}
 815
 816/*
 817 * Function iriap_data_indication (handle, skb)
 818 *
 819 *    Receives data from connection identified by handle from IrLMP
 820 *
 821 */
 822static int iriap_data_indication(void *instance, void *sap,
 823                                 struct sk_buff *skb)
 824{
 825        struct iriap_cb *self;
 826        __u8  *frame;
 827        __u8  opcode;
 828
 829        IRDA_DEBUG(3, "%s()\n", __func__);
 830
 831        self = (struct iriap_cb *) instance;
 832
 833        IRDA_ASSERT(skb != NULL, return 0;);
 834        IRDA_ASSERT(self != NULL, goto out;);
 835        IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;);
 836
 837        frame = skb->data;
 838
 839        if (self->mode == IAS_SERVER) {
 840                /* Call server */
 841                IRDA_DEBUG(4, "%s(), Calling server!\n", __func__);
 842                iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
 843                goto out;
 844        }
 845        opcode = frame[0];
 846        if (~opcode & IAP_LST) {
 847                IRDA_WARNING("%s:, IrIAS multiframe commands or "
 848                             "results is not implemented yet!\n",
 849                             __func__);
 850                goto out;
 851        }
 852
 853        /* Check for ack frames since they don't contain any data */
 854        if (opcode & IAP_ACK) {
 855                IRDA_DEBUG(0, "%s() Got ack frame!\n", __func__);
 856                goto out;
 857        }
 858
 859        opcode &= ~IAP_LST; /* Mask away LST bit */
 860
 861        switch (opcode) {
 862        case GET_INFO_BASE:
 863                IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
 864                break;
 865        case GET_VALUE_BY_CLASS:
 866                iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
 867
 868                switch (frame[1]) {
 869                case IAS_SUCCESS:
 870                        iriap_getvaluebyclass_confirm(self, skb);
 871                        break;
 872                case IAS_CLASS_UNKNOWN:
 873                        IRDA_DEBUG(1, "%s(), No such class!\n", __func__);
 874                        /* Finished, close connection! */
 875                        iriap_disconnect_request(self);
 876
 877                        /*
 878                         * Warning, the client might close us, so remember
 879                         * no to use self anymore after calling confirm
 880                         */
 881                        if (self->confirm)
 882                                self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
 883                                              self->priv);
 884                        break;
 885                case IAS_ATTRIB_UNKNOWN:
 886                        IRDA_DEBUG(1, "%s(), No such attribute!\n", __func__);
 887                        /* Finished, close connection! */
 888                        iriap_disconnect_request(self);
 889
 890                        /*
 891                         * Warning, the client might close us, so remember
 892                         * no to use self anymore after calling confirm
 893                         */
 894                        if (self->confirm)
 895                                self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL,
 896                                              self->priv);
 897                        break;
 898                }
 899                break;
 900        default:
 901                IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __func__,
 902                           opcode);
 903                break;
 904        }
 905
 906out:
 907        /* Cleanup - sub-calls will have done skb_get() as needed. */
 908        dev_kfree_skb(skb);
 909        return 0;
 910}
 911
 912/*
 913 * Function iriap_call_indication (self, skb)
 914 *
 915 *    Received call to server from peer LM-IAS
 916 *
 917 */
 918void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
 919{
 920        __u8 *fp;
 921        __u8 opcode;
 922
 923        IRDA_DEBUG(4, "%s()\n", __func__);
 924
 925        IRDA_ASSERT(self != NULL, return;);
 926        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 927        IRDA_ASSERT(skb != NULL, return;);
 928
 929        fp = skb->data;
 930
 931        opcode = fp[0];
 932        if (~opcode & 0x80) {
 933                IRDA_WARNING("%s: IrIAS multiframe commands or results "
 934                             "is not implemented yet!\n", __func__);
 935                return;
 936        }
 937        opcode &= 0x7f; /* Mask away LST bit */
 938
 939        switch (opcode) {
 940        case GET_INFO_BASE:
 941                IRDA_WARNING("%s: GetInfoBaseDetails not implemented yet!\n",
 942                             __func__);
 943                break;
 944        case GET_VALUE_BY_CLASS:
 945                iriap_getvaluebyclass_indication(self, skb);
 946                break;
 947        }
 948        /* skb will be cleaned up in iriap_data_indication */
 949}
 950
 951/*
 952 * Function iriap_watchdog_timer_expired (data)
 953 *
 954 *    Query has taken too long time, so abort
 955 *
 956 */
 957static void iriap_watchdog_timer_expired(void *data)
 958{
 959        struct iriap_cb *self = (struct iriap_cb *) data;
 960
 961        IRDA_ASSERT(self != NULL, return;);
 962        IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
 963
 964        /* iriap_close(self); */
 965}
 966
 967#ifdef CONFIG_PROC_FS
 968
 969static const char *ias_value_types[] = {
 970        "IAS_MISSING",
 971        "IAS_INTEGER",
 972        "IAS_OCT_SEQ",
 973        "IAS_STRING"
 974};
 975
 976static inline struct ias_object *irias_seq_idx(loff_t pos)
 977{
 978        struct ias_object *obj;
 979
 980        for (obj = (struct ias_object *) hashbin_get_first(irias_objects);
 981             obj; obj = (struct ias_object *) hashbin_get_next(irias_objects)) {
 982                if (pos-- == 0)
 983                        break;
 984        }
 985
 986        return obj;
 987}
 988
 989static void *irias_seq_start(struct seq_file *seq, loff_t *pos)
 990{
 991        spin_lock_irq(&irias_objects->hb_spinlock);
 992
 993        return *pos ? irias_seq_idx(*pos - 1) : SEQ_START_TOKEN;
 994}
 995
 996static void *irias_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 997{
 998        ++*pos;
 999
1000        return (v == SEQ_START_TOKEN)
1001                ? (void *) hashbin_get_first(irias_objects)
1002                : (void *) hashbin_get_next(irias_objects);
1003}
1004
1005static void irias_seq_stop(struct seq_file *seq, void *v)
1006{
1007        spin_unlock_irq(&irias_objects->hb_spinlock);
1008}
1009
1010static int irias_seq_show(struct seq_file *seq, void *v)
1011{
1012        if (v == SEQ_START_TOKEN)
1013                seq_puts(seq, "LM-IAS Objects:\n");
1014        else {
1015                struct ias_object *obj = v;
1016                struct ias_attrib *attrib;
1017
1018                IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -EINVAL;);
1019
1020                seq_printf(seq, "name: %s, id=%d\n",
1021                           obj->name, obj->id);
1022
1023                /* Careful for priority inversions here !
1024                 * All other uses of attrib spinlock are independent of
1025                 * the object spinlock, so we are safe. Jean II */
1026                spin_lock(&obj->attribs->hb_spinlock);
1027
1028                /* List all attributes for this object */
1029                for (attrib = (struct ias_attrib *) hashbin_get_first(obj->attribs);
1030                     attrib != NULL;
1031                     attrib = (struct ias_attrib *) hashbin_get_next(obj->attribs)) {
1032
1033                        IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC,
1034                                    goto outloop; );
1035
1036                        seq_printf(seq, " - Attribute name: \"%s\", ",
1037                                   attrib->name);
1038                        seq_printf(seq, "value[%s]: ",
1039                                   ias_value_types[attrib->value->type]);
1040
1041                        switch (attrib->value->type) {
1042                        case IAS_INTEGER:
1043                                seq_printf(seq, "%d\n",
1044                                           attrib->value->t.integer);
1045                                break;
1046                        case IAS_STRING:
1047                                seq_printf(seq, "\"%s\"\n",
1048                                           attrib->value->t.string);
1049                                break;
1050                        case IAS_OCT_SEQ:
1051                                seq_printf(seq, "octet sequence (%d bytes)\n",
1052                                           attrib->value->len);
1053                                break;
1054                        case IAS_MISSING:
1055                                seq_puts(seq, "missing\n");
1056                                break;
1057                        default:
1058                                seq_printf(seq, "type %d?\n",
1059                                           attrib->value->type);
1060                        }
1061                        seq_putc(seq, '\n');
1062
1063                }
1064        IRDA_ASSERT_LABEL(outloop:)
1065                spin_unlock(&obj->attribs->hb_spinlock);
1066        }
1067
1068        return 0;
1069}
1070
1071static const struct seq_operations irias_seq_ops = {
1072        .start  = irias_seq_start,
1073        .next   = irias_seq_next,
1074        .stop   = irias_seq_stop,
1075        .show   = irias_seq_show,
1076};
1077
1078static int irias_seq_open(struct inode *inode, struct file *file)
1079{
1080        IRDA_ASSERT( irias_objects != NULL, return -EINVAL;);
1081
1082        return seq_open(file, &irias_seq_ops);
1083}
1084
1085const struct file_operations irias_seq_fops = {
1086        .owner                = THIS_MODULE,
1087        .open           = irias_seq_open,
1088        .read           = seq_read,
1089        .llseek         = seq_lseek,
1090        .release        = seq_release,
1091};
1092
1093#endif /* PROC_FS */