diff options
author | Rob Gulewich <robert.gulewich@joyent.com> | 2011-08-31 20:09:59 -0700 |
---|---|---|
committer | Rob Gulewich <robert.gulewich@joyent.com> | 2011-08-31 20:09:59 -0700 |
commit | 390587f3994d90c4bf7181ec4b09d402c004664f (patch) | |
tree | f224e592d4cf2c0a380fc20583fb0ef5f986c7c2 | |
parent | 8fa43e83a2e0b6c9227285eb85a0c0949a4915e7 (diff) | |
download | illumos-kvm-cmd-390587f3994d90c4bf7181ec4b09d402c004664f.tar.gz |
[HVM-636] Add support for more than one DHCP server
-rw-r--r-- | README.md | 13 | ||||
-rw-r--r-- | net.c | 20 | ||||
-rw-r--r-- | net/vnic-dhcp.c | 57 | ||||
-rw-r--r-- | net/vnic-dhcp.h | 4 |
4 files changed, 70 insertions, 24 deletions
@@ -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). @@ -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); |