const char *name;
const char *proto;
const char *ifname;
- const char *ipaddr;
+ unsigned char ipaddr[4];
int test;
bool enabled;
struct ucimap_list *aliases;
struct uci_network *interface;
};
+static int
+network_parse_ip(void *section, struct uci_optmap *om, union ucimap_data *data, const char *str)
+{
+ struct uci_network *net = section;
+ unsigned char *target = data->s;
+ unsigned int tmp[4];
+ int i;
+
+ if (sscanf(str, "%d.%d.%d.%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3]) != 4)
+ return -1;
+
+ for (i = 0; i < 4; i++)
+ target[i] = (char) tmp[i];
+
+ return 0;
+}
+
static int
network_init_interface(struct uci_map *map, void *section, struct uci_section *s)
{
{
.map = {
UCIMAP_OPTION(struct uci_network, ipaddr),
- .type = UCIMAP_STRING,
+ .type = UCIMAP_CUSTOM,
.name = "ipaddr",
+ .parse = network_parse_ip,
}
},
{
printf("New network section '%s'\n"
" type: %s\n"
" ifname: %s\n"
- " ipaddr: %s\n"
+ " ipaddr: %d.%d.%d.%d\n"
" test: %d\n"
" enabled: %s\n",
net->name,
net->proto,
net->ifname,
- net->ipaddr,
+ net->ipaddr[0], net->ipaddr[1],
+ net->ipaddr[2], net->ipaddr[3],
net->test,
(net->enabled ? "on" : "off"));
return ((type & UCIMAP_TYPE) == UCIMAP_LIST);
}
+static inline bool
+ucimap_is_custom(enum ucimap_type type)
+{
+ return ((type & UCIMAP_SUBTYPE) == UCIMAP_CUSTOM);
+}
+
+static inline void *
+ucimap_section_ptr(struct uci_sectmap_data *sd)
+{
+ void *data = sd + 1;
+ return data;
+}
+
static inline union ucimap_data *
ucimap_get_data(struct uci_sectmap_data *sd, struct uci_optmap *om)
{
void *data;
- data = (char *) sd + sizeof(struct uci_sectmap_data) + om->offset;
+ data = (char *) ucimap_section_ptr(sd) + om->offset;
return data;
}
static void
ucimap_free_section(struct uci_map *map, struct uci_sectmap_data *sd)
{
- void *section = sd;
+ void *section;
int i;
- section = (char *) section + sizeof(struct uci_sectmap_data);
+ section = ucimap_section_ptr(sd);
if (!list_empty(&sd->list))
list_del(&sd->list);
static void
ucimap_add_value(union ucimap_data *data, struct uci_optmap *om, struct uci_sectmap_data *sd, const char *str)
{
- union ucimap_data *tdata = data;
+ union ucimap_data tdata = *data;
char *eptr = NULL;
char *s;
int val;
if (ucimap_is_list(om->type) && !ucimap_is_fixup(om->type))
- tdata = &data->list->item[data->list->n_items++];
+ data = &data->list->item[data->list->n_items++];
switch(om->type & UCIMAP_SUBTYPE) {
case UCIMAP_STRING:
return;
s = strdup(str);
- tdata->s = s;
+ tdata.s = s;
ucimap_add_alloc(sd, s);
break;
case UCIMAP_BOOL:
if (val == -1)
return;
- tdata->b = val;
+ tdata.b = val;
break;
case UCIMAP_INT:
val = strtol(str, &eptr, om->data.i.base);
if (!eptr || *eptr == '\0')
- tdata->i = val;
+ tdata.i = val;
else
return;
break;
case UCIMAP_SECTION:
ucimap_add_fixup(sd->map, data, om, str);
+ return;
+ case UCIMAP_CUSTOM:
+ tdata.s = (char *) data;
break;
}
+ if (om->parse) {
+ if (om->parse(ucimap_section_ptr(sd), om, &tdata, str) < 0)
+ return;
+ }
+ if (ucimap_is_custom(om->type))
+ return;
+ memcpy(data, &tdata, sizeof(union ucimap_data));
}
ucimap_add_alloc(sd, ucimap_get_data(sd, om)->list);
}
- section = (char *)sd + sizeof(struct uci_sectmap_data);
+ section = ucimap_section_ptr(sd);
err = sm->init(map, section, s);
if (err)
(_name[(_bit) / 8] & (1 << ((_bit) % 8)))
#define UCIMAP_OPTION(_type, _field) \
+ .type = UCIMAP_CUSTOM, \
.name = #_field, \
.offset = offsetof(_type, _field)
UCIMAP_BOOL = 0x1,
UCIMAP_INT = 0x2,
UCIMAP_SECTION = 0x3,
+ UCIMAP_CUSTOM = 0x4,
UCIMAP_SUBTYPE = 0xf, /* subtype mask */
};
union ucimap_data {
int i;
bool b;
- const char *s;
+ char *s;
void *section;
struct ucimap_list *list;
};
unsigned int offset;
const char *name;
enum ucimap_type type;
+ int (*parse)(void *section, struct uci_optmap *om, union ucimap_data *data, const char *string);
union {
struct {
int base;