343c5d4a1a1de4cdc09b80432b45dae6e6b01c9e
[linux-2.6.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
31 /*
32  * Function irlan_filter_request (self, skb)
33  *
34  *    Handle filter request from client peer device
35  *
36  */
37 void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb)
38 {
39         IRDA_ASSERT(self != NULL, return;);
40         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
41
42         if ((self->provider.filter_type == IRLAN_DIRECTED) && 
43             (self->provider.filter_operation == DYNAMIC))
44         {
45                 IRDA_DEBUG(0, "Giving peer a dynamic Ethernet address\n");
46                 self->provider.mac_address[0] = 0x40;
47                 self->provider.mac_address[1] = 0x00;
48                 self->provider.mac_address[2] = 0x00;
49                 self->provider.mac_address[3] = 0x00;
50                 
51                 /* Use arbitration value to generate MAC address */
52                 if (self->provider.access_type == ACCESS_PEER) {
53                         self->provider.mac_address[4] = 
54                                 self->provider.send_arb_val & 0xff;
55                         self->provider.mac_address[5] = 
56                                 (self->provider.send_arb_val >> 8) & 0xff;
57                 } else {
58                         /* Just generate something for now */
59                         get_random_bytes(self->provider.mac_address+4, 1);
60                         get_random_bytes(self->provider.mac_address+5, 1);
61                 }
62
63                 skb->data[0] = 0x00; /* Success */
64                 skb->data[1] = 0x03;
65                 irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
66                 irlan_insert_short_param(skb, "MAX_ENTRY", 0x0001);
67                 irlan_insert_array_param(skb, "FILTER_ENTRY", 
68                                          self->provider.mac_address, 6);
69                 return;
70         }
71         
72         if ((self->provider.filter_type == IRLAN_DIRECTED) && 
73             (self->provider.filter_mode == FILTER))
74         {
75                 IRDA_DEBUG(0, "Directed filter on\n");
76                 skb->data[0] = 0x00; /* Success */
77                 skb->data[1] = 0x00;
78                 return;
79         }
80         if ((self->provider.filter_type == IRLAN_DIRECTED) && 
81             (self->provider.filter_mode == NONE))
82         {
83                 IRDA_DEBUG(0, "Directed filter off\n");
84                 skb->data[0] = 0x00; /* Success */
85                 skb->data[1] = 0x00;
86                 return;
87         }
88
89         if ((self->provider.filter_type == IRLAN_BROADCAST) && 
90             (self->provider.filter_mode == FILTER))
91         {
92                 IRDA_DEBUG(0, "Broadcast filter on\n");
93                 skb->data[0] = 0x00; /* Success */
94                 skb->data[1] = 0x00;
95                 return;
96         }
97         if ((self->provider.filter_type == IRLAN_BROADCAST) && 
98             (self->provider.filter_mode == NONE))
99         {
100                 IRDA_DEBUG(0, "Broadcast filter off\n");
101                 skb->data[0] = 0x00; /* Success */
102                 skb->data[1] = 0x00;
103                 return;
104         }
105         if ((self->provider.filter_type == IRLAN_MULTICAST) && 
106             (self->provider.filter_mode == FILTER))
107         {
108                 IRDA_DEBUG(0, "Multicast filter on\n");
109                 skb->data[0] = 0x00; /* Success */
110                 skb->data[1] = 0x00;
111                 return;
112         }
113         if ((self->provider.filter_type == IRLAN_MULTICAST) && 
114             (self->provider.filter_mode == NONE))
115         {
116                 IRDA_DEBUG(0, "Multicast filter off\n");
117                 skb->data[0] = 0x00; /* Success */
118                 skb->data[1] = 0x00;
119                 return;
120         }
121         if ((self->provider.filter_type == IRLAN_MULTICAST) && 
122             (self->provider.filter_operation == GET))
123         {
124                 IRDA_DEBUG(0, "Multicast filter get\n");
125                 skb->data[0] = 0x00; /* Success? */
126                 skb->data[1] = 0x02;
127                 irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
128                 irlan_insert_short_param(skb, "MAX_ENTRY", 16);
129                 return;
130         }
131         skb->data[0] = 0x00; /* Command not supported */
132         skb->data[1] = 0x00;
133
134         IRDA_DEBUG(0, "Not implemented!\n");
135 }
136
137 /*
138  * Function check_request_param (self, param, value)
139  *
140  *    Check parameters in request from peer device
141  *
142  */
143 void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
144 {
145         __u8 *bytes;
146
147         IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
148
149         bytes = value;
150
151         IRDA_ASSERT(self != NULL, return;);
152         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
153
154         IRDA_DEBUG(4, "%s, %s\n", param, value);
155
156         /*
157          *  This is experimental!! DB.
158          */
159          if (strcmp(param, "MODE") == 0) {
160                 IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
161                 self->use_udata = TRUE;
162                 return;
163         }
164
165         /*
166          *  FILTER_TYPE
167          */
168         if (strcmp(param, "FILTER_TYPE") == 0) {
169                 if (strcmp(value, "DIRECTED") == 0) {
170                         self->provider.filter_type = IRLAN_DIRECTED;
171                         return;
172                 }
173                 if (strcmp(value, "MULTICAST") == 0) {
174                         self->provider.filter_type = IRLAN_MULTICAST;
175                         return;
176                 }
177                 if (strcmp(value, "BROADCAST") == 0) {
178                         self->provider.filter_type = IRLAN_BROADCAST;
179                         return;
180                 }
181         }
182         /*
183          *  FILTER_MODE
184          */
185         if (strcmp(param, "FILTER_MODE") == 0) {
186                 if (strcmp(value, "ALL") == 0) {
187                         self->provider.filter_mode = ALL;
188                         return;
189                 }
190                 if (strcmp(value, "FILTER") == 0) {
191                         self->provider.filter_mode = FILTER;
192                         return;
193                 }
194                 if (strcmp(value, "NONE") == 0) {
195                         self->provider.filter_mode = FILTER;
196                         return;
197                 }
198         }
199         /*
200          *  FILTER_OPERATION
201          */
202         if (strcmp(param, "FILTER_OPERATION") == 0) {
203                 if (strcmp(value, "DYNAMIC") == 0) {
204                         self->provider.filter_operation = DYNAMIC;
205                         return;
206                 }
207                 if (strcmp(value, "GET") == 0) {
208                         self->provider.filter_operation = GET;
209                         return;
210                 }
211         }
212 }
213
214 /*
215  * Function irlan_print_filter (filter_type, buf)
216  *
217  *    Print status of filter. Used by /proc file system
218  *
219  */
220 #ifdef CONFIG_PROC_FS
221 #define MASK2STR(m,s)   { .mask = m, .str = s }
222
223 void irlan_print_filter(struct seq_file *seq, int filter_type)
224 {
225         static struct {
226                 int mask;
227                 const char *str;
228         } filter_mask2str[] = {
229                 MASK2STR(IRLAN_DIRECTED,        "DIRECTED"),
230                 MASK2STR(IRLAN_FUNCTIONAL,      "FUNCTIONAL"),
231                 MASK2STR(IRLAN_GROUP,           "GROUP"),
232                 MASK2STR(IRLAN_MAC_FRAME,       "MAC_FRAME"),
233                 MASK2STR(IRLAN_MULTICAST,       "MULTICAST"),
234                 MASK2STR(IRLAN_BROADCAST,       "BROADCAST"),
235                 MASK2STR(IRLAN_IPX_SOCKET,      "IPX_SOCKET"),
236                 MASK2STR(0,                     NULL)
237         }, *p;
238
239         for (p = filter_mask2str; p->str; p++) {
240                 if (filter_type & p->mask)
241                         seq_printf(seq, "%s ", p->str);
242         }
243         seq_putc(seq, '\n');
244 }
245 #undef MASK2STR
246 #endif