xenParseVif: Refactor parser

Use g_strsplit to split the string and avoid use of stack'd strings.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Peter Krempa 2021-03-02 11:49:34 +01:00
parent e7976ea2f4
commit a7cb4dbca5

View File

@ -1027,7 +1027,7 @@ xenParseCharDev(virConfPtr conf, virDomainDefPtr def, const char *nativeFormat)
static int
xenParseVifBridge(virDomainNetDefPtr net, char *bridge)
xenParseVifBridge(virDomainNetDefPtr net, const char *bridge)
{
char *vlanstr;
unsigned int tag;
@ -1141,104 +1141,53 @@ xenParseVif(char *entry, const char *vif_typename)
{
virDomainNetDefPtr net = NULL;
virDomainNetDefPtr ret = NULL;
char *script = NULL;
char model[10];
char type[10];
char ip[128];
char mac[18];
char bridge[50];
char vifname[50];
char rate[50];
char *key;
g_auto(GStrv) keyvals = NULL;
GStrv keyval;
const char *script = NULL;
const char *model = NULL;
const char *type = NULL;
const char *ip = NULL;
const char *mac = NULL;
const char *bridge = NULL;
const char *vifname = NULL;
const char *rate = NULL;
bridge[0] = '\0';
mac[0] = '\0';
ip[0] = '\0';
model[0] = '\0';
type[0] = '\0';
vifname[0] = '\0';
rate[0] = '\0';
keyvals = g_strsplit(entry, ",", 0);
key = entry;
while (key) {
char *data;
char *nextkey = strchr(key, ',');
for (keyval = keyvals; keyval && *keyval; keyval++) {
const char *key = *keyval;
char *val = strchr(key, '=');
if (!(data = strchr(key, '=')))
virSkipSpaces(&key);
if (!val)
return NULL;
data++;
val++;
if (STRPREFIX(key, "mac=")) {
int len = nextkey ? (nextkey - data) : strlen(data);
if (virStrncpy(mac, data, len, sizeof(mac)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("MAC address %s too big for destination"),
data);
return NULL;
}
mac = val;
} else if (STRPREFIX(key, "bridge=")) {
int len = nextkey ? (nextkey - data) : strlen(data);
if (virStrncpy(bridge, data, len, sizeof(bridge)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Bridge %s too big for destination"),
data);
return NULL;
}
bridge = val;
} else if (STRPREFIX(key, "script=")) {
int len = nextkey ? (nextkey - data) : strlen(data);
VIR_FREE(script);
script = g_strndup(data, len);
script = val;
} else if (STRPREFIX(key, "model=")) {
int len = nextkey ? (nextkey - data) : strlen(data);
if (virStrncpy(model, data, len, sizeof(model)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Model %s too big for destination"),
data);
return NULL;
}
model = val;
} else if (STRPREFIX(key, "type=")) {
int len = nextkey ? (nextkey - data) : strlen(data);
if (virStrncpy(type, data, len, sizeof(type)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Type %s too big for destination"),
data);
return NULL;
}
type = val;
} else if (STRPREFIX(key, "vifname=")) {
int len = nextkey ? (nextkey - data) : strlen(data);
if (virStrncpy(vifname, data, len, sizeof(vifname)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Vifname %s too big for destination"),
data);
return NULL;
}
vifname = val;
} else if (STRPREFIX(key, "ip=")) {
int len = nextkey ? (nextkey - data) : strlen(data);
if (virStrncpy(ip, data, len, sizeof(ip)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("IP %s too big for destination"), data);
return NULL;
}
ip = val;
} else if (STRPREFIX(key, "rate=")) {
int len = nextkey ? (nextkey - data) : strlen(data);
if (virStrncpy(rate, data, len, sizeof(rate)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("rate %s too big for destination"), data);
return NULL;
}
rate = val;
}
while (nextkey && (nextkey[0] == ',' ||
nextkey[0] == ' ' ||
nextkey[0] == '\t'))
nextkey++;
key = nextkey;
}
if (!(net = virDomainNetDefNew(NULL)))
goto cleanup;
if (mac[0]) {
if (mac) {
if (virMacAddrParse(mac, &net->mac) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("malformed mac address '%s'"), mac);
@ -1246,18 +1195,18 @@ xenParseVif(char *entry, const char *vif_typename)
}
}
if (bridge[0] || STREQ_NULLABLE(script, "vif-bridge") ||
if (bridge || STREQ_NULLABLE(script, "vif-bridge") ||
STREQ_NULLABLE(script, "vif-vnic")) {
net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
} else {
net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
}
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE && bridge[0]) {
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE && bridge) {
if (xenParseVifBridge(net, bridge) < 0)
goto cleanup;
}
if (ip[0]) {
if (ip) {
char **ip_list = g_strsplit(ip, " ", 0);
size_t i;
@ -1276,18 +1225,18 @@ xenParseVif(char *entry, const char *vif_typename)
if (script && script[0])
net->script = g_strdup(script);
if (model[0]) {
if (model) {
if (virDomainNetSetModelString(net, model) < 0)
goto cleanup;
} else {
if (type[0] && STREQ(type, vif_typename))
if (type && STREQ(type, vif_typename))
net->model = VIR_DOMAIN_NET_MODEL_NETFRONT;
}
if (vifname[0])
if (vifname && vifname[0])
net->ifname = g_strdup(vifname);
if (rate[0]) {
if (rate) {
virNetDevBandwidthPtr bandwidth;
unsigned long long kbytes_per_sec;
@ -1304,7 +1253,6 @@ xenParseVif(char *entry, const char *vif_typename)
cleanup:
virDomainNetDefFree(net);
VIR_FREE(script);
return ret;
}