Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
irlan_filter.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Filename: irlan_filter.c
4  * Version:
5  * Description:
6  * Status: Experimental.
7  * Author: Dag Brattli <[email protected]>
8  * Created at: Fri Jan 29 11:16:38 1999
9  * Modified at: Sat Oct 30 12:58:45 1999
10  * Modified by: Dag Brattli <[email protected]>
11  *
12  * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2 of
17  * the License, or (at your option) any later version.
18  *
19  * Neither Dag Brattli nor University of Tromsø admit liability nor
20  * provide warranty for any of this software. This material is
21  * provided "AS-IS" and at no charge.
22  *
23  ********************************************************************/
24 
25 #include <linux/skbuff.h>
26 #include <linux/random.h>
27 #include <linux/seq_file.h>
28 
29 #include <net/irda/irlan_common.h>
30 #include <net/irda/irlan_filter.h>
31 
32 /*
33  * Function irlan_filter_request (self, skb)
34  *
35  * Handle filter request from client peer device
36  *
37  */
38 void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb)
39 {
40  IRDA_ASSERT(self != NULL, return;);
41  IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
42 
43  if ((self->provider.filter_type == IRLAN_DIRECTED) &&
44  (self->provider.filter_operation == DYNAMIC))
45  {
46  IRDA_DEBUG(0, "Giving peer a dynamic Ethernet address\n");
47  self->provider.mac_address[0] = 0x40;
48  self->provider.mac_address[1] = 0x00;
49  self->provider.mac_address[2] = 0x00;
50  self->provider.mac_address[3] = 0x00;
51 
52  /* Use arbitration value to generate MAC address */
53  if (self->provider.access_type == ACCESS_PEER) {
54  self->provider.mac_address[4] =
55  self->provider.send_arb_val & 0xff;
56  self->provider.mac_address[5] =
57  (self->provider.send_arb_val >> 8) & 0xff;
58  } else {
59  /* Just generate something for now */
60  get_random_bytes(self->provider.mac_address+4, 1);
61  get_random_bytes(self->provider.mac_address+5, 1);
62  }
63 
64  skb->data[0] = 0x00; /* Success */
65  skb->data[1] = 0x03;
66  irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
67  irlan_insert_short_param(skb, "MAX_ENTRY", 0x0001);
68  irlan_insert_array_param(skb, "FILTER_ENTRY",
69  self->provider.mac_address, 6);
70  return;
71  }
72 
73  if ((self->provider.filter_type == IRLAN_DIRECTED) &&
74  (self->provider.filter_mode == FILTER))
75  {
76  IRDA_DEBUG(0, "Directed filter on\n");
77  skb->data[0] = 0x00; /* Success */
78  skb->data[1] = 0x00;
79  return;
80  }
81  if ((self->provider.filter_type == IRLAN_DIRECTED) &&
82  (self->provider.filter_mode == NONE))
83  {
84  IRDA_DEBUG(0, "Directed filter off\n");
85  skb->data[0] = 0x00; /* Success */
86  skb->data[1] = 0x00;
87  return;
88  }
89 
90  if ((self->provider.filter_type == IRLAN_BROADCAST) &&
91  (self->provider.filter_mode == FILTER))
92  {
93  IRDA_DEBUG(0, "Broadcast filter on\n");
94  skb->data[0] = 0x00; /* Success */
95  skb->data[1] = 0x00;
96  return;
97  }
98  if ((self->provider.filter_type == IRLAN_BROADCAST) &&
99  (self->provider.filter_mode == NONE))
100  {
101  IRDA_DEBUG(0, "Broadcast filter off\n");
102  skb->data[0] = 0x00; /* Success */
103  skb->data[1] = 0x00;
104  return;
105  }
106  if ((self->provider.filter_type == IRLAN_MULTICAST) &&
107  (self->provider.filter_mode == FILTER))
108  {
109  IRDA_DEBUG(0, "Multicast filter on\n");
110  skb->data[0] = 0x00; /* Success */
111  skb->data[1] = 0x00;
112  return;
113  }
114  if ((self->provider.filter_type == IRLAN_MULTICAST) &&
115  (self->provider.filter_mode == NONE))
116  {
117  IRDA_DEBUG(0, "Multicast filter off\n");
118  skb->data[0] = 0x00; /* Success */
119  skb->data[1] = 0x00;
120  return;
121  }
122  if ((self->provider.filter_type == IRLAN_MULTICAST) &&
123  (self->provider.filter_operation == GET))
124  {
125  IRDA_DEBUG(0, "Multicast filter get\n");
126  skb->data[0] = 0x00; /* Success? */
127  skb->data[1] = 0x02;
128  irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
129  irlan_insert_short_param(skb, "MAX_ENTRY", 16);
130  return;
131  }
132  skb->data[0] = 0x00; /* Command not supported */
133  skb->data[1] = 0x00;
134 
135  IRDA_DEBUG(0, "Not implemented!\n");
136 }
137 
138 /*
139  * Function check_request_param (self, param, value)
140  *
141  * Check parameters in request from peer device
142  *
143  */
144 void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
145 {
146  IRDA_DEBUG(4, "%s()\n", __func__ );
147 
148  IRDA_ASSERT(self != NULL, return;);
149  IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
150 
151  IRDA_DEBUG(4, "%s, %s\n", param, value);
152 
153  /*
154  * This is experimental!! DB.
155  */
156  if (strcmp(param, "MODE") == 0) {
157  IRDA_DEBUG(0, "%s()\n", __func__ );
158  self->use_udata = TRUE;
159  return;
160  }
161 
162  /*
163  * FILTER_TYPE
164  */
165  if (strcmp(param, "FILTER_TYPE") == 0) {
166  if (strcmp(value, "DIRECTED") == 0) {
167  self->provider.filter_type = IRLAN_DIRECTED;
168  return;
169  }
170  if (strcmp(value, "MULTICAST") == 0) {
171  self->provider.filter_type = IRLAN_MULTICAST;
172  return;
173  }
174  if (strcmp(value, "BROADCAST") == 0) {
175  self->provider.filter_type = IRLAN_BROADCAST;
176  return;
177  }
178  }
179  /*
180  * FILTER_MODE
181  */
182  if (strcmp(param, "FILTER_MODE") == 0) {
183  if (strcmp(value, "ALL") == 0) {
184  self->provider.filter_mode = ALL;
185  return;
186  }
187  if (strcmp(value, "FILTER") == 0) {
188  self->provider.filter_mode = FILTER;
189  return;
190  }
191  if (strcmp(value, "NONE") == 0) {
192  self->provider.filter_mode = FILTER;
193  return;
194  }
195  }
196  /*
197  * FILTER_OPERATION
198  */
199  if (strcmp(param, "FILTER_OPERATION") == 0) {
200  if (strcmp(value, "DYNAMIC") == 0) {
201  self->provider.filter_operation = DYNAMIC;
202  return;
203  }
204  if (strcmp(value, "GET") == 0) {
205  self->provider.filter_operation = GET;
206  return;
207  }
208  }
209 }
210 
211 /*
212  * Function irlan_print_filter (filter_type, buf)
213  *
214  * Print status of filter. Used by /proc file system
215  *
216  */
217 #ifdef CONFIG_PROC_FS
218 #define MASK2STR(m,s) { .mask = m, .str = s }
219 
220 void irlan_print_filter(struct seq_file *seq, int filter_type)
221 {
222  static struct {
223  int mask;
224  const char *str;
225  } filter_mask2str[] = {
226  MASK2STR(IRLAN_DIRECTED, "DIRECTED"),
227  MASK2STR(IRLAN_FUNCTIONAL, "FUNCTIONAL"),
228  MASK2STR(IRLAN_GROUP, "GROUP"),
229  MASK2STR(IRLAN_MAC_FRAME, "MAC_FRAME"),
230  MASK2STR(IRLAN_MULTICAST, "MULTICAST"),
231  MASK2STR(IRLAN_BROADCAST, "BROADCAST"),
232  MASK2STR(IRLAN_IPX_SOCKET, "IPX_SOCKET"),
233  MASK2STR(0, NULL)
234  }, *p;
235 
236  for (p = filter_mask2str; p->str; p++) {
237  if (filter_type & p->mask)
238  seq_printf(seq, "%s ", p->str);
239  }
240  seq_putc(seq, '\n');
241 }
242 #undef MASK2STR
243 #endif