• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/netifd/handler.c

  1 /*
  2  * netifd - network interface daemon
  3  * Copyright (C) 2012-2013 Felix Fietkau <nbd@openwrt.org>
  4  *
  5  * This program is free software; you can redistribute it and/or modify
  6  * it under the terms of the GNU General Public License version 2
  7  * as published by the Free Software Foundation
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  */
 14 
 15 #define _GNU_SOURCE
 16 #include <glob.h>
 17 #include <fcntl.h>
 18 #include <stdio.h>
 19 
 20 #include "netifd.h"
 21 #include "system.h"
 22 #include "handler.h"
 23 
 24 static int
 25 netifd_dir_push(int fd)
 26 {
 27         int prev_fd = open(".", O_RDONLY | O_DIRECTORY);
 28         system_fd_set_cloexec(prev_fd);
 29         if (fd >= 0)
 30                 if (fchdir(fd)) {}
 31         return prev_fd;
 32 }
 33 
 34 static void
 35 netifd_dir_pop(int prev_fd)
 36 {
 37         if (prev_fd < 0)
 38                 return;
 39 
 40         if (fchdir(prev_fd)) {}
 41         close(prev_fd);
 42 }
 43 
 44 int netifd_open_subdir(const char *name)
 45 {
 46         int prev_dir;
 47         int ret = -1;
 48 
 49         prev_dir = netifd_dir_push(-1);
 50         if (chdir(main_path)) {
 51                 perror("chdir(main path)");
 52                 goto out;
 53         }
 54 
 55         ret = open(name, O_RDONLY | O_DIRECTORY);
 56         if (ret >= 0)
 57                 system_fd_set_cloexec(ret);
 58 
 59 out:
 60         netifd_dir_pop(prev_dir);
 61         return ret;
 62 }
 63 
 64 static void
 65 netifd_init_script_handler(const char *script, json_object *obj, script_dump_cb cb)
 66 {
 67         json_object *tmp;
 68         const char *name;
 69 
 70         if (!json_check_type(obj, json_type_object))
 71                 return;
 72 
 73         tmp = json_get_field(obj, "name", json_type_string);
 74         if (!tmp)
 75                 return;
 76 
 77         name = json_object_get_string(tmp);
 78         cb(script, name, obj);
 79 }
 80 
 81 static void
 82 netifd_init_extdev_handler(const char *config_file, json_object *obj,
 83                            create_extdev_handler_cb cb)
 84 {
 85         json_object *tmp, *cfg, *info, *stats;
 86         const char *name, *ubus_name, *br_prefix = NULL;
 87         bool bridge_support = true;
 88         char *err_missing;
 89 
 90         if (!json_check_type(obj, json_type_object))
 91                 return;
 92 
 93         tmp = json_get_field(obj, "name", json_type_string);
 94         if (!tmp) {
 95                 err_missing = "name";
 96                 goto field_missing;
 97         }
 98 
 99         name = json_object_get_string(tmp);
100 
101         tmp = json_get_field(obj, "ubus_name", json_type_string);
102         if (!tmp) {
103                 err_missing = "ubus_name";
104                 goto field_missing;
105         }
106 
107         ubus_name = json_object_get_string(tmp);
108 
109         tmp = json_get_field(obj, "bridge", json_type_string);
110         if (!tmp || !strcmp(json_object_get_string(tmp), ""))
111                 bridge_support = false;
112 
113         if (bridge_support) {
114                 tmp = json_get_field(obj, "br-prefix", json_type_string);
115                 if (!tmp)
116                         br_prefix = name;
117                 else
118                         br_prefix = json_object_get_string(tmp);
119         }
120 
121         tmp = json_get_field(obj, "config", json_type_array);
122         if (!tmp) {
123                 err_missing = "config";
124                 goto field_missing;
125         }
126 
127         cfg = tmp;
128 
129         info = json_get_field(obj, "info", json_type_array);
130         stats = json_get_field(obj, "stats", json_type_array);
131 
132         cb(config_file, name, ubus_name, bridge_support, br_prefix, cfg, info, stats);
133         return;
134 
135 field_missing:
136         netifd_log_message(L_WARNING, "external device handler description '%s' is"
137                                "missing field '%s'\n", config_file, err_missing);
138 }
139 
140 static void
141 netifd_parse_script_handler(const char *name, script_dump_cb cb)
142 {
143         struct json_tokener *tok = NULL;
144         json_object *obj;
145         static char buf[512];
146         char *start, *cmd;
147         FILE *f;
148         int len;
149 
150 #define DUMP_SUFFIX     " '' dump"
151 
152         cmd = alloca(strlen(name) + 1 + sizeof(DUMP_SUFFIX));
153         sprintf(cmd, "%s" DUMP_SUFFIX, name);
154 
155         f = popen(cmd, "r");
156         if (!f)
157                 return;
158 
159         do {
160                 start = fgets(buf, sizeof(buf), f);
161                 if (!start)
162                         continue;
163 
164                 len = strlen(start);
165                 if (!len)
166                         continue;
167 
168                 if (!tok)
169                         tok = json_tokener_new();
170 
171                 obj = json_tokener_parse_ex(tok, start, len);
172                 if (obj) {
173                         netifd_init_script_handler(name, obj, cb);
174                         json_object_put(obj);
175                         json_tokener_free(tok);
176                         tok = NULL;
177                 } else if (start[len - 1] == '\n') {
178                         json_tokener_free(tok);
179                         tok = NULL;
180                 }
181         } while (!feof(f) && !ferror(f));
182 
183         if (tok)
184                 json_tokener_free(tok);
185 
186         pclose(f);
187 }
188 
189 static void
190 netifd_parse_extdev_handler(const char *path_to_file, create_extdev_handler_cb cb)
191 {
192         struct json_tokener *tok = NULL;
193         json_object *obj;
194         FILE *file;
195         int len;
196         char buf[512], *start;
197 
198         file = fopen(path_to_file, "r");
199         if (!file)
200                 return;
201 
202         do {
203                 start = fgets(buf, sizeof(buf), file);
204                 if (!start)
205                         continue;
206 
207                 len = strlen(start);
208                 if (!len)
209                         continue;
210 
211                 if (!tok)
212                         tok = json_tokener_new();
213 
214                 obj = json_tokener_parse_ex(tok, start, len);
215 
216                 if (obj) {
217                         netifd_init_extdev_handler(path_to_file, obj, cb);
218                         json_object_put(obj);
219                         json_tokener_free(tok);
220                         tok = NULL;
221                 } else if (start[len - 1] == '\n') {
222                         json_tokener_free(tok);
223                         tok = NULL;
224                 }
225         } while (!feof(file) && !ferror(file));
226 
227         if (tok)
228                 json_tokener_free(tok);
229 
230         fclose(file);
231 }
232 
233 void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
234 {
235         glob_t g;
236         int prev_fd;
237         size_t i;
238 
239         prev_fd = netifd_dir_push(dir_fd);
240         if (glob("./*.sh", 0, NULL, &g)) {
241                 netifd_dir_pop(prev_fd);
242                 return;
243         }
244 
245         for (i = 0; i < g.gl_pathc; i++)
246                 netifd_parse_script_handler(g.gl_pathv[i], cb);
247         netifd_dir_pop(prev_fd);
248 
249         globfree(&g);
250 }
251 
252 void
253 netifd_init_extdev_handlers(int dir_fd, create_extdev_handler_cb cb)
254 {
255         glob_t g;
256         int prev_fd;
257 
258         prev_fd = netifd_dir_push(dir_fd);
259         if (glob("*.json", 0, NULL, &g)) {
260                 netifd_dir_pop(prev_fd);
261                 return;
262         }
263 
264         for (size_t i = 0; i < g.gl_pathc; i++)
265                 netifd_parse_extdev_handler(g.gl_pathv[i], cb);
266         netifd_dir_pop(prev_fd);
267 
268         globfree(&g);
269 }
270 
271 void
272 netifd_handler_free_config(struct uci_blob_param_list *config)
273 {
274         free((void *)config->params);
275         free((void *)config->validate);
276         config->params = NULL;
277         config->validate = NULL;
278         config->n_params = 0;
279 }
280 
281 char *
282 netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj)
283 {
284         struct blobmsg_policy *attrs;
285         char *str_buf, *str_cur;
286         char const **validate;
287         int str_len = 0;
288         int i;
289 
290         config->n_params = json_object_array_length(obj);
291         config->params = attrs = calloc(1, sizeof(*attrs) * config->n_params);
292         if (!attrs)
293                 goto error;
294 
295         config->validate = validate = calloc(1, sizeof(char*) * config->n_params);
296         if (!validate)
297                 goto error;
298         for (i = 0; i < config->n_params; i++) {
299                 json_object *cur, *name, *type;
300                 int type_val;
301 
302                 cur = json_check_type(json_object_array_get_idx(obj, i), json_type_array);
303                 if (!cur)
304                         goto error;
305 
306                 name = json_check_type(json_object_array_get_idx(cur, 0), json_type_string);
307                 if (!name)
308                         goto error;
309 
310                 type = json_check_type(json_object_array_get_idx(cur, 1), json_type_int);
311                 if (!type)
312                         goto error;
313 
314                 type_val = json_object_get_int(type);
315                 if (type_val < 0 || type_val > BLOBMSG_TYPE_LAST)
316                         goto error;
317 
318                 attrs[i].name = json_object_get_string(name);
319                 attrs[i].type = type_val;
320 
321                 str_len += strlen(attrs[i].name) + 1;
322         }
323 
324         str_buf = malloc(str_len);
325         if (!str_buf)
326                 goto error;
327 
328         str_cur = str_buf;
329         for (i = 0; i < config->n_params; i++) {
330                 const char *name = attrs[i].name;
331                 char *dest = str_cur;
332                 char *delim;
333 
334                 attrs[i].name = dest;
335                 str_cur += sprintf(dest, "%s", name) + 1;
336                 delim = strchr(dest, ':');
337                 if (delim) {
338                         *delim = '\0';
339                         validate[i] = ++delim;
340                 } else {
341                         validate[i] = NULL;
342                 }
343         }
344 
345         return str_buf;
346 
347 error:
348         netifd_handler_free_config(config);
349         return NULL;
350 }
351 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt