1/********************************************************************* 2 * 3 * Filename: irlan_client.c 4 * Version: 0.9 5 * Description: IrDA LAN Access Protocol (IrLAN) Client 6 * Status: Experimental. 7 * Author: Dag Brattli <dagb@cs.uit.no> 8 * Created at: Sun Aug 31 20:14:37 1997 9 * Modified at: Tue Dec 14 15:47:02 1999 10 * Modified by: Dag Brattli <dagb@cs.uit.no> 11 * Sources: skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov> 12 * slip.c by Laurence Culhane, <loz@holmes.demon.co.uk> 13 * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> 14 * 15 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 16 * All Rights Reserved. 17 * 18 * This program is free software; you can redistribute it and/or 19 * modify it under the terms of the GNU General Public License as 20 * published by the Free Software Foundation; either version 2 of 21 * the License, or (at your option) any later version. 22 * 23 * Neither Dag Brattli nor University of Tromsø admit liability nor 24 * provide warranty for any of this software. This material is 25 * provided "AS-IS" and at no charge. 26 * 27 ********************************************************************/ 28 29#include <linux/kernel.h> 30#include <linux/string.h> 31#include <linux/slab.h> 32#include <linux/errno.h> 33#include <linux/init.h> 34#include <linux/netdevice.h> 35#include <linux/etherdevice.h> 36#include <linux/if_arp.h> 37#include <linux/bitops.h> 38#include <net/arp.h> 39 40#include <asm/byteorder.h> 41 42#include <net/irda/irda.h> 43#include <net/irda/irttp.h> 44#include <net/irda/irlmp.h> 45#include <net/irda/irias_object.h> 46#include <net/irda/iriap.h> 47#include <net/irda/timer.h> 48 49#include <net/irda/irlan_common.h> 50#include <net/irda/irlan_event.h> 51#include <net/irda/irlan_eth.h> 52#include <net/irda/irlan_provider.h> 53#include <net/irda/irlan_client.h> 54 55#undef CONFIG_IRLAN_GRATUITOUS_ARP 56 57static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 58 LM_REASON reason, 59 struct sk_buff *); 60static int irlan_client_ctrl_data_indication(void *instance, void *sap, 61 struct sk_buff *skb); 62static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 63 struct qos_info *qos, 64 __u32 max_sdu_size, 65 __u8 max_header_size, 66 struct sk_buff *); 67static void irlan_check_response_param(struct irlan_cb *self, char *param, 68 char *value, int val_len); 69static void irlan_client_open_ctrl_tsap(struct irlan_cb *self); 70 71static void irlan_client_kick_timer_expired(void *data) 72{ 73 struct irlan_cb *self = (struct irlan_cb *) data; 74 75 IRDA_ASSERT(self != NULL, return;); 76 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); 77 78 /* 79 * If we are in peer mode, the client may not have got the discovery 80 * indication it needs to make progress. If the client is still in 81 * IDLE state, we must kick it to, but only if the provider is not IDLE 82 */ 83 if ((self->provider.access_type == ACCESS_PEER) && 84 (self->client.state == IRLAN_IDLE) && 85 (self->provider.state != IRLAN_IDLE)) { 86 irlan_client_wakeup(self, self->saddr, self->daddr); 87 } 88} 89 90static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout) 91{ 92 irda_start_timer(&self->client.kick_timer, timeout, (void *) self, 93 irlan_client_kick_timer_expired); 94} 95 96/* 97 * Function irlan_client_wakeup (self, saddr, daddr) 98 * 99 * Wake up client 100 * 101 */ 102void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr) 103{ 104 IRDA_ASSERT(self != NULL, return;); 105 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); 106 107 /* 108 * Check if we are already awake, or if we are a provider in direct 109 * mode (in that case we must leave the client idle 110 */ 111 if ((self->client.state != IRLAN_IDLE) || 112 (self->provider.access_type == ACCESS_DIRECT)) 113 { 114 pr_debug("%s(), already awake!\n", __func__); 115 return; 116 } 117 118 /* Addresses may have changed! */ 119 self->saddr = saddr; 120 self->daddr = daddr; 121 122 if (self->disconnect_reason == LM_USER_REQUEST) { 123 pr_debug("%s(), still stopped by user\n", __func__); 124 return; 125 } 126 127 /* Open TSAPs */ 128 irlan_client_open_ctrl_tsap(self); 129 irlan_open_data_tsap(self); 130 131 irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL); 132 133 /* Start kick timer */ 134 irlan_client_start_kick_timer(self, 2*HZ); 135} 136 137/* 138 * Function irlan_discovery_indication (daddr) 139 * 140 * Remote device with IrLAN server support discovered 141 * 142 */ 143void irlan_client_discovery_indication(discinfo_t *discovery, 144 DISCOVERY_MODE mode, 145 void *priv) 146{ 147 struct irlan_cb *self; 148 __u32 saddr, daddr; 149 150 IRDA_ASSERT(discovery != NULL, return;); 151 152 /* 153 * I didn't check it, but I bet that IrLAN suffer from the same 154 * deficiency as IrComm and doesn't handle two instances 155 * simultaneously connecting to each other. 156 * Same workaround, drop passive discoveries. 157 * Jean II */ 158 if(mode == DISCOVERY_PASSIVE) 159 return; 160 161 saddr = discovery->saddr; 162 daddr = discovery->daddr; 163 164 /* Find instance */ 165 rcu_read_lock(); 166 self = irlan_get_any(); 167 if (self) { 168 IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;); 169 170 pr_debug("%s(), Found instance (%08x)!\n", __func__ , 171 daddr); 172 173 irlan_client_wakeup(self, saddr, daddr); 174 } 175IRDA_ASSERT_LABEL(out:) 176 rcu_read_unlock(); 177} 178 179/* 180 * Function irlan_client_data_indication (handle, skb) 181 * 182 * This function gets the data that is received on the control channel 183 * 184 */ 185static int irlan_client_ctrl_data_indication(void *instance, void *sap, 186 struct sk_buff *skb) 187{ 188 struct irlan_cb *self; 189 190 self = instance; 191 192 IRDA_ASSERT(self != NULL, return -1;); 193 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;); 194 IRDA_ASSERT(skb != NULL, return -1;); 195 196 irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb); 197 198 /* Ready for a new command */ 199 pr_debug("%s(), clearing tx_busy\n", __func__); 200 self->client.tx_busy = FALSE; 201 202 /* Check if we have some queued commands waiting to be sent */ 203 irlan_run_ctrl_tx_queue(self); 204 205 return 0; 206} 207 208static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 209 LM_REASON reason, 210 struct sk_buff *userdata) 211{ 212 struct irlan_cb *self; 213 struct tsap_cb *tsap; 214 struct sk_buff *skb; 215 216 pr_debug("%s(), reason=%d\n", __func__ , reason); 217 218 self = instance; 219 tsap = sap; 220 221 IRDA_ASSERT(self != NULL, return;); 222 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); 223 IRDA_ASSERT(tsap != NULL, return;); 224 IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;); 225 226 IRDA_ASSERT(tsap == self->client.tsap_ctrl, return;); 227 228 /* Remove frames queued on the control channel */ 229 while ((skb = skb_dequeue(&self->client.txq)) != NULL) { 230 dev_kfree_skb(skb); 231 } 232 self->client.tx_busy = FALSE; 233 234 irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL); 235} 236 237/* 238 * Function irlan_client_open_tsaps (self) 239 * 240 * Initialize callbacks and open IrTTP TSAPs 241 * 242 */ 243static void irlan_client_open_ctrl_tsap(struct irlan_cb *self) 244{ 245 struct tsap_cb *tsap; 246 notify_t notify; 247 248 IRDA_ASSERT(self != NULL, return;); 249 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); 250 251 /* Check if already open */ 252 if (self->client.tsap_ctrl) 253 return; 254 255 irda_notify_init(¬ify); 256 257 /* Set up callbacks */ 258 notify.data_indication = irlan_client_ctrl_data_indication; 259 notify.connect_confirm = irlan_client_ctrl_connect_confirm; 260 notify.disconnect_indication = irlan_client_ctrl_disconnect_indication; 261 notify.instance = self; 262 strlcpy(notify.name, "IrLAN ctrl (c)", sizeof(notify.name)); 263 264 tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify); 265 if (!tsap) { 266 pr_debug("%s(), Got no tsap!\n", __func__); 267 return; 268 } 269 self->client.tsap_ctrl = tsap; 270} 271 272/* 273 * Function irlan_client_connect_confirm (handle, skb) 274 * 275 * Connection to peer IrLAN laye confirmed 276 * 277 */ 278static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 279 struct qos_info *qos, 280 __u32 max_sdu_size, 281 __u8 max_header_size, 282 struct sk_buff *skb) 283{ 284 struct irlan_cb *self; 285 286 self = instance; 287 288 IRDA_ASSERT(self != NULL, return;); 289 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); 290 291 self->client.max_sdu_size = max_sdu_size; 292 self->client.max_header_size = max_header_size; 293 294 /* TODO: we could set the MTU depending on the max_sdu_size */ 295 296 irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL); 297} 298 299/* 300 * Function print_ret_code (code) 301 * 302 * Print return code of request to peer IrLAN layer. 303 * 304 */ 305static void print_ret_code(__u8 code) 306{ 307 switch(code) { 308 case 0: 309 printk(KERN_INFO "Success\n"); 310 break; 311 case 1: 312 net_warn_ratelimited("IrLAN: Insufficient resources\n"); 313 break; 314 case 2: 315 net_warn_ratelimited("IrLAN: Invalid command format\n"); 316 break; 317 case 3: 318 net_warn_ratelimited("IrLAN: Command not supported\n"); 319 break; 320 case 4: 321 net_warn_ratelimited("IrLAN: Parameter not supported\n"); 322 break; 323 case 5: 324 net_warn_ratelimited("IrLAN: Value not supported\n"); 325 break; 326 case 6: 327 net_warn_ratelimited("IrLAN: Not open\n"); 328 break; 329 case 7: 330 net_warn_ratelimited("IrLAN: Authentication required\n"); 331 break; 332 case 8: 333 net_warn_ratelimited("IrLAN: Invalid password\n"); 334 break; 335 case 9: 336 net_warn_ratelimited("IrLAN: Protocol error\n"); 337 break; 338 case 255: 339 net_warn_ratelimited("IrLAN: Asynchronous status\n"); 340 break; 341 } 342} 343 344/* 345 * Function irlan_client_parse_response (self, skb) 346 * 347 * Extract all parameters from received buffer, then feed them to 348 * check_params for parsing 349 */ 350void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb) 351{ 352 __u8 *frame; 353 __u8 *ptr; 354 int count; 355 int ret; 356 __u16 val_len; 357 int i; 358 char *name; 359 char *value; 360 361 IRDA_ASSERT(skb != NULL, return;); 362 363 pr_debug("%s() skb->len=%d\n", __func__ , (int)skb->len); 364 365 IRDA_ASSERT(self != NULL, return;); 366 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); 367 368 if (!skb) { 369 net_err_ratelimited("%s(), Got NULL skb!\n", __func__); 370 return; 371 } 372 frame = skb->data; 373 374 /* 375 * Check return code and print it if not success 376 */ 377 if (frame[0]) { 378 print_ret_code(frame[0]); 379 return; 380 } 381 382 name = kmalloc(255, GFP_ATOMIC); 383 if (!name) 384 return; 385 value = kmalloc(1016, GFP_ATOMIC); 386 if (!value) { 387 kfree(name); 388 return; 389 } 390 391 /* How many parameters? */ 392 count = frame[1]; 393 394 pr_debug("%s(), got %d parameters\n", __func__ , count); 395 396 ptr = frame+2; 397 398 /* For all parameters */ 399 for (i=0; i<count;i++) { 400 ret = irlan_extract_param(ptr, name, value, &val_len); 401 if (ret < 0) { 402 pr_debug("%s(), IrLAN, Error!\n", __func__); 403 break; 404 } 405 ptr += ret; 406 irlan_check_response_param(self, name, value, val_len); 407 } 408 /* Cleanup */ 409 kfree(name); 410 kfree(value); 411} 412 413/* 414 * Function irlan_check_response_param (self, param, value, val_len) 415 * 416 * Check which parameter is received and update local variables 417 * 418 */ 419static void irlan_check_response_param(struct irlan_cb *self, char *param, 420 char *value, int val_len) 421{ 422 __u16 tmp_cpu; /* Temporary value in host order */ 423 __u8 *bytes; 424 int i; 425 426 pr_debug("%s(), parm=%s\n", __func__ , param); 427 428 IRDA_ASSERT(self != NULL, return;); 429 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); 430 431 /* Media type */ 432 if (strcmp(param, "MEDIA") == 0) { 433 if (strcmp(value, "802.3") == 0) 434 self->media = MEDIA_802_3; 435 else 436 self->media = MEDIA_802_5; 437 return; 438 } 439 if (strcmp(param, "FILTER_TYPE") == 0) { 440 if (strcmp(value, "DIRECTED") == 0) 441 self->client.filter_type |= IRLAN_DIRECTED; 442 else if (strcmp(value, "FUNCTIONAL") == 0) 443 self->client.filter_type |= IRLAN_FUNCTIONAL; 444 else if (strcmp(value, "GROUP") == 0) 445 self->client.filter_type |= IRLAN_GROUP; 446 else if (strcmp(value, "MAC_FRAME") == 0) 447 self->client.filter_type |= IRLAN_MAC_FRAME; 448 else if (strcmp(value, "MULTICAST") == 0) 449 self->client.filter_type |= IRLAN_MULTICAST; 450 else if (strcmp(value, "BROADCAST") == 0) 451 self->client.filter_type |= IRLAN_BROADCAST; 452 else if (strcmp(value, "IPX_SOCKET") == 0) 453 self->client.filter_type |= IRLAN_IPX_SOCKET; 454 455 } 456 if (strcmp(param, "ACCESS_TYPE") == 0) { 457 if (strcmp(value, "DIRECT") == 0) 458 self->client.access_type = ACCESS_DIRECT; 459 else if (strcmp(value, "PEER") == 0) 460 self->client.access_type = ACCESS_PEER; 461 else if (strcmp(value, "HOSTED") == 0) 462 self->client.access_type = ACCESS_HOSTED; 463 else { 464 pr_debug("%s(), unknown access type!\n", __func__); 465 } 466 } 467 /* IRLAN version */ 468 if (strcmp(param, "IRLAN_VER") == 0) { 469 pr_debug("IrLAN version %d.%d\n", (__u8)value[0], 470 (__u8)value[1]); 471 472 self->version[0] = value[0]; 473 self->version[1] = value[1]; 474 return; 475 } 476 /* Which remote TSAP to use for data channel */ 477 if (strcmp(param, "DATA_CHAN") == 0) { 478 self->dtsap_sel_data = value[0]; 479 pr_debug("Data TSAP = %02x\n", self->dtsap_sel_data); 480 return; 481 } 482 if (strcmp(param, "CON_ARB") == 0) { 483 memcpy(&tmp_cpu, value, 2); /* Align value */ 484 le16_to_cpus(&tmp_cpu); /* Convert to host order */ 485 self->client.recv_arb_val = tmp_cpu; 486 pr_debug("%s(), receive arb val=%d\n", __func__ , 487 self->client.recv_arb_val); 488 } 489 if (strcmp(param, "MAX_FRAME") == 0) { 490 memcpy(&tmp_cpu, value, 2); /* Align value */ 491 le16_to_cpus(&tmp_cpu); /* Convert to host order */ 492 self->client.max_frame = tmp_cpu; 493 pr_debug("%s(), max frame=%d\n", __func__ , 494 self->client.max_frame); 495 } 496 497 /* RECONNECT_KEY, in case the link goes down! */ 498 if (strcmp(param, "RECONNECT_KEY") == 0) { 499 pr_debug("Got reconnect key: "); 500 /* for (i = 0; i < val_len; i++) */ 501/* printk("%02x", value[i]); */ 502 memcpy(self->client.reconnect_key, value, val_len); 503 self->client.key_len = val_len; 504 pr_debug("\n"); 505 } 506 /* FILTER_ENTRY, have we got an ethernet address? */ 507 if (strcmp(param, "FILTER_ENTRY") == 0) { 508 bytes = value; 509 pr_debug("Ethernet address = %pM\n", bytes); 510 for (i = 0; i < 6; i++) 511 self->dev->dev_addr[i] = bytes[i]; 512 } 513} 514 515/* 516 * Function irlan_client_get_value_confirm (obj_id, value) 517 * 518 * Got results from remote LM-IAS 519 * 520 */ 521void irlan_client_get_value_confirm(int result, __u16 obj_id, 522 struct ias_value *value, void *priv) 523{ 524 struct irlan_cb *self; 525 526 IRDA_ASSERT(priv != NULL, return;); 527 528 self = priv; 529 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); 530 531 /* We probably don't need to make any more queries */ 532 iriap_close(self->client.iriap); 533 self->client.iriap = NULL; 534 535 /* Check if request succeeded */ 536 if (result != IAS_SUCCESS) { 537 pr_debug("%s(), got NULL value!\n", __func__); 538 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, 539 NULL); 540 return; 541 } 542 543 switch (value->type) { 544 case IAS_INTEGER: 545 self->dtsap_sel_ctrl = value->t.integer; 546 547 if (value->t.integer != -1) { 548 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL, 549 NULL); 550 return; 551 } 552 irias_delete_value(value); 553 break; 554 default: 555 pr_debug("%s(), unknown type!\n", __func__); 556 break; 557 } 558 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL); 559} 560