+ if (n_v4 < 0 || n_v6 < 0)
+ goto out;
+
+ if (n_v4 && tb[OPT_GATEWAY]) {
+ if (!parse_gateway_option(state, tb[OPT_GATEWAY], false))
+ goto out;
+ }
+
+ if (n_v6 && tb[OPT_IP6GW]) {
+ if (!parse_gateway_option(state, tb[OPT_IP6GW], true))
+ goto out;
+ }
+
+ return true;
+
+error:
+ interface_add_error(state->iface, "proto-static", error, NULL, 0);
+out:
+ return false;
+}
+
+static int
+static_handler(struct interface_proto_state *proto,
+ enum interface_proto_cmd cmd, bool force)
+{
+ struct static_proto_state *state;
+ int ret = 0;
+
+ state = container_of(proto, struct static_proto_state, proto);
+
+ switch (cmd) {
+ case PROTO_CMD_SETUP:
+ if (static_proto_setup(state))
+ break;
+
+ /* fall through */
+ case PROTO_CMD_TEARDOWN:
+ interface_del_ctx_addr(state->iface, state);
+ break;
+ }
+ return ret;
+}
+
+static void
+static_free(struct interface_proto_state *proto)
+{
+ struct static_proto_state *state;
+
+ state = container_of(proto, struct static_proto_state, proto);
+ free(state->config);
+ free(state);
+}
+
+struct interface_proto_state *
+static_attach(const struct proto_handler *h, struct interface *iface,
+ struct blob_attr *attr)
+{
+ struct static_proto_state *state;
+
+ state = calloc(1, sizeof(*state));
+ if (!state)
+ return NULL;
+
+ state->iface = iface;
+ state->config = malloc(blob_pad_len(attr));
+ if (!state->config)
+ goto error;