Add support for <option> tag in network config

This patch adds support for a new <option>-Tag in the <dhcp> block of
network configs, based on a subset of the fifth proposal by Laine
Stump in the mailing list discussion at
https://www.redhat.com/archives/libvir-list/2012-November/msg01054.html.
Any such defined option will result in a dhcp-option=<number>,"<value>"
statement in the generated dnsmasq configuration file.

Currently, DHCP options can be specified by number only and there is
no whitelisting or blacklisting of option numbers, which should
probably be added.

Signed-off-by: Pieter Hollants <pieter@hollants.com>
Signed-off-by: Laine Stump <laine@laine.org>
This commit is contained in:
Pieter Hollants authored and Laine Stump committed 2013-02-22 19:45:19 -05:00
1 parent 2795813c69
commit 383ebc4694
10 files changed
+96

No files matched your search

+6
View File
@@ -293,6 +293,12 @@
</optional>
</element>
</optional>
<zeroOrMore>
<element name="option">
<attribute name="number"><ref name="uint8range"/></attribute>
<attribute name="value"><text/></attribute>
</element>
</zeroOrMore>
</element>
</optional>
</element>
+48
View File
@@ -776,6 +776,37 @@ cleanup:
return ret;
}
static int
virNetworkDHCPOptionDefParseXML(const char *networkName,
xmlNodePtr node,
virNetworkDHCPOptionDefPtr option)
{
char *number = NULL;
int ret = -1;
if (!(number = virXMLPropString(node, "number"))) {
virReportError(VIR_ERR_XML_ERROR,
_("Option definition in IPv4 network '%s' "
"must have number attribute"),
networkName);
goto cleanup;
}
if (virStrToLong_ui(number, NULL, 10, &option->number) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("Malformed <option> number attribute: %s"),
number);
goto cleanup;
}
option->value = virXMLPropString(node, "value");
ret = 0;
cleanup:
VIR_FREE(number);
return ret;
}
static int
virNetworkDHCPDefParseXML(const char *networkName,
xmlNodePtr node,
@@ -837,6 +868,17 @@ virNetworkDHCPDefParseXML(const char *networkName,
def->bootfile = file;
def->bootserver = inaddr;
VIR_FREE(server);
} else if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "option")) {
if (VIR_REALLOC_N(def->options, def->noptions + 1) < 0) {
virReportOOMError();
return -1;
}
if (virNetworkDHCPOptionDefParseXML(networkName, cur,
&def->options[def->noptions])) {
return -1;
}
def->noptions++;
}
cur = cur->next;
@@ -2171,6 +2213,12 @@ virNetworkIpDefFormat(virBufferPtr buf,
virBufferAddLit(buf, "/>\n");
}
for (ii = 0 ; ii < def->noptions ; ii++) {
virBufferAsprintf(buf, "<option number='%u'",
def->options[ii].number);
virBufferEscapeString(buf, " value='%s'", def->options[ii].value);
virBufferAddLit(buf, "/>\n");
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</dhcp>\n");
+11
View File
@@ -70,6 +70,13 @@ struct _virNetworkDHCPHostDef {
virSocketAddr ip;
};
typedef struct _virNetworkDHCPOptionDef virNetworkDHCPOptionDef;
typedef virNetworkDHCPOptionDef *virNetworkDHCPOptionDefPtr;
struct _virNetworkDHCPOptionDef {
unsigned int number;
char *value;
};
typedef struct _virNetworkDNSTxtDef virNetworkDNSTxtDef;
typedef virNetworkDNSTxtDef *virNetworkDNSTxtDefPtr;
struct _virNetworkDNSTxtDef {
@@ -129,9 +136,13 @@ struct _virNetworkIpDef {
size_t nhosts; /* Zero or more dhcp hosts */
virNetworkDHCPHostDefPtr hosts;
size_t noptions; /* Zero or more additional dhcp options */
virNetworkDHCPOptionDefPtr options;
char *tftproot;
char *bootfile;
virSocketAddr bootserver;
};
typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
+17
View File
@@ -926,6 +926,23 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
virBufferAsprintf(&configbuf, "dhcp-boot=%s\n", ipdef->bootfile);
}
}
for (r = 0 ; r < ipdef->noptions ; r++) {
virBufferAsprintf(&configbuf, "dhcp-option=%u",
ipdef->options[r].number);
/* value is optional, and only needs quoting if it contains spaces */
if (ipdef->options[r].value) {
const char *quote = "";
if (strchr(ipdef->options[r].value, ' ') ||
strchr(ipdef->options[r].value, '\\')) {
quote = "\"";
}
virBufferAsprintf(&configbuf, ",%s%s%s",
quote, ipdef->options[r].value, quote);
}
virBufferAddLit(&configbuf, "\n");
}
}
ipdef = (ipdef == ipv6def) ? NULL : ipv6def;
}
@@ -12,6 +12,11 @@ bind-dynamic
interface=virbr0
dhcp-range=192.168.122.2,192.168.122.254
dhcp-no-override
dhcp-option=42,192.168.122.20
dhcp-option=23,50
dhcp-option=40,libvirt
dhcp-option=252,"\n"
dhcp-option=253," leading and trailing spaces "
dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases
dhcp-lease-max=253
dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
@@ -8,6 +8,11 @@
<range start='192.168.122.2' end='192.168.122.254' />
<host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' />
<host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' />
<option number='42' value='192.168.122.20'/>
<option number='23' value='50'/>
<option number='40' value='libvirt'/>
<option number='252' value='\n'/>
<option number='253' value=' leading and trailing spaces '/>
</dhcp>
</ip>
<ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'>
@@ -9,6 +9,7 @@
<dhcp>
<range start="192.168.122.2" end="192.168.122.254" />
<bootp file="pxeboot.img" />
<option number="252" value="\n"/>
</dhcp>
</ip>
</network>
@@ -8,6 +8,7 @@
<dhcp>
<range start="192.168.122.2" end="192.168.122.254" />
<bootp file="pxeboot.img" server="10.20.30.40" />
<option number="252" value="\n"/>
</dhcp>
</ip>
</network>
@@ -9,6 +9,7 @@
<dhcp>
<range start='192.168.122.2' end='192.168.122.254' />
<bootp file='pxeboot.img' />
<option number='252' value='\n'/>
</dhcp>
</ip>
</network>
@@ -8,6 +8,7 @@
<dhcp>
<range start='192.168.122.2' end='192.168.122.254' />
<bootp file='pxeboot.img' server='10.20.30.40' />
<option number='252' value='\n'/>
</dhcp>
</ip>
</network>