/* * Create a new ppp interface */ static dbus_bool_t ni_objectmodel_ppp_device_new(ni_dbus_object_t *factory_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_server_t *server = ni_dbus_object_get_server(factory_object); ni_netdev_t *dev, *cfg; const char *ifname = NULL; if (argc != 2) goto error; if (!ni_dbus_variant_get_string(&argv[0], &ifname)) goto error; if (!(cfg = ni_objectmodel_ppp_device_arg(&argv[1]))) goto error; dev = ni_objectmodel_ppp_device_create(cfg, ifname, error); ni_netdev_put(cfg); if (dev) return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); else return FALSE; error: return ni_dbus_error_invalid_args(error, factory_object->path, method->name); }
/* * ethtool.changeDevice method */ static dbus_bool_t ni_objectmodel_ethtool_setup(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_netdev_t *dev, *cfg; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (!(cfg = ni_objectmodel_ethtool_request_arg(&argv[0]))) { ni_dbus_error_invalid_args(error, object->path, method->name); return FALSE; } if (ni_system_ethtool_setup(NULL, dev, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to apply ethtool settings"); ni_netdev_put(cfg); return FALSE; } ni_netdev_put(cfg); return TRUE; }
/* * Filesystem.getInfo(path) * */ static dbus_bool_t __ni_Testbus_Agent_Filesystem_getInfo(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_variant_t res = NI_DBUS_VARIANT_INIT; struct stat stb; const char *path; dbus_bool_t rv; if (argc != 1 || !ni_dbus_variant_get_string(&argv[0], &path) || path[0] != '/') return ni_dbus_error_invalid_args(error, object->path, method->name); if (stat(path, &stb) < 0) { ni_dbus_set_error_from_errno(error, errno, "unable to stat file \"%s\"", path); return FALSE; } if (!S_ISREG(stb.st_mode)) { dbus_set_error(error, DBUS_ERROR_FAILED, "not a regular file"); return FALSE; } ni_dbus_variant_init_dict(&res); ni_dbus_dict_add_uint64(&res, "size", stb.st_size); rv = ni_dbus_message_serialize_variants(reply, 1, &res, error); ni_dbus_variant_destroy(&res); return rv; }
/* * PPP.changeDevice method */ static dbus_bool_t ni_objectmodel_ppp_device_change(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_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *ifp, *cfg; dbus_bool_t rv = FALSE; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(ifp = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (!(cfg = ni_objectmodel_ppp_device_arg(&argv[0]))) { ni_dbus_error_invalid_args(error, object->path, method->name); goto out; } if (ni_system_ppp_setup(nc, ifp, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to set up ppp device"); goto out; } rv = TRUE; out: if (cfg) ni_netdev_put(cfg); return rv; }
/* * Create a new PPP interface * We're given two arguments, the interface name and the <ppp> configuration data. * However, we ignore all the config data at this point and just create the * device. The configuration data is consumed by a subsequent call to changeDevice * (where we build a config file from it). */ dbus_bool_t ni_objectmodel_ppp_newlink(ni_dbus_object_t *factory_object, const ni_dbus_method_t *method, unsigned int argc, const ni_dbus_variant_t *argv, ni_dbus_message_t *reply, DBusError *error, __get_device_arg_fn_t get_device_arg_fn) { ni_dbus_server_t *server = ni_dbus_object_get_server(factory_object); const char *ifname = NULL; ni_netdev_t *dev, *dev_cfg; NI_TRACE_ENTER(); ni_assert(argc == 2); if (!ni_dbus_variant_get_string(&argv[0], &ifname)) return ni_dbus_error_invalid_args(error, factory_object->path, method->name); if (!(dev_cfg = get_device_arg_fn(&argv[1], error))) return FALSE; dev = __ni_objectmodel_ppp_newlink(dev_cfg, ifname, error); ni_netdev_put(dev_cfg); if (dev == NULL) return FALSE; return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); }
/* * Eventlog.purge(seqno) */ static dbus_bool_t __ni_Testbus_Eventlog_purge(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_eventlog_t *log; uint32_t upto_seq; if (!(log = __ni_objectmodel_get_eventlog(object, TRUE, error))) return FALSE; if (argc != 1 || !ni_dbus_variant_get_uint32(&argv[0], &upto_seq)) return ni_dbus_error_invalid_args(error, object->path, method->name); if (upto_seq == 0) { /* Means: really flush all events */ ni_eventlog_flush(log); } else { /* Mark all events up to and including upto_seq as consumed. */ ni_eventlog_consume_upto(log, upto_seq); } return TRUE; }
dbus_bool_t ni_objectmodel_macvtap_newlink(ni_dbus_object_t *factory_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_server_t *server = ni_dbus_object_get_server(factory_object); ni_netdev_t *dev; const char *ifname = NULL; NI_TRACE_ENTER(); ni_assert(argc == 2); if (!ni_dbus_variant_get_string(&argv[0], &ifname) || !(dev = __ni_objectmodel_macvlan_device_arg(&argv[1], NI_IFTYPE_MACVTAP))) { return ni_dbus_error_invalid_args(error, factory_object->path, method->name); } if (!(dev = __ni_objectmodel_macvlan_newlink(dev, ifname, error))) return FALSE; return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); }
static dbus_bool_t __ni_objectmodel_tuntap_newlink(ni_iftype_t iftype, ni_dbus_object_t *factory_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_server_t *server = ni_dbus_object_get_server(factory_object); const char *ifname = NULL; ni_netdev_t *dev; ni_netdev_t *cfg; NI_TRACE_ENTER(); ni_assert(argc == 2); if (!ni_dbus_variant_get_string(&argv[0], &ifname) || !(cfg = __ni_objectmodel_tuntap_device_arg(&argv[1], iftype))) { return ni_dbus_error_invalid_args(error, factory_object->path, method->name); } ni_string_dup(&cfg->name, ifname); dev = __ni_objectmodel_tuntap_create(cfg, error); ni_netdev_put(cfg); if (!dev) return FALSE; return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); }
/* * Filesystem.download(path, offset, count) * */ static dbus_bool_t __ni_Testbus_Agent_Filesystem_download(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_variant_t res = NI_DBUS_VARIANT_INIT; const char *path; uint64_t offset; uint32_t count; dbus_bool_t rv; ni_buffer_t *bp = NULL; int fd = -1; if (argc != 3 || !ni_dbus_variant_get_string(&argv[0], &path) || path[0] != '/' || !ni_dbus_variant_get_uint64(&argv[1], &offset) || !ni_dbus_variant_get_uint32(&argv[2], &count) || count > 1024 * 1024 || offset + count < offset) return ni_dbus_error_invalid_args(error, object->path, method->name); if ((fd = open(path, O_RDONLY)) < 0) { ni_dbus_set_error_from_errno(error, errno, "unable to open file \"%s\"", path); return FALSE; } if (lseek(fd, offset, SEEK_SET) < 0) { ni_dbus_set_error_from_errno(error, errno, "seek faile"); goto out_fail; } bp = ni_buffer_new(count); while (count) { int n; n = read(fd, ni_buffer_tail(bp), ni_buffer_tailroom(bp)); if (n < 0) { ni_dbus_set_error_from_errno(error, errno, "read failed"); goto out_fail; } if (n == 0) break; ni_buffer_push_tail(bp, n); } ni_dbus_variant_init_dict(&res); ni_dbus_variant_set_byte_array(&res, ni_buffer_head(bp), ni_buffer_count(bp)); rv = ni_dbus_message_serialize_variants(reply, 1, &res, error); ni_dbus_variant_destroy(&res); ni_buffer_free(bp); close(fd); return rv; out_fail: if (fd >= 0) close(fd); return FALSE; }
/* * Tmpfile.upload(path, offset, data) */ static dbus_bool_t __ni_Testbus_Agent_Filesystem_upload(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_buffer_t wbuf; const char *path; uint64_t offset; unsigned int written = 0; int fd; if (argc != 3 || !ni_dbus_variant_get_string(&argv[0], &path) || path[0] != '/' || !ni_dbus_variant_get_uint64(&argv[1], &offset) || !ni_dbus_variant_is_byte_array(&argv[2])) return ni_dbus_error_invalid_args(error, object->path, method->name); if (offset == 0) fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644); else fd = open(path, O_WRONLY); if (fd < 0) { ni_dbus_set_error_from_errno(error, errno, "unable to open file \"%s\"", path); return FALSE; } if (lseek(fd, offset, SEEK_SET) < 0) { ni_dbus_set_error_from_errno(error, errno, "seek faile"); goto out_fail; } ni_buffer_init_reader(&wbuf, argv[2].byte_array_value, argv[2].array.len); while (ni_buffer_count(&wbuf)) { int n; n = write(fd, ni_buffer_head(&wbuf), ni_buffer_count(&wbuf)); if (n < 0) { ni_dbus_set_error_from_errno(error, errno, "error writing to \"%s\" at offset %Lu", path, (unsigned long long) offset + written); goto out_fail; } ni_buffer_pull_head(&wbuf, n); written += n; } close(fd); ni_debug_testbus("%s: wrote %u bytes at offset %Lu", path, written, (unsigned long long) offset); return TRUE; out_fail: if (fd >= 0) close(fd); return FALSE; }
static dbus_bool_t ni_objectmodel_gre_change(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_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev, *cfg; ni_gre_t *gre; const char *err; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error)) || !(cfg = __ni_objectmodel_gre_device_arg(&argv[0])) || !(ni_netdev_get_gre(dev))) { ni_dbus_error_invalid_args(error, object->path, method->name); return FALSE; } gre = ni_netdev_get_gre(cfg); if ((err = ni_gre_validate(gre))) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); return FALSE; } cfg->link.ifindex = dev->link.ifindex; if (ni_string_empty(cfg->name)) ni_string_dup(&cfg->name, dev->name); if (ni_netdev_device_is_up(dev)) { ni_debug_objectmodel("Skipping gre changeDevice call on %s: " "device is up", dev->name); return TRUE; } if (!ni_string_empty(cfg->link.lowerdev.name) && !ni_objectmodel_bind_netdev_ref_index(cfg->name, "gre tunnel", &cfg->link.lowerdev, nc, error)) return FALSE; if (ni_system_tunnel_change(nc, dev, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to change gre properties on interface %s", dev->name); return FALSE; } return TRUE; }
/* * Infiniband(Child).changeDevice method */ static dbus_bool_t ni_objectmodel_ib_setup(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_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *ifp, *cfg; dbus_bool_t rv = FALSE; /* we've already checked that argv matches our signature */ if (argc != 1 || !(ifp = ni_objectmodel_unwrap_netif(object, error))) return FALSE; if (ifp->link.type == NI_IFTYPE_INFINIBAND) { cfg = __ni_objectmodel_ibparent_device_arg(&argv[0]); } else if (ifp->link.type == NI_IFTYPE_INFINIBAND_CHILD) { cfg = __ni_objectmodel_ibchild_device_arg(&argv[0]); } else { cfg = NULL; } if (!cfg) { ni_dbus_error_invalid_args(error, object->path, method->name); goto out; } /* when <infiniband/> node is empty (defaults only), skip setup */ if (cfg->infiniband) { const char *err; if ((err = ni_infiniband_validate(ifp->link.type, cfg->infiniband, &cfg->link.lowerdev))) { dbus_set_error(error, DBUS_ERROR_FAILED, "%s", err); goto out; } if (ni_system_infiniband_setup(nc, ifp, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to configure infiniband device %s", ifp->name); goto out; } } rv = TRUE; out: if (cfg) ni_netdev_put(cfg); return rv; }
static dbus_bool_t ni_objectmodel_dummy_change(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_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev, *cfg; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error)) || !(cfg = __ni_objectmodel_dummy_device_arg(&argv[0]))) { ni_dbus_error_invalid_args(error, object->path, method->name); return FALSE; } cfg->link.ifindex = dev->link.ifindex; if (ni_string_empty(cfg->name)) ni_string_dup(&cfg->name, dev->name); if (ni_netdev_device_is_up(dev)) { ni_debug_objectmodel("Skipping dummy changeDevice call on %s: " "device is up", dev->name); return TRUE; } if (ni_system_dummy_change(nc, dev, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to change dummy properties on interface %s", dev->name); return FALSE; } if (cfg->link.hwaddr.type == ARPHRD_VOID) cfg->link.hwaddr.type = ARPHRD_ETHER; if (!ni_link_address_is_invalid(&cfg->link.hwaddr) && ni_system_hwaddr_change(nc, dev, &cfg->link.hwaddr) < 0) { ni_error("Unable to change hwaddr on dummy interface %s", dev->name); /* fail? */ } return TRUE; }
static dbus_bool_t ni_objectmodel_macvtap_change(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_netdev_t *dev, *cfg; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error)) || !(cfg = __ni_objectmodel_macvlan_device_arg(&argv[0], NI_IFTYPE_MACVTAP)) || !(ni_netdev_get_macvlan(dev))) { ni_dbus_error_invalid_args(error, object->path, method->name); return FALSE; } return __ni_objectmodel_macvlan_change(cfg, dev, error); }
/* * Create a new ovs bridge interface */ static dbus_bool_t __ni_objectmodel_ovs_bridge_create(ni_dbus_object_t *factory_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_server_t *server = ni_dbus_object_get_server(factory_object); ni_netdev_t *ifp; const char *ifname = NULL; ni_assert(argc == 2); if (!ni_dbus_variant_get_string(&argv[0], &ifname) || !(ifp = __ni_objectmodel_ovs_bridge_device_arg(&argv[1]))) return ni_dbus_error_invalid_args(error, factory_object->path, method->name); if (!(ifp = __ni_objectmodel_ovs_bridge_newlink(ifp, ifname, error))) return FALSE; return ni_objectmodel_netif_factory_result(server, reply, ifp, NULL, error); }
/* * LLDP.lldpUp */ static dbus_bool_t ni_objectmodel_lldp_up(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_netdev_t *dev, *cfg; dbus_bool_t rv = FALSE; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; ni_debug_lldp("ni_objectmodel_lldp_up(%s -> %s)", object->path, dev->name); if (!ni_system_lldp_available(dev)) { ni_error("Cannot enable LLDP for device %s: incompatible layer 2 protocol", dev->name); return TRUE; } if (!(cfg = __ni_objectmodel_protocol_arg(&argv[0], &ni_objectmodel_lldp_service))) { ni_dbus_error_invalid_args(error, object->path, method->name); goto out; } if (cfg->lldp && !__ni_objectmodel_lldp_verify(object, method, dev, cfg->lldp, error)) goto out; if (ni_system_lldp_up(dev, cfg->lldp) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "failed to set up LLDP on device %s", dev->name); goto out; } rv = TRUE; out: if (cfg) ni_netdev_put(cfg); return rv; }
/* * Eventlog.add(event) */ static dbus_bool_t __ni_Testbus_Eventlog_add(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_eventlog_t *log; const ni_event_t *last; ni_event_t *ev; uint32_t last_seq = 0; if (!(log = __ni_objectmodel_get_eventlog(object, TRUE, error))) return FALSE; if ((last = ni_eventlog_last(log)) != NULL) last_seq = last->sequence; if (argc != 1) goto invalid_args; ev = ni_event_array_add(&log->events); if (!ni_testbus_event_deserialize(&argv[0], ev)) { /* Dispose of the incomplete event. Would be nice if there were * a proper function for this. */ ni_event_destroy(ev); log->events.count -= 1; goto invalid_args; } if (last_seq && ev->sequence != last_seq + 1) ni_warn("%s: lost event(s): expected seq %u, got seq %u", object->path, last_seq + 1, ev->sequence); ni_debug_dbus("%s: adding %s-%s event from %s to log", object->path, ev->class, ev->type, ev->source); ni_testbus_eventlog_signal_eventsAdded(object, ev->sequence); return TRUE; invalid_args: return ni_dbus_error_invalid_args(error, object->path, method->name); }
static dbus_bool_t ni_objectmodel_ib_newchild(ni_dbus_object_t *factory_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_server_t *server = ni_dbus_object_get_server(factory_object); ni_netdev_t *cfg, *dev; const char *ifname = NULL; NI_TRACE_ENTER(); if (argc != 2 || !ni_dbus_variant_get_string(&argv[0], &ifname) || !ifname || !(cfg = __ni_objectmodel_ibchild_device_arg(&argv[1]))) { return ni_dbus_error_invalid_args(error, factory_object->path, method->name); } if (!(dev = __ni_objectmodel_ib_newchild(cfg, ifname, error))) { ni_netdev_put(cfg); return FALSE; } ni_netdev_put(cfg); return ni_objectmodel_netif_factory_result(server, reply, dev, NULL, error); }
static dbus_bool_t ni_objectmodel_tuntap_change(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_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev, *cfg; ni_tuntap_t *tuntap; const char *err; const char *iftype_name; /* we've already checked that argv matches our signature */ ni_assert(argc == 1); if (!(dev = ni_objectmodel_unwrap_netif(object, error)) || !(cfg = __ni_objectmodel_tuntap_device_arg(&argv[0], dev->link.type)) || !(ni_netdev_get_tuntap(dev))) { ni_dbus_error_invalid_args(error, object->path, method->name); return FALSE; } /* changeDevice method is only needed in case of TAP devices */ if (dev->link.type != NI_IFTYPE_TAP) return TRUE; iftype_name = ni_linktype_type_to_name(dev->link.type); tuntap = ni_netdev_get_tuntap(cfg); if ((err = ni_tuntap_validate(tuntap))) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); return FALSE; } cfg->link.ifindex = dev->link.ifindex; if (ni_string_empty(cfg->name)) ni_string_dup(&cfg->name, dev->name); if (ni_netdev_device_is_up(dev)) { ni_debug_objectmodel("Skipping %s changeDevice call on %s: " "device is up", iftype_name, dev->name); return TRUE; } if (ni_system_tap_change(nc, dev, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to change %s properties on interface %s", iftype_name, dev->name); return FALSE; } if (cfg->link.hwaddr.type == ARPHRD_VOID) cfg->link.hwaddr.type = ARPHRD_ETHER; if (ni_system_hwaddr_change(nc, dev, &cfg->link.hwaddr) < 0) { ni_error("Unable to change hwaddr on %s interface %s", iftype_name, dev->name); /* fail? */ } return TRUE; }