const char *dns_server_string(DnsServer *server) { assert(server); if (!server->server_string) (void) in_addr_to_string(server->family, &server->address, &server->server_string); return strna(server->server_string); }
static void test_in_addr_to_string_one(int f, const char *addr) { union in_addr_union ua; _cleanup_free_ char *r = NULL; assert_se(in_addr_from_string(f, addr, &ua) >= 0); assert_se(in_addr_to_string(f, &ua, &r) >= 0); printf("test_in_addr_to_string_one: %s == %s\n", addr, r); assert_se(streq(addr, r)); }
static void print_local_addresses(struct local_address *a, unsigned n) { unsigned i; for (i = 0; i < n; i++) { _cleanup_free_ char *b = NULL; assert_se(in_addr_to_string(a[i].family, &a[i].address, &b) >= 0); printf("%s if%i scope=%i metric=%u address=%s\n", af_to_name(a[i].family), a[i].ifindex, a[i].scope, a[i].metric, b); } }
static int dump_gateways( sd_netlink *rtnl, sd_hwdb *hwdb, const char *prefix, int ifindex) { _cleanup_free_ struct local_address *local = NULL; int r, n, i; n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local); if (n < 0) return n; for (i = 0; i < n; i++) { _cleanup_free_ char *gateway = NULL, *description = NULL; r = in_addr_to_string(local[i].family, &local[i].address, &gateway); if (r < 0) return r; r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description); if (r < 0) log_debug_errno(r, "Could not get description of gateway: %m"); printf("%*s%s", (int) strlen(prefix), i == 0 ? prefix : "", gateway); if (description) printf(" (%s)", description); /* Show interface name for the entry if we show * entries for all interfaces */ if (ifindex <= 0) { char name[IF_NAMESIZE+1]; if (if_indextoname(local[i].ifindex, name)) { fputs(" on ", stdout); fputs(name, stdout); } else printf(" on %%%i", local[i].ifindex); } fputc('\n', stdout); } return 0; }
static int map_server_address(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { char **p = (char **) userdata; const void *d; int family, r; size_t sz; assert(p); r = sd_bus_message_enter_container(m, 'r', "iay"); if (r < 0) return r; r = sd_bus_message_read(m, "i", &family); if (r < 0) return r; r = sd_bus_message_read_array(m, 'y', &d, &sz); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; if (sz == 0 && family == AF_UNSPEC) { *p = mfree(*p); return 0; } if (!IN_SET(family, AF_INET, AF_INET6)) { log_error("Unknown address family %i", family); return -EINVAL; } if (sz != FAMILY_ADDRESS_SIZE(family)) { log_error("Invalid address size"); return -EINVAL; } r = in_addr_to_string(family, d, p); if (r < 0) return r; return 0; }
static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) { _cleanup_free_ char *pretty = NULL; DnsZoneItem *z; assert(t); assert(p); if (manager_our_packet(t->scope->manager, p) != 0) return; in_addr_to_string(p->family, &p->sender, &pretty); log_debug("Transaction on scope %s on %s/%s got tentative packet from %s", dns_protocol_to_string(t->scope->protocol), t->scope->link ? t->scope->link->name : "*", t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family), pretty); /* RFC 4795, Section 4.1 says that the peer with the * lexicographically smaller IP address loses */ if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) { log_debug("Peer has lexicographically larger IP address and thus lost in the conflict."); return; } log_debug("We have the lexicographically larger IP address and thus lost in the conflict."); t->block_gc++; while ((z = set_first(t->zone_items))) { /* First, make sure the zone item drops the reference * to us */ dns_zone_item_probe_stop(z); /* Secondly, report this as conflict, so that we might * look for a different hostname */ dns_zone_item_conflict(z); } t->block_gc--; dns_transaction_gc(t); }
DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) { assert(m); if (m->current_dns_server == s) return s; if (s) { _cleanup_free_ char *ip = NULL; in_addr_to_string(s->family, &s->address, &ip); log_info("Switching to system DNS server %s.", strna(ip)); } dns_server_unref(m->current_dns_server); m->current_dns_server = dns_server_ref(s); if (m->unicast_scope) dns_cache_flush(&m->unicast_scope->cache); return s; }
static int dump_addresses( sd_netlink *rtnl, const char *prefix, int ifindex) { _cleanup_free_ struct local_address *local = NULL; int r, n, i; n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local); if (n < 0) return n; for (i = 0; i < n; i++) { _cleanup_free_ char *pretty = NULL; r = in_addr_to_string(local[i].family, &local[i].address, &pretty); if (r < 0) return r; printf("%*s%s", (int) strlen(prefix), i == 0 ? prefix : "", pretty); if (ifindex <= 0) { char name[IF_NAMESIZE+1]; if (if_indextoname(local[i].ifindex, name)) { fputs(" on ", stdout); fputs(name, stdout); } else printf(" on %%%i", local[i].ifindex); } fputc('\n', stdout); } return 0; }
static void ll_handler(sd_ipv4ll *ll, int event, void *userdata) { _cleanup_free_ char *address = NULL; struct in_addr addr = {}; assert_se(ll); if (sd_ipv4ll_get_address(ll, &addr) >= 0) assert_se(in_addr_to_string(AF_INET, (const union in_addr_union*) &addr, &address) >= 0); switch (event) { case SD_IPV4LL_EVENT_BIND: log_info("bound %s", strna(address)); break; case SD_IPV4LL_EVENT_CONFLICT: log_info("conflict on %s", strna(address)); break; case SD_IPV4LL_EVENT_STOP: log_error("the client was stopped with address %s", strna(address)); break; default: assert_not_reached("invalid LL event"); } }
static int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) { _cleanup_free_ struct local_address *local = NULL; int r, n, i; n = local_addresses(rtnl, ifindex, &local); if (n < 0) return n; for (i = 0; i < n; i++) { _cleanup_free_ char *pretty = NULL; r = in_addr_to_string(local[i].family, &local[i].address, &pretty); if (r < 0) return r; printf("%*s%s\n", (int) strlen(prefix), i == 0 ? prefix : "", pretty); } return 0; }
int routing_policy_serialize_rules(Set *rules, FILE *f) { RoutingPolicyRule *rule = NULL; Iterator i; int r; assert(f); SET_FOREACH(rule, rules, i) { _cleanup_free_ char *from_str = NULL, *to_str = NULL; bool space = false; fputs("RULE=", f); if (!in_addr_is_null(rule->family, &rule->from)) { r = in_addr_to_string(rule->family, &rule->from, &from_str); if (r < 0) return r; fprintf(f, "from=%s/%hhu", from_str, rule->from_prefixlen); space = true; } if (!in_addr_is_null(rule->family, &rule->to)) { r = in_addr_to_string(rule->family, &rule->to, &to_str); if (r < 0) return r; fprintf(f, "%sto=%s/%hhu", space ? " " : "", to_str, rule->to_prefixlen); space = true; } if (rule->tos != 0) { fprintf(f, "%stos=%hhu", space ? " " : "", rule->tos); space = true; } if (rule->fwmark != 0) { fprintf(f, "%sfwmark=%"PRIu32"/%"PRIu32, space ? " " : "", rule->fwmark, rule->fwmask); space = true; } if (rule->iif) { fprintf(f, "%siif=%s", space ? " " : "", rule->iif); space = true; } if (rule->oif) { fprintf(f, "%soif=%s", space ? " " : "", rule->oif); space = true; } fprintf(f, "%stable=%"PRIu32 "\n", space ? " " : "", rule->table); }
static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) { sd_ipv4acd *ll = userdata; int r = 0; assert(ll); switch (ll->state) { case IPV4ACD_STATE_INIT: ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_PROBE, true); if (ll->conflict >= MAX_CONFLICTS) { log_ipv4acd_notice(ll, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL); r = ipv4acd_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT); if (r < 0) goto out; ll->conflict = 0; } else { r = ipv4acd_set_next_wakeup(ll, 0, PROBE_WAIT); if (r < 0) goto out; } break; case IPV4ACD_STATE_WAITING_PROBE: case IPV4ACD_STATE_PROBING: /* Send a probe */ r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr); if (r < 0) { log_ipv4acd_error_errno(ll, r, "Failed to send ARP probe: %m"); goto out; } else { _cleanup_free_ char *address = NULL; union in_addr_union addr = { .in.s_addr = ll->address }; r = in_addr_to_string(AF_INET, &addr, &address); if (r >= 0) log_ipv4acd_debug(ll, "Probing %s", address); } if (ll->iteration < PROBE_NUM - 2) { ipv4acd_set_state(ll, IPV4ACD_STATE_PROBING, false); r = ipv4acd_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN)); if (r < 0) goto out; } else { ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_ANNOUNCE, true); r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_WAIT, 0); if (r < 0) goto out; } break; case IPV4ACD_STATE_ANNOUNCING: if (ll->iteration >= ANNOUNCE_NUM - 1) { ipv4acd_set_state(ll, IPV4ACD_STATE_RUNNING, false); break; } case IPV4ACD_STATE_WAITING_ANNOUNCE: /* Send announcement packet */ r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr); if (r < 0) { log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m"); goto out; } else log_ipv4acd_debug(ll, "ANNOUNCE"); ipv4acd_set_state(ll, IPV4ACD_STATE_ANNOUNCING, false); r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0); if (r < 0) goto out; if (ll->iteration == 0) { ll->conflict = 0; ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_BIND); } break; default: assert_not_reached("Invalid state."); } out: if (r < 0) sd_ipv4acd_stop(ll); return 1; } static void ipv4acd_on_conflict(sd_ipv4acd *ll) { _cleanup_free_ char *address = NULL; union in_addr_union addr = { .in.s_addr = ll->address }; int r; assert(ll); ll->conflict++; r = in_addr_to_string(AF_INET, &addr, &address); if (r >= 0) log_ipv4acd_debug(ll, "Conflict on %s (%u)", address, ll->conflict); ipv4acd_stop(ll); ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_CONFLICT); } static int ipv4acd_on_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_ipv4acd *ll = userdata; struct ether_arp packet; int r; assert(ll); assert(fd >= 0); r = read(fd, &packet, sizeof(struct ether_arp)); if (r < (int) sizeof(struct ether_arp)) goto out; switch (ll->state) { case IPV4ACD_STATE_ANNOUNCING: case IPV4ACD_STATE_RUNNING: if (ipv4acd_arp_conflict(ll, &packet)) { usec_t ts; assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &ts) >= 0); /* Defend address */ if (ts > ll->defend_window) { ll->defend_window = ts + DEFEND_INTERVAL * USEC_PER_SEC; r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr); if (r < 0) { log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m"); goto out; } else log_ipv4acd_debug(ll, "DEFEND"); } else ipv4acd_on_conflict(ll); } break; case IPV4ACD_STATE_WAITING_PROBE: case IPV4ACD_STATE_PROBING: case IPV4ACD_STATE_WAITING_ANNOUNCE: /* BPF ensures this packet indicates a conflict */ ipv4acd_on_conflict(ll); break; default: assert_not_reached("Invalid state."); } out: if (r < 0) sd_ipv4acd_stop(ll); return 1; }
static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) { sd_ipv4acd *acd = userdata; int r = 0; assert(acd); switch (acd->state) { case IPV4ACD_STATE_STARTED: ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true); if (acd->n_conflict >= MAX_CONFLICTS) { char ts[FORMAT_TIMESPAN_MAX]; log_ipv4acd(acd, "Max conflicts reached, delaying by %s", format_timespan(ts, sizeof(ts), RATE_LIMIT_INTERVAL_USEC, 0)); r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC); if (r < 0) goto fail; } else { r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC); if (r < 0) goto fail; } break; case IPV4ACD_STATE_WAITING_PROBE: case IPV4ACD_STATE_PROBING: /* Send a probe */ r = arp_send_probe(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); if (r < 0) { log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m"); goto fail; } else { _cleanup_free_ char *address = NULL; union in_addr_union addr = { .in.s_addr = acd->address }; (void) in_addr_to_string(AF_INET, &addr, &address); log_ipv4acd(acd, "Probing %s", strna(address)); } if (acd->n_iteration < PROBE_NUM - 2) { ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false); r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC)); if (r < 0) goto fail; } else { ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true); r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0); if (r < 0) goto fail; } break; case IPV4ACD_STATE_ANNOUNCING: if (acd->n_iteration >= ANNOUNCE_NUM - 1) { ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false); break; } /* fall through */ case IPV4ACD_STATE_WAITING_ANNOUNCE: /* Send announcement packet */ r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); if (r < 0) { log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); goto fail; } else log_ipv4acd(acd, "ANNOUNCE"); ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false); r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0); if (r < 0) goto fail; if (acd->n_iteration == 0) { acd->n_conflict = 0; ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND); } break; default: assert_not_reached("Invalid state."); } return 0; fail: sd_ipv4acd_stop(acd); return 0; } static void ipv4acd_on_conflict(sd_ipv4acd *acd) { _cleanup_free_ char *address = NULL; union in_addr_union addr = { .in.s_addr = acd->address }; assert(acd); acd->n_conflict++; (void) in_addr_to_string(AF_INET, &addr, &address); log_ipv4acd(acd, "Conflict on %s (%u)", strna(address), acd->n_conflict); ipv4acd_reset(acd); ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT); } static int ipv4acd_on_packet( sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_ipv4acd *acd = userdata; struct ether_arp packet; ssize_t n; int r; assert(s); assert(acd); assert(fd >= 0); n = recv(fd, &packet, sizeof(struct ether_arp), 0); if (n < 0) { if (errno == EAGAIN || errno == EINTR) return 0; log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); goto fail; } if ((size_t) n != sizeof(struct ether_arp)) { log_ipv4acd(acd, "Ignoring too short ARP packet."); return 0; } switch (acd->state) { case IPV4ACD_STATE_ANNOUNCING: case IPV4ACD_STATE_RUNNING: if (ipv4acd_arp_conflict(acd, &packet)) { usec_t ts; assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &ts) >= 0); /* Defend address */ if (ts > acd->defend_window) { acd->defend_window = ts + DEFEND_INTERVAL_USEC; r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); if (r < 0) { log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); goto fail; } else log_ipv4acd(acd, "DEFEND"); } else ipv4acd_on_conflict(acd); } break; case IPV4ACD_STATE_WAITING_PROBE: case IPV4ACD_STATE_PROBING: case IPV4ACD_STATE_WAITING_ANNOUNCE: /* BPF ensures this packet indicates a conflict */ ipv4acd_on_conflict(acd); break; default: assert_not_reached("Invalid state."); } return 0; fail: sd_ipv4acd_stop(acd); return 0; }
static void bus_method_resolve_address_complete(DnsQuery *q) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; unsigned added = 0, i; int r; assert(q); if (q->state != DNS_TRANSACTION_SUCCESS) { r = reply_query_state(q); goto finish; } r = sd_bus_message_new_method_return(q->request, &reply); if (r < 0) goto finish; r = sd_bus_message_append(reply, "i", q->answer_ifindex); if (r < 0) goto finish; r = sd_bus_message_open_container(reply, 'a', "s"); if (r < 0) goto finish; if (q->answer) { answer = dns_answer_ref(q->answer); for (i = 0; i < answer->n_rrs; i++) { r = dns_question_matches_rr(q->question, answer->rrs[i]); if (r < 0) goto finish; if (r == 0) continue; r = sd_bus_message_append(reply, "s", answer->rrs[i]->ptr.name); if (r < 0) goto finish; added ++; } } if (added <= 0) { _cleanup_free_ char *ip = NULL; in_addr_to_string(q->request_family, &q->request_address, &ip); r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", ip); goto finish; } r = sd_bus_message_close_container(reply); if (r < 0) goto finish; r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family)); if (r < 0) goto finish; r = sd_bus_send(q->manager->bus, reply, NULL); finish: if (r < 0) { log_error_errno(r, "Failed to send address reply: %m"); sd_bus_reply_method_errno(q->request, -r, NULL); } dns_query_free(q); }
static int reply_query_state(DnsQuery *q) { _cleanup_free_ char *ip = NULL; const char *name; int r; if (q->request_hostname) name = q->request_hostname; else { r = in_addr_to_string(q->request_family, &q->request_address, &ip); if (r < 0) return r; name = ip; } switch (q->state) { case DNS_TRANSACTION_NO_SERVERS: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); case DNS_TRANSACTION_TIMEOUT: return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out"); case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED: return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed"); case DNS_TRANSACTION_INVALID_REPLY: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply"); case DNS_TRANSACTION_RESOURCES: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources"); case DNS_TRANSACTION_ABORTED: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted"); case DNS_TRANSACTION_FAILURE: { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; if (q->answer_rcode == DNS_RCODE_NXDOMAIN) sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name); else { const char *rc, *n; char p[3]; /* the rcode is 4 bits long */ rc = dns_rcode_to_string(q->answer_rcode); if (!rc) { sprintf(p, "%i", q->answer_rcode); rc = p; } n = strappenda(_BUS_ERROR_DNS, rc); sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc); } return sd_bus_reply_method_error(q->request, &error); } case DNS_TRANSACTION_NULL: case DNS_TRANSACTION_PENDING: case DNS_TRANSACTION_SUCCESS: default: assert_not_reached("Impossible state"); } }