/* * 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; }
static ni_netdev_t * __ni_objectmodel_dummy_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev_ifp = NULL; int rv; if (ni_string_empty(ifname)) { if (ni_string_empty(cfg_ifp->name) && (ifname = ni_netdev_make_name(nc, "dummy", 0))) { ni_string_dup(&cfg_ifp->name, ifname); } else { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Unable to create dummy interface: " "name argument missed"); goto out; } ifname = NULL; } else if(!ni_string_eq(cfg_ifp->name, ifname)) { ni_string_dup(&cfg_ifp->name, ifname); } if (cfg_ifp->link.hwaddr.len) { if (cfg_ifp->link.hwaddr.type == ARPHRD_VOID) cfg_ifp->link.hwaddr.type = ARPHRD_ETHER; if (cfg_ifp->link.hwaddr.type != ARPHRD_ETHER || cfg_ifp->link.hwaddr.len != ni_link_address_length(ARPHRD_ETHER)) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot create dummy interface: " "invalid ethernet address '%s'", ni_link_address_print(&cfg_ifp->link.hwaddr)); return NULL; } } if ((rv = ni_system_dummy_create(nc, cfg_ifp, &dev_ifp)) < 0) { if (rv != -NI_ERROR_DEVICE_EXISTS || dev_ifp == NULL || (ifname && dev_ifp && !ni_string_eq(dev_ifp->name, ifname))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create dummy interface: %s", ni_strerror(rv)); dev_ifp = NULL; goto out; } ni_debug_dbus("dummy interface exists (and name matches)"); } if (dev_ifp->link.type != NI_IFTYPE_DUMMY) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create dummy interface: " "new interface is of type %s", ni_linktype_type_to_name(dev_ifp->link.type)); dev_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return dev_ifp; }
/* * Embed rtnetlink socket into ni_socket_t and set ifevent handler */ int ni_server_listen_interface_events(void (*ifevent_handler)(ni_netdev_t *, ni_event_t)) { ni_rtevent_handle_t *handle; unsigned int family; if (__ni_rtevent_sock || ni_global.interface_event) { ni_error("Interface event handler is already set"); return -1; } if (!(__ni_rtevent_sock = __ni_rtevent_sock_open())) return -1; family = ni_netconfig_get_family_filter(ni_global_state_handle(0)); handle = __ni_rtevent_sock->user_data; /* TODO: Move IPv6 info to separate function, dhcp4 does not need it */ if (!__ni_rtevent_join_group(handle, RTNLGRP_LINK) || (family != AF_INET && !__ni_rtevent_join_group(handle, RTNLGRP_IPV6_IFINFO))) { ni_socket_release(__ni_rtevent_sock); __ni_rtevent_sock = NULL; return -1; } ni_global.interface_event = ifevent_handler; ni_socket_activate(__ni_rtevent_sock); return 0; }
/* * Receive events from netlink socket and generate events. */ static int __ni_rtevent_process_cb(struct nl_msg *msg, void *ptr) { const struct sockaddr_nl *sender = nlmsg_get_src(msg); struct nlmsghdr *nlh; ni_netconfig_t *nc; if ((nc = ni_global_state_handle(0)) == NULL) return NL_SKIP; if (sender->nl_pid != 0) { ni_error("ignoring rtnetlink event message from PID %u", sender->nl_pid); return NL_SKIP; } nlh = nlmsg_hdr(msg); if (__ni_rtevent_process(nc, sender, nlh) < 0) { ni_debug_events("ignoring %s rtnetlink event", ni_rtnl_msg_type_to_name(nlh->nlmsg_type, "unknown")); return NL_SKIP; } return NL_OK; }
/* * Callback from wpa_supplicant client whenever the association state changes * in a significant way. */ void ni_wireless_association_changed(unsigned int ifindex, ni_wireless_assoc_state_t new_state) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev; ni_wireless_t *wlan; if (!(dev = ni_netdev_by_index(nc, ifindex))) return; if (!(wlan = dev->wireless)) return; if (new_state == wlan->assoc.state) return; wlan->assoc.state = new_state; if (new_state == NI_WIRELESS_ESTABLISHED) __ni_netdev_event(nc, dev, NI_EVENT_LINK_ASSOCIATED); /* We keep track of when we were last changing to or * from fully authenticated state. * We use this to decide when to give up and announce * that we've lost the network - see the timer handling * code above. */ ni_wireless_update_association_timer(dev); }
/* * Extract interface index from object path. * Path names must be NI_OBJECTMODEL_OBJECT_PATH "/" <something> "/Interface/" <index> */ static ni_netdev_t * ni_objectmodel_addrconf_path_to_device(const char *path) { unsigned int ifindex; ni_netconfig_t *nc; char cc; if (strncmp(path, NI_OBJECTMODEL_OBJECT_PATH, strlen(NI_OBJECTMODEL_OBJECT_PATH))) return NULL; path += strlen(NI_OBJECTMODEL_OBJECT_PATH); if (*path++ != '/') return NULL; while ((cc = *path++) != '/') { if (cc == '\0') return NULL; } if (strncmp(path, "Interface/", 10)) return NULL; path += 10; if (ni_parse_uint(path, &ifindex, 10) < 0) return NULL; nc = ni_global_state_handle(1); if (nc == NULL) { ni_error("%s: unable to refresh interfaces", __func__); return NULL; } return ni_netdev_by_index(nc, ifindex); }
static ni_netdev_t * ni_objectmodel_ppp_device_create(ni_netdev_t *cfg, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev = NULL; int rv; ni_netdev_get_ppp(cfg); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "ppp", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ppp interface - too many interfaces"); return NULL; } ni_string_dup(&cfg->name, ifname); if ((rv = ni_system_ppp_create(nc, cfg, &dev)) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ppp interface '%s'", cfg->name); return NULL; } if (dev && dev->link.type != NI_IFTYPE_PPP) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ppp interface: new interface is of type %s", ni_linktype_type_to_name(dev->link.type)); return NULL; } return dev; }
/* * InfinibandChild.Factory.newDevice: * Create a new infiniband child interface */ static ni_netdev_t * __ni_objectmodel_ib_newchild(ni_netdev_t *cfg, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev = NULL; const ni_infiniband_t *ib; const char *err; int rv; ib = ni_netdev_get_infiniband(cfg); if ((err = ni_infiniband_validate(NI_IFTYPE_INFINIBAND_CHILD, ib, &cfg->link.lowerdev)) != NULL) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); return NULL; } if (ni_string_empty(ifname)) { if (ni_string_empty(cfg->name) && !ni_string_printf(&cfg->name, "%s.%04x", cfg->link.lowerdev.name, ib->pkey)) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create infiniband child: " "name argument missed, failed to construct"); return NULL; } ifname = NULL; } else if (!ni_string_eq(cfg->name, ifname)) { ni_string_dup(&cfg->name, ifname); } if (ni_string_eq(cfg->name, cfg->link.lowerdev.name)) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot to create infiniband child: " "child name %s equal with parent device name", cfg->name); return NULL; } if ((rv = ni_system_infiniband_child_create(nc, cfg, &dev)) < 0) { if (rv != -NI_ERROR_DEVICE_EXISTS || !dev || (ifname && dev && !ni_string_eq(ifname, dev->name))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create infiniband child interface: %s", ni_strerror(rv)); return NULL; } } if (dev && dev->link.type != NI_IFTYPE_INFINIBAND_CHILD) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create infiniband child interface %s: it exists with type %s", cfg->name, ni_linktype_type_to_name(dev->link.type)); return NULL; } return dev; }
static ni_netdev_t * __ni_objectmodel_team_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; int rv; ni_netdev_get_team(cfg_ifp); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "team", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface - too many interfaces"); goto out; } ni_string_dup(&cfg_ifp->name, ifname); if (cfg_ifp->link.hwaddr.len) { if (cfg_ifp->link.hwaddr.type == ARPHRD_VOID) cfg_ifp->link.hwaddr.type = ARPHRD_ETHER; if (cfg_ifp->link.hwaddr.type != ARPHRD_ETHER || cfg_ifp->link.hwaddr.len != ni_link_address_length(ARPHRD_ETHER)) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot create team interface: invalid ethernet address '%s'", ni_link_address_print(&cfg_ifp->link.hwaddr)); goto out; } } if ((rv = ni_system_team_create(nc, cfg_ifp, &new_ifp)) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface '%s'", cfg_ifp->name); new_ifp = NULL; goto out; #if 0 if (rv != -NI_ERROR_DEVICE_EXISTS && (ifname != NULL && strcmp(ifname, new_ifp->name))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface: %s", ni_strerror(rv)); goto out; } ni_debug_dbus("Bonding interface exists (and name matches)"); #endif } if (new_ifp->link.type != NI_IFTYPE_TEAM) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create team interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
void ni_dhcp4_fsm_process_arp_packet(ni_arp_socket_t *arph, const ni_arp_packet_t *pkt, void *user_data) { ni_dhcp4_device_t *dev = user_data; ni_netconfig_t *nc = ni_global_state_handle(0); const ni_netdev_t *ifp; ni_bool_t false_alarm = FALSE; ni_bool_t found_addr = FALSE; if (!pkt || pkt->op != ARPOP_REPLY || !dev || !dev->lease) return; /* Is it about the address we're validating at all? */ if (pkt->sip.s_addr != dev->lease->dhcp4.address.s_addr) return; /* Ignore any ARP replies that seem to come from our own * MAC address. Some helpful switches seem to generate * these. */ if (ni_link_address_equal(&dev->system.hwaddr, &pkt->sha)) return; /* As well as ARP replies that seem to come from our own * host: dup if same address, not a dup if there are two * interfaces connected to the same broadcast domain. */ for (ifp = ni_netconfig_devlist(nc); ifp; ifp = ifp->next) { if (ifp->link.ifindex == dev->link.ifindex) continue; if (!ni_netdev_link_is_up(ifp)) continue; if (!ni_link_address_equal(&ifp->link.hwaddr, &pkt->sha)) continue; /* OK, we have an interface matching the hwaddr, * which will answer arp requests when it is on * the same broadcast domain and causes a false * alarm, except it really has the IP assigned. */ false_alarm = TRUE; if (__ni_dhcp4_address_on_device(ifp, pkt->sip)) found_addr = TRUE; } if (false_alarm && !found_addr) return; ni_debug_dhcp("%s: address %s already in use by %s", dev->ifname, inet_ntoa(pkt->sip), ni_link_address_print(&pkt->sha)); ni_dhcp4_device_arp_close(dev); ni_dhcp4_fsm_decline(dev); }
static ni_bool_t __ni_dhcp4_address_on_link(ni_dhcp4_device_t *dev, struct in_addr ipv4) { ni_netconfig_t *nc; ni_netdev_t *ifp; nc = ni_global_state_handle(0); if (!nc || !(ifp = ni_netdev_by_index(nc, dev->link.ifindex))) return FALSE; return __ni_dhcp4_address_on_device(ifp, ipv4); }
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; }
/* * Refresh the device mtu and MAC address info prior to taking any actions */ int ni_dhcp4_device_refresh(ni_dhcp4_device_t *dev) { ni_netconfig_t *nih = ni_global_state_handle(0); int rv; if ((rv = __ni_device_refresh_link_info(nih, &dev->link)) < 0) { ni_error("%s: cannot refresh interface: %s", __func__, ni_strerror(rv)); return rv; } return ni_capture_devinfo_refresh(&dev->system, dev->ifname, &dev->link); }
/* * 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 ni_netdev_t * __ni_objectmodel_tun_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; const ni_tun_t *tun; const char *err; int rv; /* There's nothing in the device argument that we could use. */ ni_debug_dbus("TUN.newDevice(name=%s)", ifname); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "tun", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create tun - too many interfaces"); goto out; } tun = ni_netdev_get_tun(cfg_ifp); if ((err = ni_tun_validate(tun))) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); goto out; } if ((rv = ni_system_tun_create(nc, ifname, tun, &new_ifp)) < 0) { if (rv != -NI_ERROR_DEVICE_EXISTS || new_ifp == NULL || (ifname && new_ifp && !ni_string_eq(new_ifp->name, ifname))) { ni_dbus_set_error_from_code(error, rv, "unable to create TUN interface %s", ifname); new_ifp = NULL; goto out; } ni_debug_dbus("TUN interface exists (and name matches)"); } if (new_ifp->link.type != NI_IFTYPE_TUN) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create TUN interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
ni_netdev_t * ni_netdev_ref_bind_ifindex(ni_netdev_ref_t *ref, ni_netconfig_t *nc) { ni_netdev_t *dev; if (!ref || (!nc && !(nc = ni_global_state_handle(0)))) return NULL; dev = ni_netdev_by_name(nc, ref->name); if (dev == NULL) return NULL; ref->index = dev->link.ifindex; return dev; }
ni_netdev_t * ni_netdev_ref_bind_ifname(ni_netdev_ref_t *ref, ni_netconfig_t *nc) { ni_netdev_t *dev; if (!ref || (!nc && !(nc = ni_global_state_handle(0)))) return NULL; dev = ni_netdev_by_index(nc, ref->index); if (dev == NULL) return NULL; if (!ni_string_eq(ref->name, dev->name)) ni_string_dup(&ref->name, dev->name); return dev; }
/* * Process a request to reconfigure the device (ie rebind a lease, or discover * a new lease). */ int ni_autoip_device_refresh(ni_autoip_device_t *dev) { ni_netconfig_t *nih = ni_global_state_handle(0); int rv; /* Go back to INIT state to force a reclaim */ dev->fsm.state = NI_AUTOIP_STATE_INIT; if ((rv = __ni_device_refresh_link_info(nih, &dev->link)) < 0) { ni_error("%s: cannot refresh interface: %s", __func__, ni_strerror(rv)); return rv; } return ni_capture_devinfo_refresh(&dev->devinfo, dev->ifname, &dev->link); }
ni_netdev_t * ni_netdev_ref_resolve(ni_netdev_ref_t *ref, ni_netconfig_t *nc) { ni_netdev_t *dev = NULL; if (!ref || (!nc && !(nc = ni_global_state_handle(0)))) return NULL; if (ref->index && (dev = ni_netdev_by_index(nc, ref->index))) return dev; if (ref->name && (dev = ni_netdev_by_name(nc, ref->name))) return dev; return NULL; }
static ni_netdev_t * __ni_objectmodel_bond_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; const ni_bonding_t *bond; int rv; bond = ni_netdev_get_bonding(cfg_ifp); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "bond", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface - too many interfaces"); goto out; } ni_string_dup(&cfg_ifp->name, ifname); if ((rv = ni_system_bond_create(nc, cfg_ifp->name, bond, &new_ifp)) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface '%s'", cfg_ifp->name); new_ifp = NULL; goto out; #if 0 if (rv != -NI_ERROR_DEVICE_EXISTS && (ifname != NULL && strcmp(ifname, new_ifp->name))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface: %s", ni_strerror(rv)); goto out; } ni_debug_dbus("Bonding interface exists (and name matches)"); #endif } if (new_ifp->link.type != NI_IFTYPE_BOND) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bonding interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
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 void __ni_wireless_association_timeout(void *ptr, const ni_timer_t *timer) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *dev = ptr; ni_wireless_t *wlan = dev->wireless; if (wlan->assoc.timer != timer) return; ni_debug_wireless("%s: association timed out", dev->name); wlan->assoc.timer = NULL; __ni_netdev_event(nc, dev, NI_EVENT_LINK_DOWN); __ni_netdev_event(nc, dev, NI_EVENT_LINK_ASSOCIATION_LOST); ni_wireless_disconnect(dev); }
static ni_netdev_t * __ni_objectmodel_ppp_newlink(ni_netdev_t *cfg, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_dev = NULL; int rv; ni_debug_dbus("PPP.newDevice(name=%s)", ifname); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "ppp"))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ppp - too many interfaces"); return NULL; } if ((rv = ni_system_ppp_create(nc, ifname, cfg->ppp, &new_dev)) < 0) { if (rv != -NI_ERROR_DEVICE_EXISTS && (ifname != NULL && strcmp(ifname, new_dev->name))) { ni_dbus_set_error_from_code(error, rv, "unable to create PPP interface %s", ifname); return NULL; } ni_debug_dbus("PPP interface exists (and name matches)"); } if (new_dev->link.type != NI_IFTYPE_PPP) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create PPP interface: new interface is of type %s", ni_linktype_type_to_name(new_dev->link.type)); /* FIXME: delete device? */ return NULL; } if (ni_ppp_write_config(new_dev->ppp) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create PPP interface: failed to write coniguration files"); /* FIXME: delete device */ return NULL; } return new_dev; }
/* * PPP.delete method */ static dbus_bool_t ni_objectmodel_ppp_device_delete(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; if (!(dev = ni_objectmodel_unwrap_netif(object, error))) return FALSE; NI_TRACE_ENTER_ARGS("dev=%s", dev->name); if (ni_system_ppp_delete(nc, dev) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Error deleting ppp interface %s", dev->name); return FALSE; } ni_client_state_drop(dev->link.ifindex); return TRUE; }
static int __do_arp_validate_init(struct arp_handle *handle, ni_capture_devinfo_t *dev_info) { ni_netconfig_t *nc; ni_netdev_t *dev; if (ni_server_listen_interface_events(NULL) < 0) { ni_error("unable to initialize netlink link listener"); return NI_LSB_RC_ERROR; } if (ni_server_enable_interface_addr_events(NULL) < 0) { ni_error("unable to initialize netlink addr listener"); return NI_LSB_RC_ERROR; } if (!(nc = ni_global_state_handle(1))) { ni_error("Cannot refresh interface list!"); return NI_LSB_RC_ERROR; } if (!(dev = ni_netdev_by_name(nc, handle->ifname))) { ni_error("Cannot find interface with name '%s'", handle->ifname); return NI_LSB_RC_ERROR; } if (!ni_netdev_supports_arp(dev)) { ni_error("%s: arp is not supported/enabled", dev->name); return NI_LSB_RC_ERROR; } if (!ni_netdev_link_is_up(dev)) { ni_error("%s: link is not up", dev->name); return NI_LSB_RC_ERROR; } if (ni_capture_devinfo_init(dev_info, dev->name, &dev->link) < 0) { ni_error("%s: cannot initialize capture", dev->name); return NI_LSB_RC_ERROR; } return 0; }
static ni_netdev_t * __ni_objectmodel_ovs_bridge_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; int rv; ni_netdev_get_ovs_bridge(cfg_ifp); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "ovsbr", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ovs bridge interface - too many interfaces"); goto out; } ni_string_dup(&cfg_ifp->name, ifname); if ((rv = ni_system_ovs_bridge_create(nc, cfg_ifp, &new_ifp)) < 0) { if (rv != -NI_ERROR_DEVICE_EXISTS || new_ifp == NULL || (ifname && new_ifp && !ni_string_eq(ifname, new_ifp->name))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create OVS bridge device: %s", ni_strerror(rv)); new_ifp = NULL; goto out; } ni_debug_dbus("OVS bridge device %s exists (and with correct type)", ifname); } if (new_ifp->link.type != NI_IFTYPE_OVS_BRIDGE) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create ovs bridge interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
static ni_netdev_t * __ni_objectmodel_bridge_newlink(ni_netdev_t *cfg_ifp, const char *ifname, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); ni_netdev_t *new_ifp = NULL; const ni_bridge_t *bridge; int rv; bridge = ni_netdev_get_bridge(cfg_ifp); if (ifname == NULL && !(ifname = ni_netdev_make_name(nc, "br", 0))) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bridging interface - too many interfaces"); goto out; } ni_string_dup(&cfg_ifp->name, ifname); if ((rv = ni_system_bridge_create(nc, cfg_ifp->name, bridge, &new_ifp)) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bridging interface: %s", ni_strerror(rv)); new_ifp = NULL; goto out; } if (new_ifp->link.type != NI_IFTYPE_BRIDGE) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to create bridging interface: new interface is of type %s", ni_linktype_type_to_name(new_ifp->link.type)); new_ifp = NULL; } out: if (cfg_ifp) ni_netdev_put(cfg_ifp); return new_ifp; }
int ni_server_enable_interface_addr_events(void (*ifaddr_handler)(ni_netdev_t *, ni_event_t, const ni_address_t *)) { ni_rtevent_handle_t *handle; unsigned int family; if (!__ni_rtevent_sock || ni_global.interface_addr_event) { ni_error("Interface address event handler already set"); return -1; } family = ni_netconfig_get_family_filter(ni_global_state_handle(0)); handle = __ni_rtevent_sock->user_data; if ((family != AF_INET6 && !__ni_rtevent_join_group(handle, RTNLGRP_IPV4_IFADDR)) || (family != AF_INET && !__ni_rtevent_join_group(handle, RTNLGRP_IPV6_IFADDR))) { ni_error("Cannot add rtnetlink address event membership: %m"); return -1; } ni_global.interface_addr_event = ifaddr_handler; return 0; }
static void __do_arp_validate_process(ni_arp_socket_t *sock, const ni_arp_packet_t *pkt, void *user_data) { struct arp_handle *handle = user_data; ni_netconfig_t *nc = ni_global_state_handle(0); const ni_netdev_t *ifp; ni_bool_t false_alarm = FALSE; ni_bool_t found_addr = FALSE; const ni_address_t *ap; ni_sockaddr_t addr; if (!pkt || pkt->op != ARPOP_REPLY || !handle->replies) return; /* Is it about the address we're validating at all? */ if (pkt->sip.s_addr != handle->ipaddr.sin.sin_addr.s_addr) { ni_debug_application("%s: report about different address", handle->ifname); return; } /* Ignore any ARP replies that seem to come from our own * MAC address. Some helpful switches seem to generate * these. */ if (ni_link_address_equal(&sock->dev_info.hwaddr, &pkt->sha)) { ni_debug_application("%s: adress in use by ourself", handle->ifname); return; } /* As well as ARP replies that seem to come from our own * host: dup if same address, not a dup if there are two * interfaces connected to the same broadcast domain. */ ni_sockaddr_set_ipv4(&addr, pkt->sip, 0); for (ifp = ni_netconfig_devlist(nc); ifp; ifp = ifp->next) { if (ifp->link.ifindex == sock->dev_info.ifindex) continue; if (!ni_netdev_link_is_up(ifp)) continue; if (!ni_link_address_equal(&ifp->link.hwaddr, &pkt->sha)) continue; /* OK, we have an interface matching the hwaddr, * which will answer arp requests when it is on * the same broadcast domain and causes a false * alarm, except it really has the IP assigned. */ false_alarm = TRUE; for (ap = ifp->addrs; !found_addr && ap; ap = ap->next) { if (ap->family != AF_INET) continue; if (ni_sockaddr_equal(&ap->local_addr, &addr)) found_addr = TRUE; } } if (false_alarm && !found_addr) { ni_debug_application("%s: reply from one of our interfaces", handle->ifname); return; } ni_info("%s: adress %s in use by %s reported", handle->ifname, inet_ntoa(pkt->sip), ni_link_address_print(&pkt->sha)); handle->hwaddr = pkt->sha; }
/* * Change a macvlan/macvtap interface */ static dbus_bool_t __ni_objectmodel_macvlan_change(ni_netdev_t *cfg, ni_netdev_t *dev, DBusError *error) { ni_netconfig_t *nc = ni_global_state_handle(0); const char *err; ni_macvlan_t *macvlan; const char *dev_iftype = NULL; macvlan = ni_netdev_get_macvlan(cfg); if ((err = ni_macvlan_validate(macvlan))) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "%s", err); return FALSE; } if ((cfg->link.lowerdev.index && (cfg->link.lowerdev.index != dev->link.lowerdev.index)) || (cfg->link.lowerdev.name && !ni_string_eq(cfg->link.lowerdev.name, dev->link.lowerdev.name))) { const char *cfg_iftype = ni_linktype_type_to_name(cfg->link.type); if (cfg->link.lowerdev.name) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot change %s lower device to %s", cfg_iftype, cfg->link.lowerdev.name); } else { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot change %s lower device to %u", cfg_iftype, cfg->link.lowerdev.index); } return FALSE; } cfg->link.lowerdev.index = dev->link.lowerdev.index; ni_string_dup(&cfg->link.lowerdev.name, dev->link.lowerdev.name); cfg->link.ifindex = dev->link.ifindex; if (ni_string_empty(cfg->name)) ni_string_dup(&cfg->name, dev->name); dev_iftype = ni_linktype_type_to_name(dev->link.type); if (!macvlan->mode) { macvlan->mode = dev->macvlan->mode; } else if ((macvlan->mode == NI_MACVLAN_MODE_PASSTHRU) != (dev->macvlan->mode == NI_MACVLAN_MODE_PASSTHRU)) { /* Passthrough mode can't be set or cleared dynamically */ dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Cannot change %s mode to %s", dev_iftype, ni_macvlan_mode_to_name(macvlan->mode)); return FALSE; } if (ni_netdev_device_is_up(dev)) { ni_debug_objectmodel("Skipping %s changeDevice call on %s: " "device is up", dev_iftype, dev->name); return TRUE; } if (ni_system_macvlan_change(nc, dev, cfg) < 0) { dbus_set_error(error, DBUS_ERROR_FAILED, "Unable to change %s properties on interface %s", dev_iftype, 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 %s interface %s", dev_iftype, dev->name); /* fail? */ } return TRUE; }