6 #include <netinet/in.h>
22 struct static_proto_state
{
23 struct interface_proto_state proto
;
33 static_handler(struct interface_proto_state
*proto
,
34 enum interface_proto_cmd cmd
, bool force
)
40 static_free(struct interface_proto_state
*proto
)
42 struct static_proto_state
*state
;
44 state
= container_of(proto
, struct static_proto_state
, proto
);
48 struct interface_proto_state
*
49 static_create_state(struct v4_addr
*v4
, int n_v4
, struct v6_addr
*v6
, int n_v6
)
51 struct static_proto_state
*state
;
52 int v4_len
= sizeof(struct v4_addr
) * n_v4
;
53 int v6_len
= sizeof(struct v6_addr
) * n_v6
;
56 state
= calloc(1, sizeof(*state
) + v4_len
+ v6_len
);
57 state
->proto
.free
= static_free
;
58 state
->proto
.handler
= static_handler
;
59 state
->proto
.flags
= PROTO_FLAG_IMMEDIATE
;
60 next
= (void *) state
+ 1;
64 memcpy(state
->v4
, v4
, sizeof(*v4
) * n_v4
);
65 next
= state
->v4
+ n_v4
;
70 memcpy(state
->v6
, v6
, sizeof(*v6
) * n_v6
);
77 split_netmask(char *str
, unsigned int *netmask
)
79 char *delim
, *err
= NULL
;
81 delim
= strchr(str
, '/');
85 *netmask
= strtoul(delim
, &err
, 10);
93 parse_ip_and_netmask(int af
, const char *str
, void *addr
, unsigned int *netmask
)
95 char *astr
= alloca(strlen(str
) + 1);
98 if (!split_netmask(astr
, netmask
))
101 if (af
== AF_INET6
) {
109 return inet_pton(af
, str
, addr
);
113 parse_v4(const char *str
, struct v4_addr
*v4
, int netmask
)
115 v4
->prefix
= netmask
;
116 return parse_ip_and_netmask(AF_INET
, str
, &v4
->addr
, &v4
->prefix
);
120 parse_v6(const char *str
, struct v6_addr
*v6
, int netmask
)
122 v6
->prefix
= netmask
;
123 return parse_ip_and_netmask(AF_INET6
, str
, &v6
->addr
, &v6
->prefix
);
135 static const struct uci_parse_option opts
[__OPT_MAX
] = {
136 [OPT_IPADDR
] = { .name
= "ipaddr" },
137 [OPT_IP6ADDR
] = { .name
= "ip6addr" },
138 [OPT_NETMASK
] = { .name
= "netmask", .type
= UCI_TYPE_STRING
},
139 [OPT_GATEWAY
] = { .name
= "gateway", .type
= UCI_TYPE_STRING
},
140 [OPT_DNS
] = { .name
= "dns" },
143 struct interface_proto_state
*
144 static_attach(struct proto_handler
*h
, struct interface
*iface
,
145 struct uci_section
*s
)
147 struct uci_option
*tb
[__OPT_MAX
];
148 struct uci_element
*e
;
149 struct v4_addr
*v4
= NULL
;
150 struct v6_addr
*v6
= NULL
;
151 int n_v4
= 0, n_v6
= 0;
152 struct in_addr ina
= {};
153 const char *error
= NULL
;
157 uci_parse_section(s
, opts
, __OPT_MAX
, tb
);
159 if (tb
[OPT_NETMASK
]) {
160 if (!inet_aton(tb
[OPT_NETMASK
]->v
.string
, &ina
)) {
161 error
= "INVALID_NETMASK";
165 netmask
= 32 - fls(~(ntohl(ina
.s_addr
)));
168 if (tb
[OPT_IPADDR
]) {
169 if (tb
[OPT_IPADDR
]->type
== UCI_TYPE_STRING
) {
171 v4
= alloca(sizeof(*v4
));
172 if (!parse_v4(tb
[OPT_IPADDR
]->v
.string
, v4
, netmask
))
175 uci_foreach_element(&tb
[OPT_IPADDR
]->v
.list
, e
)
179 v4
= alloca(sizeof(*v4
) * n_v4
);
180 uci_foreach_element(&tb
[OPT_IPADDR
]->v
.list
, e
) {
181 if (!parse_v4(e
->name
, &v4
[i
++], netmask
))
187 if (tb
[OPT_IP6ADDR
]) {
188 if (tb
[OPT_IP6ADDR
]->type
== UCI_TYPE_STRING
) {
190 v6
= alloca(sizeof(*v6
));
191 v6
->prefix
= netmask
;
192 if (!parse_v6(tb
[OPT_IP6ADDR
]->v
.string
, v6
, netmask
))
195 uci_foreach_element(&tb
[OPT_IP6ADDR
]->v
.list
, e
)
199 v6
= alloca(sizeof(*v6
) * n_v6
);
200 uci_foreach_element(&tb
[OPT_IP6ADDR
]->v
.list
, e
) {
201 if (!parse_v6(e
->name
, &v6
[i
++], netmask
))
208 if (!n_v4
&& !n_v6
) {
209 error
= "NO_ADDRESS";
213 return static_create_state(v4
, n_v4
, v6
, n_v6
);
216 error
= "INVALID_ADDRESS";
219 interface_add_error(iface
, "proto-static", error
, NULL
, 0);
223 static struct proto_handler static_proto
= {
225 .attach
= static_attach
,
229 static_proto_init(void)
231 add_proto_handler(&static_proto
);