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