1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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_DEBUG(2, "%s()\n", __func__ );
76
77 IRDA_ASSERT(self != NULL, return;);
78 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
79
80
81
82
83
84
85 if ((self->provider.access_type == ACCESS_PEER) &&
86 (self->client.state == IRLAN_IDLE) &&
87 (self->provider.state != IRLAN_IDLE)) {
88 irlan_client_wakeup(self, self->saddr, self->daddr);
89 }
90}
91
92static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
93{
94 IRDA_DEBUG(4, "%s()\n", __func__ );
95
96 irda_start_timer(&self->client.kick_timer, timeout, (void *) self,
97 irlan_client_kick_timer_expired);
98}
99
100
101
102
103
104
105
106void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
107{
108 IRDA_DEBUG(1, "%s()\n", __func__ );
109
110 IRDA_ASSERT(self != NULL, return;);
111 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
112
113
114
115
116
117 if ((self->client.state != IRLAN_IDLE) ||
118 (self->provider.access_type == ACCESS_DIRECT))
119 {
120 IRDA_DEBUG(0, "%s(), already awake!\n", __func__ );
121 return;
122 }
123
124
125 self->saddr = saddr;
126 self->daddr = daddr;
127
128 if (self->disconnect_reason == LM_USER_REQUEST) {
129 IRDA_DEBUG(0, "%s(), still stopped by user\n", __func__ );
130 return;
131 }
132
133
134 irlan_client_open_ctrl_tsap(self);
135 irlan_open_data_tsap(self);
136
137 irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL);
138
139
140 irlan_client_start_kick_timer(self, 2*HZ);
141}
142
143
144
145
146
147
148
149void irlan_client_discovery_indication(discinfo_t *discovery,
150 DISCOVERY_MODE mode,
151 void *priv)
152{
153 struct irlan_cb *self;
154 __u32 saddr, daddr;
155
156 IRDA_DEBUG(1, "%s()\n", __func__ );
157
158 IRDA_ASSERT(discovery != NULL, return;);
159
160
161
162
163
164
165
166 if(mode == DISCOVERY_PASSIVE)
167 return;
168
169 saddr = discovery->saddr;
170 daddr = discovery->daddr;
171
172
173 rcu_read_lock();
174 self = irlan_get_any();
175 if (self) {
176 IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;);
177
178 IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __func__ ,
179 daddr);
180
181 irlan_client_wakeup(self, saddr, daddr);
182 }
183IRDA_ASSERT_LABEL(out:)
184 rcu_read_unlock();
185}
186
187
188
189
190
191
192
193static int irlan_client_ctrl_data_indication(void *instance, void *sap,
194 struct sk_buff *skb)
195{
196 struct irlan_cb *self;
197
198 IRDA_DEBUG(2, "%s()\n", __func__ );
199
200 self = instance;
201
202 IRDA_ASSERT(self != NULL, return -1;);
203 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
204 IRDA_ASSERT(skb != NULL, return -1;);
205
206 irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
207
208
209 IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __func__ );
210 self->client.tx_busy = FALSE;
211
212
213 irlan_run_ctrl_tx_queue(self);
214
215 return 0;
216}
217
218static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
219 LM_REASON reason,
220 struct sk_buff *userdata)
221{
222 struct irlan_cb *self;
223 struct tsap_cb *tsap;
224 struct sk_buff *skb;
225
226 IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
227
228 self = instance;
229 tsap = sap;
230
231 IRDA_ASSERT(self != NULL, return;);
232 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
233 IRDA_ASSERT(tsap != NULL, return;);
234 IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
235
236 IRDA_ASSERT(tsap == self->client.tsap_ctrl, return;);
237
238
239 while ((skb = skb_dequeue(&self->client.txq)) != NULL) {
240 dev_kfree_skb(skb);
241 }
242 self->client.tx_busy = FALSE;
243
244 irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
245}
246
247
248
249
250
251
252
253static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
254{
255 struct tsap_cb *tsap;
256 notify_t notify;
257
258 IRDA_DEBUG(4, "%s()\n", __func__ );
259
260 IRDA_ASSERT(self != NULL, return;);
261 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
262
263
264 if (self->client.tsap_ctrl)
265 return;
266
267 irda_notify_init(¬ify);
268
269
270 notify.data_indication = irlan_client_ctrl_data_indication;
271 notify.connect_confirm = irlan_client_ctrl_connect_confirm;
272 notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
273 notify.instance = self;
274 strlcpy(notify.name, "IrLAN ctrl (c)", sizeof(notify.name));
275
276 tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify);
277 if (!tsap) {
278 IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
279 return;
280 }
281 self->client.tsap_ctrl = tsap;
282}
283
284
285
286
287
288
289
290static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
291 struct qos_info *qos,
292 __u32 max_sdu_size,
293 __u8 max_header_size,
294 struct sk_buff *skb)
295{
296 struct irlan_cb *self;
297
298 IRDA_DEBUG(4, "%s()\n", __func__ );
299
300 self = instance;
301
302 IRDA_ASSERT(self != NULL, return;);
303 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
304
305 self->client.max_sdu_size = max_sdu_size;
306 self->client.max_header_size = max_header_size;
307
308
309
310 irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
311}
312
313
314
315
316
317
318
319static void print_ret_code(__u8 code)
320{
321 switch(code) {
322 case 0:
323 printk(KERN_INFO "Success\n");
324 break;
325 case 1:
326 IRDA_WARNING("IrLAN: Insufficient resources\n");
327 break;
328 case 2:
329 IRDA_WARNING("IrLAN: Invalid command format\n");
330 break;
331 case 3:
332 IRDA_WARNING("IrLAN: Command not supported\n");
333 break;
334 case 4:
335 IRDA_WARNING("IrLAN: Parameter not supported\n");
336 break;
337 case 5:
338 IRDA_WARNING("IrLAN: Value not supported\n");
339 break;
340 case 6:
341 IRDA_WARNING("IrLAN: Not open\n");
342 break;
343 case 7:
344 IRDA_WARNING("IrLAN: Authentication required\n");
345 break;
346 case 8:
347 IRDA_WARNING("IrLAN: Invalid password\n");
348 break;
349 case 9:
350 IRDA_WARNING("IrLAN: Protocol error\n");
351 break;
352 case 255:
353 IRDA_WARNING("IrLAN: Asynchronous status\n");
354 break;
355 }
356}
357
358
359
360
361
362
363
364void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
365{
366 __u8 *frame;
367 __u8 *ptr;
368 int count;
369 int ret;
370 __u16 val_len;
371 int i;
372 char *name;
373 char *value;
374
375 IRDA_ASSERT(skb != NULL, return;);
376
377 IRDA_DEBUG(4, "%s() skb->len=%d\n", __func__ , (int) skb->len);
378
379 IRDA_ASSERT(self != NULL, return;);
380 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
381
382 if (!skb) {
383 IRDA_ERROR("%s(), Got NULL skb!\n", __func__);
384 return;
385 }
386 frame = skb->data;
387
388
389
390
391 if (frame[0]) {
392 print_ret_code(frame[0]);
393 return;
394 }
395
396 name = kmalloc(255, GFP_ATOMIC);
397 if (!name)
398 return;
399 value = kmalloc(1016, GFP_ATOMIC);
400 if (!value) {
401 kfree(name);
402 return;
403 }
404
405
406 count = frame[1];
407
408 IRDA_DEBUG(4, "%s(), got %d parameters\n", __func__ , count);
409
410 ptr = frame+2;
411
412
413 for (i=0; i<count;i++) {
414 ret = irlan_extract_param(ptr, name, value, &val_len);
415 if (ret < 0) {
416 IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __func__ );
417 break;
418 }
419 ptr += ret;
420 irlan_check_response_param(self, name, value, val_len);
421 }
422
423 kfree(name);
424 kfree(value);
425}
426
427
428
429
430
431
432
433static void irlan_check_response_param(struct irlan_cb *self, char *param,
434 char *value, int val_len)
435{
436 __u16 tmp_cpu;
437 __u8 *bytes;
438 int i;
439
440 IRDA_DEBUG(4, "%s(), parm=%s\n", __func__ , param);
441
442 IRDA_ASSERT(self != NULL, return;);
443 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
444
445
446 if (strcmp(param, "MEDIA") == 0) {
447 if (strcmp(value, "802.3") == 0)
448 self->media = MEDIA_802_3;
449 else
450 self->media = MEDIA_802_5;
451 return;
452 }
453 if (strcmp(param, "FILTER_TYPE") == 0) {
454 if (strcmp(value, "DIRECTED") == 0)
455 self->client.filter_type |= IRLAN_DIRECTED;
456 else if (strcmp(value, "FUNCTIONAL") == 0)
457 self->client.filter_type |= IRLAN_FUNCTIONAL;
458 else if (strcmp(value, "GROUP") == 0)
459 self->client.filter_type |= IRLAN_GROUP;
460 else if (strcmp(value, "MAC_FRAME") == 0)
461 self->client.filter_type |= IRLAN_MAC_FRAME;
462 else if (strcmp(value, "MULTICAST") == 0)
463 self->client.filter_type |= IRLAN_MULTICAST;
464 else if (strcmp(value, "BROADCAST") == 0)
465 self->client.filter_type |= IRLAN_BROADCAST;
466 else if (strcmp(value, "IPX_SOCKET") == 0)
467 self->client.filter_type |= IRLAN_IPX_SOCKET;
468
469 }
470 if (strcmp(param, "ACCESS_TYPE") == 0) {
471 if (strcmp(value, "DIRECT") == 0)
472 self->client.access_type = ACCESS_DIRECT;
473 else if (strcmp(value, "PEER") == 0)
474 self->client.access_type = ACCESS_PEER;
475 else if (strcmp(value, "HOSTED") == 0)
476 self->client.access_type = ACCESS_HOSTED;
477 else {
478 IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
479 }
480 }
481
482 if (strcmp(param, "IRLAN_VER") == 0) {
483 IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0],
484 (__u8) value[1]);
485
486 self->version[0] = value[0];
487 self->version[1] = value[1];
488 return;
489 }
490
491 if (strcmp(param, "DATA_CHAN") == 0) {
492 self->dtsap_sel_data = value[0];
493 IRDA_DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
494 return;
495 }
496 if (strcmp(param, "CON_ARB") == 0) {
497 memcpy(&tmp_cpu, value, 2);
498 le16_to_cpus(&tmp_cpu);
499 self->client.recv_arb_val = tmp_cpu;
500 IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __func__ ,
501 self->client.recv_arb_val);
502 }
503 if (strcmp(param, "MAX_FRAME") == 0) {
504 memcpy(&tmp_cpu, value, 2);
505 le16_to_cpus(&tmp_cpu);
506 self->client.max_frame = tmp_cpu;
507 IRDA_DEBUG(4, "%s(), max frame=%d\n", __func__ ,
508 self->client.max_frame);
509 }
510
511
512 if (strcmp(param, "RECONNECT_KEY") == 0) {
513 IRDA_DEBUG(4, "Got reconnect key: ");
514
515
516 memcpy(self->client.reconnect_key, value, val_len);
517 self->client.key_len = val_len;
518 IRDA_DEBUG(4, "\n");
519 }
520
521 if (strcmp(param, "FILTER_ENTRY") == 0) {
522 bytes = value;
523 IRDA_DEBUG(4, "Ethernet address = %pM\n", bytes);
524 for (i = 0; i < 6; i++)
525 self->dev->dev_addr[i] = bytes[i];
526 }
527}
528
529
530
531
532
533
534
535void irlan_client_get_value_confirm(int result, __u16 obj_id,
536 struct ias_value *value, void *priv)
537{
538 struct irlan_cb *self;
539
540 IRDA_DEBUG(4, "%s()\n", __func__ );
541
542 IRDA_ASSERT(priv != NULL, return;);
543
544 self = priv;
545 IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
546
547
548 iriap_close(self->client.iriap);
549 self->client.iriap = NULL;
550
551
552 if (result != IAS_SUCCESS) {
553 IRDA_DEBUG(2, "%s(), got NULL value!\n", __func__ );
554 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
555 NULL);
556 return;
557 }
558
559 switch (value->type) {
560 case IAS_INTEGER:
561 self->dtsap_sel_ctrl = value->t.integer;
562
563 if (value->t.integer != -1) {
564 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
565 NULL);
566 return;
567 }
568 irias_delete_value(value);
569 break;
570 default:
571 IRDA_DEBUG(2, "%s(), unknown type!\n", __func__ );
572 break;
573 }
574 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
575}
576