• 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 
166                 if (!tok)
167                         tok = json_tokener_new();
168 
169                 obj = json_tokener_parse_ex(tok, start, len);
170                 if (obj) {
171                         netifd_init_script_handler(name, obj, cb);
172                         json_object_put(obj);
173                         json_tokener_free(tok);
174                         tok = NULL;
175                 } else if (start[len - 1] == '\n') {
176                         json_tokener_free(tok);
177                         tok = NULL;
178                 }
179         } while (!feof(f) && !ferror(f));
180 
181         if (tok)
182                 json_tokener_free(tok);
183 
184         pclose(f);
185 }
186 
187 static void
188 netifd_parse_extdev_handler(const char *path_to_file, create_extdev_handler_cb cb)
189 {
190         struct json_tokener *tok = NULL;
191         json_object *obj;
192         FILE *file;
193         int len;
194         char buf[512], *start;
195 
196         file = fopen(path_to_file, "r");
197         if (!file)
198                 return;
199 
200         do {
201                 start = fgets(buf, sizeof(buf), file);
202                 if (!start)
203                         continue;
204 
205                 len = strlen(start);
206 
207                 if (!tok)
208                         tok = json_tokener_new();
209 
210                 obj = json_tokener_parse_ex(tok, start, len);
211 
212                 if (obj) {
213                         netifd_init_extdev_handler(path_to_file, obj, cb);
214                         json_object_put(obj);
215                         json_tokener_free(tok);
216                         tok = NULL;
217                 } else if (start[len - 1] == '\n') {
218                         json_tokener_free(tok);
219                         tok = NULL;
220                 }
221         } while (!feof(file) && !ferror(file));
222 
223         if (tok)
224                 json_tokener_free(tok);
225 
226         fclose(file);
227 }
228 
229 void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
230 {
231         glob_t g;
232         int i, prev_fd;
233 
234         prev_fd = netifd_dir_push(dir_fd);
235         if (glob("./*.sh", 0, NULL, &g)) {
236                 netifd_dir_pop(prev_fd);
237                 return;
238         }
239 
240         for (i = 0; i < g.gl_pathc; i++)
241                 netifd_parse_script_handler(g.gl_pathv[i], cb);
242         netifd_dir_pop(prev_fd);
243 
244         globfree(&g);
245 }
246 
247 void
248 netifd_init_extdev_handlers(int dir_fd, create_extdev_handler_cb cb)
249 {
250         glob_t g;
251         int prev_fd;
252 
253         prev_fd = netifd_dir_push(dir_fd);
254         glob("*.json", 0, NULL, &g);
255         for (int i = 0; i < g.gl_pathc; i++)
256                 netifd_parse_extdev_handler(g.gl_pathv[i], cb);
257         netifd_dir_pop(prev_fd);
258 }
259 
260 char *
261 netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj)
262 {
263         struct blobmsg_policy *attrs;
264         char *str_buf, *str_cur;
265         char const **validate;
266         int str_len = 0;
267         int i;
268 
269         config->n_params = json_object_array_length(obj);
270         attrs = calloc(1, sizeof(*attrs) * config->n_params);
271         if (!attrs)
272                 return NULL;
273 
274         validate = calloc(1, sizeof(char*) * config->n_params);
275         if (!validate)
276                 goto error;
277 
278         config->params = attrs;
279         config->validate = validate;
280         for (i = 0; i < config->n_params; i++) {
281                 json_object *cur, *name, *type;
282 
283                 cur = json_check_type(json_object_array_get_idx(obj, i), json_type_array);
284                 if (!cur)
285                         goto error;
286 
287                 name = json_check_type(json_object_array_get_idx(cur, 0), json_type_string);
288                 if (!name)
289                         goto error;
290 
291                 type = json_check_type(json_object_array_get_idx(cur, 1), json_type_int);
292                 if (!type)
293                         goto error;
294 
295                 attrs[i].name = json_object_get_string(name);
296                 attrs[i].type = json_object_get_int(type);
297                 if (attrs[i].type > BLOBMSG_TYPE_LAST)
298                         goto error;
299 
300                 str_len += strlen(attrs[i].name) + 1;
301         }
302 
303         str_buf = malloc(str_len);
304         if (!str_buf)
305                 goto error;
306 
307         str_cur = str_buf;
308         for (i = 0; i < config->n_params; i++) {
309                 const char *name = attrs[i].name;
310                 char *delim;
311 
312                 attrs[i].name = str_cur;
313                 str_cur += sprintf(str_cur, "%s", name) + 1;
314                 delim = strchr(attrs[i].name, ':');
315                 if (delim) {
316                         *delim = '\0';
317                         validate[i] = ++delim;
318                 } else {
319                         validate[i] = NULL;
320                 }
321         }
322 
323         return str_buf;
324 
325 error:
326         free(attrs);
327         if (validate)
328                 free(validate);
329         config->n_params = 0;
330         return NULL;
331 }
332 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt