• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
57 static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
58 						    LM_REASON reason,
59 						    struct sk_buff *);
60 static int irlan_client_ctrl_data_indication(void *instance, void *sap,
61 					     struct sk_buff *skb);
62 static 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 *);
67 static void irlan_check_response_param(struct irlan_cb *self, char *param,
68 				       char *value, int val_len);
69 static void irlan_client_open_ctrl_tsap(struct irlan_cb *self);
70 
irlan_client_kick_timer_expired(void * data)71 static 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 
irlan_client_start_kick_timer(struct irlan_cb * self,int timeout)90 static 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  */
irlan_client_wakeup(struct irlan_cb * self,__u32 saddr,__u32 daddr)102 void 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  */
irlan_client_discovery_indication(discinfo_t * discovery,DISCOVERY_MODE mode,void * priv)143 void 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 	}
175 IRDA_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  */
irlan_client_ctrl_data_indication(void * instance,void * sap,struct sk_buff * skb)185 static 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 
irlan_client_ctrl_disconnect_indication(void * instance,void * sap,LM_REASON reason,struct sk_buff * userdata)208 static 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  */
irlan_client_open_ctrl_tsap(struct irlan_cb * self)243 static 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(&notify);
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, &notify);
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  */
irlan_client_ctrl_connect_confirm(void * instance,void * sap,struct qos_info * qos,__u32 max_sdu_size,__u8 max_header_size,struct sk_buff * skb)278 static 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  */
print_ret_code(__u8 code)305 static 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  */
irlan_client_parse_response(struct irlan_cb * self,struct sk_buff * skb)350 void 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  */
irlan_check_response_param(struct irlan_cb * self,char * param,char * value,int val_len)419 static 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  */
irlan_client_get_value_confirm(int result,__u16 obj_id,struct ias_value * value,void * priv)521 void 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