char *config_buf;
char *script_name;
bool init_available;
+ bool no_proto_task;
struct uci_blob_param_list config;
};
struct proto_shell_dependency {
struct list_head list;
- char *interface;
struct proto_shell_state *proto;
struct interface_user dep;
union if_addr host;
bool v6;
+ bool any;
+
+ char interface[];
};
struct proto_shell_state {
if (dep->dep.iface)
goto out;
- if (dep->interface[0])
+ if (dep->interface[0]) {
iface = vlist_find(&interfaces, dep->interface, iface, node);
- iface = interface_ip_add_target_route(&dep->host, dep->v6, iface);
+ if (!iface || iface->state != IFS_UP)
+ goto out;
+ }
+
+ if (!dep->any)
+ iface = interface_ip_add_target_route(&dep->host, dep->v6, iface);
+
if (!iface)
goto out;
if (task == &state->proto_task)
proto_shell_handler(&state->proto, PROTO_CMD_TEARDOWN,
false);
- if (task == &state->script_task && state->renew_pending)
- proto_shell_handler(&state->proto, PROTO_CMD_RENEW,
- false);
+ else if (task == &state->script_task) {
+ if (state->renew_pending)
+ proto_shell_handler(&state->proto,
+ PROTO_CMD_RENEW, false);
+ else if (!state->handler->no_proto_task &&
+ !state->proto_task.uloop.pending &&
+ state->sm == S_SETUP)
+ proto_shell_handler(&state->proto,
+ PROTO_CMD_TEARDOWN,
+ false);
+ }
break;
case S_SETUP_ABORT:
proto_shell_add_host_dependency(struct proto_shell_state *state, struct blob_attr **tb)
{
struct proto_shell_dependency *dep;
- struct blob_attr *host = tb[NOTIFY_HOST];
- struct blob_attr *ifname_a = tb[NOTIFY_IFNAME];
- const char *ifname_str = ifname_a ? blobmsg_data(ifname_a) : "";
- char *ifname;
+ const char *ifname = tb[NOTIFY_IFNAME] ? blobmsg_data(tb[NOTIFY_IFNAME]) : "";
+ const char *host = tb[NOTIFY_HOST] ? blobmsg_data(tb[NOTIFY_HOST]) : "";
if (state->sm == S_TEARDOWN || state->sm == S_SETUP_ABORT)
return UBUS_STATUS_PERMISSION_DENIED;
- if (!host)
- return UBUS_STATUS_INVALID_ARGUMENT;
+ dep = calloc(1, sizeof(*dep) + strlen(ifname) + 1);
- dep = calloc_a(sizeof(*dep), &ifname, strlen(ifname_str) + 1);
- if (inet_pton(AF_INET, blobmsg_data(host), &dep->host) < 1) {
- if (inet_pton(AF_INET6, blobmsg_data(host), &dep->host) < 1) {
+ if (!host[0] && ifname[0]) {
+ dep->any = true;
+ } else if (inet_pton(AF_INET, host, &dep->host) < 1) {
+ if (inet_pton(AF_INET6, host, &dep->host) < 1) {
free(dep);
return UBUS_STATUS_INVALID_ARGUMENT;
} else {
}
dep->proto = state;
- dep->interface = strcpy(ifname, ifname_str);
+ strcpy(dep->interface, ifname);
dep->dep.cb = proto_shell_if_up_cb;
interface_add_user(&dep->dep, NULL);
if (tmp && json_object_get_boolean(tmp))
handler->proto.flags |= PROTO_FLAG_NODEV;
+ tmp = json_get_field(obj, "no-proto-task", json_type_boolean);
+ handler->no_proto_task = tmp && json_object_get_boolean(tmp);
+
tmp = json_get_field(obj, "available", json_type_boolean);
if (tmp && json_object_get_boolean(tmp))
handler->proto.flags |= PROTO_FLAG_INIT_AVAILABLE;
if (tmp && json_object_get_boolean(tmp))
handler->proto.flags |= PROTO_FLAG_RENEW_AVAILABLE;
+ tmp = json_get_field(obj, "lasterror", json_type_boolean);
+ if (tmp && json_object_get_boolean(tmp))
+ handler->proto.flags |= PROTO_FLAG_LASTERROR;
+
config = json_get_field(obj, "config", json_type_array);
if (config)
handler->config_buf = netifd_handler_parse_config(&handler->config, config);