static void test_address_equality(void) { _cleanup_(address_freep) Address *a1 = NULL, *a2 = NULL; assert_se(address_new(&a1) >= 0); assert_se(address_new(&a2) >= 0); assert_se(address_equal(NULL, NULL)); assert_se(!address_equal(a1, NULL)); assert_se(!address_equal(NULL, a2)); assert_se(address_equal(a1, a2)); a1->family = AF_INET; assert_se(!address_equal(a1, a2)); a2->family = AF_INET; assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in)); assert_se(!address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in)); assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in)); assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in)); assert_se(address_equal(a1, a2)); a1->prefixlen = 10; assert_se(!address_equal(a1, a2)); a2->prefixlen = 10; assert_se(address_equal(a1, a2)); a1->family = AF_INET6; assert_se(!address_equal(a1, a2)); a2->family = AF_INET6; assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr.in6)); assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr.in6)); assert_se(address_equal(a1, a2)); a2->prefixlen = 8; assert_se(address_equal(a1, a2)); assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr.in6)); assert_se(!address_equal(a1, a2)); }
static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { _cleanup_address_free_ Address *ll_addr = NULL; _cleanup_route_free_ Route *route = NULL; struct in_addr address; int r; assert(ll); assert(link); r = sd_ipv4ll_get_address(ll, &address); if (r == -ENOENT) return 0; else if (r < 0) return r; log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u", ADDRESS_FMT_VAL(address)); r = address_new(&ll_addr); if (r < 0) return r; ll_addr->family = AF_INET; ll_addr->in_addr.in = address; ll_addr->prefixlen = 16; ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen); ll_addr->scope = RT_SCOPE_LINK; r = address_configure(ll_addr, link, ipv4ll_address_handler, false); if (r < 0) return r; link->ipv4ll_address = false; r = route_new(&route); if (r < 0) return r; route->family = AF_INET; route->scope = RT_SCOPE_LINK; route->protocol = RTPROT_STATIC; route->priority = IPV4LL_ROUTE_METRIC; r = route_configure(route, link, ipv4ll_route_handler); if (r < 0) return r; link->ipv4ll_route = false; return 0; }
static bool test_native_set(struct ConfigSet *cs, struct Buffer *err) { log_line(__func__); struct Address *a = address_new("*****@*****.**"); const char *name = "Ilama"; char *addr = NULL; bool result = false; mutt_buffer_reset(err); int rc = cs_str_native_set(cs, name, (intptr_t) a, err); if (!TEST_CHECK(CSR_RESULT(rc) == CSR_SUCCESS)) { TEST_MSG("%s\n", err->data); goto tbns_out; } addr = VarIlama ? VarIlama->mailbox : NULL; if (!TEST_CHECK(mutt_str_strcmp(addr, a->mailbox) == 0)) { TEST_MSG("Value of %s wasn't changed\n", name); goto tbns_out; } TEST_MSG("%s = '%s', set by '%s'\n", name, NONULL(addr), a->mailbox); name = "Jackfruit"; mutt_buffer_reset(err); rc = cs_str_native_set(cs, name, 0, err); if (!TEST_CHECK(CSR_RESULT(rc) == CSR_SUCCESS)) { TEST_MSG("%s\n", err->data); goto tbns_out; } if (!TEST_CHECK(VarJackfruit == NULL)) { TEST_MSG("Value of %s wasn't changed\n", name); goto tbns_out; } addr = VarJackfruit ? VarJackfruit->mailbox : NULL; TEST_MSG("%s = '%s', set by NULL\n", name, NONULL(addr)); log_line(__func__); result = true; tbns_out: address_free(&a); return result; }
static int ipv4ll_address_lost(Link *link) { _cleanup_address_free_ Address *address = NULL; _cleanup_route_free_ Route *route = NULL; struct in_addr addr; int r; assert(link); link->ipv4ll_route = false; link->ipv4ll_address = false; r = sd_ipv4ll_get_address(link->ipv4ll, &addr); if (r < 0) return 0; log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr)); r = address_new(&address); if (r < 0) { log_link_error_errno(link, r, "Could not allocate address: %m"); return r; } address->family = AF_INET; address->in_addr.in = addr; address->prefixlen = 16; address->scope = RT_SCOPE_LINK; address_remove(address, link, &link_address_remove_handler); r = route_new(&route); if (r < 0) { log_link_error_errno(link, r, "Could not allocate route: %m"); return r; } route->family = AF_INET; route->scope = RT_SCOPE_LINK; route->priority = IPV4LL_ROUTE_METRIC; route_remove(route, link, &link_route_remove_handler); link_check_ready(link); return 0; }
static int dhcp_lease_lost(Link *link) { _cleanup_address_free_ Address *address = NULL; struct in_addr addr; struct in_addr netmask; struct in_addr gateway; unsigned prefixlen = 0; int r; assert(link); assert(link->dhcp_lease); log_link_warning(link, "DHCP lease lost"); if (link->network->dhcp_use_routes) { _cleanup_free_ sd_dhcp_route **routes = NULL; int n, i; n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes); if (n >= 0) { for (i = 0; i < n; i++) { _cleanup_route_free_ Route *route = NULL; r = route_new(&route); if (r >= 0) { route->family = AF_INET; assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0); assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0); route_remove(route, link, link_route_remove_handler); } } } } r = address_new(&address); if (r >= 0) { r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); if (r >= 0) { _cleanup_route_free_ Route *route_gw = NULL; _cleanup_route_free_ Route *route = NULL; r = route_new(&route_gw); if (r >= 0) { route_gw->family = AF_INET; route_gw->dst.in = gateway; route_gw->dst_prefixlen = 32; route_gw->scope = RT_SCOPE_LINK; route_remove(route_gw, link, link_route_remove_handler); } r = route_new(&route); if (r >= 0) { route->family = AF_INET; route->gw.in = gateway; route_remove(route, link, link_route_remove_handler); } } r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr); if (r >= 0) { r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask); if (r >= 0) prefixlen = in_addr_netmask_to_prefixlen(&netmask); address->family = AF_INET; address->in_addr.in = addr; address->prefixlen = prefixlen; address_remove(address, link, link_address_remove_handler); } } if (link->network->dhcp_use_mtu) { uint16_t mtu; r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu); if (r >= 0 && link->original_mtu != mtu) { r = link_set_mtu(link, link->original_mtu); if (r < 0) { log_link_warning(link, "DHCP error: could not reset MTU"); link_enter_failed(link); return r; } } } if (link->network->dhcp_use_hostname) { const char *hostname = NULL; if (link->network->dhcp_hostname) hostname = link->network->dhcp_hostname; else (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname); if (hostname) { /* If a hostname was set due to the lease, then unset it now. */ r = manager_set_hostname(link->manager, NULL); if (r < 0) log_link_warning_errno(link, r, "Failed to reset transient hostname: %m"); } } link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); link_dirty(link); link->dhcp4_configured = false; return 0; }
NetworkInterface* networkinterface_new(Network* network, GQuark address, gchar* name, guint64 bwDownKiBps, guint64 bwUpKiBps, gboolean logPcap, gchar* pcapDir, gchar* qdisc, guint64 interfaceReceiveLength) { NetworkInterface* interface = g_new0(NetworkInterface, 1); MAGIC_INIT(interface); interface->network = network; interface->address = address_new(address, (const gchar*) name); /* interface speeds */ interface->bwUpKiBps = bwUpKiBps; gdouble bytesPerSecond = (gdouble)(bwUpKiBps * 1024); interface->timePerByteUp = (gdouble) (((gdouble)SIMTIME_ONE_SECOND) / bytesPerSecond); interface->bwDownKiBps = bwDownKiBps; bytesPerSecond = (gdouble)(bwDownKiBps * 1024); interface->timePerByteDown = (gdouble) (((gdouble)SIMTIME_ONE_SECOND) / bytesPerSecond); /* incoming packet buffer */ interface->inBuffer = g_queue_new(); interface->inBufferSize = interfaceReceiveLength; /* incoming packets get passed along to sockets */ interface->boundSockets = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, descriptor_unref); /* sockets tell us when they want to start sending */ interface->rrQueue = g_queue_new(); interface->fifoQueue = priorityqueue_new((GCompareDataFunc)_networkinterface_compareSocket, NULL, descriptor_unref); /* parse queuing discipline */ if (qdisc && !g_ascii_strcasecmp(qdisc, "rr")) { interface->qdisc = NIQ_RR; } else { interface->qdisc = NIQ_FIFO; } /* log status */ char addressStr[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &address, addressStr, INET_ADDRSTRLEN); /* open the PCAP file for writing */ interface->logPcap = logPcap; interface->pcapDir = pcapDir; interface->pcapFile = NULL; if(interface->logPcap) { GString *filename = g_string_new(""); if (interface->pcapDir) { g_string_append(filename, interface->pcapDir); /* Append trailing slash if not present */ if (!g_str_has_suffix(interface->pcapDir, "/")) { g_string_append(filename, "/"); } } else { /* Use default directory */ g_string_append(filename, "data/pcapdata/"); } g_string_append_printf(filename, "%s-%s.pcap", name, addressStr); interface->pcapFile = fopen(filename->str, "w"); if(!interface->pcapFile) { warning("error trying to open PCAP file '%s' for writing", filename->str); } else { _networkinterface_pcapInit(interface); } } info("bringing up network interface '%s' at '%s', %"G_GUINT64_FORMAT" KiB/s up and %"G_GUINT64_FORMAT" KiB/s down using queuing discipline %s", name, addressStr, bwUpKiBps, bwDownKiBps, interface->qdisc == NIQ_RR ? "rr" : "fifo"); return interface; }
static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) { _cleanup_address_free_ Address *address = NULL; uint32_t lifetime_valid, lifetime_preferred; unsigned prefixlen; int r; assert(link); assert(rt); r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); if (r < 0) { log_link_error_errno(link, r, "Failed to get prefix length: %m"); return; } r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid); if (r < 0) { log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m"); return; } r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred); if (r < 0) { log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m"); return; } r = address_new(&address); if (r < 0) { log_link_error_errno(link, r, "Could not allocate address: %m"); return; } address->family = AF_INET6; r = sd_ndisc_router_prefix_get_address(rt, &address->in_addr.in6); if (r < 0) { log_link_error_errno(link, r, "Failed to get prefix address: %m"); return; } if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0) memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8); else { /* see RFC4291 section 2.5.1 */ address->in_addr.in6.s6_addr[8] = link->mac.ether_addr_octet[0]; address->in_addr.in6.s6_addr[8] ^= 1 << 1; address->in_addr.in6.s6_addr[9] = link->mac.ether_addr_octet[1]; address->in_addr.in6.s6_addr[10] = link->mac.ether_addr_octet[2]; address->in_addr.in6.s6_addr[11] = 0xff; address->in_addr.in6.s6_addr[12] = 0xfe; address->in_addr.in6.s6_addr[13] = link->mac.ether_addr_octet[3]; address->in_addr.in6.s6_addr[14] = link->mac.ether_addr_octet[4]; address->in_addr.in6.s6_addr[15] = link->mac.ether_addr_octet[5]; } address->prefixlen = prefixlen; address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR; address->cinfo.ifa_prefered = lifetime_preferred; address->cinfo.ifa_valid = lifetime_valid; r = address_configure(address, link, ndisc_netlink_handler, true); if (r < 0) { log_link_warning_errno(link, r, "Could not set SLAAC address: %m"); link_enter_failed(link); return; } link->ndisc_messages++; }
static bool test_validator(struct ConfigSet *cs, struct Buffer *err) { log_line(__func__); char *addr = NULL; struct Address *a = address_new("*****@*****.**"); bool result = false; const char *name = "Nectarine"; mutt_buffer_reset(err); int rc = cs_str_string_set(cs, name, "*****@*****.**", err); if (TEST_CHECK(CSR_RESULT(rc) == CSR_SUCCESS)) { TEST_MSG("%s\n", err->data); } else { TEST_MSG("%s\n", err->data); goto tv_out; } addr = VarNectarine ? VarNectarine->mailbox : NULL; TEST_MSG("Address: %s = %s\n", name, NONULL(addr)); mutt_buffer_reset(err); rc = cs_str_native_set(cs, name, IP a, err); if (TEST_CHECK(CSR_RESULT(rc) == CSR_SUCCESS)) { TEST_MSG("%s\n", err->data); } else { TEST_MSG("%s\n", err->data); goto tv_out; } addr = VarNectarine ? VarNectarine->mailbox : NULL; TEST_MSG("Native: %s = %s\n", name, NONULL(addr)); name = "Olive"; mutt_buffer_reset(err); rc = cs_str_string_set(cs, name, "*****@*****.**", err); if (TEST_CHECK(CSR_RESULT(rc) == CSR_SUCCESS)) { TEST_MSG("%s\n", err->data); } else { TEST_MSG("%s\n", err->data); goto tv_out; } addr = VarOlive ? VarOlive->mailbox : NULL; TEST_MSG("Address: %s = %s\n", name, NONULL(addr)); mutt_buffer_reset(err); rc = cs_str_native_set(cs, name, IP a, err); if (TEST_CHECK(CSR_RESULT(rc) == CSR_SUCCESS)) { TEST_MSG("%s\n", err->data); } else { TEST_MSG("%s\n", err->data); goto tv_out; } addr = VarOlive ? VarOlive->mailbox : NULL; TEST_MSG("Native: %s = %s\n", name, NONULL(addr)); name = "Papaya"; mutt_buffer_reset(err); rc = cs_str_string_set(cs, name, "*****@*****.**", err); if (TEST_CHECK(CSR_RESULT(rc) != CSR_SUCCESS)) { TEST_MSG("Expected error: %s\n", err->data); } else { TEST_MSG("%s\n", err->data); goto tv_out; } addr = VarPapaya ? VarPapaya->mailbox : NULL; TEST_MSG("Address: %s = %s\n", name, NONULL(addr)); mutt_buffer_reset(err); rc = cs_str_native_set(cs, name, IP a, err); if (TEST_CHECK(CSR_RESULT(rc) != CSR_SUCCESS)) { TEST_MSG("Expected error: %s\n", err->data); } else { TEST_MSG("%s\n", err->data); goto tv_out; } addr = VarPapaya ? VarPapaya->mailbox : NULL; TEST_MSG("Native: %s = %s\n", name, NONULL(addr)); result = true; tv_out: address_free(&a); log_line(__func__); return result; }
static Address *address_parse_simple(Vis *vis, const char **s, enum SamError *err) { skip_spaces(s); Address addr = { .type = **s, .regex = NULL, .number = 0, .left = NULL, .right = NULL, }; switch (addr.type) { case '#': /* character #n */ (*s)++; addr.number = parse_number(s); break; case '0': case '1': case '2': case '3': case '4': /* line n */ case '5': case '6': case '7': case '8': case '9': addr.type = 'l'; addr.number = parse_number(s); break; case '/': /* regexp forwards */ case '?': /* regexp backwards */ addr.regex = parse_regex(vis, s); if (!addr.regex) { *err = SAM_ERR_REGEX; return NULL; } break; case '$': /* end of file */ case '.': case '+': case '-': case '%': (*s)++; break; default: return NULL; } if ((addr.right = address_parse_simple(vis, s, err))) { switch (addr.right->type) { case '.': case '$': return NULL; case '#': case 'l': case '/': case '?': if (addr.type != '+' && addr.type != '-') { Address *plus = address_new(); if (!plus) { address_free(addr.right); return NULL; } plus->type = '+'; plus->right = addr.right; addr.right = plus; } break; } } Address *ret = address_new(); if (!ret) { address_free(addr.right); return NULL; } *ret = addr; return ret; } static Address *address_parse_compound(Vis *vis, const char **s, enum SamError *err) { Address addr = { 0 }, *left = address_parse_simple(vis, s, err), *right = NULL; skip_spaces(s); addr.type = **s; switch (addr.type) { case ',': /* a1,a2 */ case ';': /* a1;a2 */ (*s)++; right = address_parse_compound(vis, s, err); if (right && (right->type == ',' || right->type == ';') && !right->left) { *err = SAM_ERR_ADDRESS; goto fail; } break; default: return left; } addr.left = left; addr.right = right; Address *ret = address_new(); if (ret) { *ret = addr; return ret; } fail: address_free(left); address_free(right); return NULL; }