summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Gulewich <robert.gulewich@joyent.com>2011-08-31 20:09:59 -0700
committerRob Gulewich <robert.gulewich@joyent.com>2011-08-31 20:09:59 -0700
commit390587f3994d90c4bf7181ec4b09d402c004664f (patch)
treef224e592d4cf2c0a380fc20583fb0ef5f986c7c2
parent8fa43e83a2e0b6c9227285eb85a0c0949a4915e7 (diff)
downloadillumos-kvm-cmd-390587f3994d90c4bf7181ec4b09d402c004664f.tar.gz
[HVM-636] Add support for more than one DHCP server
-rw-r--r--README.md13
-rw-r--r--net.c20
-rw-r--r--net/vnic-dhcp.c57
-rw-r--r--net/vnic-dhcp.h4
4 files changed, 70 insertions, 24 deletions
diff --git a/README.md b/README.md
index 0edbf1f..3a8fd1c 100644
--- a/README.md
+++ b/README.md
@@ -35,11 +35,11 @@ a VNIC and a ZVOL. The following is a sample configuration for qemu running a Li
-smp 4 \
-m 1024 \
-vnc 0.0.0.0:0 \
- -net nic,vlan=0,name=net0,model=virtio,macaddr=90:b8:d0:c0:ff:ee \
- -net vnic,vlan=0,name=net0,ifname=eth0,macaddr=90:b8:d0:c0:ff:ee, \
- ip=10.88.88.50,netmask=255.255.255.0,gateway_ip=10.88.88.2, \
- server_ip=10.88.88.200,dns_ip=8.8.4.4,hostname=host1, \
- lease_time=3600
+ -net nic,vlan=0,name=net0,model=virtio,macaddr=90:b8:d0:c0:ff:ee\
+ -net vnic,vlan=0,name=net0,ifname=eth0,macaddr=90:b8:d0:c0:ff:ee,\
+ ip=10.88.88.50,netmask=255.255.255.0,gateway_ip=10.88.88.2,\
+ server_ip=10.88.88.200,dns_ip0=8.8.4.4,dns_ip1=8.8.4.4,\
+ hostname=host1,lease_time=3600 \
-no-hpet \
-chardev socket,id=serial0,path=/tmp/vm.console,server,nowait \
-serial chardev:serial0 \
@@ -87,6 +87,9 @@ machine. To enable vnic dhcp, specify the following arguments:
IP address of qemu's DHCP server.
* __dns_ip__ (eg: 8.8.4.4) is optional, and allows specifying the DNS
server the virtual machine will use. The default value is 8.8.8.8.
+* __dns_ip0__, __dns_ip1__, __dns_ip2__, and __dns_ip3__ are optional,
+ and allow specifying a list of DNS servers, rather than just one.
+ These options override the dns_ip option.
* __hostname__ (eg: myhostname) is optional. This defaults to no hostname.
* __lease_time__ (eg: 3600) is optional, and allows specifying the DHCP
lease time in seconds. The default value is 86400 (or 1 day).
diff --git a/net.c b/net.c
index fe8ba3d..77e856a 100644
--- a/net.c
+++ b/net.c
@@ -1134,6 +1134,26 @@ static const struct {
.help = "DHCP DNS server IP address",
},
{
+ .name = "dns_ip0",
+ .type = QEMU_OPT_STRING,
+ .help = "DHCP DNS server IP address",
+ },
+ {
+ .name = "dns_ip1",
+ .type = QEMU_OPT_STRING,
+ .help = "DHCP DNS server IP address",
+ },
+ {
+ .name = "dns_ip2",
+ .type = QEMU_OPT_STRING,
+ .help = "DHCP DNS server IP address",
+ },
+ {
+ .name = "dns_ip3",
+ .type = QEMU_OPT_STRING,
+ .help = "DHCP DNS server IP address",
+ },
+ {
.name = "hostname",
.type = QEMU_OPT_STRING,
.help = "DHCP DNS server IP address",
diff --git a/net/vnic-dhcp.c b/net/vnic-dhcp.c
index 4573ec9..9806055 100644
--- a/net/vnic-dhcp.c
+++ b/net/vnic-dhcp.c
@@ -375,7 +375,7 @@ populate_dhcp_reply(const struct bootp_t *bp, struct bootp_t *rbp,
{
uint8_t *q;
struct in_addr preq_addr;
- int dhcp_msg_type, val;
+ int dhcp_msg_type, val, i;
/* extract exact DHCP msg type */
dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
@@ -434,9 +434,11 @@ populate_dhcp_reply(const struct bootp_t *bp, struct bootp_t *rbp,
// dns server list
*q++ = RFC1533_DNS;
- *q++ = 4;
- memcpy(q, &vdsp->vnds_dns_addr, sizeof(struct in_addr));
- q += 4;
+ *q++ = 4 * vdsp->vnds_num_dns_addrs;
+ for (i = 0; i < vdsp->vnds_num_dns_addrs; i++) {
+ memcpy(q, &vdsp->vnds_dns_addrs[i], sizeof(struct in_addr));
+ q += 4;
+ }
// lease time
*q++ = RFC2132_LEASE_TIME;
@@ -625,15 +627,16 @@ is_dhcp_request(const uint8_t *buf_p, size_t size)
}
static int
-qemu_ip_opt(QemuOpts *opts, const char *opt_name, struct in_addr *addr)
+qemu_ip_opt(QemuOpts *opts, const char *opt_name, struct in_addr *addr, int required)
{
const char *opt;
if ((opt = qemu_opt_get(opts, opt_name)) == NULL) {
- error_report("missing %s for vnic dhcp\n", opt_name);
+ if (required)
+ error_report("missing %s for vnic dhcp\n", opt_name);
return (0);
}
- if (!inet_pton(AF_INET, opt, addr)) {
+ if (inet_pton(AF_INET, opt, addr) != 1) {
error_report("invalid %s '%s' for vnic dhcp\n", opt_name, opt);
return (-1);
}
@@ -644,9 +647,11 @@ qemu_ip_opt(QemuOpts *opts, const char *opt_name, struct in_addr *addr)
int
vnic_dhcp_init(VNICDHCPState *vdsp, QemuOpts *opts)
{
- int ret;
+ int ret, i;
uint32_t lease_time;
const char *hostname;
+ char dns_opt[8];
+ int num_dns_servers = 0;
/* Use the ip option to determine if dhcp should be enabled */
if (qemu_opt_get(opts, "ip") == NULL) {
@@ -655,13 +660,13 @@ vnic_dhcp_init(VNICDHCPState *vdsp, QemuOpts *opts)
return (1);
}
- if (!qemu_ip_opt(opts, "ip", &(vdsp->vnds_client_addr)))
+ if (!qemu_ip_opt(opts, "ip", &(vdsp->vnds_client_addr), 1))
return (0);
- if (!qemu_ip_opt(opts, "netmask", &(vdsp->vnds_netmask_addr)))
+ if (!qemu_ip_opt(opts, "netmask", &(vdsp->vnds_netmask_addr), 1))
return (0);
- if (!(ret = qemu_ip_opt(opts, "server_ip", &(vdsp->vnds_srv_addr)))) {
+ if (!(ret = qemu_ip_opt(opts, "server_ip", &(vdsp->vnds_srv_addr), 0))) {
if (ret == 0) {
/* default DHCP server address */
inet_pton(AF_INET, "169.254.169.254",
@@ -671,23 +676,39 @@ vnic_dhcp_init(VNICDHCPState *vdsp, QemuOpts *opts)
}
}
- if (!qemu_ip_opt(opts, "gateway_ip", &(vdsp->vnds_gw_addr)))
+ if (!qemu_ip_opt(opts, "gateway_ip", &(vdsp->vnds_gw_addr), 1))
return (0);
- if (!(ret = qemu_ip_opt(opts, "dns_ip", &(vdsp->vnds_dns_addr)))) {
- if (ret == 0) {
- /* default DNS server */
- inet_pton(AF_INET, "8.8.8.8", &(vdsp->vnds_dns_addr));
- } else {
+ if ((ret = qemu_ip_opt(opts, "dns_ip", &(vdsp->vnds_dns_addrs[0]), 0)) != 0) {
+ if (ret == -1)
return (0);
+ num_dns_servers = 1;
+ }
+
+ for(i = 0; i < VNIC_DHCP_NUM_RESOLVERS; i++) {
+ sprintf(dns_opt, "dns_ip%d", i);
+ if (!(ret = qemu_ip_opt(opts, dns_opt, &(vdsp->vnds_dns_addrs[i]), 0))) {
+ if (ret == 0) {
+ break;
+ } else {
+ return (0);
+ }
}
+ num_dns_servers = i + 1;
}
+ if (num_dns_servers == 0) {
+ /* default DNS server */
+ inet_pton(AF_INET, "8.8.8.8", &(vdsp->vnds_dns_addrs[0]));
+ num_dns_servers = 1;
+ }
+ vdsp->vnds_num_dns_addrs = num_dns_servers;
+
if ((hostname = qemu_opt_get(opts, "hostname")) != NULL) {
ret = strlen(hostname);
if (ret > sizeof(vdsp->vnds_client_hostname)) {
error_report("hostname is too long\n");
- return (-1);
+ return (0);
}
memcpy(&vdsp->vnds_client_hostname, hostname, ret);
} else {
diff --git a/net/vnic-dhcp.h b/net/vnic-dhcp.h
index ab32da7..b47e343 100644
--- a/net/vnic-dhcp.h
+++ b/net/vnic-dhcp.h
@@ -31,6 +31,7 @@
#define VNIC_BUFFSIZE 65536
#define VNIC_DHCP_DEBUG 0
#define VNIC_DHCP_HEX_DUMP 0
+#define VNIC_DHCP_NUM_RESOLVERS 4
typedef struct VNICDHCPState {
unsigned int vnds_enabled;
@@ -40,9 +41,10 @@ typedef struct VNICDHCPState {
struct in_addr vnds_client_addr;
struct in_addr vnds_netmask_addr;
struct in_addr vnds_gw_addr;
- struct in_addr vnds_dns_addr;
+ struct in_addr vnds_dns_addrs[VNIC_DHCP_NUM_RESOLVERS];
uint32_t vnds_lease_time;
char vnds_client_hostname[33];
+ unsigned int vnds_num_dns_addrs;
} VNICDHCPState;
int create_dhcp_response(const uint8_t *buf_p, int pkt_len, VNICDHCPState *vdsp);