6 #include <netinet/in.h>
10 #include "interface-ip.h"
24 static const struct blobmsg_policy static_attrs
[__OPT_MAX
] = {
25 [OPT_IPADDR
] = { .name
= "ipaddr", .type
= BLOBMSG_TYPE_ARRAY
},
26 [OPT_IP6ADDR
] = { .name
= "ip6addr", .type
= BLOBMSG_TYPE_ARRAY
},
27 [OPT_NETMASK
] = { .name
= "netmask", .type
= BLOBMSG_TYPE_STRING
},
28 [OPT_GATEWAY
] = { .name
= "gateway", .type
= BLOBMSG_TYPE_STRING
},
29 [OPT_IP6GW
] = { .name
= "ip6gw", .type
= BLOBMSG_TYPE_STRING
},
30 [OPT_DNS
] = { .name
= "dns", .type
= BLOBMSG_TYPE_ARRAY
},
33 static const union config_param_info static_attr_info
[__OPT_MAX
] = {
34 [OPT_IPADDR
] = { .type
= BLOBMSG_TYPE_STRING
},
35 [OPT_IP6ADDR
] = { .type
= BLOBMSG_TYPE_STRING
},
36 [OPT_DNS
] = { .type
= BLOBMSG_TYPE_STRING
},
39 static const struct config_param_list static_attr_list
= {
40 .n_params
= __OPT_MAX
,
41 .params
= static_attrs
,
42 .info
= static_attr_info
,
45 struct static_proto_state
{
46 struct interface_proto_state proto
;
48 struct blob_attr
*config
;
52 parse_addr(struct interface
*iface
, const char *str
, bool v6
, int mask
)
54 struct device_addr
*addr
;
56 addr
= proto_parse_ip_addr_string(str
, v6
, mask
);
58 interface_add_error(iface
, "proto-static", "INVALID_ADDRESS", &str
, 1);
61 vlist_add(&iface
->proto_ip
.addr
, &addr
->node
);
66 parse_address_option(struct interface
*iface
, struct blob_attr
*attr
, bool v6
, int netmask
)
68 struct blob_attr
*cur
;
72 blobmsg_for_each_attr(cur
, attr
, rem
) {
74 if (!parse_addr(iface
, blobmsg_data(cur
), v6
, netmask
))
82 parse_gateway_option(struct interface
*iface
, struct blob_attr
*attr
, bool v6
)
84 struct device_route
*route
;
85 const char *str
= blobmsg_data(attr
);
86 int af
= v6
? AF_INET6
: AF_INET
;
88 route
= calloc(1, sizeof(*route
));
89 if (!inet_pton(af
, str
, &route
->nexthop
)) {
90 interface_add_error(iface
, "proto-static",
91 "INVALID_GATEWAY", &str
, 1);
96 route
->flags
= DEVADDR_DEVICE
| (v6
? DEVADDR_INET6
: DEVADDR_INET4
);
97 vlist_add(&iface
->proto_ip
.route
, &route
->node
);
103 proto_apply_static_settings(struct interface
*iface
, struct blob_attr
*attr
)
105 struct blob_attr
*tb
[__OPT_MAX
];
107 unsigned int netmask
= 32;
108 int n_v4
= 0, n_v6
= 0;
110 blobmsg_parse(static_attrs
, __OPT_MAX
, tb
, blob_data(attr
), blob_len(attr
));
112 if (tb
[OPT_NETMASK
]) {
113 netmask
= parse_netmask_string(blobmsg_data(tb
[OPT_NETMASK
]), false);
115 error
= "INVALID_NETMASK";
121 n_v4
= parse_address_option(iface
, tb
[OPT_IPADDR
], false, netmask
);
124 n_v6
= parse_address_option(iface
, tb
[OPT_IP6ADDR
], true, netmask
);
126 if (!n_v4
&& !n_v6
) {
127 error
= "NO_ADDRESS";
131 if (n_v4
< 0 || n_v6
< 0)
134 if (n_v4
&& tb
[OPT_GATEWAY
]) {
135 if (!parse_gateway_option(iface
, tb
[OPT_GATEWAY
], false))
139 if (n_v6
&& tb
[OPT_IP6GW
]) {
140 if (!parse_gateway_option(iface
, tb
[OPT_IP6GW
], true))
145 interface_add_dns_server_list(&iface
->proto_ip
, tb
[OPT_DNS
]);
150 interface_add_error(iface
, "proto-static", error
, NULL
, 0);
156 static_proto_setup(struct static_proto_state
*state
)
158 return proto_apply_static_settings(state
->proto
.iface
, state
->config
) == 0;
162 static_handler(struct interface_proto_state
*proto
,
163 enum interface_proto_cmd cmd
, bool force
)
165 struct static_proto_state
*state
;
168 state
= container_of(proto
, struct static_proto_state
, proto
);
171 case PROTO_CMD_SETUP
:
172 if (!static_proto_setup(state
))
176 case PROTO_CMD_TEARDOWN
:
183 static_free(struct interface_proto_state
*proto
)
185 struct static_proto_state
*state
;
187 state
= container_of(proto
, struct static_proto_state
, proto
);
192 static struct interface_proto_state
*
193 static_attach(const struct proto_handler
*h
, struct interface
*iface
,
194 struct blob_attr
*attr
)
196 struct static_proto_state
*state
;
198 state
= calloc(1, sizeof(*state
));
202 state
->config
= malloc(blob_pad_len(attr
));
206 memcpy(state
->config
, attr
, blob_pad_len(attr
));
207 state
->proto
.free
= static_free
;
208 state
->proto
.cb
= static_handler
;
210 return &state
->proto
;
217 static struct proto_handler static_proto
= {
219 .flags
= PROTO_FLAG_IMMEDIATE
,
220 .config_params
= &static_attr_list
,
221 .attach
= static_attach
,
225 static_proto_init(void)
227 add_proto_handler(&static_proto
);