Implement RPC calls for virNetworkGetDHCPLeases, virNetworkGetDHCPLeasesForMAC daemon/remote.c * Define remoteSerializeNetworkDHCPLeases, remoteDispatchNetworkGetDHCPLeases * Define remoteDispatchNetworkGetDHCPLeasesForMAC * Define helper function make_dhcp_lease src/remote/remote_driver.c * Define remoteNetworkGetDHCPLeases * Define remoteNetworkGetDHCPLeasesForMAC * Define helper function make_dhcp_lease src/remote/remote_protocol.x * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES * Define structs remote_network_dhcp_leases, remote_network_get_dhcp_leases_args, remote_network_get_dhcp_leases_ret * New RPC procedure: REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC * Define structs remote_network_dhcp_leases_for_mac, remote_network_get_dhcp_leases_for_mac_args, remote_network_get_dhcp_leases_for_mac_ret src/remote_protocol-structs * New structs added src/rpc/gendispatch.pl * Add exception (s/Dhcp/DHCP) for auto-generating names of the remote functions in daemon/remote_dispatch.h --- daemon/remote.c | 157 ++++++++++++++++++++++++++++++++++++++++ src/remote/remote_driver.c | 169 ++++++++++++++++++++++++++++++++++++++++++- src/remote/remote_protocol.x | 59 ++++++++++++++- src/remote_protocol-structs | 47 ++++++++++++ src/rpc/gendispatch.pl | 1 + 5 files changed, 429 insertions(+), 4 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 9497cc1..770f62a 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -88,6 +88,7 @@ static void make_nonnull_node_device(remote_nonnull_node_device *dev_dst, virNod static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src); static void make_nonnull_nwfilter(remote_nonnull_nwfilter *net_dst, virNWFilterPtr nwfilter_src); static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src); +static void make_dhcp_lease(remote_network_dhcp_lease *lease_dst, virNetworkDHCPLeasesPtr lease_src); static virTypedParameterPtr remoteDeserializeTypedParameters(remote_typed_param *args_params_val, @@ -5209,6 +5210,136 @@ cleanup: } +static int +remoteDispatchNetworkGetDHCPLeases(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_network_get_dhcp_leases_args *args, + remote_network_get_dhcp_leases_ret *ret) +{ + int rv = -1; + size_t i; + struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); + virNetworkDHCPLeasesPtr *leases = NULL; + virNetworkPtr net = NULL; + int nleases = 0; + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(priv->conn, args->net))) + goto cleanup; + + if ((nleases = virNetworkGetDHCPLeases(net, + args->need_results ? &leases : NULL, + args->flags)) < 0) + goto cleanup; + + if (nleases > REMOTE_NETWORK_DHCP_LEASES_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of leases is %d, which exceeds max limit: %d"), + nleases, REMOTE_NETWORK_DHCP_LEASES_MAX); + return -1; + } + + if (leases && nleases) { + if (VIR_ALLOC_N(ret->leases.leases_val, nleases) < 0) + goto cleanup; + + ret->leases.leases_len = nleases; + for (i = 0; i < nleases; i++) + make_dhcp_lease(ret->leases.leases_val + i, leases[i]); + } else { + ret->leases.leases_len = 0; + ret->leases.leases_val = NULL; + } + + ret->ret = nleases; + + rv = 0; + +cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + if (leases) { + for (i = 0; i < nleases; i++) + virNetworkDHCPLeaseFree(leases[i]); + VIR_FREE(leases); + } + virNetworkFree(net); + return rv; +} + + +static int +remoteDispatchNetworkGetDHCPLeasesForMAC(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_network_get_dhcp_leases_for_mac_args *args, + remote_network_get_dhcp_leases_for_mac_ret *ret) +{ + int rv = -1; + size_t i; + struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client); + virNetworkDHCPLeasesPtr *leases = NULL; + virNetworkPtr net = NULL; + int nleases = 0; + const char *mac = NULL; + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(net = get_nonnull_network(priv->conn, args->net))) + goto cleanup; + + mac = args->mac; + + if ((nleases = virNetworkGetDHCPLeasesForMAC(net, mac, + args->need_results ? &leases : NULL, + args->flags)) < 0) + goto cleanup; + + if (nleases > REMOTE_NETWORK_DHCP_LEASES_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of leases is %d, which exceeds max limit: %d"), + nleases, REMOTE_NETWORK_DHCP_LEASES_MAX); + return -1; + } + + if (leases && nleases) { + if (VIR_ALLOC_N(ret->leases.leases_val, nleases) < 0) + goto cleanup; + + ret->leases.leases_len = nleases; + for (i = 0; i < nleases; i++) + make_dhcp_lease(ret->leases.leases_val + i, leases[i]); + } else { + ret->leases.leases_len = 0; + ret->leases.leases_val = NULL; + } + + ret->ret = nleases; + + rv = 0; + +cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + if (leases) { + for (i = 0; i < nleases; i++) + virNetworkDHCPLeaseFree(leases[i]); + VIR_FREE(leases); + } + virNetworkFree(net); + return rv; +} + /*----- Helpers. -----*/ @@ -5343,6 +5474,32 @@ make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDo make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain); } + +/* Copy contents of virNetworkDHCPLeasesPtr to remote_network_dhcp_lease */ +static void +make_dhcp_lease(remote_network_dhcp_lease *lease_dst, virNetworkDHCPLeasesPtr lease_src) +{ + char **hostname_tmp = NULL; + char **clientid_tmp = NULL; + ignore_value(VIR_ALLOC_QUIET(hostname_tmp)); + ignore_value(VIR_ALLOC_QUIET(clientid_tmp)); + + lease_dst->expirytime = lease_src->expirytime; + lease_dst->type = lease_src->type; + lease_dst->prefix = lease_src->prefix; + if (lease_src->type == VIR_IP_ADDR_TYPE_IPV4) + ignore_value(VIR_STRDUP_QUIET(lease_dst->id.remote_interface_id_u.mac, + lease_src->id.mac)); + else + lease_dst->id.remote_interface_id_u.iaid = lease_src->id.iaid; + ignore_value(VIR_STRDUP_QUIET(lease_dst->ipaddr, lease_src->ipaddr)); + ignore_value(VIR_STRDUP_QUIET(*hostname_tmp, lease_src->hostname)); + ignore_value(VIR_STRDUP_QUIET(*clientid_tmp, lease_src->clientid)); + lease_dst->hostname = *hostname_tmp ? hostname_tmp : NULL; + lease_dst->clientid = *clientid_tmp ? clientid_tmp : NULL; +} + + static int remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors, int nerrors, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 96ccb99..95910b6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -14,7 +14,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public + * You should have received a make of the GNU Lesser General Public * License along with this library. If not, see * <http://www.gnu.org/licenses/>. * @@ -150,6 +150,7 @@ static void make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virSto static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src); static void make_nonnull_nwfilter(remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src); static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src); +static void make_dhcp_lease(virNetworkDHCPLeasesPtr lease_src, remote_network_dhcp_lease *lease_dst); static void remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event); /*----------------------------------------------------------------------*/ @@ -1058,7 +1059,7 @@ doRemoteClose(virConnectPtr conn, struct private_data *priv) virObjectUnref(priv->qemuProgram); priv->remoteProgram = priv->qemuProgram = priv->lxcProgram = NULL; - /* Free hostname copy */ + /* Free hostname make */ VIR_FREE(priv->hostname); /* See comment for remoteType. */ @@ -3756,7 +3757,7 @@ static sasl_callback_t *remoteAuthMakeCallbacks(int *credtype, int ncredtype) * * Builds up an array of libvirt credential structs, populating * with data from the SASL interaction struct. These two structs - * are basically a 1-to-1 copy of each other. + * are basically a 1-to-1 make of each other. */ static int remoteAuthMakeCredentials(sasl_interact_t *interact, virConnectCredentialPtr *cred, @@ -6661,6 +6662,143 @@ done: return rv; } + +static int +remoteNetworkGetDHCPLeases(virNetworkPtr net, + virNetworkDHCPLeasesPtr **leases, + unsigned int flags) +{ + int rv = -1; + size_t i; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_get_dhcp_leases_args args; + remote_network_get_dhcp_leases_ret ret; + + virNetworkDHCPLeasesPtr *leases_ret = NULL; + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + args.flags = flags; + args.need_results = !!leases; + + memset(&ret, 0, sizeof(ret)); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_DHCP_LEASES, + (xdrproc_t)xdr_remote_network_get_dhcp_leases_args, (char *)&args, + (xdrproc_t)xdr_remote_network_get_dhcp_leases_ret, (char *)&ret) == -1) { + goto done; + } + + if (ret.leases.leases_len > REMOTE_NETWORK_DHCP_LEASES_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of leases is %d, which exceeds max limit: %d"), + ret.leases.leases_len, REMOTE_NETWORK_DHCP_LEASES_MAX); + goto cleanup; + } + + if (leases) { + if (ret.leases.leases_len && + VIR_ALLOC_N(leases_ret, ret.leases.leases_len + 1) < 0) { + goto cleanup; + } + + for (i = 0; i < ret.leases.leases_len; i++) { + if (VIR_ALLOC(leases_ret[i]) < 0) + goto cleanup; + + make_dhcp_lease(leases_ret[i], &ret.leases.leases_val[i]); + } + + *leases = leases_ret; + leases_ret = NULL; + } + + rv = ret.ret; + +cleanup: + if (leases_ret) { + for (i = 0; i < ret.leases.leases_len; i++) + virNetworkDHCPLeaseFree(leases_ret[i]); + VIR_FREE(leases_ret); + } + xdr_free((xdrproc_t)xdr_remote_network_get_dhcp_leases_ret, + (char *) &ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + + +static int +remoteNetworkGetDHCPLeasesForMAC(virNetworkPtr net, + const char *mac, + virNetworkDHCPLeasesPtr **leases, + unsigned int flags) +{ + int rv = -1; + size_t i; + struct private_data *priv = net->conn->networkPrivateData; + remote_network_get_dhcp_leases_for_mac_args args; + remote_network_get_dhcp_leases_for_mac_ret ret; + + virNetworkDHCPLeasesPtr *leases_ret = NULL; + remoteDriverLock(priv); + + make_nonnull_network(&args.net, net); + args.mac = (char *) mac; + args.flags = flags; + args.need_results = !!leases; + + memset(&ret, 0, sizeof(ret)); + + if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC, + (xdrproc_t)xdr_remote_network_get_dhcp_leases_for_mac_args, (char *)&args, + (xdrproc_t)xdr_remote_network_get_dhcp_leases_for_mac_ret, (char *)&ret) == -1) { + goto done; + } + + if (ret.leases.leases_len > REMOTE_NETWORK_DHCP_LEASES_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Number of leases is %d, which exceeds max limit: %d"), + ret.leases.leases_len, REMOTE_NETWORK_DHCP_LEASES_MAX); + goto cleanup; + } + + if (leases) { + if (ret.leases.leases_len && + VIR_ALLOC_N(leases_ret, ret.leases.leases_len + 1) < 0) { + goto cleanup; + } + + for (i = 0; i < ret.leases.leases_len; i++) { + if (VIR_ALLOC(leases_ret[i]) < 0) + goto cleanup; + + make_dhcp_lease(leases_ret[i], &ret.leases.leases_val[i]); + } + + *leases = leases_ret; + leases_ret = NULL; + } + + rv = ret.ret; + +cleanup: + if (leases_ret) { + for (i = 0; i < ret.leases.leases_len; i++) + virNetworkDHCPLeaseFree(leases_ret[i]); + VIR_FREE(leases_ret); + } + xdr_free((xdrproc_t)xdr_remote_network_get_dhcp_leases_for_mac_ret, + (char *) &ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + + static void remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event) { @@ -6793,6 +6931,29 @@ make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDo make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain); } + +/* Copy contents of remote_network_dhcp_lease to virNetworkDHCPLeasesPtr */ +static void +make_dhcp_lease(virNetworkDHCPLeasesPtr lease_dst, remote_network_dhcp_lease *lease_src) +{ + lease_dst->expirytime = lease_src->expirytime; + lease_dst->type = lease_src->type; + lease_dst->prefix = lease_src->prefix; + if (lease_src->type == VIR_IP_ADDR_TYPE_IPV4) + ignore_value(VIR_STRDUP_QUIET(lease_dst->id.mac, + lease_src->id.remote_interface_id_u.mac)); + else + lease_dst->id.iaid = lease_src->id.remote_interface_id_u.iaid; + ignore_value(VIR_STRDUP_QUIET(lease_dst->ipaddr, lease_src->ipaddr)); + if (lease_src->hostname) + ignore_value(VIR_STRDUP_QUIET(lease_dst->hostname, *lease_src->hostname)); + else + lease_dst->hostname = NULL; + if (lease_src->clientid) + ignore_value(VIR_STRDUP_QUIET(lease_dst->clientid, *lease_src->clientid)); + else + lease_dst->clientid = NULL; +} /*----------------------------------------------------------------------*/ unsigned long remoteVersion(void) @@ -7021,6 +7182,8 @@ static virNetworkDriver network_driver = { .networkSetAutostart = remoteNetworkSetAutostart, /* 0.3.0 */ .networkIsActive = remoteNetworkIsActive, /* 0.7.3 */ .networkIsPersistent = remoteNetworkIsPersistent, /* 0.7.3 */ + .networkGetDHCPLeases = remoteNetworkGetDHCPLeases, /* 1.1.3 */ + .networkGetDHCPLeasesForMAC = remoteNetworkGetDHCPLeasesForMAC, /* 1.1.3 */ }; static virInterfaceDriver interface_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 8d17bad..c630951 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -235,6 +235,11 @@ const REMOTE_DOMAIN_JOB_STATS_MAX = 16; /* Upper limit on number of CPU models */ const REMOTE_CONNECT_CPU_MODELS_MAX = 8192; +/* + * Upper limit on the maximum number of leases in one lease file + */ +const REMOTE_NETWORK_DHCP_LEASES_MAX = 32768; + /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -2849,6 +2854,46 @@ struct remote_connect_get_cpu_model_names_ret { int ret; }; +union remote_interface_id switch (int type) { +case VIR_IP_ADDR_TYPE_IPV4: + remote_nonnull_string mac; +case VIR_IP_ADDR_TYPE_IPV6: + unsigned hyper iaid; +}; + +struct remote_network_dhcp_lease { + hyper expirytime; + remote_interface_id id; + remote_nonnull_string ipaddr; + remote_string hostname; + remote_string clientid; + int type; + unsigned int prefix; +}; + +struct remote_network_get_dhcp_leases_args { + remote_nonnull_network net; + int need_results; + unsigned int flags; +}; + +struct remote_network_get_dhcp_leases_ret { + remote_network_dhcp_lease leases<REMOTE_NETWORK_DHCP_LEASES_MAX>; + unsigned int ret; +}; + +struct remote_network_get_dhcp_leases_for_mac_args { + remote_nonnull_network net; + remote_nonnull_string mac; + int need_results; + unsigned int flags; +}; + +struct remote_network_get_dhcp_leases_for_mac_ret { + remote_network_dhcp_lease leases<REMOTE_NETWORK_DHCP_LEASES_MAX>; + unsigned int ret; +}; + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -5018,5 +5063,17 @@ enum remote_procedure { * @generate: none * @acl: connect:read */ - REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312 + REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312, + + /** + * @generate: none + * @acl: network:read + */ + REMOTE_PROC_NETWORK_GET_DHCP_LEASES = 313, + + /** + * @generate: none + * @acl: network:read + */ + REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC = 314 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 98d2d5b..b6779d5 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -8,6 +8,10 @@ enum { VIR_TYPED_PARAM_BOOLEAN = 6, VIR_TYPED_PARAM_STRING = 7, }; +enum { + VIR_IP_ADDR_TYPE_IPV4 = 0, + VIR_IP_ADDR_TYPE_IPV6 = 1, +}; struct remote_nonnull_domain { remote_nonnull_string name; remote_uuid uuid; @@ -2328,6 +2332,47 @@ struct remote_connect_get_cpu_model_names_ret { } models; int ret; }; +struct remote_dhcp_interface_id { + int type; + union { + remote_nonnull_string mac; + uint64_t iaid; + } remote_interface_id_u; +}; +struct remote_network_dhcp_lease { + int64_t expirytime; + remote_interface_id id; + remote_nonnull_string ipaddr; + remote_string hostname; + remote_string clientid; + int type; + u_int prefix; +}; +struct remote_network_get_dhcp_leases_args { + remote_nonnull_network net; + int need_results; + u_int flags; +}; +struct remote_network_get_dhcp_leases_ret { + struct { + u_int leases_len; + remote_network_dhcp_lease * leases_val; + } leases; + u_int ret; +}; +struct remote_network_get_dhcp_leases_for_mac_args { + remote_nonnull_network net; + remote_nonnull_string mac; + int need_results; + u_int flags; +}; +struct remote_network_get_dhcp_leases_for_mac_ret { + struct { + u_int leases_len; + remote_network_dhcp_lease * leases_val; + } leases; + u_int ret; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -2641,4 +2686,6 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_CREATE_WITH_FILES = 310, REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311, REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES = 312, + REMOTE_PROC_NETWORK_GET_DHCP_LEASES = 313, + REMOTE_PROC_NETWORK_GET_DHCP_LEASES_FOR_MAC = 314, }; diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index ceb1ad8..5a503cf 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -66,6 +66,7 @@ sub fixup_name { $name =~ s/Fstrim$/FSTrim/; $name =~ s/Scsi/SCSI/; $name =~ s/Wwn$/WWN/; + $name =~ s/Dhcp$/DHCP/; return $name; } -- 1.7.11.7 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list