Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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                 pr_debug("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                 pr_debug("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                 pr_debug("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                 pr_debug("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                 pr_debug("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                 pr_debug("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                 pr_debug("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                 pr_debug("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         pr_debug("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_ASSERT(self != NULL, return;);
147         IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
148
149         pr_debug("%s, %s\n", param, value);
150
151         /*
152          *  This is experimental!! DB.
153          */
154          if (strcmp(param, "MODE") == 0) {
155                 self->use_udata = TRUE;
156                 return;
157         }
158
159         /*
160          *  FILTER_TYPE
161          */
162         if (strcmp(param, "FILTER_TYPE") == 0) {
163                 if (strcmp(value, "DIRECTED") == 0) {
164                         self->provider.filter_type = IRLAN_DIRECTED;
165                         return;
166                 }
167                 if (strcmp(value, "MULTICAST") == 0) {
168                         self->provider.filter_type = IRLAN_MULTICAST;
169                         return;
170                 }
171                 if (strcmp(value, "BROADCAST") == 0) {
172                         self->provider.filter_type = IRLAN_BROADCAST;
173                         return;
174                 }
175         }
176         /*
177          *  FILTER_MODE
178          */
179         if (strcmp(param, "FILTER_MODE") == 0) {
180                 if (strcmp(value, "ALL") == 0) {
181                         self->provider.filter_mode = ALL;
182                         return;
183                 }
184                 if (strcmp(value, "FILTER") == 0) {
185                         self->provider.filter_mode = FILTER;
186                         return;
187                 }
188                 if (strcmp(value, "NONE") == 0) {
189                         self->provider.filter_mode = FILTER;
190                         return;
191                 }
192         }
193         /*
194          *  FILTER_OPERATION
195          */
196         if (strcmp(param, "FILTER_OPERATION") == 0) {
197                 if (strcmp(value, "DYNAMIC") == 0) {
198                         self->provider.filter_operation = DYNAMIC;
199                         return;
200                 }
201                 if (strcmp(value, "GET") == 0) {
202                         self->provider.filter_operation = GET;
203                         return;
204                 }
205         }
206 }
207
208 /*
209  * Function irlan_print_filter (filter_type, buf)
210  *
211  *    Print status of filter. Used by /proc file system
212  *
213  */
214 #ifdef CONFIG_PROC_FS
215 #define MASK2STR(m,s)   { .mask = m, .str = s }
216
217 void irlan_print_filter(struct seq_file *seq, int filter_type)
218 {
219         static struct {
220                 int mask;
221                 const char *str;
222         } filter_mask2str[] = {
223                 MASK2STR(IRLAN_DIRECTED,        "DIRECTED"),
224                 MASK2STR(IRLAN_FUNCTIONAL,      "FUNCTIONAL"),
225                 MASK2STR(IRLAN_GROUP,           "GROUP"),
226                 MASK2STR(IRLAN_MAC_FRAME,       "MAC_FRAME"),
227                 MASK2STR(IRLAN_MULTICAST,       "MULTICAST"),
228                 MASK2STR(IRLAN_BROADCAST,       "BROADCAST"),
229                 MASK2STR(IRLAN_IPX_SOCKET,      "IPX_SOCKET"),
230                 MASK2STR(0,                     NULL)
231         }, *p;
232
233         for (p = filter_mask2str; p->str; p++) {
234                 if (filter_type & p->mask)
235                         seq_printf(seq, "%s ", p->str);
236         }
237         seq_putc(seq, '\n');
238 }
239 #undef MASK2STR
240 #endif