Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-drm-fsl-dcu.git] / net / irda / irlan / irlan_filter.c
1 /*********************************************************************
2  *
3  * Filename:      irlan_filter.c
4  * Version:
5  * Description:
6  * Status:        Experimental.
7  * Author:        Dag Brattli <dagb@cs.uit.no>
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 <dagb@cs.uit.no>
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         __u8 *bytes;
147
148         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
149
150         bytes = value;
151
152         IRDA_ASSERT(self != NULL, return;);
153         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
154
155         IRDA_DEBUG(4, "%s, %s\n", param, value);
156
157         /*
158          *  This is experimental!! DB.
159          */
160          if (strcmp(param, "MODE") == 0) {
161                 IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
162                 self->use_udata = TRUE;
163                 return;
164         }
165
166         /*
167          *  FILTER_TYPE
168          */
169         if (strcmp(param, "FILTER_TYPE") == 0) {
170                 if (strcmp(value, "DIRECTED") == 0) {
171                         self->provider.filter_type = IRLAN_DIRECTED;
172                         return;
173                 }
174                 if (strcmp(value, "MULTICAST") == 0) {
175                         self->provider.filter_type = IRLAN_MULTICAST;
176                         return;
177                 }
178                 if (strcmp(value, "BROADCAST") == 0) {
179                         self->provider.filter_type = IRLAN_BROADCAST;
180                         return;
181                 }
182         }
183         /*
184          *  FILTER_MODE
185          */
186         if (strcmp(param, "FILTER_MODE") == 0) {
187                 if (strcmp(value, "ALL") == 0) {
188                         self->provider.filter_mode = ALL;
189                         return;
190                 }
191                 if (strcmp(value, "FILTER") == 0) {
192                         self->provider.filter_mode = FILTER;
193                         return;
194                 }
195                 if (strcmp(value, "NONE") == 0) {
196                         self->provider.filter_mode = FILTER;
197                         return;
198                 }
199         }
200         /*
201          *  FILTER_OPERATION
202          */
203         if (strcmp(param, "FILTER_OPERATION") == 0) {
204                 if (strcmp(value, "DYNAMIC") == 0) {
205                         self->provider.filter_operation = DYNAMIC;
206                         return;
207                 }
208                 if (strcmp(value, "GET") == 0) {
209                         self->provider.filter_operation = GET;
210                         return;
211                 }
212         }
213 }
214
215 /*
216  * Function irlan_print_filter (filter_type, buf)
217  *
218  *    Print status of filter. Used by /proc file system
219  *
220  */
221 #ifdef CONFIG_PROC_FS
222 #define MASK2STR(m,s)   { .mask = m, .str = s }
223
224 void irlan_print_filter(struct seq_file *seq, int filter_type)
225 {
226         static struct {
227                 int mask;
228                 const char *str;
229         } filter_mask2str[] = {
230                 MASK2STR(IRLAN_DIRECTED,        "DIRECTED"),
231                 MASK2STR(IRLAN_FUNCTIONAL,      "FUNCTIONAL"),
232                 MASK2STR(IRLAN_GROUP,           "GROUP"),
233                 MASK2STR(IRLAN_MAC_FRAME,       "MAC_FRAME"),
234                 MASK2STR(IRLAN_MULTICAST,       "MULTICAST"),
235                 MASK2STR(IRLAN_BROADCAST,       "BROADCAST"),
236                 MASK2STR(IRLAN_IPX_SOCKET,      "IPX_SOCKET"),
237                 MASK2STR(0,                     NULL)
238         }, *p;
239
240         for (p = filter_mask2str; p->str; p++) {
241                 if (filter_type & p->mask)
242                         seq_printf(seq, "%s ", p->str);
243         }
244         seq_putc(seq, '\n');
245 }
246 #undef MASK2STR
247 #endif