2 * netifd - network interface daemon
3 * Copyright (C) 2012-2013 Felix Fietkau <nbd@openwrt.org>
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
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.
25 netifd_dir_push(int fd
)
27 int prev_fd
= open(".", O_RDONLY
| O_DIRECTORY
);
28 system_fd_set_cloexec(prev_fd
);
35 netifd_dir_pop(int prev_fd
)
40 if (fchdir(prev_fd
)) {}
44 int netifd_open_subdir(const char *name
)
49 prev_dir
= netifd_dir_push(-1);
50 if (chdir(main_path
)) {
51 perror("chdir(main path)");
55 ret
= open(name
, O_RDONLY
| O_DIRECTORY
);
57 system_fd_set_cloexec(ret
);
60 netifd_dir_pop(prev_dir
);
65 netifd_init_script_handler(const char *script
, json_object
*obj
, script_dump_cb cb
)
70 if (!json_check_type(obj
, json_type_object
))
73 tmp
= json_get_field(obj
, "name", json_type_string
);
77 name
= json_object_get_string(tmp
);
78 cb(script
, name
, obj
);
82 netifd_init_extdev_handler(const char *config_file
, json_object
*obj
,
83 create_extdev_handler_cb cb
)
85 json_object
*tmp
, *cfg
, *info
, *stats
;
86 const char *name
, *ubus_name
, *br_prefix
= NULL
;
87 bool bridge_support
= true;
90 if (!json_check_type(obj
, json_type_object
))
93 tmp
= json_get_field(obj
, "name", json_type_string
);
99 name
= json_object_get_string(tmp
);
101 tmp
= json_get_field(obj
, "ubus_name", json_type_string
);
103 err_missing
= "ubus_name";
107 ubus_name
= json_object_get_string(tmp
);
109 tmp
= json_get_field(obj
, "bridge", json_type_string
);
110 if (!tmp
|| !strcmp(json_object_get_string(tmp
), "0"))
111 bridge_support
= false;
113 if (bridge_support
) {
114 tmp
= json_get_field(obj
, "br-prefix", json_type_string
);
118 br_prefix
= json_object_get_string(tmp
);
121 tmp
= json_get_field(obj
, "config", json_type_array
);
123 err_missing
= "config";
129 info
= json_get_field(obj
, "info", json_type_array
);
130 stats
= json_get_field(obj
, "stats", json_type_array
);
132 cb(config_file
, name
, ubus_name
, bridge_support
, br_prefix
, cfg
, info
, stats
);
136 netifd_log_message(L_WARNING
, "external device handler description '%s' is"
137 "missing field '%s'\n", config_file
, err_missing
);
141 netifd_parse_script_handler(const char *name
, script_dump_cb cb
)
143 struct json_tokener
*tok
= NULL
;
145 static char buf
[512];
150 #define DUMP_SUFFIX " '' dump"
152 cmd
= alloca(strlen(name
) + 1 + sizeof(DUMP_SUFFIX
));
153 sprintf(cmd
, "%s" DUMP_SUFFIX
, name
);
160 start
= fgets(buf
, sizeof(buf
), f
);
167 tok
= json_tokener_new();
169 obj
= json_tokener_parse_ex(tok
, start
, len
);
171 netifd_init_script_handler(name
, obj
, cb
);
172 json_object_put(obj
);
173 json_tokener_free(tok
);
175 } else if (start
[len
- 1] == '\n') {
176 json_tokener_free(tok
);
179 } while (!feof(f
) && !ferror(f
));
182 json_tokener_free(tok
);
188 netifd_parse_extdev_handler(const char *path_to_file
, create_extdev_handler_cb cb
)
190 struct json_tokener
*tok
= NULL
;
194 char buf
[512], *start
;
196 file
= fopen(path_to_file
, "r");
201 start
= fgets(buf
, sizeof(buf
), file
);
208 tok
= json_tokener_new();
210 obj
= json_tokener_parse_ex(tok
, start
, len
);
213 netifd_init_extdev_handler(path_to_file
, obj
, cb
);
214 json_object_put(obj
);
215 json_tokener_free(tok
);
217 } else if (start
[len
- 1] == '\n') {
218 json_tokener_free(tok
);
221 } while (!feof(file
) && !ferror(file
));
224 json_tokener_free(tok
);
229 void netifd_init_script_handlers(int dir_fd
, script_dump_cb cb
)
234 prev_fd
= netifd_dir_push(dir_fd
);
235 if (glob("./*.sh", 0, NULL
, &g
)) {
236 netifd_dir_pop(prev_fd
);
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
);
248 netifd_init_extdev_handlers(int dir_fd
, create_extdev_handler_cb cb
)
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
);
261 netifd_handler_parse_config(struct uci_blob_param_list
*config
, json_object
*obj
)
263 struct blobmsg_policy
*attrs
;
264 char *str_buf
, *str_cur
;
265 char const **validate
;
269 config
->n_params
= json_object_array_length(obj
);
270 attrs
= calloc(1, sizeof(*attrs
) * config
->n_params
);
274 validate
= calloc(1, sizeof(char*) * config
->n_params
);
278 config
->params
= attrs
;
279 config
->validate
= validate
;
280 for (i
= 0; i
< config
->n_params
; i
++) {
281 json_object
*cur
, *name
, *type
;
283 cur
= json_check_type(json_object_array_get_idx(obj
, i
), json_type_array
);
287 name
= json_check_type(json_object_array_get_idx(cur
, 0), json_type_string
);
291 type
= json_check_type(json_object_array_get_idx(cur
, 1), json_type_int
);
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
)
300 str_len
+= strlen(attrs
[i
].name
) + 1;
303 str_buf
= malloc(str_len
);
308 for (i
= 0; i
< config
->n_params
; i
++) {
309 const char *name
= attrs
[i
].name
;
312 attrs
[i
].name
= str_cur
;
313 str_cur
+= sprintf(str_cur
, "%s", name
) + 1;
314 delim
= strchr(attrs
[i
].name
, ':');
317 validate
[i
] = ++delim
;
329 config
->n_params
= 0;