static int __ni_rtevent_process_rdnss_info(ni_netdev_t *dev, const struct nd_opt_hdr *opt, size_t len) { const struct ni_nd_opt_rdnss_info_p *ropt; char buf[INET6_ADDRSTRLEN+1] = {'\0'}; const struct in6_addr* addr; ni_ipv6_devinfo_t *ipv6; unsigned int lifetime; struct timeval acquired; ni_bool_t emit = FALSE; const char *server; if (opt == NULL || len < (sizeof(*ropt) + sizeof(*addr))) { ni_error("%s: unable to parse ipv6 rdnss info event data -- too short", dev->name); return -1; } ipv6 = ni_netdev_get_ipv6(dev); if (!ipv6) { ni_error("%s: unable to allocate device ipv6 structure: %m", dev->name); return -1; } ropt = (const struct ni_nd_opt_rdnss_info_p *)opt; ni_timer_get_time(&acquired); lifetime = ntohl(ropt->nd_opt_rdnss_lifetime); len -= sizeof(*ropt); addr = &ropt->nd_opt_rdnss_addr[0]; for ( ; len >= sizeof(*addr); len -= sizeof(*addr), ++addr) { if (IN6_IS_ADDR_LOOPBACK(addr) || IN6_IS_ADDR_UNSPECIFIED(addr)) { server = inet_ntop(AF_INET6, addr, buf, sizeof(buf)); ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS, "%s: ignoring invalid rdnss server address %s", dev->name, server); continue; } if (!ni_ipv6_ra_rdnss_list_update(&ipv6->radv.rdnss, addr, lifetime, &acquired)) { server = inet_ntop(AF_INET6, addr, buf, sizeof(buf)); ni_debug_verbose(NI_LOG_DEBUG, NI_TRACE_IPV6|NI_TRACE_EVENTS, "%s: failed to track ipv6 rnssl server %s", dev->name, server); continue; } emit = TRUE; } if (emit) __ni_netdev_nduseropt_event(dev, NI_EVENT_RDNSS_UPDATE); return 0; }
static int __ni_dhcp4_build_msg_release(const ni_dhcp4_device_t *dev, const ni_addrconf_lease_t *lease, ni_buffer_t *msgbuf) { unsigned int msg_code = DHCP4_RELEASE; ni_dhcp4_message_t *message; ni_sockaddr_t addr; /* Release an IP address from a lease we own */ ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0); if (!ni_sockaddr_is_ipv4_specified(&addr)) { ni_error("%s: cannot release - no ip-address in lease", dev->ifname); return -1; } if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf))) return -1; message->ciaddr = lease->dhcp4.address.s_addr; ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using release ip-address: %s", dev->ifname, ni_sockaddr_print(&addr)); if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0) return -1; if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) < 0) return -1; if (__ni_dhcp4_build_msg_put_server_id(dev, lease, msg_code, msgbuf) < 0) return -1; return 0; }
static ni_dhcp4_message_t * __ni_dhcp4_build_msg_init_head(const ni_dhcp4_device_t *dev, unsigned int msg_code, ni_buffer_t *msgbuf) { ni_dhcp4_message_t *message; /* Build the main message (header) */ if (!(message = ni_buffer_push_tail(msgbuf, sizeof(*message)))) { ni_error("%s: buffer too short for dhcp4 message", dev->ifname); return NULL; } memset(message, 0, sizeof(*message)); message->op = DHCP4_BOOTREQUEST; message->xid = dev->dhcp4.xid; message->secs = htons(ni_dhcp4_device_uptime(dev, 0xFFFF)); message->cookie = htonl(MAGIC_COOKIE); message->hwtype = dev->system.hwaddr.type; ni_dhcp4_option_put8(msgbuf, DHCP4_MESSAGETYPE, msg_code); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using message type: %s", dev->ifname, ni_dhcp4_message_name(msg_code)); return message; }
static int __ni_dhcp4_build_msg_put_client_id(const ni_dhcp4_device_t *dev, unsigned int msg_code, ni_dhcp4_message_t *message, ni_buffer_t *msgbuf) { const ni_dhcp4_config_t *options = dev->config; if (options->client_id.len) { ni_dhcp4_option_put(msgbuf, DHCP4_CLIENTID, options->client_id.data, options->client_id.len); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using client-id: %s", dev->ifname, ni_print_hex(options->client_id.data, options->client_id.len)); } else if (!message->hwlen) { ni_error("%s: cannot construct %s without usable hw-addr and client-id", dev->ifname, ni_dhcp4_message_name(msg_code)); return -1; } else { return 1; /* skipped client-id */ } return 0; }
int __ni_dhcp4_build_msg_request_offer(const ni_dhcp4_device_t *dev, const ni_addrconf_lease_t *lease, ni_buffer_t *msgbuf) { const ni_dhcp4_config_t *options = dev->config; unsigned int msg_code = DHCP4_REQUEST; ni_dhcp4_message_t *message; ni_sockaddr_t addr; /* Request an offer provided by a server (id!) while discover */ ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0); if (!ni_sockaddr_is_ipv4_specified(&addr)) { ni_error("%s: not requesting this offer - no ip-address in lease", dev->ifname); return -1; } if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf))) return -1; if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0) return -1; if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) < 0) return -1; if (__ni_dhcp4_build_msg_put_server_id(dev, lease, msg_code, msgbuf) < 0) return -1; ni_dhcp4_option_put_ipv4(msgbuf, DHCP4_ADDRESS, lease->dhcp4.address); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using offered ip-address: %s", dev->ifname, ni_sockaddr_print(&addr)); if (__ni_dhcp4_build_msg_put_our_hostname(dev, msgbuf) < 0) return -1; if (__ni_dhcp4_build_msg_put_option_request(dev, msg_code, msgbuf) < 0) return -1; ni_dhcp4_option_put16(msgbuf, DHCP4_MAXMESSAGESIZE, dev->system.mtu); if (lease->dhcp4.lease_time != 0) { ni_dhcp4_option_put32(msgbuf, DHCP4_LEASETIME, lease->dhcp4.lease_time); } if (options->userclass.len > 0) { ni_dhcp4_option_put(msgbuf, DHCP4_USERCLASS, options->userclass.data, options->userclass.len); } if (options->classid && options->classid[0]) { ni_dhcp4_option_puts(msgbuf, DHCP4_CLASSID, options->classid); } return 0; }
void ni_server_trace_interface_nduseropt_events(ni_netdev_t *dev, ni_event_t event) { ni_ipv6_devinfo_t *ipv6 = dev->ipv6; if (!ni_debug_guard(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS)) return; switch (event) { case NI_EVENT_RDNSS_UPDATE: if (ipv6 && ipv6->radv.rdnss) { ni_ipv6_ra_rdnss_t *rdnss; char buf[32] = {'\0'}; const char *rainfo; rainfo = ipv6->radv.managed_addr ? "managed" : ipv6->radv.other_config ? "config" : "unmanaged"; for (rdnss = ipv6->radv.rdnss; rdnss; rdnss = rdnss->next) { ni_stringbuf_t lft = NI_STRINGBUF_INIT_BUFFER(buf); ni_trace("%s: update IPv6 RA<%s> RDNSS<%s>[%s]", dev->name, rainfo, ni_sockaddr_print(&rdnss->server), ni_lifetime_print_valid(&lft, rdnss->lifetime)); ni_stringbuf_destroy(&lft); } } break; case NI_EVENT_DNSSL_UPDATE: if (ipv6 && ipv6->radv.dnssl) { ni_ipv6_ra_dnssl_t *dnssl; char buf[32] = {'\0'}; const char *rainfo; rainfo = ipv6->radv.managed_addr ? "managed" : ipv6->radv.other_config ? "config" : "unmanaged"; for (dnssl = ipv6->radv.dnssl; dnssl; dnssl = dnssl->next) { ni_stringbuf_t lft = NI_STRINGBUF_INIT_BUFFER(buf); ni_trace("%s: update IPv6 RA<%s> DNSSL<%s>[%s]", dev->name, rainfo, dnssl->domain, ni_lifetime_print_valid(&lft, dnssl->lifetime)); ni_stringbuf_destroy(&lft); } } break; default: ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS, "%s: IPv6 RA %s event: ", dev->name, ni_event_type_to_name(event)); break; } }
int ni_ethtool_set_priv_flags(const char *ifname, ni_ethtool_t *ethtool, const ni_ethtool_priv_flags_t *pflags) { static const ni_ethtool_cmd_info_t NI_ETHTOOL_CMD_SPFLAGS = { ETHTOOL_SPFLAGS, "set priv-flags" }; struct ethtool_value ecmd; unsigned int i, bit; const char *name; ni_bool_t enabled; int ret; if (!pflags || !pflags->names.count) return 1; /* nothing to set */ if (!ethtool->priv_flags && (ret = ni_ethtool_get_priv_flags(ifname, ethtool)) < 0) return ret; if (!ethtool->priv_flags || !ethtool->priv_flags->names.count) return -EOPNOTSUPP; memset(&ecmd, 0, sizeof(ecmd)); ecmd.data = ethtool->priv_flags->bitmap; /* set every single bit separately in case one fails? */ for (i = 0; i < pflags->names.count; ++i) { name = pflags->names.data[i]; if (ni_string_empty(name)) continue; enabled = !!(pflags->bitmap & NI_BIT(i)); bit = ni_string_array_index(ðtool->priv_flags->names, name); if (bit == -1U) { ni_info("%s: unable to set unknown driver private flag '%s'", ifname, name); continue; } ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_IFCONFIG, "%s: setting driver private flag '%s' to %s", ifname, name, ni_format_boolean(enabled)); if (enabled) ecmd.data |= NI_BIT(bit); else ecmd.data &= ~NI_BIT(bit); } if (ecmd.data == ethtool->priv_flags->bitmap) return 0; ret = ni_ethtool_call(ifname, &NI_ETHTOOL_CMD_SPFLAGS, &ecmd, NULL); ni_ethtool_set_supported(ethtool, NI_ETHTOOL_SUPP_SET_PRIV_FLAGS, ret != -EOPNOTSUPP); if (ret < 0) return ret; return 0; }
static int __ni_dhcp4_build_msg_discover(const ni_dhcp4_device_t *dev, const ni_addrconf_lease_t *lease, ni_buffer_t *msgbuf) { const ni_dhcp4_config_t *options = dev->config; unsigned int msg_code = DHCP4_DISCOVER; ni_dhcp4_message_t *message; ni_sockaddr_t addr; /* Discover server able to provide usable offer */ if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf))) return -1; if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0) return -1; if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) < 0) return -1; /* An optional hint that we've had this address in the past, * so the server __may__ assign it again to us. */ ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0); if (ni_sockaddr_is_ipv4_specified(&addr)) { ni_dhcp4_option_put_ipv4(msgbuf, DHCP4_ADDRESS, lease->dhcp4.address); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using ip-address hint: %s", dev->ifname, ni_sockaddr_print(&addr)); } if (__ni_dhcp4_build_msg_put_option_request(dev, msg_code, msgbuf) < 0) return -1; ni_dhcp4_option_put16(msgbuf, DHCP4_MAXMESSAGESIZE, dev->system.mtu); if (lease->dhcp4.lease_time != 0) { ni_dhcp4_option_put32(msgbuf, DHCP4_LEASETIME, lease->dhcp4.lease_time); } if (options->userclass.len > 0) { ni_dhcp4_option_put(msgbuf, DHCP4_USERCLASS, options->userclass.data, options->userclass.len); } if (options->classid && options->classid[0]) { ni_dhcp4_option_puts(msgbuf, DHCP4_CLASSID, options->classid); } return 0; }
static int __ni_dhcp4_build_msg_put_hwspec(const ni_dhcp4_device_t *dev, ni_dhcp4_message_t *message) { switch (dev->system.hwaddr.type) { case ARPHRD_ETHER: case ARPHRD_IEEE802: if (dev->system.hwaddr.len && dev->system.hwaddr.len <= sizeof(message->chaddr)) { message->hwlen = dev->system.hwaddr.len; memcpy(&message->chaddr, dev->system.hwaddr.data, dev->system.hwaddr.len); } break; case ARPHRD_IEEE1394: case ARPHRD_INFINIBAND: /* See http://tools.ietf.org/html/rfc4390 * * Note: set the ciaddr before if needed. */ message->hwlen = 0; if (message->ciaddr == 0) message->flags = htons(BROADCAST_FLAG); break; default: ni_error("%s: dhcp4 unsupported hardware type %s (0x%x)", dev->ifname, ni_arphrd_type_to_name(dev->system.hwaddr.type), dev->system.hwaddr.type); return -1; } if (message->hwlen) { ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using hw-address[%u]: %s", dev->ifname, message->hwtype, ni_print_hex(message->chaddr, message->hwlen)); } if (message->flags & htons(BROADCAST_FLAG)) { ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using broadcast response flag", dev->ifname); } return 0; }
static int __ni_rtevent_process_nd_radv_opts(ni_netdev_t *dev, const struct nd_opt_hdr *opt, size_t len) { while (len > 0) { size_t opt_len; if (len < 2) { ni_error("%s: nd user option length too short", dev->name); return -1; } opt_len = (opt->nd_opt_len << 3); if (opt_len == 0) { ni_error("%s: zero length nd user option", dev->name); return -1; } else if (opt_len > len) { ni_error("%s: nd user option length exceeds total length", dev->name); return -1; } switch(opt->nd_opt_type) { case NI_ND_OPT_RDNSS_INFORMATION: if (__ni_rtevent_process_rdnss_info(dev, opt, opt_len) < 0) { ni_error("%s: Cannot process RDNSS info option", dev->name); return -1; } break; case NI_ND_OPT_DNSSL_INFORMATION: if (__ni_rtevent_process_dnssl_info(dev, opt, opt_len) < 0) { ni_error("%s: Cannot process DNSSL info option", dev->name); return -1; } break; default: /* kernels up to at least 3.4 do not provide other */ ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_IPV6|NI_TRACE_EVENTS, "%s: unhandled nd user option %d", dev->name, opt->nd_opt_type); break; } len -= opt_len; opt = (struct nd_opt_hdr *)(((uint8_t *)opt) + opt_len); } return 0; }
void ni_server_trace_interface_addr_events(ni_netdev_t *dev, ni_event_t event, const ni_address_t *ap) { ni_stringbuf_t flags = NI_STRINGBUF_INIT_DYNAMIC; ni_address_format_flags(&flags, ap->family, ap->flags, NULL); ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS, "%s: %s event: %s flags[%u] %s", dev->name, ni_event_type_to_name(event), ni_sockaddr_prefix_print(&ap->local_addr, ap->prefixlen), ap->flags, flags.string ? flags.string : ""); ni_stringbuf_destroy(&flags); }
/* * Reload an old lease from file, and see whether we can reuse it. * This is used during restart of wickedd. */ int ni_dhcp4_recover_lease(ni_dhcp4_device_t *dev) { ni_addrconf_lease_t *lease; ni_sockaddr_t addr; if (dev->lease) return 1; lease = ni_addrconf_lease_file_read(dev->ifname, NI_ADDRCONF_DHCP, AF_INET); if (!lease) return -1; if (!ni_addrconf_lease_is_valid(dev->lease)) { ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: discarding existing lease, not granted", dev->ifname); goto discard; } /* We cannot renew/rebind/reboot without it */ ni_sockaddr_set_ipv4(&addr, lease->dhcp4.server_id, 0); if (!ni_sockaddr_is_ipv4_specified(&addr)) { ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: discarding existing lease, no server-id", dev->ifname); goto discard; } ni_dhcp4_device_set_lease(dev, lease); return 0; discard: ni_addrconf_lease_free(lease); return -1; }
int __ni_dhcp4_build_msg_inform(const ni_dhcp4_device_t *dev, const ni_addrconf_lease_t *lease, ni_buffer_t *msgbuf) { const ni_dhcp4_config_t *options = dev->config; unsigned int msg_code = DHCP4_INFORM; ni_dhcp4_message_t *message; ni_sockaddr_t addr; /* Inform server about IP address we use and request other config */ ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0); if (!ni_sockaddr_is_ipv4_specified(&addr)) { ni_error("%s: cannot inform - no ip-address set", dev->ifname); return -1; } if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf))) return -1; message->ciaddr = lease->dhcp4.address.s_addr; ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using inform ip-address: %s", dev->ifname, ni_sockaddr_print(&addr)); if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0) return -1; if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) < 0) return -1; if (__ni_dhcp4_build_msg_put_option_request(dev, msg_code, msgbuf) < 0) return -1; ni_dhcp4_option_put16(msgbuf, DHCP4_MAXMESSAGESIZE, dev->system.mtu); if (options->userclass.len > 0) { ni_dhcp4_option_put(msgbuf, DHCP4_USERCLASS, options->userclass.data, options->userclass.len); } if (options->classid && options->classid[0]) { ni_dhcp4_option_puts(msgbuf, DHCP4_CLASSID, options->classid); } return 0; }
static int ni_ethtool_call(const char *ifname, const ni_ethtool_cmd_info_t *ioc, void *evp, const char *flag) { int ret; ret = __ni_ethtool(ifname, ioc->cmd, evp); if (ret < 0) { ret = -errno; if (errno != EOPNOTSUPP && errno != ENODEV) ni_warn("%s: ethtool %s%s failed: %m", ifname, ioc->name, flag ? flag : ""); else ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IFCONFIG, "%s: ethtool %s%s failed: %m", ifname, ioc->name, flag ? flag : ""); errno = -ret; } return ret; }
static int __ni_dhcp4_build_msg_put_server_id(const ni_dhcp4_device_t *dev, const ni_addrconf_lease_t *lease, unsigned int msg_code, ni_buffer_t *msgbuf) { ni_sockaddr_t addr; ni_sockaddr_set_ipv4(&addr, lease->dhcp4.server_id, 0); if (!ni_sockaddr_is_ipv4_specified(&addr)) { ni_error("%s: cannot construct %s without server-id", dev->ifname, ni_dhcp4_message_name(msg_code)); return -1; } ni_dhcp4_option_put_ipv4(msgbuf, DHCP4_SERVERIDENTIFIER, lease->dhcp4.server_id); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using server-id: %s", dev->ifname, ni_sockaddr_print(&addr)); return 0; }
void ni_server_trace_interface_prefix_events(ni_netdev_t *dev, ni_event_t event, const ni_ipv6_ra_pinfo_t *pi) { char vbuf[32] = {'\0'}, pbuf[32] = {'\0'}; ni_stringbuf_t vlft = NI_STRINGBUF_INIT_BUFFER(vbuf); ni_stringbuf_t plft = NI_STRINGBUF_INIT_BUFFER(pbuf); ni_debug_verbose(NI_LOG_DEBUG2, NI_TRACE_IPV6|NI_TRACE_EVENTS, "%s: %s IPv6 RA<%s> Prefix<%s/%u %s,%s>[%s,%s]", dev->name, (event == NI_EVENT_PREFIX_UPDATE ? "update" : "delete"), (dev->ipv6 && dev->ipv6->radv.managed_addr ? "managed" : (dev->ipv6 && dev->ipv6->radv.other_config ? "config" : "unmanaged")), ni_sockaddr_print(&pi->prefix), pi->length, (pi->on_link ? "onlink" : "not-onlink"), (pi->autoconf ? "autoconf" : "no-autoconf"), ni_lifetime_print_valid(&vlft, pi->valid_lft), ni_lifetime_print_preferred(&plft, pi->preferred_lft)); ni_stringbuf_destroy(&vlft); ni_stringbuf_destroy(&plft); }
void ni_server_trace_rule_events(ni_netconfig_t *nc, ni_event_t event, const ni_rule_t *rule) { ni_stringbuf_t buf = NI_STRINGBUF_INIT_DYNAMIC; unsigned int family_trace; switch (rule->family) { case AF_INET: family_trace = NI_TRACE_IPV4; break; case AF_INET6: family_trace = NI_TRACE_IPV6; break; default: family_trace = 0; break; } ni_debug_verbose(NI_LOG_DEBUG2, family_trace|NI_TRACE_ROUTE|NI_TRACE_EVENTS, "%s event: %s", ni_event_type_to_name(event), ni_rule_print(&buf, rule)); ni_stringbuf_destroy(&buf); }
static int __ni_dhcp4_build_msg_decline(const ni_dhcp4_device_t *dev, const ni_addrconf_lease_t *lease, ni_buffer_t *msgbuf) { unsigned int msg_code = DHCP4_DECLINE; ni_dhcp4_message_t *message; ni_sockaddr_t addr; /* Decline IP address the server offered to us; * we've found another host using it already. */ ni_sockaddr_set_ipv4(&addr, lease->dhcp4.address, 0); if (!ni_sockaddr_is_ipv4_specified(&addr)) { ni_error("%s: cannot decline - no ip-address in lease", dev->ifname); return -1; } if (!(message = __ni_dhcp4_build_msg_init_head(dev, msg_code, msgbuf))) return -1; if (__ni_dhcp4_build_msg_put_hwspec(dev, message) < 0) return -1; if (__ni_dhcp4_build_msg_put_client_id(dev, msg_code, message, msgbuf) < 0) return -1; if (__ni_dhcp4_build_msg_put_server_id(dev, lease, msg_code, msgbuf) < 0) return -1; ni_dhcp4_option_put_ipv4(msgbuf, DHCP4_ADDRESS, lease->dhcp4.address); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using decline ip-address: %s", dev->ifname, ni_sockaddr_print(&addr)); return 0; }
static int __ni_dhcp4_build_msg_put_our_hostname(const ni_dhcp4_device_t *dev, ni_buffer_t *msgbuf) { const ni_dhcp4_config_t *options = dev->config; size_t len = ni_string_len(options->hostname); if (!len) return 1; /* skipped hint */ if (options->fqdn == FQDN_DISABLE) { char hname[64] = {'\0'}, *end; /* * Truncate the domain part if fqdn to avoid attempts * to update DNS with foo.bar + update-domain. */ strncat(hname, options->hostname, sizeof(hname)-1); if ((end = strchr(hname, '.'))) *end = '\0'; len = ni_string_len(hname); if (ni_check_domain_name(hname, len, 0)) { ni_dhcp4_option_puts(msgbuf, DHCP4_HOSTNAME, hname); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using hostname: %s", dev->ifname, hname); } else { ni_info("%s: not sending suspect hostname: '%s'", dev->ifname, ni_print_suspect(hname, len)); return 1; } } else if (ni_check_domain_name(options->hostname, len, 0)) { /* IETF DHC-FQDN option(81) * http://tools.ietf.org/html/rfc4702#section-2.1 * * Flags: 0000NEOS * S: 1 => Client requests Server to update * a RR in DNS as well as PTR * O: 1 => Server indicates to client that * DNS has been updated * E: 1 => Name data is DNS format * N: 1 => Client requests Server to not * update DNS */ ni_buffer_putc(msgbuf, DHCP4_FQDN); ni_buffer_putc(msgbuf, len + 3); ni_buffer_putc(msgbuf, options->fqdn & 0x9); ni_buffer_putc(msgbuf, 0); /* from server for PTR RR */ ni_buffer_putc(msgbuf, 0); /* from server for A RR if S=1 */ ni_buffer_put(msgbuf, options->hostname, len); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using fqdn: %s", dev->ifname, options->hostname); } else { ni_info("%s: not sending suspect fqdn: '%s'", dev->ifname, ni_print_suspect(options->hostname, len)); return 1; } return 0; }
static int __ni_rtevent_process_dnssl_info(ni_netdev_t *dev, const struct nd_opt_hdr *opt, size_t len) { const struct ni_nd_opt_dnssl_info_p *dopt; ni_ipv6_devinfo_t *ipv6; unsigned int lifetime; struct timeval acquired; size_t length, cnt, off; ni_bool_t emit = FALSE; char domain[256]; if (opt == NULL || len < sizeof(*dopt)) { ni_error("%s: unable to parse ipv6 dnssl info event data -- too short", dev->name); return -1; } ipv6 = ni_netdev_get_ipv6(dev); if (!ipv6) { ni_error("%s: unable to allocate device ipv6 structure: %m", dev->name); return -1; } dopt = (const struct ni_nd_opt_dnssl_info_p *)opt; len -= sizeof(*dopt); ni_timer_get_time(&acquired); lifetime = ntohl(dopt->nd_opt_dnssl_lifetime); length = 0; domain[length] = '\0'; for (off = 0; off < len ; ) { cnt = dopt->nd_opt_dnssl_list[off++]; if (cnt == 0) { /* just padding */ if (domain[0] == '\0') continue; domain[length] = '\0'; if (!ni_check_domain_name(domain, length, 0)) { ni_debug_verbose(NI_LOG_DEBUG, NI_TRACE_IPV6|NI_TRACE_EVENTS, "%s: ignoring suspect DNSSL domain: %s", dev->name, ni_print_suspect(domain, length)); } else if (!ni_ipv6_ra_dnssl_list_update(&ipv6->radv.dnssl, domain, lifetime, &acquired)) { ni_debug_verbose(NI_LOG_DEBUG, NI_TRACE_IPV6|NI_TRACE_EVENTS, "%s: unable to track ipv6 dnssl domain %s", dev->name, domain); } else emit = TRUE; length = 0; domain[length] = '\0'; continue; } if ((off + cnt >= len) || (length + cnt + 2 > sizeof(domain))) break; if (length) domain[length++] = '.'; memcpy(&domain[length], &dopt->nd_opt_dnssl_list[off], cnt); off += cnt; length += cnt; domain[length] = '\0'; } if (emit) __ni_netdev_nduseropt_event(dev, NI_EVENT_DNSSL_UPDATE); return 0; }
static int __ni_dhcp4_build_msg_put_option_request(const ni_dhcp4_device_t *dev, unsigned int msg_code, ni_buffer_t *msgbuf) { const ni_dhcp4_config_t *options = dev->config; unsigned int params_begin; switch (msg_code) { case DHCP4_DISCOVER: case DHCP4_REQUEST: case DHCP4_INFORM: break; default: return 1; /* skipped hint */ } params_begin = ni_dhcp4_option_begin(msgbuf, DHCP4_PARAMETERREQUESTLIST); if (msg_code != DHCP4_INFORM) { ni_buffer_putc(msgbuf, DHCP4_RENEWALTIME); ni_buffer_putc(msgbuf, DHCP4_REBINDTIME); } ni_buffer_putc(msgbuf, DHCP4_NETMASK); ni_buffer_putc(msgbuf, DHCP4_BROADCAST); ni_buffer_putc(msgbuf, DHCP4_MTU); /* * RFC 3442 states classless static routes override both, * the (default) router and (class) static routes options. * Keep them in front also on request... just in case. */ if (options->doflags & DHCP4_DO_CSR) { ni_buffer_putc(msgbuf, DHCP4_CSR); } if (options->doflags & DHCP4_DO_MSCSR) { ni_buffer_putc(msgbuf, DHCP4_MSCSR); } if (options->doflags & DHCP4_DO_GATEWAY) { ni_buffer_putc(msgbuf, DHCP4_STATICROUTE); ni_buffer_putc(msgbuf, DHCP4_ROUTERS); } if (options->doflags & DHCP4_DO_HOSTNAME) { if (options->fqdn == FQDN_DISABLE) { ni_buffer_putc(msgbuf, DHCP4_HOSTNAME); } else { ni_buffer_putc(msgbuf, DHCP4_FQDN); } } if (options->doflags & DHCP4_DO_DNS) { ni_buffer_putc(msgbuf, DHCP4_DNSSEARCH); ni_buffer_putc(msgbuf, DHCP4_DNSDOMAIN); ni_buffer_putc(msgbuf, DHCP4_DNSSERVER); } if (options->doflags & DHCP4_DO_NIS) { ni_buffer_putc(msgbuf, DHCP4_NISDOMAIN); ni_buffer_putc(msgbuf, DHCP4_NISSERVER); } if (options->doflags & DHCP4_DO_NTP) { ni_buffer_putc(msgbuf, DHCP4_NTPSERVER); } if (options->doflags & DHCP4_DO_ROOT) { ni_buffer_putc(msgbuf, DHCP4_ROOTPATH); } if (options->doflags & DHCP4_DO_LPR) { ni_buffer_putc(msgbuf, DHCP4_LPRSERVER); } if (options->doflags & DHCP4_DO_LOG) { ni_buffer_putc(msgbuf, DHCP4_LOGSERVER); } if (options->doflags & DHCP4_DO_NDS) { ni_buffer_putc(msgbuf, DHCP4_NDS_SERVER); ni_buffer_putc(msgbuf, DHCP4_NDS_TREE); ni_buffer_putc(msgbuf, DHCP4_NDS_CTX); } if (options->doflags & DHCP4_DO_SIP) { ni_buffer_putc(msgbuf, DHCP4_SIPSERVER); } if (options->doflags & DHCP4_DO_SMB) { ni_buffer_putc(msgbuf, DHCP4_NETBIOSNAMESERVER); ni_buffer_putc(msgbuf, DHCP4_NETBIOSDDSERVER); ni_buffer_putc(msgbuf, DHCP4_NETBIOSNODETYPE); ni_buffer_putc(msgbuf, DHCP4_NETBIOSSCOPE); } if (options->doflags & DHCP4_DO_POSIX_TZ) { ni_buffer_putc(msgbuf, DHCP4_POSIX_TZ_STRING); ni_buffer_putc(msgbuf, DHCP4_POSIX_TZ_DBNAME); } ni_dhcp4_option_end(msgbuf, params_begin); ni_debug_verbose(NI_LOG_DEBUG1, NI_TRACE_DHCP, "%s: using an option request", dev->ifname); return 0; }