diff --git a/autoip4/autoip.h b/autoip4/autoip.h index 255e5c2dc..979c38564 100644 --- a/autoip4/autoip.h +++ b/autoip4/autoip.h @@ -8,6 +8,7 @@ #define __WICKED_AUTOIP_PRIVATE_H__ #include +#include #include "netinfo_priv.h" typedef enum ni_autoip_state { @@ -16,7 +17,7 @@ typedef enum ni_autoip_state { NI_AUTOIP_STATE_CLAIMED, } ni_autoip_state_t; -typedef struct ni_autoip_device ni_autoip_device_t; +typedef struct ni_autoip_device ni_autoip_device_t; struct ni_autoip_device { ni_autoip_device_t * next; @@ -44,19 +45,27 @@ struct ni_autoip_device { time_t last_defense; } autoip; + ni_auto4_request_t request; + ni_addrconf_lease_t * lease; }; extern ni_autoip_device_t *ni_autoip_active; -extern int ni_autoip_acquire(ni_autoip_device_t *); +typedef void ni_autoip_event_handler_t(enum ni_lease_event, + const ni_autoip_device_t *, + ni_addrconf_lease_t *lease); + +extern void ni_autoip_set_event_handler(ni_autoip_event_handler_t); + +extern int ni_autoip_acquire(ni_autoip_device_t *, const ni_auto4_request_t *); extern int ni_autoip_release(ni_autoip_device_t *, const ni_uuid_t *); extern long ni_autoip_fsm_get_timeout(void); extern void ni_autoip_fsm_check_timeout(void); extern int ni_autoip_fsm_select(ni_autoip_device_t *); extern const char * ni_autoip_fsm_state_name(ni_autoip_state_t); -extern int ni_autoip_fsm_commit_lease(ni_autoip_device_t *, ni_addrconf_lease_t *); +extern void ni_autoip_fsm_release(ni_autoip_device_t *); extern ni_autoip_device_t *ni_autoip_device_new(const char *, const ni_linkinfo_t *); extern ni_autoip_device_t *ni_autoip_device_get(ni_autoip_device_t *); diff --git a/autoip4/dbus-api.c b/autoip4/dbus-api.c index 950c84a4a..01e3f6785 100644 --- a/autoip4/dbus-api.c +++ b/autoip4/dbus-api.c @@ -3,7 +3,6 @@ * * Copyright (C) 2011-2012 Olaf Kirch * - * Much of this code is in dbus-objects/autoip4.c for now. */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -23,13 +22,17 @@ #include #include #include +#include #include #include "autoip.h" +#include "util_priv.h" +static void __ni_objectmodel_autoip4_device_release(ni_dbus_object_t *); static const ni_dbus_service_t ni_objectmodel_autoip4_service; -static ni_dbus_class_t ni_objectmodel_autoip4dev_class = { +static ni_dbus_class_t ni_objectmodel_autoip4_device_class = { .name = "autoip4-device", + .destroy = __ni_objectmodel_autoip4_device_release, .superclass = &ni_objectmodel_addrconf_device_class, }; @@ -41,7 +44,7 @@ ni_objectmodel_autoip4_init(void) { if (ni_objectmodel_init(NULL) == NULL) ni_fatal("Cannot initialize objectmodel, giving up."); - ni_objectmodel_register_class(&ni_objectmodel_autoip4dev_class); + ni_objectmodel_register_class(&ni_objectmodel_autoip4_device_class); ni_objectmodel_register_service(&ni_objectmodel_autoip4_service); } @@ -64,10 +67,10 @@ __ni_objectmodel_build_autoip4_device_object(ni_dbus_server_t *server, ni_autoip if (server != NULL) { snprintf(object_path, sizeof(object_path), "Interface/%d", dev->link.ifindex); object = ni_dbus_server_register_object(server, object_path, - &ni_objectmodel_autoip4dev_class, + &ni_objectmodel_autoip4_device_class, ni_autoip_device_get(dev)); } else { - object = ni_dbus_object_new(&ni_objectmodel_autoip4dev_class, NULL, + object = ni_dbus_object_new(&ni_objectmodel_autoip4_device_class, NULL, ni_autoip_device_get(dev)); } @@ -93,11 +96,37 @@ ni_objectmodel_register_autoip4_device(ni_dbus_server_t *server, ni_autoip_devic * Extract the autoip_device handle from a dbus object */ static ni_autoip_device_t * -ni_objectmodel_unwrap_autoip4_device(const ni_dbus_object_t *object) +ni_objectmodel_unwrap_autoip4_device(const ni_dbus_object_t *object, DBusError *error) { - ni_autoip_device_t *dev = object->handle; + if (!object) { + if (error) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "Cannot unwrap autoip4 device from a NULL dbus object"); + } + return NULL; + } + if (!ni_dbus_object_isa(object, &ni_objectmodel_autoip4_device_class)) { + if (error) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "method not compatible with object %s of class %s (not autoip4 device)", + object->path, object->class->name); + } + return NULL; + } + return object->handle; +} - return object->class == &ni_objectmodel_autoip4dev_class? dev : NULL; +/* + * Destroy a dbus object wrapping an autoip device. + */ +static void +__ni_objectmodel_autoip4_device_release(ni_dbus_object_t *object) +{ + ni_autoip_device_t *dev = ni_objectmodel_unwrap_autoip4_device(object, NULL); + + object->handle = NULL; + if (dev) + ni_autoip_device_put(dev); } /* @@ -107,18 +136,51 @@ ni_objectmodel_unwrap_autoip4_device(const ni_dbus_object_t *object) * Server side method implementation */ static dbus_bool_t -__wicked_dbus_autoip4_acquire_svc(ni_dbus_object_t *object, const ni_dbus_method_t *method, +ni_objectmodel_autoip4_acquire_svc(ni_dbus_object_t *object, const ni_dbus_method_t *method, unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error) { - ni_autoip_device_t *dev = ni_objectmodel_unwrap_autoip4_device(object); + ni_auto4_request_t req; + ni_autoip_device_t *dev; dbus_bool_t ret = FALSE; + ni_uuid_t req_uuid = NI_UUID_INIT; int rv; - ni_debug_dbus("%s(dev=%s)", __func__, dev->ifname); + if (!(dev = ni_objectmodel_unwrap_autoip4_device(object, error))) + return FALSE; + + ni_debug_dbus("%s(dev=%s, argc=%u)", __func__, dev->ifname, argc); + + if (argc == 2) { + /* + * Extract the request uuid and pass that along to acquire. + */ + if (!ni_dbus_variant_get_uuid(&argv[0], &req_uuid)) { + dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, + "%s: unable to extract acquire request uuid argument", + method->name); + goto failed; + } + argc--; + argv++; + } + + if (argc != 1) { + dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, + "%s: unable to extract arguments", method->name); + goto failed; + } - /* Ignore all arguments for now */ - if ((rv = ni_autoip_acquire(dev)) < 0) { + ni_auto4_request_init(&req, TRUE); + if (!ni_objectmodel_set_auto4_request_dict(&req, &argv[0], error)) { + dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, + "%s: unable to extract request from argument", + method->name); + goto failed; + } + req.uuid = req_uuid; + + if ((rv = ni_autoip_acquire(dev, &req)) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot configure interface %s: %s", dev->ifname, ni_strerror(rv)); @@ -140,32 +202,36 @@ __wicked_dbus_autoip4_acquire_svc(ni_dbus_object_t *object, const ni_dbus_method * Drop a IPv4ll lease */ static dbus_bool_t -__wicked_dbus_autoip4_drop_svc(ni_dbus_object_t *object, const ni_dbus_method_t *method, +ni_objectmodel_autoip4_drop_svc(ni_dbus_object_t *object, const ni_dbus_method_t *method, unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error) { - ni_autoip_device_t *dev = ni_objectmodel_unwrap_autoip4_device(object); + ni_autoip_device_t *dev; dbus_bool_t ret = FALSE; - ni_uuid_t uuid; + ni_uuid_t req_uuid = NI_UUID_INIT; int rv; - ni_debug_dbus("%s(dev=%s)", __func__, dev->ifname); + if (!(dev = ni_objectmodel_unwrap_autoip4_device(object, error))) + return FALSE; + + ni_debug_dbus("%s(dev=%s, argc=%u)", __func__, dev->ifname, argc); - memset(&uuid, 0, sizeof(uuid)); if (argc == 1) { - /* Extract the lease uuid and pass that along to ni_autoip_release. - * This makes sure we don't cancel the wrong lease. + /* + * Extract the lease uuid and pass that along to ni_autoip_release. */ - if (!ni_dbus_variant_get_uuid(&argv[0], &uuid)) { - dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "bad uuid argument"); + if (!ni_dbus_variant_get_uuid(&argv[0], &req_uuid)) { + dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, + "%s: unable to extract drop request uuid argument", + method->name); goto failed; } } - if ((rv = ni_autoip_release(dev, &uuid)) < 0) { - dbus_set_error(error, DBUS_ERROR_FAILED, - "Unable to drop IPv4ll lease for interface %s: %s", dev->ifname, - ni_strerror(rv)); + if ((rv = ni_autoip_release(dev, &req_uuid)) < 0) { + ni_dbus_set_error_from_code(error, rv, + "Unable to drop auto4 lease for interface %s: %s", + dev->ifname, ni_strerror(rv)); goto failed; } @@ -175,13 +241,16 @@ __wicked_dbus_autoip4_drop_svc(ni_dbus_object_t *object, const ni_dbus_method_t return ret; } -static ni_dbus_method_t wicked_dbus_autoip4_methods[] = { - { "acquire", "a{sv}", __wicked_dbus_autoip4_acquire_svc }, - { "drop", "ay", __wicked_dbus_autoip4_drop_svc }, +/* + * Request class and properties + */ +static ni_dbus_method_t ni_objectmodel_autoip4_methods[] = { + { "acquire", "aya{sv}", ni_objectmodel_autoip4_acquire_svc }, + { "drop", "ay", ni_objectmodel_autoip4_drop_svc }, { NULL } }; -static ni_dbus_method_t wicked_dbus_autoip4_signals[] = { +static ni_dbus_method_t ni_objectmodel_autoip4_signals[] = { { NI_OBJECTMODEL_LEASE_ACQUIRED_SIGNAL }, { NI_OBJECTMODEL_LEASE_RELEASED_SIGNAL }, { NI_OBJECTMODEL_LEASE_LOST_SIGNAL }, @@ -189,50 +258,57 @@ static ni_dbus_method_t wicked_dbus_autoip4_signals[] = { }; /* - * Property name + * Device property access functions -- just showing + * the device name and currently assigned request. */ +static void * +ni_objectmodel_get_autoip_device(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) +{ + return ni_objectmodel_unwrap_autoip4_device(object, error); +} + static dbus_bool_t -__wicked_dbus_autoip4_get_name(const ni_dbus_object_t *object, +ni_objectmodel_autoip_device_get_request(const ni_dbus_object_t *object, const ni_dbus_property_t *property, ni_dbus_variant_t *result, DBusError *error) { - ni_autoip_device_t *dev = ni_dbus_object_get_handle(object); + ni_autoip_device_t *dev; + + if (!(dev = ni_objectmodel_unwrap_autoip4_device(object, error))) + return FALSE; - ni_dbus_variant_set_string(result, dev->ifname); - return TRUE; + if (!dev->request.enabled) + return ni_dbus_error_property_not_present(error, object->path, property->name); + + return ni_objectmodel_get_auto4_request_dict(&dev->request, result, error); } static dbus_bool_t -__wicked_dbus_autoip4_set_name(ni_dbus_object_t *object, +ni_objectmodel_autoip_device_set_request(ni_dbus_object_t *object, const ni_dbus_property_t *property, const ni_dbus_variant_t *argument, DBusError *error) { - ni_autoip_device_t *dev = ni_dbus_object_get_handle(object); - const char *value; + ni_autoip_device_t *dev; - if (!ni_dbus_variant_get_string(argument, &value)) + if (!(dev = ni_objectmodel_unwrap_autoip4_device(object, error))) return FALSE; - ni_string_dup(&dev->ifname, value); - return TRUE; -} -#define WICKED_INTERFACE_PROPERTY(type, __name, rw) \ - NI_DBUS_PROPERTY(type, __name, __wicked_dbus_autoip4, rw) -#define WICKED_INTERFACE_PROPERTY_SIGNATURE(signature, __name, rw) \ - __NI_DBUS_PROPERTY(signature, __name, __wicked_dbus_autoip4, rw) - -static ni_dbus_property_t wicked_dbus_autoip4_properties[] = { - WICKED_INTERFACE_PROPERTY(STRING, name, RO), + return ni_objectmodel_set_auto4_request_dict(&dev->request, argument, error); +} +static ni_dbus_property_t ni_objectmodel_autoip4_properties[] = { + NI_DBUS_GENERIC_STRING_PROPERTY(autoip_device, name, ifname, RO), + ___NI_DBUS_PROPERTY(NI_DBUS_DICT_SIGNATURE, request, request, + ni_objectmodel_autoip_device, RO), { NULL } }; static const ni_dbus_service_t ni_objectmodel_autoip4_service = { .name = NI_OBJECTMODEL_AUTO4_INTERFACE, - .compatible = &ni_objectmodel_autoip4dev_class, - .methods = wicked_dbus_autoip4_methods, - .signals = wicked_dbus_autoip4_signals, - .properties = wicked_dbus_autoip4_properties, + .compatible = &ni_objectmodel_autoip4_device_class, + .methods = ni_objectmodel_autoip4_methods, + .signals = ni_objectmodel_autoip4_signals, + .properties = ni_objectmodel_autoip4_properties, }; diff --git a/autoip4/device.c b/autoip4/device.c index 298bfb661..6a222d396 100644 --- a/autoip4/device.c +++ b/autoip4/device.c @@ -117,10 +117,6 @@ ni_autoip_device_drop_lease(ni_autoip_device_t *dev) ni_addrconf_lease_t *lease; if ((lease = dev->lease) != NULL) { - /* if we've configured the network using this - * lease, we need to isse a link down request */ - dev->notify = 1; - /* delete the lease file. */ ni_addrconf_lease_file_remove(dev->ifname, lease->type, lease->family); ni_autoip_device_set_lease(dev, NULL); @@ -195,7 +191,6 @@ ni_autoip_device_refresh(ni_autoip_device_t *dev) int ni_autoip_device_start(ni_autoip_device_t *dev) { - ni_autoip_device_drop_lease(dev); dev->failed = 0; if (ni_autoip_fsm_select(dev) < 0) { @@ -210,14 +205,50 @@ ni_autoip_device_start(ni_autoip_device_t *dev) * Acquire an IPv4ll lease */ int -ni_autoip_acquire(ni_autoip_device_t *dev) +ni_autoip_acquire(ni_autoip_device_t *dev, const ni_auto4_request_t *request) { - return ni_autoip_device_start(dev); + if (!dev || !request) + return -1; + + ni_auto4_request_copy(&dev->request, request); + ni_note("%s: Request to acquire AUTOv4 lease with UUID %s", + dev->ifname, ni_uuid_print(&request->uuid)); + + dev->lease = ni_addrconf_lease_file_read(dev->ifname, NI_ADDRCONF_AUTOCONF, AF_INET); + if (ni_autoip_device_start(dev) < 0) + return -1; + return 1; } int ni_autoip_release(ni_autoip_device_t *dev, const ni_uuid_t *uuid) { + char *rel_uuid = NULL; + char *our_uuid = NULL; + + if (dev->lease == NULL) { + ni_debug_autoip("%s: no lease set", dev->ifname); + return -NI_ERROR_ADDRCONF_NO_LEASE; + } + + ni_string_dup(&rel_uuid, ni_uuid_is_null(uuid) ? NULL : ni_uuid_print(uuid)); + ni_string_dup(&our_uuid, ni_uuid_print(&dev->lease->uuid)); + + if (!ni_uuid_is_null(uuid) && !ni_uuid_equal(uuid, &dev->lease->uuid)) { + ni_warn("%s: lease UUID %s to release does not match current lease UUID %s", + dev->ifname, rel_uuid, our_uuid); + ni_string_free(&rel_uuid); + ni_string_free(&our_uuid); + return -NI_ERROR_ADDRCONF_NO_LEASE; + } + ni_string_free(&our_uuid); + + ni_note("%s: Request to release AUTOv4 lease%s%s", dev->ifname, + rel_uuid ? " with UUID " : "", rel_uuid ? rel_uuid : ""); + ni_string_free(&rel_uuid); + + ni_autoip_fsm_release(dev); ni_autoip_device_stop(dev); + ni_auto4_request_destroy(&dev->request); return 0; } diff --git a/autoip4/fsm.c b/autoip4/fsm.c index 11c88dcd4..dbb65d479 100644 --- a/autoip4/fsm.c +++ b/autoip4/fsm.c @@ -36,11 +36,13 @@ #define IPV4LL_ANNOUNCE_WAIT 2000 #define IPV4LL_PROBE_COUNT 3 -#define IPV4LL_ANNOUNCE_COUNT 2 +#define IPV4LL_ANNOUNCE_COUNT 0 /* do not announce -- deliver lease */ #define IPV4LL_MAX_CONFLICTS 10 #define IPV4LL_RATE_LIMIT_INTERVAL 60000 #define IPV4LL_DEFEND_INTERVAL 10000 +static ni_autoip_event_handler_t * ni_autoip_fsm_event_handler; + extern int ni_autoip_device_get_address(ni_autoip_device_t *, struct in_addr *); static int ni_autoip_send_arp(ni_autoip_device_t *); static void ni_autoip_fsm_process_arp_packet(ni_arp_socket_t *, const ni_arp_packet_t *, void *); @@ -48,9 +50,25 @@ static void ni_autoip_fsm_set_timeout(ni_autoip_device_t *, unsigned int, unsign static void __ni_autoip_fsm_timeout(void *, const ni_timer_t *); +void +ni_autoip_set_event_handler(ni_autoip_event_handler_t func) +{ + ni_autoip_fsm_event_handler = func; +} + +void +ni_autoip_send_event(enum ni_lease_event ev, const ni_autoip_device_t *dev, + ni_addrconf_lease_t *lease) +{ + if (ni_autoip_fsm_event_handler) + ni_autoip_fsm_event_handler(ev, dev, lease); +} + int ni_autoip_fsm_select(ni_autoip_device_t *dev) { + ni_address_t *ap; + /* * RFC 3927, Section 2.1: * Hosts that are equipped with persistent storage MAY, for each @@ -60,6 +78,12 @@ ni_autoip_fsm_select(ni_autoip_device_t *dev) */ if (dev->fsm.state == NI_AUTOIP_STATE_CLAIMED && dev->autoip.candidate.s_addr != 0) { ni_debug_autoip("%s: trying to reclaim %s", + dev->ifname, inet_ntoa(dev->autoip.candidate)); + } else if (dev->lease && (ap = dev->lease->addrs) && + ni_sockaddr_is_ipv4_linklocal(&ap->local_addr) && + dev->autoip.candidate.s_addr == 0) { + dev->autoip.candidate = dev->lease->addrs->local_addr.sin.sin_addr; + ni_debug_autoip("%s: trying to reuse our previous address %s", dev->ifname, inet_ntoa(dev->autoip.candidate)); } else { dev->autoip.candidate.s_addr = htonl(IPV4LL_ADDRESS_FIRST + (random() % IPV4LL_ADDRESS_RANGE)); @@ -75,6 +99,7 @@ ni_autoip_fsm_select(ni_autoip_device_t *dev) dev->fsm.state = NI_AUTOIP_STATE_CLAIMING; dev->autoip.nprobes = IPV4LL_PROBE_COUNT; + /* do not claim here -- deliver the lease */ dev->autoip.nclaims = IPV4LL_ANNOUNCE_COUNT; /* @@ -143,7 +168,7 @@ ni_autoip_fsm_defend(ni_autoip_device_t *dev, const ni_hwaddr_t *hwa) } } -int +ni_addrconf_lease_t * ni_autoip_fsm_build_lease(ni_autoip_device_t *dev) { ni_addrconf_lease_t *lease; @@ -161,16 +186,42 @@ ni_autoip_fsm_build_lease(ni_autoip_device_t *dev) ni_route_create(16, &addr, NULL, 0, &lease->routes); lease->state = NI_ADDRCONF_STATE_GRANTED; - ni_autoip_device_set_lease(dev, lease); + lease->time_acquired = time(NULL); + lease->uuid = dev->request.uuid; + lease->flags = dev->request.flags; - /* Write the lease to lease cache */ - ni_addrconf_lease_file_write(dev->ifname, lease); + return lease; +} - /* Inform the master about the newly acquired lease */ - dev->notify = 1; +static int +ni_autoip_fsm_commit_lease(ni_autoip_device_t *dev, ni_addrconf_lease_t *lease) +{ + if (lease) { + ni_debug_autoip("%s: commiting lease", dev->ifname); + ni_autoip_device_set_lease(dev, lease); + + /* Write the lease to lease cache */ + ni_addrconf_lease_file_write(dev->ifname, lease); + + /* Inform the master about the newly acquired lease */ + ni_autoip_send_event(NI_EVENT_LEASE_ACQUIRED, dev, lease); + } else { + ni_debug_autoip("%s: dropping lease", dev->ifname); + if ((lease = dev->lease) != NULL) { + lease->state = NI_ADDRCONF_STATE_RELEASED; + lease->uuid = dev->request.uuid; + ni_autoip_send_event(NI_EVENT_LEASE_RELEASED, dev, lease); + } + ni_autoip_device_drop_lease(dev); + } return 0; } +void +ni_autoip_fsm_release(ni_autoip_device_t *dev) +{ + ni_autoip_fsm_commit_lease(dev, NULL); +} int ni_autoip_send_arp(ni_autoip_device_t *dev) @@ -207,16 +258,16 @@ ni_autoip_send_arp(ni_autoip_device_t *dev) ni_debug_autoip("%s: successfully claimed %s", dev->ifname, inet_ntoa(claim)); /* Build the lease */ - ni_autoip_fsm_build_lease(dev); - dev->fsm.state = NI_AUTOIP_STATE_CLAIMED; + ni_autoip_fsm_commit_lease(dev, ni_autoip_fsm_build_lease(dev)); dev->autoip.nconflicts = 0; dev->autoip.last_defense = 0; } } else { - ni_error("%s: nprobes and nclaims are zero; shouldn't be here", __FUNCTION__); - ni_autoip_fsm_conflict(dev); - return -1; + dev->fsm.state = NI_AUTOIP_STATE_CLAIMED; + ni_autoip_fsm_commit_lease(dev, ni_autoip_fsm_build_lease(dev)); + dev->autoip.nconflicts = 0; + dev->autoip.last_defense = 0; } return 0; } diff --git a/autoip4/main.c b/autoip4/main.c index 60fb2f518..0efa9a45d 100644 --- a/autoip4/main.c +++ b/autoip4/main.c @@ -265,8 +265,7 @@ autoip4_register_services(ni_dbus_server_t *server) autoip4_discover_devices(server); -// ni_autoip_set_event_handler(autoip4_protocol_event); - (void) (autoip4_protocol_event); + ni_autoip_set_event_handler(autoip4_protocol_event); } ni_bool_t @@ -492,10 +491,12 @@ autoip4_interface_event(ni_netdev_t *ifp, ni_event_t event) } void -autoip4_protocol_event(enum ni_lease_event ev, const ni_autoip_device_t *dev, ni_addrconf_lease_t *lease) +autoip4_protocol_event(enum ni_lease_event ev, const ni_autoip_device_t *dev, + ni_addrconf_lease_t *lease) { - ni_dbus_variant_t argv[1]; + ni_dbus_variant_t argv[2]; ni_dbus_object_t *dev_object; + ni_dbus_variant_t *var; int argc = 0; ni_debug_autoip("%s(ev=%u, dev=%d)", __func__, ev, dev->link.ifindex); @@ -507,9 +508,11 @@ autoip4_protocol_event(enum ni_lease_event ev, const ni_autoip_device_t *dev, ni } memset(argv, 0, sizeof(argv)); - if (lease) { - ni_dbus_variant_t *var = &argv[argc++]; + var = &argv[argc++]; + ni_dbus_variant_set_uuid(var, &dev->request.uuid); + if (lease) { + var = &argv[argc++]; ni_dbus_variant_init_dict(var); if (!ni_objectmodel_get_addrconf_lease(lease, var)) { ni_warn("%s: could not extract lease data", __func__); diff --git a/include/wicked/addrconf.h b/include/wicked/addrconf.h index 9dbb10713..96511aa01 100644 --- a/include/wicked/addrconf.h +++ b/include/wicked/addrconf.h @@ -231,4 +231,16 @@ extern ni_bool_t ni_netbios_node_type_to_code(const char *, unsigned int *); extern unsigned int ni_addrconf_lease_get_priority(const ni_addrconf_lease_t *); +struct ni_auto4_request { + ni_bool_t enabled; + unsigned int flags; + ni_uuid_t uuid; +}; + +extern ni_auto4_request_t * ni_auto4_request_new(void); +extern ni_bool_t ni_auto4_request_copy(ni_auto4_request_t *, const ni_auto4_request_t *); +extern void ni_auto4_request_init(ni_auto4_request_t *, ni_bool_t); +extern void ni_auto4_request_destroy(ni_auto4_request_t *); +extern void ni_auto4_request_free(ni_auto4_request_t *); + #endif /* __WICKED_ADDRCONF_H__ */ diff --git a/include/wicked/objectmodel.h b/include/wicked/objectmodel.h index f2b9bde4c..747862f63 100644 --- a/include/wicked/objectmodel.h +++ b/include/wicked/objectmodel.h @@ -163,6 +163,8 @@ extern dbus_bool_t ni_objectmodel_unmarshal_security_id(ni_security_id_t *, con extern dbus_bool_t ni_objectmodel_get_name_array(const xml_node_t *names, ni_dbus_variant_t *); extern dbus_bool_t ni_objectmodel_set_name_array(xml_node_t *names, const ni_dbus_variant_t *); +extern dbus_bool_t ni_objectmodel_get_auto4_request_dict(const ni_auto4_request_t *req, ni_dbus_variant_t *, DBusError *); +extern dbus_bool_t ni_objectmodel_set_auto4_request_dict(ni_auto4_request_t *req, const ni_dbus_variant_t *, DBusError *); extern int ni_objectmodel_signal_to_event(const char *, ni_event_t *); extern const char * ni_objectmodel_event_to_signal(ni_event_t); diff --git a/include/wicked/types.h b/include/wicked/types.h index 62df28ea5..e780dac4d 100644 --- a/include/wicked/types.h +++ b/include/wicked/types.h @@ -54,6 +54,7 @@ typedef struct ni_lldp ni_lldp_t; typedef struct ni_nis_info ni_nis_info_t; typedef struct ni_resolver_info ni_resolver_info_t; typedef struct ni_addrconf_lease ni_addrconf_lease_t; +typedef struct ni_auto4_request ni_auto4_request_t; typedef struct ni_netdev_req ni_netdev_req_t; typedef struct ni_ipv4_devinfo ni_ipv4_devinfo_t; typedef struct ni_ipv4_devconf ni_ipv4_devconf_t; diff --git a/schema/addrconf.xml b/schema/addrconf.xml index 061a25372..6de856717 100644 --- a/schema/addrconf.xml +++ b/schema/addrconf.xml @@ -269,8 +269,9 @@ ================================================= --> - + + diff --git a/src/dbus-objects/addrconf.c b/src/dbus-objects/addrconf.c index c05322db1..b6d7af55b 100644 --- a/src/dbus-objects/addrconf.c +++ b/src/dbus-objects/addrconf.c @@ -1,7 +1,6 @@ /* * Generic dbus client functions for address configuration - * services implemented as separate DBus services (like dhcp, - * ipv4ll) + * services implemented as separate DBus services (like dhcp). * * Copyright (C) 2011-2012 Olaf Kirch */ @@ -31,9 +30,15 @@ #include "dbus-common.h" #include "model.h" #include "debug.h" +#include "util_priv.h" + const ni_dbus_class_t ni_objectmodel_addrconf_device_class = { - .name = "addrconf-device", + .name = "addrconf-device", +}; + +static ni_dbus_class_t ni_objectmodel_auto4_request_class = { + .name = "auto4-request", }; typedef struct ni_dbus_addrconf_forwarder { @@ -48,6 +53,11 @@ typedef struct ni_dbus_addrconf_forwarder { const char * object_path; } supplicant; + struct { + ni_dbus_class_t * class; + unsigned int mask; + } request; + unsigned int addrfamily; ni_addrconf_mode_t addrconf; @@ -62,6 +72,10 @@ static dbus_bool_t ni_objectmodel_addrconf_forward_release(ni_dbus_addrconf_forw ni_netdev_t *dev, const ni_dbus_variant_t *dict, ni_dbus_message_t *reply, DBusError *error); +static dbus_bool_t ni_objectmodel_addrconf_fallback_request(ni_netdev_t *dev, unsigned int family); +static dbus_bool_t ni_objectmodel_addrconf_fallback_release(ni_netdev_t *dev, unsigned int family); +static dbus_bool_t ni_objectmodel_addrconf_fallback_reinstall(ni_netdev_t *dev, ni_addrconf_lease_t *lease); + #define NI_OBJECTMODEL_ADDRCONF_IPV4STATIC_INTERFACE NI_OBJECTMODEL_ADDRCONF_INTERFACE ".ipv4.static" #define NI_OBJECTMODEL_ADDRCONF_IPV4DHCP_INTERFACE NI_OBJECTMODEL_ADDRCONF_INTERFACE ".ipv4.dhcp" #define NI_OBJECTMODEL_ADDRCONF_IPV6DHCP_INTERFACE NI_OBJECTMODEL_ADDRCONF_INTERFACE ".ipv6.dhcp" @@ -157,6 +171,7 @@ ni_objectmodel_addrconf_signal_handler(ni_dbus_connection_t *conn, ni_dbus_messa ni_addrconf_lease_t *lease = NULL; ni_dbus_variant_t argv[16]; ni_uuid_t uuid = NI_UUID_INIT; + unsigned int fallback = AF_UNSPEC; ni_event_t ifevent; int argc, optind = 0; @@ -208,6 +223,8 @@ ni_objectmodel_addrconf_signal_handler(ni_dbus_connection_t *conn, ni_dbus_messa } ifevent = NI_EVENT_ADDRESS_ACQUIRED; + if (ni_addrconf_flag_bit_is_set(lease->flags, NI_ADDRCONF_FLAGS_PRIMARY)) + fallback = lease->family; __ni_objectmodel_routes_bind_device_name(lease->routes, ifp->name); @@ -242,10 +259,19 @@ ni_objectmodel_addrconf_signal_handler(ni_dbus_connection_t *conn, ni_dbus_messa if (!_lease || !ni_uuid_equal(&_lease->uuid, &uuid)) goto done; + if (ni_addrconf_flag_bit_is_set(_lease->flags, NI_ADDRCONF_FLAGS_PRIMARY)) + fallback = _lease->family; + lease->state = _lease->state = NI_ADDRCONF_STATE_REQUESTING; ifevent = NI_EVENT_ADDRESS_DEFERRED; goto emit; } else if (!strcmp(signal_name, NI_OBJECTMODEL_LEASE_RELEASED_SIGNAL)) { + ni_addrconf_lease_t *_lease; + + _lease = ni_netdev_get_lease(ifp, lease->family, lease->type); + if (_lease && ni_addrconf_flag_bit_is_set(_lease->flags, NI_ADDRCONF_FLAGS_FALLBACK)) + fallback = _lease->family; + lease->state = NI_ADDRCONF_STATE_RELEASED; ifevent = NI_EVENT_ADDRESS_RELEASED; } else if (!strcmp(signal_name, NI_OBJECTMODEL_LEASE_LOST_SIGNAL)) { @@ -280,6 +306,22 @@ ni_objectmodel_addrconf_signal_handler(ni_dbus_connection_t *conn, ni_dbus_messa { ni_dbus_object_t *object; + if (fallback != AF_UNSPEC) { + switch (ifevent) { + case NI_EVENT_ADDRESS_ACQUIRED: + ni_objectmodel_addrconf_fallback_release(ifp, fallback); + break; + case NI_EVENT_ADDRESS_DEFERRED: + ni_objectmodel_addrconf_fallback_request(ifp, fallback); + break; + case NI_EVENT_ADDRESS_RELEASED: + ni_objectmodel_addrconf_fallback_reinstall(ifp, lease); + break; + default: + break; + } + } + object = ni_objectmodel_get_netif_object(__ni_objectmodel_server, ifp); if (object) ni_objectmodel_send_netif_event(__ni_objectmodel_server, object, @@ -445,41 +487,39 @@ ni_objectmodel_addrconf_forward_request(ni_dbus_addrconf_forwarder_t *forwarder, ni_dbus_message_t *reply, DBusError *error) { ni_addrconf_lease_t *lease; - ni_uuid_t req_uuid; dbus_bool_t rv, enabled; uint32_t flags = 0; /* Check whether we already have a lease on this interface. */ lease = ni_netdev_get_lease(dev, forwarder->addrfamily, forwarder->addrconf); - /* Generate a uuid and assign an event ID */ - ni_uuid_generate(&req_uuid); - /* If the caller tells us to disable this addrconf family, we may need * to do a release() call. */ if (!ni_dbus_dict_get_bool(dict, "enabled", &enabled) || !enabled) return ni_objectmodel_addrconf_forward_release(forwarder, dev, NULL, reply, error); - if (!ni_dbus_dict_get_uint32(dict, "flags", &flags)) + if (ni_dbus_dict_get_uint32(dict, "flags", &flags)) + flags &= forwarder->request.mask; + else flags = 0; if (lease == NULL) { /* We didn't have a lease for this address family and addrconf protocol yet. * Create one and track it. */ lease = ni_addrconf_lease_new(forwarder->addrconf, forwarder->addrfamily); + ni_uuid_generate(&lease->uuid); ni_netdev_set_lease(dev, lease); } - lease->uuid = req_uuid; lease->state = NI_ADDRCONF_STATE_REQUESTING; lease->flags = flags; - rv = ni_objectmodel_addrconf_forwarder_call(forwarder, dev, "acquire", &req_uuid, dict, error); + rv = ni_objectmodel_addrconf_forwarder_call(forwarder, dev, "acquire", &lease->uuid, dict, error); if (rv) { ni_objectmodel_callback_data_t data = { .lease = lease }; /* Tell the client to wait for an addressAcquired event with the given uuid */ rv = __ni_objectmodel_return_callback_info(reply, NI_EVENT_ADDRESS_ACQUIRED, - &req_uuid, &data, error); + &lease->uuid, &data, error); } return rv; } @@ -612,6 +652,12 @@ static ni_dbus_addrconf_forwarder_t dhcp4_forwarder = { .interface = NI_OBJECTMODEL_DHCP4_INTERFACE, .object_path = NI_OBJECTMODEL_OBJECT_PATH "/DHCP4/Interface", }, + .request = { + .class = NULL, + .mask = (1U << NI_ADDRCONF_FLAGS_GROUP) + | (1U << NI_ADDRCONF_FLAGS_PRIMARY) + | (1U << NI_ADDRCONF_FLAGS_OPTIONAL), + }, .addrfamily = AF_INET, .addrconf = NI_ADDRCONF_DHCP, .class = { @@ -624,6 +670,7 @@ ni_objectmodel_addrconf_ipv4_dhcp_request(ni_dbus_object_t *object, const ni_dbu unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error) { + ni_dbus_addrconf_forwarder_t *forwarder = &dhcp4_forwarder; ni_netdev_t *dev; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) @@ -632,11 +679,11 @@ ni_objectmodel_addrconf_ipv4_dhcp_request(ni_dbus_object_t *object, const ni_dbu if (argc != 1 || !ni_dbus_variant_is_dict(&argv[0])) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s.%s: expected one dict argument", - NI_OBJECTMODEL_ADDRCONF_IPV4DHCP_INTERFACE, method->name); + forwarder->caller.interface, method->name); return FALSE; } - return ni_objectmodel_addrconf_forward_request(&dhcp4_forwarder, dev, &argv[0], reply, error); + return ni_objectmodel_addrconf_forward_request(forwarder, dev, &argv[0], reply, error); } static dbus_bool_t @@ -664,6 +711,11 @@ static ni_dbus_addrconf_forwarder_t dhcp6_forwarder = { .interface = NI_OBJECTMODEL_DHCP6_INTERFACE, .object_path = NI_OBJECTMODEL_OBJECT_PATH "/DHCP6/Interface", }, + .request = { + .class = NULL, + .mask = (1U << NI_ADDRCONF_FLAGS_GROUP) + | (1U << NI_ADDRCONF_FLAGS_OPTIONAL), + }, .addrfamily = AF_INET6, .addrconf = NI_ADDRCONF_DHCP, .class = { @@ -676,6 +728,7 @@ ni_objectmodel_addrconf_ipv6_dhcp_request(ni_dbus_object_t *object, const ni_dbu unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error) { + ni_dbus_addrconf_forwarder_t *forwarder = &dhcp6_forwarder; ni_netdev_t *dev; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) @@ -684,11 +737,11 @@ ni_objectmodel_addrconf_ipv6_dhcp_request(ni_dbus_object_t *object, const ni_dbu if (argc != 1 || !ni_dbus_variant_is_dict(&argv[0])) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s.%s: expected one dict argument", - NI_OBJECTMODEL_ADDRCONF_IPV6DHCP_INTERFACE, method->name); + forwarder->caller.interface, method->name); return FALSE; } - return ni_objectmodel_addrconf_forward_request(&dhcp6_forwarder, dev, &argv[0], reply, error); + return ni_objectmodel_addrconf_forward_request(forwarder, dev, &argv[0], reply, error); } static dbus_bool_t @@ -707,7 +760,7 @@ ni_objectmodel_addrconf_ipv6_dhcp_drop(ni_dbus_object_t *object, const ni_dbus_m /* * Configure IPv4 addresses via IPv4ll */ -static ni_dbus_addrconf_forwarder_t ipv4ll_forwarder = { +static ni_dbus_addrconf_forwarder_t auto4_forwarder = { .caller = { .interface = NI_OBJECTMODEL_ADDRCONF_IPV4AUTO_INTERFACE, }, @@ -716,19 +769,29 @@ static ni_dbus_addrconf_forwarder_t ipv4ll_forwarder = { .interface = NI_OBJECTMODEL_AUTO4_INTERFACE, .object_path = NI_OBJECTMODEL_OBJECT_PATH "/AUTO4/Interface", }, + .request = { + .class = &ni_objectmodel_auto4_request_class, + .mask = (1U << NI_ADDRCONF_FLAGS_FALLBACK), + }, .addrfamily = AF_INET, .addrconf = NI_ADDRCONF_AUTOCONF, .class = { - .name = "netif-ipv4ll-forwarder", + .name = "netif-auto4-forwarder", } }; static dbus_bool_t -ni_objectmodel_addrconf_ipv4ll_request(ni_dbus_object_t *object, const ni_dbus_method_t *method, +ni_objectmodel_addrconf_ipv4_auto_request(ni_dbus_object_t *object, const ni_dbus_method_t *method, unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error) { + ni_dbus_addrconf_forwarder_t *forwarder = &auto4_forwarder; + ni_objectmodel_callback_data_t data = { .lease = NULL }; + const ni_dbus_variant_t *dict; + ni_addrconf_lease_t *lease; + dbus_bool_t enabled; ni_netdev_t *dev; + uint32_t flags; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; @@ -736,24 +799,200 @@ ni_objectmodel_addrconf_ipv4ll_request(ni_dbus_object_t *object, const ni_dbus_m if (argc != 1 || !ni_dbus_variant_is_dict(&argv[0])) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s.%s: expected one dict argument", - NI_OBJECTMODEL_ADDRCONF_IPV4AUTO_INTERFACE, method->name); + forwarder->caller.interface, method->name); return FALSE; } - return ni_objectmodel_addrconf_forward_request(&ipv4ll_forwarder, dev, &argv[0], reply, error); + dict = &argv[0]; + if (!ni_dbus_dict_get_bool(dict, "enabled", &enabled) || !enabled) + return ni_objectmodel_addrconf_forward_release(forwarder, dev, NULL, reply, error); + + if (ni_dbus_dict_get_uint32(dict, "flags", &flags)) + flags &= forwarder->request.mask; + else + flags = 0; + + if (!ni_addrconf_flag_bit_is_set(flags, NI_ADDRCONF_FLAGS_FALLBACK)) + return ni_objectmodel_addrconf_forward_request(forwarder, dev, dict, reply, error); + + if (!(lease = ni_netdev_get_lease(dev, forwarder->addrfamily, forwarder->addrconf))) { + lease = ni_addrconf_lease_new(forwarder->addrconf, forwarder->addrfamily); + ni_netdev_set_lease(dev, lease); + } + ni_uuid_generate(&lease->uuid); + lease->state = NI_ADDRCONF_STATE_REQUESTING; + lease->flags = flags; + data.lease = lease; + return __ni_objectmodel_return_callback_info(reply, NI_EVENT_ADDRESS_ACQUIRED, &lease->uuid, &data, error); } static dbus_bool_t -ni_objectmodel_addrconf_ipv4ll_drop(ni_dbus_object_t *object, const ni_dbus_method_t *method, +ni_objectmodel_addrconf_ipv4_auto_drop(ni_dbus_object_t *object, const ni_dbus_method_t *method, unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error) { + ni_dbus_addrconf_forwarder_t *forwarder = &auto4_forwarder; + ni_addrconf_lease_t *lease; ni_netdev_t *dev; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; - return ni_objectmodel_addrconf_forward_release(&ipv4ll_forwarder, dev, NULL, reply, error); + /* When we get a drop request, remove fallback flag to not trigger reinstall ... */ + if ((lease = ni_netdev_get_lease(dev, forwarder->addrfamily, forwarder->addrconf))) + lease->flags = 0; + + return ni_objectmodel_addrconf_forward_release(forwarder, dev, NULL, reply, error); +} + +/* + * Fallback lease request + */ +static ni_addrconf_lease_t * +ni_objectmodel_addrconf_fallback_find_lease(ni_netdev_t *dev, unsigned int family) +{ + ni_stringbuf_t buf = NI_STRINGBUF_INIT_DYNAMIC; + ni_addrconf_lease_t *lease; + + for (lease = dev->leases; lease; lease = lease->next) { + ni_addrconf_flags_format(&buf, lease->flags, "|"); + ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_OBJECTMODEL, + "%s(%s): check %s fallback lease %s:%s, state: %s, flags: %s", + __func__, dev->name, ni_addrfamily_type_to_name(family), + ni_addrfamily_type_to_name(lease->family), + ni_addrconf_type_to_name(lease->type), + ni_addrconf_state_to_name(lease->state), + buf.string ? buf.string : "none"); + ni_stringbuf_destroy(&buf); + + if (lease->family != family) + continue; + if (ni_addrconf_flag_bit_is_set(lease->flags, NI_ADDRCONF_FLAGS_FALLBACK)) + return lease; + } + return NULL; +} + +static dbus_bool_t +ni_objectmodel_addrconf_fallback_request(ni_netdev_t *dev, unsigned int family) +{ + ni_dbus_variant_t dict = NI_DBUS_VARIANT_INIT; + DBusError error = DBUS_ERROR_INIT; + ni_addrconf_lease_t *lease; + dbus_bool_t rv = FALSE; + + if (!(lease = ni_objectmodel_addrconf_fallback_find_lease(dev, family))) { + ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_OBJECTMODEL, + "%s(%s): no %s fallback lease active", __func__, + dev->name, ni_addrfamily_type_to_name(family)); + return FALSE; + } + + ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_OBJECTMODEL, + "%s(%s): found %s fallback lease %s:%s", __func__, + dev->name, ni_addrfamily_type_to_name(family), + ni_addrfamily_type_to_name(lease->family), + ni_addrconf_type_to_name(lease->type)); + + if (lease->type == NI_ADDRCONF_AUTOCONF && lease->family == AF_INET) { + ni_dbus_addrconf_forwarder_t *forwarder = &auto4_forwarder; + ni_auto4_request_t *req = ni_auto4_request_new(); + + /* make sure, we enter requesting state here */ + lease->state = NI_ADDRCONF_STATE_REQUESTING; + + req->enabled = TRUE; + req->flags = lease->flags; + req->uuid = lease->uuid; + + memset(&dict, 0, sizeof(dict)); + if (!ni_objectmodel_get_auto4_request_dict(req, &dict, &error)) { + ni_dbus_variant_destroy(&dict); + ni_auto4_request_free(req); + return FALSE; + } + + rv = ni_objectmodel_addrconf_forwarder_call(forwarder, dev, "acquire", + &lease->uuid, &dict, &error); + if (!rv) { + ni_debug_objectmodel("%s: service returned %s (%s)", + forwarder->supplicant.interface, + error.name, error.message); + /* emit failure... */ + } + ni_dbus_variant_destroy(&dict); + dbus_error_free(&error); + } + return rv; +} + +static dbus_bool_t +ni_objectmodel_addrconf_fallback_release(ni_netdev_t *dev, unsigned int family) +{ + DBusError error = DBUS_ERROR_INIT; + ni_addrconf_lease_t *lease; + dbus_bool_t rv = FALSE; + + if (!(lease = ni_objectmodel_addrconf_fallback_find_lease(dev, family))) { + ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_OBJECTMODEL, + "%s(%s): no %s fallback lease active", __func__, + dev->name, ni_addrfamily_type_to_name(family)); + return FALSE; + } + + ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_OBJECTMODEL, + "%s(%s): found %s fallback lease %s:%s", __func__, + dev->name, ni_addrfamily_type_to_name(family), + ni_addrfamily_type_to_name(lease->family), + ni_addrconf_type_to_name(lease->type)); + + if (lease->type == NI_ADDRCONF_AUTOCONF && lease->family == AF_INET) { + ni_dbus_addrconf_forwarder_t *forwarder = &auto4_forwarder; + + rv = ni_objectmodel_addrconf_forwarder_call(forwarder, dev, "drop", + &lease->uuid, NULL, &error); + if (!rv) { + switch (ni_dbus_get_error(&error, NULL)) { + case -NI_ERROR_ADDRCONF_NO_LEASE: + ni_debug_objectmodel("%s: no %s/%s lease", dev->name, + ni_addrconf_type_to_name(forwarder->addrconf), + ni_addrfamily_type_to_name(forwarder->addrfamily)); + rv = TRUE; + break; + default: + ni_debug_objectmodel("%s: service returned %s (%s)", + forwarder->supplicant.interface, + error.name, error.message); + break; + } + } + dbus_error_free(&error); + } + return rv; +} + +static dbus_bool_t +ni_objectmodel_addrconf_fallback_reinstall(ni_netdev_t *dev, ni_addrconf_lease_t *lease) +{ + ni_addrconf_lease_t *nlease; + + if (!dev || !lease) + return FALSE; + + nlease = ni_addrconf_lease_new(lease->type, lease->family); + nlease->state = NI_ADDRCONF_STATE_RELEASED; + if (lease->old) { + nlease->flags = lease->old->flags; + nlease->uuid = lease->old->uuid; + } else { + nlease->flags = lease->flags; + nlease->uuid = lease->uuid; + } + /* Hmm... generate a new uuid? */ + ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_OBJECTMODEL, + "%s: reinstalled released fallback lease", dev->name); + ni_netdev_set_lease(dev, nlease); + return TRUE; } /* @@ -866,7 +1105,7 @@ __ni_objectmodel_addrconf_ipv6_dhcp_set_lease(ni_dbus_object_t *object, } static dbus_bool_t -__ni_objectmodel_addrconf_ipv4ll_get_lease(const ni_dbus_object_t *object, +__ni_objectmodel_addrconf_ipv4_auto_get_lease(const ni_dbus_object_t *object, const ni_dbus_property_t *property, ni_dbus_variant_t *result, DBusError *error) @@ -875,7 +1114,7 @@ __ni_objectmodel_addrconf_ipv4ll_get_lease(const ni_dbus_object_t *object, } static dbus_bool_t -__ni_objectmodel_addrconf_ipv4ll_set_lease(ni_dbus_object_t *object, +__ni_objectmodel_addrconf_ipv4_auto_set_lease(ni_dbus_object_t *object, const ni_dbus_property_t *property, const ni_dbus_variant_t *argument, DBusError *error) @@ -921,8 +1160,8 @@ static ni_dbus_property_t ni_objectmodel_addrconf_ipv6_dhcp_properties[] = { { NULL } }; -static ni_dbus_property_t ni_objectmodel_addrconf_ipv4ll_properties[] = { - __NI_DBUS_PROPERTY(NI_DBUS_DICT_SIGNATURE, lease, __ni_objectmodel_addrconf_ipv4ll, RO), +static ni_dbus_property_t ni_objectmodel_addrconf_ipv4_auto_properties[] = { + __NI_DBUS_PROPERTY(NI_DBUS_DICT_SIGNATURE, lease, __ni_objectmodel_addrconf_ipv4_auto, RO), { NULL } }; @@ -953,9 +1192,9 @@ static const ni_dbus_method_t ni_objectmodel_addrconf_ipv6_dhcp_methods[] = { { NULL } }; -static const ni_dbus_method_t ni_objectmodel_addrconf_ipv4ll_methods[] = { - { "requestLease", "a{sv}", ni_objectmodel_addrconf_ipv4ll_request }, - { "dropLease", "", ni_objectmodel_addrconf_ipv4ll_drop }, +static const ni_dbus_method_t ni_objectmodel_addrconf_ipv4_auto_methods[] = { + { "requestLease", "a{sv}", ni_objectmodel_addrconf_ipv4_auto_request }, + { "dropLease", "", ni_objectmodel_addrconf_ipv4_auto_drop }, { NULL } }; @@ -986,8 +1225,129 @@ ni_dbus_service_t ni_objectmodel_addrconf_ipv6_dhcp_service = { .properties = ni_objectmodel_addrconf_ipv6_dhcp_properties, }; -ni_dbus_service_t ni_objectmodel_addrconf_ipv4ll_service = { +ni_dbus_service_t ni_objectmodel_addrconf_ipv4_auto_service = { .name = NI_OBJECTMODEL_ADDRCONF_IPV4AUTO_INTERFACE, - .methods = ni_objectmodel_addrconf_ipv4ll_methods, - .properties = ni_objectmodel_addrconf_ipv4ll_properties, + .methods = ni_objectmodel_addrconf_ipv4_auto_methods, + .properties = ni_objectmodel_addrconf_ipv4_auto_properties, +}; + + +/* + * Auto4 supplicant request + */ + +ni_auto4_request_t * +ni_auto4_request_new(void) +{ + ni_auto4_request_t *req; + + req = xmalloc(sizeof(*req)); + ni_auto4_request_init(req, FALSE); + return req; +} + +void +ni_auto4_request_init(ni_auto4_request_t *req, ni_bool_t enabled) +{ + if (req) { + memset(req, 0, sizeof(*req)); + req->enabled = enabled; + } +} + +ni_bool_t +ni_auto4_request_copy(ni_auto4_request_t *dst, const ni_auto4_request_t *src) +{ + if (dst && src) { + *dst = *src; + return TRUE; + } + return FALSE; +} + +void +ni_auto4_request_destroy(ni_auto4_request_t *req) +{ + if (req) { + memset(req, 0, sizeof(*req)); + } +} + +void +ni_auto4_request_free(ni_auto4_request_t *req) +{ + ni_auto4_request_destroy(req); + free(req); +} + +static ni_auto4_request_t * +__ni_objectmodel_get_auto4_request(const ni_dbus_object_t *object, DBusError *error) +{ + if (!object) { + if (error) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "Cannot unwrap auto4 request from a NULL dbus object"); + } + return NULL; + } + if (!ni_dbus_object_isa(object, &ni_objectmodel_auto4_request_class)) { + if (error) { + dbus_set_error(error, DBUS_ERROR_FAILED, + "method not compatible with object %s of class %s (not auto4 request)", + object->path, object->class->name); + } + return NULL; + } + return object->handle; +} + +static void * +ni_objectmodel_get_auto4_request(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) +{ + return __ni_objectmodel_get_auto4_request(object, error); +} + +static ni_dbus_property_t ni_objectmodel_auto4_request_properties[] = { + NI_DBUS_GENERIC_BOOL_PROPERTY(auto4_request, enabled, enabled, RO), + NI_DBUS_GENERIC_UINT_PROPERTY(auto4_request, flags, flags, RO), + NI_DBUS_GENERIC_UUID_PROPERTY(auto4_request, uuid, uuid, RO), + { NULL } }; + +static ni_dbus_service_t ni_objectmodel_auto4_request_service = { + .name = NI_OBJECTMODEL_AUTO4_INTERFACE".Request", + .compatible = &ni_objectmodel_auto4_request_class, + .properties = ni_objectmodel_auto4_request_properties, +}; + +dbus_bool_t +ni_objectmodel_get_auto4_request_dict(const ni_auto4_request_t *req, ni_dbus_variant_t *dict, DBusError *error) +{ + ni_auto4_request_t tmp; + ni_dbus_object_t obj; + + if (!req || !dict || !ni_auto4_request_copy(&tmp, req)) + return FALSE; + + memset(&obj, 0, sizeof(obj)); + obj.handle = &tmp; + obj.class = &ni_objectmodel_auto4_request_class; + + ni_dbus_variant_init_dict(dict); + return ni_dbus_object_get_properties_as_dict(&obj, &ni_objectmodel_auto4_request_service, dict, error); +} + +dbus_bool_t +ni_objectmodel_set_auto4_request_dict(ni_auto4_request_t *req, const ni_dbus_variant_t *dict, DBusError *error) +{ + ni_dbus_object_t obj; + + if (!req || !dict || !ni_dbus_variant_is_dict(dict)) + return FALSE; + + memset(&obj, 0, sizeof(obj)); + obj.handle = req; + obj.class = &ni_objectmodel_auto4_request_class; + + return ni_dbus_object_set_properties_from_dict(&obj, &ni_objectmodel_auto4_request_service, dict, error); +} diff --git a/src/dbus-objects/interface.c b/src/dbus-objects/interface.c index 0eed3e47e..90cedee10 100644 --- a/src/dbus-objects/interface.c +++ b/src/dbus-objects/interface.c @@ -51,7 +51,7 @@ extern ni_dbus_service_t ni_objectmodel_addrconf_ipv4_static_service; extern ni_dbus_service_t ni_objectmodel_addrconf_ipv6_static_service; extern ni_dbus_service_t ni_objectmodel_addrconf_ipv4_dhcp_service; extern ni_dbus_service_t ni_objectmodel_addrconf_ipv6_dhcp_service; -extern ni_dbus_service_t ni_objectmodel_addrconf_ipv4ll_service; +extern ni_dbus_service_t ni_objectmodel_addrconf_ipv4_auto_service; extern ni_dbus_service_t ni_objectmodel_wireless_service; static ni_dbus_property_t ni_objectmodel_netif_request_properties[]; @@ -98,7 +98,7 @@ ni_objectmodel_register_netif_services(void) ni_objectmodel_register_netif_service(NI_IFTYPE_UNKNOWN, &ni_objectmodel_addrconf_ipv6_static_service); ni_objectmodel_register_netif_service(NI_IFTYPE_UNKNOWN, &ni_objectmodel_addrconf_ipv4_dhcp_service); ni_objectmodel_register_netif_service(NI_IFTYPE_UNKNOWN, &ni_objectmodel_addrconf_ipv6_dhcp_service); - ni_objectmodel_register_netif_service(NI_IFTYPE_UNKNOWN, &ni_objectmodel_addrconf_ipv4ll_service); + ni_objectmodel_register_netif_service(NI_IFTYPE_UNKNOWN, &ni_objectmodel_addrconf_ipv4_auto_service); /* LLDP agent */ ni_objectmodel_register_netif_service(NI_IFTYPE_UNKNOWN, &ni_objectmodel_lldp_service);