BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file net_backend_waitdevice.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 * Module which waits for the presence of a network interface.
32 *
33 * Synopsis: net.backend.waitdevice(string ifname)
34 * Description: statement is UP when a network interface named ifname
35 * exists, and DOWN when it does not.
36 */
37  
38 #include <stdlib.h>
39 #include <string.h>
40 #include <regex.h>
41  
42 #include <misc/parse_number.h>
43 #include <ncd/extra/NCDIfConfig.h>
44  
45 #include <ncd/module_common.h>
46  
47 #include <generated/blog_channel_ncd_net_backend_waitdevice.h>
48  
49 #define DEVPATH_REGEX "/net/[^/]+$"
50  
51 struct instance {
52 NCDModuleInst *i;
53 MemRef ifname;
54 NCDUdevClient client;
55 regex_t reg;
56 char *devpath;
57 uintmax_t ifindex;
58 };
59  
60 static void client_handler (struct instance *o, char *devpath, int have_map, BStringMap map)
61 {
62 if (o->devpath && !strcmp(devpath, o->devpath) && !NCDUdevManager_Query(o->i->params->iparams->umanager, o->devpath)) {
63 // free devpath
64 free(o->devpath);
65  
66 // set no devpath
67 o->devpath = NULL;
68  
69 // signal down
70 NCDModuleInst_Backend_Down(o->i);
71 } else {
72 const BStringMap *cache_map = NCDUdevManager_Query(o->i->params->iparams->umanager, devpath);
73 if (!cache_map) {
74 goto out;
75 }
76  
77 int match_res = regexec(&o->reg, devpath, 0, NULL, 0);
78 const char *interface = BStringMap_Get(cache_map, "INTERFACE");
79 const char *ifindex_str = BStringMap_Get(cache_map, "IFINDEX");
80  
81 uintmax_t ifindex;
82 if (!(!match_res && interface && MemRef_Equal(MemRef_MakeCstr(interface), o->ifname) && ifindex_str && parse_unsigned_integer(MemRef_MakeCstr(ifindex_str), &ifindex))) {
83 goto out;
84 }
85  
86 if (o->devpath && (strcmp(o->devpath, devpath) || o->ifindex != ifindex)) {
87 // free devpath
88 free(o->devpath);
89  
90 // set no devpath
91 o->devpath = NULL;
92  
93 // signal down
94 NCDModuleInst_Backend_Down(o->i);
95 }
96  
97 if (!o->devpath) {
98 // grab devpath
99 o->devpath = devpath;
100 devpath = NULL;
101  
102 // remember ifindex
103 o->ifindex = ifindex;
104  
105 // signal up
106 NCDModuleInst_Backend_Up(o->i);
107 }
108 }
109  
110 out:
111 free(devpath);
112 if (have_map) {
113 BStringMap_Free(&map);
114 }
115 }
116  
117 static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
118 {
119 struct instance *o = vo;
120 o->i = i;
121  
122 // check arguments
123 NCDValRef arg;
124 if (!NCDVal_ListRead(params->args, 1, &arg)) {
125 ModuleLog(o->i, BLOG_ERROR, "wrong arity");
126 goto fail0;
127 }
128 if (!NCDVal_IsStringNoNulls(arg)) {
129 ModuleLog(o->i, BLOG_ERROR, "wrong type");
130 goto fail0;
131 }
132 o->ifname = NCDVal_StringMemRef(arg);
133  
134 // init client
135 NCDUdevClient_Init(&o->client, o->i->params->iparams->umanager, o, (NCDUdevClient_handler)client_handler);
136  
137 // compile regex
138 if (regcomp(&o->reg, DEVPATH_REGEX, REG_EXTENDED)) {
139 ModuleLog(o->i, BLOG_ERROR, "regcomp failed");
140 goto fail1;
141 }
142  
143 // set no devpath
144 o->devpath = NULL;
145 return;
146  
147 fail1:
148 NCDUdevClient_Free(&o->client);
149 fail0:
150 NCDModuleInst_Backend_DeadError(i);
151 }
152  
153 static void func_die (void *vo)
154 {
155 struct instance *o = vo;
156  
157 // free devpath
158 if (o->devpath) {
159 free(o->devpath);
160 }
161  
162 // free regex
163 regfree(&o->reg);
164  
165 // free client
166 NCDUdevClient_Free(&o->client);
167  
168 NCDModuleInst_Backend_Dead(o->i);
169 }
170  
171 static struct NCDModule modules[] = {
172 {
173 .type = "net.backend.waitdevice",
174 .func_new2 = func_new,
175 .func_die = func_die,
176 .alloc_size = sizeof(struct instance)
177 }, {
178 .type = NULL
179 }
180 };
181  
182 const struct NCDModuleGroup ncdmodule_net_backend_waitdevice = {
183 .modules = modules
184 };