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