• 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 prev_fd;
233         size_t i;
234 
235         prev_fd = netifd_dir_push(dir_fd);
236         if (glob("./*.sh", 0, NULL, &g)) {
237                 netifd_dir_pop(prev_fd);
238                 return;
239         }
240 
241         for (i = 0; i < g.gl_pathc; i++)
242                 netifd_parse_script_handler(g.gl_pathv[i], cb);
243         netifd_dir_pop(prev_fd);
244 
245         globfree(&g);
246 }
247 
248 void
249 netifd_init_extdev_handlers(int dir_fd, create_extdev_handler_cb cb)
250 {
251         glob_t g;
252         int prev_fd;
253 
254         prev_fd = netifd_dir_push(dir_fd);
255         glob("*.json", 0, NULL, &g);
256         for (size_t i = 0; i < g.gl_pathc; i++)
257                 netifd_parse_extdev_handler(g.gl_pathv[i], cb);
258         netifd_dir_pop(prev_fd);
259 }
260 
261 char *
262 netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj)
263 {
264         struct blobmsg_policy *attrs;
265         char *str_buf, *str_cur;
266         char const **validate;
267         int str_len = 0;
268         int i;
269 
270         config->n_params = json_object_array_length(obj);
271         attrs = calloc(1, sizeof(*attrs) * config->n_params);
272         if (!attrs)
273                 return NULL;
274 
275         validate = calloc(1, sizeof(char*) * config->n_params);
276         if (!validate)
277                 goto error;
278 
279         config->params = attrs;
280         config->validate = validate;
281         for (i = 0; i < config->n_params; i++) {
282                 json_object *cur, *name, *type;
283 
284                 cur = json_check_type(json_object_array_get_idx(obj, i), json_type_array);
285                 if (!cur)
286                         goto error;
287 
288                 name = json_check_type(json_object_array_get_idx(cur, 0), json_type_string);
289                 if (!name)
290                         goto error;
291 
292                 type = json_check_type(json_object_array_get_idx(cur, 1), json_type_int);
293                 if (!type)
294                         goto error;
295 
296                 attrs[i].name = json_object_get_string(name);
297                 attrs[i].type = json_object_get_int(type);
298                 if (attrs[i].type > BLOBMSG_TYPE_LAST)
299                         goto error;
300 
301                 str_len += strlen(attrs[i].name) + 1;
302         }
303 
304         str_buf = malloc(str_len);
305         if (!str_buf)
306                 goto error;
307 
308         str_cur = str_buf;
309         for (i = 0; i < config->n_params; i++) {
310                 const char *name = attrs[i].name;
311                 char *delim;
312 
313                 attrs[i].name = str_cur;
314                 str_cur += sprintf(str_cur, "%s", name) + 1;
315                 delim = strchr(attrs[i].name, ':');
316                 if (delim) {
317                         *delim = '\0';
318                         validate[i] = ++delim;
319                 } else {
320                         validate[i] = NULL;
321                 }
322         }
323 
324         return str_buf;
325 
326 error:
327         free(attrs);
328         if (validate)
329                 free(validate);
330         config->n_params = 0;
331         return NULL;
332 }
333 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt