BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file net_backend_rfkill.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @section DESCRIPTION
30 *
31 * Rfkill monitoring module.
32 *
33 * Synopsis: net.backend.rfkill(string type, string name)
34 * Arguments:
35 * type - method of determining the index of the rfkill device. "index" for
36 * rfkill device index, "wlan" for wireless device. Be aware that, for
37 * the wireless device method, the index is resloved at initialization,
38 * and no attempt is made to refresh it if the device goes away. In other
39 * words, you should probably put a "net.backend.waitdevice" statement
40 * in front of the rfkill statement.
41 * name - rfkill index or wireless device name
42 */
43  
44 #include <stdlib.h>
45 #include <string.h>
46 #include <inttypes.h>
47 #include <stdio.h>
48 #include <sys/types.h>
49 #include <dirent.h>
50  
51 #include <misc/string_begins_with.h>
52 #include <ncd/extra/NCDRfkillMonitor.h>
53  
54 #include <ncd/module_common.h>
55  
56 #include <generated/blog_channel_ncd_net_backend_rfkill.h>
57  
58 struct instance {
59 NCDModuleInst *i;
60 uint32_t index;
61 NCDRfkillMonitor monitor;
62 int up;
63 };
64  
65 static int find_wlan_rfill (const char *ifname, uint32_t *out_index)
66 {
67 char ieee_path[100];
68 snprintf(ieee_path, sizeof(ieee_path), "/sys/class/net/%s/../../ieee80211", ifname);
69  
70 int res = 0;
71  
72 DIR *d = opendir(ieee_path);
73 if (!d) {
74 goto fail0;
75 }
76  
77 struct dirent *e;
78 while (e = readdir(d)) {
79 if (!string_begins_with(e->d_name, "phy")) {
80 continue;
81 }
82  
83 char phy_path[150];
84 snprintf(phy_path, sizeof(phy_path), "%s/%s", ieee_path, e->d_name);
85  
86 DIR *d2 = opendir(phy_path);
87 if (!d2) {
88 continue;
89 }
90  
91 struct dirent *e2;
92 while (e2 = readdir(d2)) {
93 int index_pos;
94 if (!(index_pos = string_begins_with(e2->d_name, "rfkill"))) {
95 continue;
96 }
97  
98 uint32_t index;
99 if (sscanf(e2->d_name + index_pos, "%"SCNu32, &index) != 1) {
100 continue;
101 }
102  
103 res = 1;
104 *out_index = index;
105 }
106  
107 closedir(d2);
108 }
109  
110 closedir(d);
111 fail0:
112 return res;
113 }
114  
115 static void monitor_handler (struct instance *o, struct rfkill_event event)
116 {
117 if (event.idx != o->index) {
118 return;
119 }
120  
121 int was_up = o->up;
122 o->up = (event.op != RFKILL_OP_DEL && !event.soft && !event.hard);
123  
124 if (o->up && !was_up) {
125 NCDModuleInst_Backend_Up(o->i);
126 }
127 else if (!o->up && was_up) {
128 NCDModuleInst_Backend_Down(o->i);
129 }
130 }
131  
132 static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
133 {
134 struct instance *o = vo;
135 o->i = i;
136  
137 // check arguments
138 NCDValRef type_arg;
139 NCDValRef name_arg;
140 if (!NCDVal_ListRead(params->args, 2, &type_arg, &name_arg)) {
141 ModuleLog(o->i, BLOG_ERROR, "wrong arity");
142 goto fail0;
143 }
144 if (!NCDVal_IsString(type_arg) || !NCDVal_IsStringNoNulls(name_arg)) {
145 ModuleLog(o->i, BLOG_ERROR, "wrong type");
146 goto fail0;
147 }
148  
149 // null terminate name
150 NCDValNullTermString name_nts;
151 if (!NCDVal_StringNullTerminate(name_arg, &name_nts)) {
152 ModuleLog(o->i, BLOG_ERROR, "NCDVal_StringNullTerminate failed");
153 goto fail0;
154 }
155  
156 if (NCDVal_StringEquals(type_arg, "index")) {
157 if (sscanf(name_nts.data, "%"SCNu32, &o->index) != 1) {
158 ModuleLog(o->i, BLOG_ERROR, "wrong index argument");
159 goto fail1;
160 }
161 }
162 else if (NCDVal_StringEquals(type_arg, "wlan")) {
163 if (!find_wlan_rfill(name_nts.data, &o->index)) {
164 ModuleLog(o->i, BLOG_ERROR, "failed to find rfkill for wlan interface");
165 goto fail1;
166 }
167 }
168 else {
169 ModuleLog(o->i, BLOG_ERROR, "unknown type argument");
170 goto fail1;
171 }
172  
173 // init monitor
174 if (!NCDRfkillMonitor_Init(&o->monitor, o->i->params->iparams->reactor, (NCDRfkillMonitor_handler)monitor_handler, o)) {
175 ModuleLog(o->i, BLOG_ERROR, "monitor failed");
176 goto fail1;
177 }
178  
179 // set not up
180 o->up = 0;
181  
182 // free name nts
183 NCDValNullTermString_Free(&name_nts);
184 return;
185  
186 fail1:
187 NCDValNullTermString_Free(&name_nts);
188 fail0:
189 NCDModuleInst_Backend_DeadError(i);
190 }
191  
192 static void func_die (void *vo)
193 {
194 struct instance *o = vo;
195  
196 // free monitor
197 NCDRfkillMonitor_Free(&o->monitor);
198  
199 NCDModuleInst_Backend_Dead(o->i);
200 }
201  
202 static struct NCDModule modules[] = {
203 {
204 .type = "net.backend.rfkill",
205 .func_new2 = func_new,
206 .func_die = func_die,
207 .alloc_size = sizeof(struct instance)
208 }, {
209 .type = NULL
210 }
211 };
212  
213 const struct NCDModuleGroup ncdmodule_net_backend_rfkill = {
214 .modules = modules
215 };