Commit 9f687759 authored by Aurelio Colosimo's avatar Aurelio Colosimo

implement and use pp_parse_conf as parser for /etc/ppsi.conf

The parser is implemented in lib/conf.c and has no libc dependencies.
It is currently used by arch-gnu-linux, whose main function is here modified
accordingly.
This commit has not been tested yet, here is pushed temporarly to show how
work is going on.
Signed-off-by: Aurelio Colosimo's avatarAurelio Colosimo <aurelio@aureliocolosimo.it>
parent 0481faba
......@@ -29,9 +29,7 @@ int main(int argc, char **argv)
{
struct pp_globals *ppg;
struct pp_instance *ppi;
char *ifname;
char tmp[16];
int i = 0;
int i = 0, ret;
struct stat conf_fs;
char *conf_buf;
int conf_fd;
......@@ -47,8 +45,10 @@ int main(int argc, char **argv)
ppg->max_links = MAX_LINKS;
ppg->links = calloc(ppg->max_links, sizeof(struct pp_link));
conf_fd = open(CONF_PATH, O_RDONLY);
if ((stat(CONF_PATH, &conf_fs) < 0) ||
(conf_fd = open(CONF_PATH, O_RDONLY) < 0)) {
(conf_fd < 0)) {
pp_printf("Warning: could not open %s, default to one-link built-in "
"config\n", CONF_PATH);
conf_buf = "link 0\niface eth0";
......@@ -59,16 +59,20 @@ int main(int argc, char **argv)
conf_buf = calloc(1, conf_fs.st_size) + 1;
do {
next_r = strlen(conf_buf) - r;
next_r = conf_fs.st_size - r;
r = read(conf_fd, &conf_buf[conf_len], next_r);
if (r <= 0)
break;
conf_len = strlen(conf_buf);
} while (conf_len < conf_fs.st_size);
close(conf_fd);
}
pp_parse_conf(ppg, conf_buf, conf_len);
if ((ret = pp_parse_conf(ppg, conf_buf, conf_len)) < 0) {
pp_printf("Fatal: Error in %s file at line %d\n", CONF_PATH, -ret);
exit(__LINE__);
}
ppg->pp_instances = calloc(ppg->nlinks, sizeof(struct pp_instance));
......@@ -77,16 +81,22 @@ int main(int argc, char **argv)
for (; i < ppg->nlinks; i++) {
ifname = ppg->links[i].iface_name;
if (!ifname) {
sprintf(tmp, "eth%d", i);
ifname = tmp;
}
struct pp_link *lnk = &ppg->links[i];
ppi = &ppg->pp_instances[i];
ppi->glbs = ppg;
/* FIXME set ppi proto and ext as defined in its pp_link */
ppi->iface_name = lnk->iface_name;
ppi->ethernet_mode = (lnk->proto == 0) ? 1 : 0;
if (lnk->proto == 1) {
ppi->master_only = 1;
ppi->slave_only = 0;
}
else if (lnk->proto == 2) {
ppi->master_only = 0;
ppi->slave_only = 1;
}
/* FIXME set ppi ext enable as defined in its pp_link */
/* FIXME check all of these calloc's, since some stuff will be
* part of pp_globals */
......@@ -111,8 +121,6 @@ int main(int argc, char **argv)
/* FIXME temporary workaround to make the first interface work as in the past */
if (ppg->nlinks == 1) {
struct pp_instance *ppi = &ppg->pp_instances[0];
ppi->iface_name = strdup(ifname);
ppi->ethernet_mode = PP_DEFAULT_ETHERNET_MODE;
pp_open_instance(ppg, NULL);
if (pp_parse_cmdline(ppi, argc, argv) != 0)
return -1;
......
......@@ -4,11 +4,219 @@
#include <ppsi/ppsi.h>
/* Each pre-defined keyword is handled in the keywords list, so that the
* same code is used to parse every token in the conf file */
struct keyword_t {
int id;
char *key;
int (*handle_key)(struct pp_globals *ppg, char *val);
};
enum {KW_INV = -1, KW_LINK, KW_IFACE, KW_PROTO, KW_RAW, KW_UDP, KW_ROLE,
KW_AUTO, KW_MASTER, KW_SLAVE, KW_EXT, KW_NONE, KW_WHITERAB,
KW_NUMBER};
static int handle_link(struct pp_globals *ppg, char *val);
static int handle_iface(struct pp_globals *ppg, char *val);
static int handle_proto(struct pp_globals *ppg, char *val);
static int handle_role(struct pp_globals *ppg, char *val);
static int handle_ext(struct pp_globals *ppg, char *val);
static struct keyword_t keywords[KW_NUMBER] = {
{KW_LINK, "link", handle_link},
{KW_IFACE, "iface", handle_iface},
{KW_PROTO, "proto", handle_proto}, {KW_RAW, "raw"}, {KW_UDP, "udp"},
{KW_ROLE, "role", handle_role}, {KW_AUTO, "auto"}, {KW_MASTER, "master"},
{KW_SLAVE, "slave"},
{KW_EXT, "extension", handle_ext}, {KW_NONE, "none"},
{KW_WHITERAB, "whiterabbit"},
};
static int detect_keyword(char *kw)
{
int i;
for (i = KW_LINK; i < KW_NUMBER; i++)
if (memcmp(keywords[i].key, kw, strnlen(kw, 16)) == 0)
return i;
return KW_INV;
}
/* Handlers for "key" keywords: return a bool value, 1 in case of success,
* 0 otherwise */
static int handle_link(struct pp_globals *ppg, char *val)
{
/* ppg->nlinks is initialized to -1 and used as index for current link,
* so increase it before using it */
ppg->nlinks++;
strcpy(ppg->links[ppg->nlinks].link_name, val); /* FIXME check val len */
return 1;
}
static int handle_iface(struct pp_globals *ppg, char *val)
{
strcpy(ppg->links[ppg->nlinks].iface_name, val); /* FIXME check iface len */
return 1;
}
static int handle_proto(struct pp_globals *ppg, char *val)
{
int v_id;
v_id = detect_keyword(val);
switch(v_id) {
case KW_RAW:
case KW_UDP:
ppg->links[ppg->nlinks].proto = v_id - KW_RAW;
break;
default:
return 0;
}
return 1;
}
static int handle_role(struct pp_globals *ppg, char *val)
{
int v_id;
v_id = detect_keyword(val);
switch(v_id) {
case KW_AUTO:
case KW_MASTER:
case KW_SLAVE:
ppg->links[ppg->nlinks].role = v_id - KW_AUTO;
break;
default:
return 0;
}
return 1;
}
static int handle_ext(struct pp_globals *ppg, char *val)
{
int v_id;
v_id = detect_keyword(val);
switch(v_id) {
case KW_NONE:
case KW_WHITERAB:
ppg->links[ppg->nlinks].ext = v_id - KW_NONE;
break;
default:
return 0;
}
return 1;
}
/* Called with the pair key-val detected by pp_parse_conf state machine */
static int handle_key_val(struct pp_globals *ppg, char *key, char *val)
{
int k_id;
k_id = detect_keyword(key);
switch(k_id) {
case KW_LINK:
case KW_IFACE:
case KW_PROTO:
case KW_ROLE:
case KW_EXT:
return keywords[k_id].handle_key(ppg, val);
default:
return 0;
}
}
/* Parse configuration (e.g. coming from /etc/ppsi.conf file) */
int pp_parse_conf(struct pp_globals *ppg, char *conf, int len)
{
/* FIXME: implement pp_parse_conf, setting ppg->links and ppg->nlinks
* as stated in the file */
int st = 0;
char c;
char key[16], val[16];
int toklen = 0;
int ln = 1; /* Line counter */
int newln;
int i;
/* ppg->nlinks is initialized to -1 and increased at first link found,
* so that we can use it as array index */
ppg->nlinks = -1;
memset(ppg->links, 0, ppg->max_links * sizeof(struct pp_link));
for (i = 0; i < len; i++) {
c = conf[i];
/* Increase line counter and check if latest line is invalid */
newln = 0;
if ((c == '\n') || (c == '\0')) {
ln++;
newln = 1;
if (st == 2)
goto ret_invalid_line;
}
switch (st) {
case 0: /* initial status */
if ((c == ' ') || (c == '\t') || (c == '\r') || (newln))
continue;
if (c == '#')
st = 1;
else {
key[0] = c;
toklen = 1;
st = 2;
}
break;
case 1: /* ignoring commented line, those starting with '#' */
if (newln)
st = 0;
else
continue;
break;
case 2: /* detecting key */
if (toklen == sizeof(key))
goto ret_invalid_line;
if ((c != ' ') && (c != '\t'))
key[toklen++] = c;
else {
st = 3;
key[toklen] = '\0';
toklen = 0;
}
break;
case 3: /* detecting val */
if (toklen == sizeof(val))
goto ret_invalid_line;
if ((c != ' ') && (c != '\t') && (c != '\r') && (!newln))
val[toklen++] = c;
else if (newln) {
val[toklen] = '\0';
if (!handle_key_val(ppg, key, val))
goto ret_invalid_line;
st = 0;
toklen = 0;
}
}
}
/* finally, increase nlinks so that it is equal to the configured links
* count */
ppg->nlinks++;
return 0;
ret_invalid_line:
ln--;
return -ln;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment