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 
58 static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
59 						    LM_REASON reason,
60 						    struct sk_buff *);
61 static int irlan_client_ctrl_data_indication(void *instance, void *sap,
62 					     struct sk_buff *skb);
63 static 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 *);
68 static void irlan_check_response_param(struct irlan_cb *self, char *param,
69 				       char *value, int val_len);
70 static void irlan_client_open_ctrl_tsap(struct irlan_cb *self);
71 
irlan_client_kick_timer_expired(void * data)72 static 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 
irlan_client_start_kick_timer(struct irlan_cb * self,int timeout)93 static 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  */
irlan_client_wakeup(struct irlan_cb * self,__u32 saddr,__u32 daddr)107 void 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  */
irlan_client_discovery_indication(discinfo_t * discovery,DISCOVERY_MODE mode,void * priv)150 void 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 	/*
162 	 * I didn't check it, but I bet that IrLAN suffer from the same
163 	 * deficiency as IrComm and doesn't handle two instances
164 	 * simultaneously connecting to each other.
165 	 * Same workaround, drop passive discoveries.
166 	 * Jean II */
167 	if(mode == DISCOVERY_PASSIVE)
168 		return;
169 
170 	saddr = discovery->saddr;
171 	daddr = discovery->daddr;
172 
173 	/* Find instance */
174 	rcu_read_lock();
175 	self = irlan_get_any();
176 	if (self) {
177 		IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;);
178 
179 		IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __func__ ,
180 		      daddr);
181 
182 		irlan_client_wakeup(self, saddr, daddr);
183 	}
184 IRDA_ASSERT_LABEL(out:)
185 	rcu_read_unlock();
186 }
187 
188 /*
189  * Function irlan_client_data_indication (handle, skb)
190  *
191  *    This function gets the data that is received on the control channel
192  *
193  */
irlan_client_ctrl_data_indication(void * instance,void * sap,struct sk_buff * skb)194 static int irlan_client_ctrl_data_indication(void *instance, void *sap,
195 					     struct sk_buff *skb)
196 {
197 	struct irlan_cb *self;
198 
199 	IRDA_DEBUG(2, "%s()\n", __func__ );
200 
201 	self = (struct irlan_cb *) instance;
202 
203 	IRDA_ASSERT(self != NULL, return -1;);
204 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
205 	IRDA_ASSERT(skb != NULL, return -1;);
206 
207 	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
208 
209 	/* Ready for a new command */
210 	IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __func__ );
211 	self->client.tx_busy = FALSE;
212 
213 	/* Check if we have some queued commands waiting to be sent */
214 	irlan_run_ctrl_tx_queue(self);
215 
216 	return 0;
217 }
218 
irlan_client_ctrl_disconnect_indication(void * instance,void * sap,LM_REASON reason,struct sk_buff * userdata)219 static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
220 						    LM_REASON reason,
221 						    struct sk_buff *userdata)
222 {
223 	struct irlan_cb *self;
224 	struct tsap_cb *tsap;
225 	struct sk_buff *skb;
226 
227 	IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
228 
229 	self = (struct irlan_cb *) instance;
230 	tsap = (struct tsap_cb *) sap;
231 
232 	IRDA_ASSERT(self != NULL, return;);
233 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
234 	IRDA_ASSERT(tsap != NULL, return;);
235 	IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
236 
237 	IRDA_ASSERT(tsap == self->client.tsap_ctrl, return;);
238 
239 	/* Remove frames queued on the control channel */
240 	while ((skb = skb_dequeue(&self->client.txq)) != NULL) {
241 		dev_kfree_skb(skb);
242 	}
243 	self->client.tx_busy = FALSE;
244 
245 	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
246 }
247 
248 /*
249  * Function irlan_client_open_tsaps (self)
250  *
251  *    Initialize callbacks and open IrTTP TSAPs
252  *
253  */
irlan_client_open_ctrl_tsap(struct irlan_cb * self)254 static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
255 {
256 	struct tsap_cb *tsap;
257 	notify_t notify;
258 
259 	IRDA_DEBUG(4, "%s()\n", __func__ );
260 
261 	IRDA_ASSERT(self != NULL, return;);
262 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
263 
264 	/* Check if already open */
265 	if (self->client.tsap_ctrl)
266 		return;
267 
268 	irda_notify_init(&notify);
269 
270 	/* Set up callbacks */
271 	notify.data_indication       = irlan_client_ctrl_data_indication;
272 	notify.connect_confirm       = irlan_client_ctrl_connect_confirm;
273 	notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
274 	notify.instance = self;
275 	strlcpy(notify.name, "IrLAN ctrl (c)", sizeof(notify.name));
276 
277 	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
278 	if (!tsap) {
279 		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
280 		return;
281 	}
282 	self->client.tsap_ctrl = tsap;
283 }
284 
285 /*
286  * Function irlan_client_connect_confirm (handle, skb)
287  *
288  *    Connection to peer IrLAN laye confirmed
289  *
290  */
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)291 static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
292 					      struct qos_info *qos,
293 					      __u32 max_sdu_size,
294 					      __u8 max_header_size,
295 					      struct sk_buff *skb)
296 {
297 	struct irlan_cb *self;
298 
299 	IRDA_DEBUG(4, "%s()\n", __func__ );
300 
301 	self = (struct irlan_cb *) instance;
302 
303 	IRDA_ASSERT(self != NULL, return;);
304 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
305 
306 	self->client.max_sdu_size = max_sdu_size;
307 	self->client.max_header_size = max_header_size;
308 
309 	/* TODO: we could set the MTU depending on the max_sdu_size */
310 
311 	irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
312 }
313 
314 /*
315  * Function print_ret_code (code)
316  *
317  *    Print return code of request to peer IrLAN layer.
318  *
319  */
print_ret_code(__u8 code)320 static void print_ret_code(__u8 code)
321 {
322 	switch(code) {
323 	case 0:
324 		printk(KERN_INFO "Success\n");
325 		break;
326 	case 1:
327 		IRDA_WARNING("IrLAN: Insufficient resources\n");
328 		break;
329 	case 2:
330 		IRDA_WARNING("IrLAN: Invalid command format\n");
331 		break;
332 	case 3:
333 		IRDA_WARNING("IrLAN: Command not supported\n");
334 		break;
335 	case 4:
336 		IRDA_WARNING("IrLAN: Parameter not supported\n");
337 		break;
338 	case 5:
339 		IRDA_WARNING("IrLAN: Value not supported\n");
340 		break;
341 	case 6:
342 		IRDA_WARNING("IrLAN: Not open\n");
343 		break;
344 	case 7:
345 		IRDA_WARNING("IrLAN: Authentication required\n");
346 		break;
347 	case 8:
348 		IRDA_WARNING("IrLAN: Invalid password\n");
349 		break;
350 	case 9:
351 		IRDA_WARNING("IrLAN: Protocol error\n");
352 		break;
353 	case 255:
354 		IRDA_WARNING("IrLAN: Asynchronous status\n");
355 		break;
356 	}
357 }
358 
359 /*
360  * Function irlan_client_parse_response (self, skb)
361  *
362  *    Extract all parameters from received buffer, then feed them to
363  *    check_params for parsing
364  */
irlan_client_parse_response(struct irlan_cb * self,struct sk_buff * skb)365 void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
366 {
367 	__u8 *frame;
368 	__u8 *ptr;
369 	int count;
370 	int ret;
371 	__u16 val_len;
372 	int i;
373 	char *name;
374 	char *value;
375 
376 	IRDA_ASSERT(skb != NULL, return;);
377 
378 	IRDA_DEBUG(4, "%s() skb->len=%d\n", __func__ , (int) skb->len);
379 
380 	IRDA_ASSERT(self != NULL, return;);
381 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
382 
383 	if (!skb) {
384 		IRDA_ERROR("%s(), Got NULL skb!\n", __func__);
385 		return;
386 	}
387 	frame = skb->data;
388 
389 	/*
390 	 *  Check return code and print it if not success
391 	 */
392 	if (frame[0]) {
393 		print_ret_code(frame[0]);
394 		return;
395 	}
396 
397 	name = kmalloc(255, GFP_ATOMIC);
398 	if (!name)
399 		return;
400 	value = kmalloc(1016, GFP_ATOMIC);
401 	if (!value) {
402 		kfree(name);
403 		return;
404 	}
405 
406 	/* How many parameters? */
407 	count = frame[1];
408 
409 	IRDA_DEBUG(4, "%s(), got %d parameters\n", __func__ , count);
410 
411 	ptr = frame+2;
412 
413 	/* For all parameters */
414 	for (i=0; i<count;i++) {
415 		ret = irlan_extract_param(ptr, name, value, &val_len);
416 		if (ret < 0) {
417 			IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __func__ );
418 			break;
419 		}
420 		ptr += ret;
421 		irlan_check_response_param(self, name, value, val_len);
422 	}
423 	/* Cleanup */
424 	kfree(name);
425 	kfree(value);
426 }
427 
428 /*
429  * Function irlan_check_response_param (self, param, value, val_len)
430  *
431  *     Check which parameter is received and update local variables
432  *
433  */
irlan_check_response_param(struct irlan_cb * self,char * param,char * value,int val_len)434 static void irlan_check_response_param(struct irlan_cb *self, char *param,
435 				       char *value, int val_len)
436 {
437 	__u16 tmp_cpu; /* Temporary value in host order */
438 	__u8 *bytes;
439 	int i;
440 
441 	IRDA_DEBUG(4, "%s(), parm=%s\n", __func__ , param);
442 
443 	IRDA_ASSERT(self != NULL, return;);
444 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
445 
446 	/* Media type */
447 	if (strcmp(param, "MEDIA") == 0) {
448 		if (strcmp(value, "802.3") == 0)
449 			self->media = MEDIA_802_3;
450 		else
451 			self->media = MEDIA_802_5;
452 		return;
453 	}
454 	if (strcmp(param, "FILTER_TYPE") == 0) {
455 		if (strcmp(value, "DIRECTED") == 0)
456 			self->client.filter_type |= IRLAN_DIRECTED;
457 		else if (strcmp(value, "FUNCTIONAL") == 0)
458 			self->client.filter_type |= IRLAN_FUNCTIONAL;
459 		else if (strcmp(value, "GROUP") == 0)
460 			self->client.filter_type |= IRLAN_GROUP;
461 		else if (strcmp(value, "MAC_FRAME") == 0)
462 			self->client.filter_type |= IRLAN_MAC_FRAME;
463 		else if (strcmp(value, "MULTICAST") == 0)
464 			self->client.filter_type |= IRLAN_MULTICAST;
465 		else if (strcmp(value, "BROADCAST") == 0)
466 			self->client.filter_type |= IRLAN_BROADCAST;
467 		else if (strcmp(value, "IPX_SOCKET") == 0)
468 			self->client.filter_type |= IRLAN_IPX_SOCKET;
469 
470 	}
471 	if (strcmp(param, "ACCESS_TYPE") == 0) {
472 		if (strcmp(value, "DIRECT") == 0)
473 			self->client.access_type = ACCESS_DIRECT;
474 		else if (strcmp(value, "PEER") == 0)
475 			self->client.access_type = ACCESS_PEER;
476 		else if (strcmp(value, "HOSTED") == 0)
477 			self->client.access_type = ACCESS_HOSTED;
478 		else {
479 			IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
480 		}
481 	}
482 	/* IRLAN version */
483 	if (strcmp(param, "IRLAN_VER") == 0) {
484 		IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0],
485 		      (__u8) value[1]);
486 
487 		self->version[0] = value[0];
488 		self->version[1] = value[1];
489 		return;
490 	}
491 	/* Which remote TSAP to use for data channel */
492 	if (strcmp(param, "DATA_CHAN") == 0) {
493 		self->dtsap_sel_data = value[0];
494 		IRDA_DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
495 		return;
496 	}
497 	if (strcmp(param, "CON_ARB") == 0) {
498 		memcpy(&tmp_cpu, value, 2); /* Align value */
499 		le16_to_cpus(&tmp_cpu);     /* Convert to host order */
500 		self->client.recv_arb_val = tmp_cpu;
501 		IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __func__ ,
502 			   self->client.recv_arb_val);
503 	}
504 	if (strcmp(param, "MAX_FRAME") == 0) {
505 		memcpy(&tmp_cpu, value, 2); /* Align value */
506 		le16_to_cpus(&tmp_cpu);     /* Convert to host order */
507 		self->client.max_frame = tmp_cpu;
508 		IRDA_DEBUG(4, "%s(), max frame=%d\n", __func__ ,
509 			   self->client.max_frame);
510 	}
511 
512 	/* RECONNECT_KEY, in case the link goes down! */
513 	if (strcmp(param, "RECONNECT_KEY") == 0) {
514 		IRDA_DEBUG(4, "Got reconnect key: ");
515 		/* for (i = 0; i < val_len; i++) */
516 /* 			printk("%02x", value[i]); */
517 		memcpy(self->client.reconnect_key, value, val_len);
518 		self->client.key_len = val_len;
519 		IRDA_DEBUG(4, "\n");
520 	}
521 	/* FILTER_ENTRY, have we got an ethernet address? */
522 	if (strcmp(param, "FILTER_ENTRY") == 0) {
523 		bytes = value;
524 		IRDA_DEBUG(4, "Ethernet address = %pM\n", bytes);
525 		for (i = 0; i < 6; i++)
526 			self->dev->dev_addr[i] = bytes[i];
527 	}
528 }
529 
530 /*
531  * Function irlan_client_get_value_confirm (obj_id, value)
532  *
533  *    Got results from remote LM-IAS
534  *
535  */
irlan_client_get_value_confirm(int result,__u16 obj_id,struct ias_value * value,void * priv)536 void irlan_client_get_value_confirm(int result, __u16 obj_id,
537 				    struct ias_value *value, void *priv)
538 {
539 	struct irlan_cb *self;
540 
541 	IRDA_DEBUG(4, "%s()\n", __func__ );
542 
543 	IRDA_ASSERT(priv != NULL, return;);
544 
545 	self = (struct irlan_cb *) priv;
546 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
547 
548 	/* We probably don't need to make any more queries */
549 	iriap_close(self->client.iriap);
550 	self->client.iriap = NULL;
551 
552 	/* Check if request succeeded */
553 	if (result != IAS_SUCCESS) {
554 		IRDA_DEBUG(2, "%s(), got NULL value!\n", __func__ );
555 		irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
556 				      NULL);
557 		return;
558 	}
559 
560 	switch (value->type) {
561 	case IAS_INTEGER:
562 		self->dtsap_sel_ctrl = value->t.integer;
563 
564 		if (value->t.integer != -1) {
565 			irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
566 					      NULL);
567 			return;
568 		}
569 		irias_delete_value(value);
570 		break;
571 	default:
572 		IRDA_DEBUG(2, "%s(), unknown type!\n", __func__ );
573 		break;
574 	}
575 	irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
576 }
577