6 #include <netinet/in.h>
23 struct static_proto_state
{
24 struct interface_proto_state proto
;
25 struct interface
*iface
;
35 static_handler(struct interface_proto_state
*proto
,
36 enum interface_proto_cmd cmd
, bool force
)
38 struct static_proto_state
*state
;
43 state
= container_of(proto
, struct static_proto_state
, proto
);
44 dev
= state
->iface
->main_dev
.dev
;
48 for (i
= 0; i
< state
->n_v4
; i
++) {
51 ret
= system_add_address(dev
, AF_INET
,
52 &state
->v4
[i
].addr
, state
->v4
[i
].prefix
);
54 for (i
= 0; i
< state
->n_v6
; i
++) {
57 ret
= system_add_address(dev
, AF_INET6
,
58 &state
->v6
[i
].addr
, state
->v6
[i
].prefix
);
64 interface_add_error(state
->iface
, "proto-static",
65 "SET_ADDRESS_FAILED", NULL
, 0);
68 case PROTO_CMD_TEARDOWN
:
69 for (i
= 0; i
< state
->n_v4
; i
++)
70 system_del_address(dev
, AF_INET
, &state
->v4
[i
].addr
);
71 for (i
= 0; i
< state
->n_v6
; i
++)
72 system_del_address(dev
, AF_INET6
, &state
->v6
[i
].addr
);
79 static_free(struct interface_proto_state
*proto
)
81 struct static_proto_state
*state
;
83 state
= container_of(proto
, struct static_proto_state
, proto
);
87 struct interface_proto_state
*
88 static_create_state(struct interface
*iface
, struct v4_addr
*v4
, int n_v4
, struct v6_addr
*v6
, int n_v6
)
90 struct static_proto_state
*state
;
91 int v4_len
= sizeof(struct v4_addr
) * n_v4
;
92 int v6_len
= sizeof(struct v6_addr
) * n_v6
;
95 state
= calloc(1, sizeof(*state
) + v4_len
+ v6_len
);
97 state
->proto
.free
= static_free
;
98 state
->proto
.handler
= static_handler
;
99 state
->proto
.flags
= PROTO_FLAG_IMMEDIATE
;
100 next
= (void *) (state
+ 1);
105 memcpy(state
->v4
, v4
, sizeof(*v4
) * n_v4
);
106 next
= state
->v4
+ n_v4
;
112 memcpy(state
->v6
, v6
, sizeof(*v6
) * n_v6
);
115 return &state
->proto
;
119 split_netmask(char *str
, unsigned int *netmask
)
121 char *delim
, *err
= NULL
;
123 delim
= strchr(str
, '/');
127 *netmask
= strtoul(delim
, &err
, 10);
135 parse_ip_and_netmask(int af
, const char *str
, void *addr
, unsigned int *netmask
)
137 char *astr
= alloca(strlen(str
) + 1);
140 if (!split_netmask(astr
, netmask
))
143 if (af
== AF_INET6
) {
151 return inet_pton(af
, str
, addr
);
155 parse_v4(const char *str
, struct v4_addr
*v4
, int netmask
)
157 v4
->prefix
= netmask
;
158 return parse_ip_and_netmask(AF_INET
, str
, &v4
->addr
, &v4
->prefix
);
162 parse_v6(const char *str
, struct v6_addr
*v6
, int netmask
)
164 v6
->prefix
= netmask
;
165 return parse_ip_and_netmask(AF_INET6
, str
, &v6
->addr
, &v6
->prefix
);
169 count_list_entries(struct uci_option
*o
)
171 struct uci_element
*e
;
174 uci_foreach_element(&o
->v
.list
, e
)
189 static const struct uci_parse_option opts
[__OPT_MAX
] = {
190 [OPT_IPADDR
] = { .name
= "ipaddr" },
191 [OPT_IP6ADDR
] = { .name
= "ip6addr" },
192 [OPT_NETMASK
] = { .name
= "netmask", .type
= UCI_TYPE_STRING
},
193 [OPT_GATEWAY
] = { .name
= "gateway", .type
= UCI_TYPE_STRING
},
194 [OPT_DNS
] = { .name
= "dns" },
197 struct interface_proto_state
*
198 static_attach(struct proto_handler
*h
, struct interface
*iface
,
199 struct uci_section
*s
)
201 struct uci_option
*tb
[__OPT_MAX
];
202 struct uci_element
*e
;
203 struct v4_addr
*v4
= NULL
;
204 struct v6_addr
*v6
= NULL
;
205 int n_v4
= 0, n_v6
= 0;
206 struct in_addr ina
= {};
207 const char *error
= NULL
;
211 uci_parse_section(s
, opts
, __OPT_MAX
, tb
);
213 if (tb
[OPT_NETMASK
]) {
214 if (!inet_aton(tb
[OPT_NETMASK
]->v
.string
, &ina
)) {
215 error
= "INVALID_NETMASK";
219 netmask
= 32 - fls(~(ntohl(ina
.s_addr
)));
222 if (tb
[OPT_IPADDR
]) {
223 if (tb
[OPT_IPADDR
]->type
== UCI_TYPE_STRING
) {
225 v4
= alloca(sizeof(*v4
));
226 if (!parse_v4(tb
[OPT_IPADDR
]->v
.string
, v4
, netmask
))
230 n_v4
= count_list_entries(tb
[OPT_IPADDR
]);
231 v4
= alloca(sizeof(*v4
) * n_v4
);
232 uci_foreach_element(&tb
[OPT_IPADDR
]->v
.list
, e
) {
233 if (!parse_v4(e
->name
, &v4
[i
++], netmask
))
239 if (tb
[OPT_IP6ADDR
]) {
240 if (tb
[OPT_IP6ADDR
]->type
== UCI_TYPE_STRING
) {
242 v6
= alloca(sizeof(*v6
));
243 v6
->prefix
= netmask
;
244 if (!parse_v6(tb
[OPT_IP6ADDR
]->v
.string
, v6
, netmask
))
248 n_v6
= count_list_entries(tb
[OPT_IP6ADDR
]);
249 v6
= alloca(sizeof(*v6
) * n_v6
);
250 uci_foreach_element(&tb
[OPT_IP6ADDR
]->v
.list
, e
) {
251 if (!parse_v6(e
->name
, &v6
[i
++], netmask
))
258 if (!n_v4
&& !n_v6
) {
259 error
= "NO_ADDRESS";
263 return static_create_state(iface
, v4
, n_v4
, v6
, n_v6
);
266 error
= "INVALID_ADDRESS";
269 interface_add_error(iface
, "proto-static", error
, NULL
, 0);
273 static struct proto_handler static_proto
= {
275 .attach
= static_attach
,
279 static_proto_init(void)
281 add_proto_handler(&static_proto
);