diff options
Diffstat (limited to 'src')
61 files changed, 2202 insertions, 1613 deletions
| diff --git a/src/basic/refcnt.h b/src/basic/refcnt.h index 0502c20a2e..8a39d69fe4 100644 --- a/src/basic/refcnt.h +++ b/src/basic/refcnt.h @@ -21,7 +21,9 @@    along with systemd; If not, see <http://www.gnu.org/licenses/>.  ***/ -/* A type-safe atomic refcounter */ +/* A type-safe atomic refcounter. + * + * DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */  typedef struct {          volatile unsigned _value; diff --git a/src/basic/ring.h b/src/basic/ring.h index a7c44d1b56..dbd6296384 100644 --- a/src/basic/ring.h +++ b/src/basic/ring.h @@ -50,7 +50,6 @@ int ring_push(Ring *r, const void *u8, size_t size);  void ring_pull(Ring *r, size_t size);  /* return size of occupied buffer in bytes */ -static inline size_t ring_get_size(Ring *r) -{ +static inline size_t ring_get_size(Ring *r) {          return r->used;  } diff --git a/src/basic/time-util.c b/src/basic/time-util.c index e278196c90..3d8d5d7568 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -26,6 +26,7 @@  #include "util.h"  #include "time-util.h" +#include "path-util.h"  #include "strv.h"  usec_t now(clockid_t clock_id) { @@ -971,7 +972,10 @@ bool timezone_is_valid(const char *name) {          const char *p, *t;          struct stat st; -        if (!name || *name == 0 || *name == '/') +        if (isempty(name)) +                return false; + +        if (name[0] == '/')                  return false;          for (p = name; *p; p++) { @@ -1021,3 +1025,30 @@ clockid_t clock_boottime_or_monotonic(void) {          return clock;  } + +int get_timezone(char **timezone) { +        _cleanup_free_ char *t = NULL; +        const char *e; +        char *z; +        int r; + +        r = readlink_malloc("/etc/localtime", &t); +        if (r < 0) +                return r; /* returns EINVAL if not a symlink */ + +        e = path_startswith(t, "/usr/share/zoneinfo/"); +        if (!e) +                e = path_startswith(t, "../usr/share/zoneinfo/"); +        if (!e) +                return -EINVAL; + +        if (!timezone_is_valid(e)) +                return -EINVAL; + +        z = strdup(e); +        if (!z) +                return -ENOMEM; + +        *timezone = z; +        return 0; +} diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 2aba042217..03a47f310d 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -110,3 +110,5 @@ bool timezone_is_valid(const char *name);  clockid_t clock_boottime_or_monotonic(void);  #define xstrftime(buf, fmt, tm) assert_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0) + +int get_timezone(char **timezone); diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 4ac193e22a..38b79da886 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -70,16 +70,14 @@ typedef struct {          BOOLEAN no_editor;  } Config; -static VOID cursor_left(UINTN *cursor, UINTN *first) -{ +static VOID cursor_left(UINTN *cursor, UINTN *first) {          if ((*cursor) > 0)                  (*cursor)--;          else if ((*first) > 0)                  (*first)--;  } -static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len) -{ +static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len) {          if ((*cursor)+1 < x_max)                  (*cursor)++;          else if ((*first) + (*cursor) < len) @@ -856,13 +854,11 @@ static VOID config_entry_free(ConfigEntry *entry) {          FreePool(entry->options);  } -static BOOLEAN is_digit(CHAR16 c) -{ +static BOOLEAN is_digit(CHAR16 c) {          return (c >= '0') && (c <= '9');  } -static UINTN c_order(CHAR16 c) -{ +static UINTN c_order(CHAR16 c) {          if (c == '\0')                  return 0;          if (is_digit(c)) @@ -873,8 +869,7 @@ static UINTN c_order(CHAR16 c)                  return c + 0x10000;  } -static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2) -{ +static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2) {          CHAR16 *os1 = s1;          CHAR16 *os2 = s2; diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h index 7c60ef123c..df6f882af5 100644 --- a/src/libsystemd-network/dhcp-internal.h +++ b/src/libsystemd-network/dhcp-internal.h @@ -45,10 +45,10 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_                         uint8_t code, size_t optlen, const void *optval);  typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len, -                                const uint8_t *option, void *user_data); +                                const void *option, void *userdata);  int dhcp_option_parse(DHCPMessage *message, size_t len, -                      dhcp_option_cb_t cb, void *user_data); +                      dhcp_option_cb_t cb, void *userdata);  int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,                        uint8_t type, uint16_t arp_type, size_t optlen, diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h index 5a3fcddb1b..c6b97ca8f7 100644 --- a/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/libsystemd-network/dhcp-lease-internal.h @@ -25,7 +25,6 @@  #include <stdint.h>  #include <linux/if_packet.h> -#include "refcnt.h"  #include "util.h"  #include "list.h" @@ -48,54 +47,62 @@ struct sd_dhcp_raw_option {  };  struct sd_dhcp_lease { -        RefCount n_ref; +        unsigned n_ref; -        int32_t time_offset; +        /* each 0 if unset */          uint32_t t1;          uint32_t t2;          uint32_t lifetime; -        uint32_t mtu_aging_timeout; + +        /* each 0 if unset */          be32_t address;          be32_t server_address; -        be32_t subnet_mask;          be32_t router;          be32_t next_server; + +        bool have_subnet_mask; +        be32_t subnet_mask; + +        bool have_broadcast;          be32_t broadcast; +          struct in_addr *dns;          size_t dns_size; +          struct in_addr *ntp;          size_t ntp_size; -        struct in_addr *policy_filter; -        size_t policy_filter_size; +          struct sd_dhcp_route *static_route; -        size_t static_route_size; -        size_t static_route_allocated; -        uint16_t boot_file_size; -        uint16_t mdr; -        uint16_t mtu; -        uint8_t ttl; -        bool ip_forward; -        bool ip_forward_non_local; +        size_t static_route_size, static_route_allocated; + +        uint16_t mtu; /* 0 if unset */ +          char *domainname;          char *hostname;          char *root_path; -        uint8_t *client_id; + +        void *client_id;          size_t client_id_len; -        uint8_t *vendor_specific; + +        void *vendor_specific;          size_t vendor_specific_len; + +        char *timezone; +          LIST_HEAD(struct sd_dhcp_raw_option, private_options);  };  int dhcp_lease_new(sd_dhcp_lease **ret); -int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, -                              void *user_data); -int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, -                                     const uint8_t *data, uint8_t len); + +int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata); +int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len);  int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease); -int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id, -                             size_t client_id_len); +int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len); + +int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); +int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);  DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);  #define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp) diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c index b6110c5f16..36be7d54ed 100644 --- a/src/libsystemd-network/dhcp-option.c +++ b/src/libsystemd-network/dhcp-option.c @@ -140,7 +140,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,  static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload,                           uint8_t *message_type, dhcp_option_cb_t cb, -                         void *user_data) { +                         void *userdata) {          uint8_t code, len;          size_t offset = 0; @@ -199,7 +199,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo                                  return -EINVAL;                          if (cb) -                                cb(code, len, &options[offset], user_data); +                                cb(code, len, &options[offset], userdata);                          offset += len; @@ -214,7 +214,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo  }  int dhcp_option_parse(DHCPMessage *message, size_t len, -                      dhcp_option_cb_t cb, void *user_data) { +                      dhcp_option_cb_t cb, void *userdata) {          uint8_t overload = 0;          uint8_t message_type = 0;          int r; @@ -228,20 +228,20 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,          len -= sizeof(DHCPMessage);          r = parse_options(message->options, len, &overload, &message_type, -                          cb, user_data); +                          cb, userdata);          if (r < 0)                  return r;          if (overload & DHCP_OVERLOAD_FILE) {                  r = parse_options(message->file, sizeof(message->file), -                                NULL, &message_type, cb, user_data); +                                NULL, &message_type, cb, userdata);                  if (r < 0)                          return r;          }          if (overload & DHCP_OVERLOAD_SNAME) {                  r = parse_options(message->sname, sizeof(message->sname), -                                NULL, &message_type, cb, user_data); +                                NULL, &message_type, cb, userdata);                  if (r < 0)                          return r;          } diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h index 4308723f91..88a81d2866 100644 --- a/src/libsystemd-network/dhcp-protocol.h +++ b/src/libsystemd-network/dhcp-protocol.h @@ -137,6 +137,8 @@ enum {          DHCP_OPTION_REBINDING_T2_TIME           = 59,          DHCP_OPTION_VENDOR_CLASS_IDENTIFIER     = 60,          DHCP_OPTION_CLIENT_IDENTIFIER           = 61, +        DHCP_OPTION_NEW_POSIX_TIMEZONE          = 100, +        DHCP_OPTION_NEW_TZDB_TIMEZONE           = 101,          DHCP_OPTION_CLASSLESS_STATIC_ROUTE      = 121,          DHCP_OPTION_PRIVATE_BASE                = 224,          DHCP_OPTION_PRIVATE_LAST                = 254, diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 58750c4418..6cc794c937 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -26,7 +26,6 @@  #include "sd-dhcp-server.h"  #include "hashmap.h" -#include "refcnt.h"  #include "util.h"  #include "log.h" @@ -34,7 +33,7 @@  typedef struct DHCPClientId {          size_t length; -        uint8_t *data; +        void *data;  } DHCPClientId;  typedef struct DHCPLease { @@ -47,7 +46,7 @@ typedef struct DHCPLease {  } DHCPLease;  struct sd_dhcp_server { -        RefCount n_ref; +        unsigned n_ref;          sd_event *event;          int event_priority; @@ -55,15 +54,22 @@ struct sd_dhcp_server {          int fd;          int fd_raw; -        int index; +        int ifindex;          be32_t address;          be32_t netmask;          be32_t pool_start;          size_t pool_size;          size_t next_offer; +        char *timezone; + +        struct in_addr *ntp, *dns; +        unsigned n_ntp, n_dns; +          Hashmap *leases_by_client_id;          DHCPLease **bound_leases; + +        uint32_t max_lease_time, default_lease_time;  };  typedef struct DHCPRequest { @@ -75,7 +81,7 @@ typedef struct DHCPRequest {          size_t max_optlen;          be32_t server_id;          be32_t requested_ip; -        int lifetime; +        uint32_t lifetime;  } DHCPRequest;  DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_server*, sd_dhcp_server_unref); diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h index 037f580eb6..4edecf7711 100644 --- a/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -24,13 +24,11 @@  #include <stdint.h> -#include "refcnt.h" -  #include "sd-dhcp6-lease.h"  #include "dhcp6-internal.h"  struct sd_dhcp6_lease { -        RefCount n_ref; +        unsigned n_ref;          uint8_t *serverid;          size_t serverid_len; diff --git a/src/libsystemd-network/dhcp6-network.c b/src/libsystemd-network/dhcp6-network.c index fe56c10273..187975364b 100644 --- a/src/libsystemd-network/dhcp6-network.c +++ b/src/libsystemd-network/dhcp6-network.c @@ -41,8 +41,7 @@          { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } } -int dhcp_network_icmp6_bind_router_solicitation(int index) -{ +int dhcp_network_icmp6_bind_router_solicitation(int index) {          struct icmp6_filter filter = { };          struct ipv6_mreq mreq = {                  .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT, @@ -92,8 +91,7 @@ int dhcp_network_icmp6_bind_router_solicitation(int index)          return r;  } -int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) -{ +int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {          struct sockaddr_in6 dst = {                  .sin6_family = AF_INET6,                  .sin6_addr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT, diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index 2fa4d5fac8..f41bebced0 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -338,9 +338,7 @@ int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,          return count;  } -int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, -                                  char ***str_arr) -{ +int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char ***str_arr) {          size_t pos = 0, idx = 0;          _cleanup_free_ char **names = NULL;          int r; diff --git a/src/libsystemd-network/lldp-internal.c b/src/libsystemd-network/lldp-internal.c index 0f354461f7..3c04898e92 100644 --- a/src/libsystemd-network/lldp-internal.c +++ b/src/libsystemd-network/lldp-internal.c @@ -374,9 +374,8 @@ int lldp_mib_add_objects(Prioq *by_expiry,                  }                  /* Admission Control: Can this port attached to the existing chassis ? */ -                if (REFCNT_GET(c->n_ref) >= LLDP_MIB_MAX_PORT_PER_CHASSIS) { -                        log_lldp("Port limit reached. Chassis has: %d ports. Dropping ...", -                                 REFCNT_GET(c->n_ref)); +                if (c->n_ref >= LLDP_MIB_MAX_PORT_PER_CHASSIS) { +                        log_lldp("Port limit reached. Chassis has: %d ports. Dropping ...", c->n_ref);                          c = NULL;                          goto drop; @@ -394,7 +393,7 @@ int lldp_mib_add_objects(Prioq *by_expiry,          /* Attach new port to chassis */          LIST_PREPEND(port, c->ports, p); -        REFCNT_INC(c->n_ref); +        c->n_ref ++;          p = NULL;          c = NULL; @@ -424,7 +423,8 @@ void lldp_neighbour_port_remove_and_free(lldp_neighbour_port *p) {          lldp_neighbour_port_free(p);          /* Drop the Chassis if no port is attached  */ -        if (REFCNT_DEC(c->n_ref) <= 1) { +        c->n_ref --; +        if (c->n_ref <= 1) {                  hashmap_remove(c->neighbour_mib, &c->chassis_id);                  lldp_chassis_free(c);          } @@ -486,7 +486,7 @@ void lldp_chassis_free(lldp_chassis *c) {          if (!c)                  return; -        if (REFCNT_GET(c->n_ref) > 1) +        if (c->n_ref > 1)                  return;          free(c->chassis_id.data); @@ -513,7 +513,7 @@ int lldp_chassis_new(tlv_packet *tlv,          if (!c)                  return -ENOMEM; -        c->n_ref = REFCNT_INIT; +        c->n_ref = 1;          c->chassis_id.type = type;          c->chassis_id.length = length; diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h index 8e09ee8f3a..f4eadbb87e 100644 --- a/src/libsystemd-network/lldp-internal.h +++ b/src/libsystemd-network/lldp-internal.h @@ -24,7 +24,6 @@  #include "log.h"  #include "list.h" -#include "refcnt.h"  #include "lldp-tlv.h"  #include "prioq.h" @@ -63,7 +62,7 @@ struct lldp_chassis_id {  };  struct lldp_chassis { -        RefCount n_ref; +        unsigned n_ref;          lldp_chassis_id chassis_id; diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index d8357c687e..26bd4088d9 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -525,7 +525,7 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t          return 0;  } -int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t size) { +int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) {          _cleanup_free_ char *hex_buf = NULL;          assert(f); @@ -541,7 +541,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t          return 0;  } -int deserialize_dhcp_option(uint8_t **data, size_t *data_len, const char *string) { +int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {          assert(data);          assert(data_len);          assert(string); diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index dca82646ce..d5d4ef42f2 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -77,5 +77,5 @@ struct sd_dhcp_route;  void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size);  int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string); -int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t size); -int deserialize_dhcp_option(uint8_t **data, size_t *data_len, const char *string); +int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); +int deserialize_dhcp_option(void **data, size_t *data_len, const char *string); diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 46104afded..c12768cf0e 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -27,7 +27,6 @@  #include <sys/ioctl.h>  #include "util.h" -#include "refcnt.h"  #include "random-util.h"  #include "async.h" @@ -41,7 +40,7 @@  #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)  struct sd_dhcp_client { -        RefCount n_ref; +        unsigned n_ref;          DHCPState state;          sd_event *event; @@ -106,7 +105,6 @@ static const uint8_t default_req_opts[] = {          DHCP_OPTION_HOST_NAME,          DHCP_OPTION_DOMAIN_NAME,          DHCP_OPTION_DOMAIN_NAME_SERVER, -        DHCP_OPTION_NTP_SERVER,  };  static int client_receive_message_raw(sd_event_source *s, int fd, @@ -377,8 +375,7 @@ static int client_initialize(sd_dhcp_client *client) {          client->state = DHCP_STATE_INIT;          client->xid = 0; -        if (client->lease) -                client->lease = sd_dhcp_lease_unref(client->lease); +        client->lease = sd_dhcp_lease_unref(client->lease);          return 0;  } @@ -1055,18 +1052,16 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,          }          lease->next_server = offer->siaddr; -          lease->address = offer->yiaddr; -        if (lease->address == INADDR_ANY || -            lease->server_address == INADDR_ANY || +        if (lease->address == 0 || +            lease->server_address == 0 ||              lease->lifetime == 0) { -                log_dhcp_client(client, "received lease lacks address, server " -                                "address or lease lifetime, ignoring"); +                log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring");                  return -ENOMSG;          } -        if (lease->subnet_mask == INADDR_ANY) { +        if (!lease->have_subnet_mask) {                  r = dhcp_lease_set_default_subnet_mask(lease);                  if (r < 0) {                          log_dhcp_client(client, "received lease lacks subnet " @@ -1168,13 +1163,17 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,          return r;  } -static uint64_t client_compute_timeout(sd_dhcp_client *client, -                                       uint32_t lifetime, double factor) { +static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) {          assert(client);          assert(client->request_sent); -        assert(lifetime); +        assert(lifetime > 0); -        return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) + +        if (lifetime > 3) +                lifetime -= 3; +        else +                lifetime = 0; + +        return client->request_sent + (lifetime * USEC_PER_SEC * factor) +                  + (random_u32() & 0x1fffff);  } @@ -1206,7 +1205,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {          /* convert the various timeouts from relative (secs) to absolute (usecs) */          lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1); -        if (client->lease->t1 && client->lease->t2) { +        if (client->lease->t1 > 0 && client->lease->t2 > 0) {                  /* both T1 and T2 are given */                  if (client->lease->t1 < client->lease->t2 &&                      client->lease->t2 < client->lease->lifetime) { @@ -1220,7 +1219,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {                          t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);                          client->lease->t1 = client->lease->lifetime / 2;                  } -        } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) { +        } else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) {                  /* only T2 is given, and it is valid */                  t2_timeout = client_compute_timeout(client, client->lease->t2, 1);                  t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); @@ -1230,7 +1229,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {                          t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);                          client->lease->t2 = (client->lease->lifetime * 7) / 8;                  } -        } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) { +        } else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) {                  /* only T1 is given, and it is valid */                  t1_timeout = client_compute_timeout(client, client->lease->t1, 1);                  t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); @@ -1676,30 +1675,41 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {  }  sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) { -        if (client) -                assert_se(REFCNT_INC(client->n_ref) >= 2); + +        if (!client) +                return NULL; + +        assert(client->n_ref >= 1); +        client->n_ref++;          return client;  }  sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) { -        if (client && REFCNT_DEC(client->n_ref) == 0) { -                log_dhcp_client(client, "FREE"); -                client_initialize(client); +        if (!client) +                return NULL; -                client->receive_message = -                        sd_event_source_unref(client->receive_message); +        assert(client->n_ref >= 1); +        client->n_ref--; -                sd_dhcp_client_detach_event(client); +        if (client->n_ref > 0) +                return NULL; -                sd_dhcp_lease_unref(client->lease); +        log_dhcp_client(client, "FREE"); -                free(client->req_opts); -                free(client->hostname); -                free(client->vendor_class_identifier); -                free(client); -        } +        client_initialize(client); + +        client->receive_message = sd_event_source_unref(client->receive_message); + +        sd_dhcp_client_detach_event(client); + +        sd_dhcp_lease_unref(client->lease); + +        free(client->req_opts); +        free(client->hostname); +        free(client->vendor_class_identifier); +        free(client);          return NULL;  } @@ -1713,7 +1723,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) {          if (!client)                  return -ENOMEM; -        client->n_ref = REFCNT_INIT; +        client->n_ref = 1;          client->state = DHCP_STATE_INIT;          client->index = -1;          client->fd = -1; diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index f5b9e22589..6551e7c94c 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -28,18 +28,31 @@  #include "unaligned.h"  #include "in-addr-util.h"  #include "hostname-util.h" +#include "dns-domain.h" +#include "network-internal.h"  #include "dhcp-protocol.h"  #include "dhcp-lease-internal.h"  #include "sd-dhcp-lease.h" -#include "network-internal.h" -#include "dns-domain.h"  int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {          assert_return(lease, -EINVAL);          assert_return(addr, -EINVAL); +        if (lease->address == 0) +                return -ENODATA; +          addr->s_addr = lease->address; +        return 0; +} +int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) { +        assert_return(lease, -EINVAL); +        assert_return(addr, -EINVAL); + +        if (!lease->have_broadcast) +                return -ENODATA; + +        addr->s_addr = lease->broadcast;          return 0;  } @@ -47,8 +60,32 @@ int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {          assert_return(lease, -EINVAL);          assert_return(lifetime, -EINVAL); +        if (lease->lifetime <= 0) +                return -ENODATA; +          *lifetime = lease->lifetime; +        return 0; +} + +int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) { +        assert_return(lease, -EINVAL); +        assert_return(t1, -EINVAL); + +        if (lease->t1 <= 0) +                return -ENODATA; +        *t1 = lease->t1; +        return 0; +} + +int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) { +        assert_return(lease, -EINVAL); +        assert_return(t2, -EINVAL); + +        if (lease->t2 <= 0) +                return -ENODATA; + +        *t2 = lease->t2;          return 0;  } @@ -56,11 +93,10 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {          assert_return(lease, -EINVAL);          assert_return(mtu, -EINVAL); -        if (lease->mtu) -                *mtu = lease->mtu; -        else -                return -ENOENT; +        if (lease->mtu <= 0) +                return -ENODATA; +        *mtu = lease->mtu;          return 0;  } @@ -68,37 +104,32 @@ int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) {          assert_return(lease, -EINVAL);          assert_return(addr, -EINVAL); -        if (lease->dns_size) { -                *addr = lease->dns; -                return lease->dns_size; -        } else -                return -ENOENT; +        if (lease->dns_size <= 0) +                return -ENODATA; -        return 0; +        *addr = lease->dns; +        return (int) lease->dns_size;  }  int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {          assert_return(lease, -EINVAL);          assert_return(addr, -EINVAL); -        if (lease->ntp_size) { -                *addr = lease->ntp; -                return lease->ntp_size; -        } else -                return -ENOENT; +        if (lease->ntp_size <= 0) +                return -ENODATA; -        return 0; +        *addr = lease->ntp; +        return (int) lease->ntp_size;  }  int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {          assert_return(lease, -EINVAL);          assert_return(domainname, -EINVAL); -        if (lease->domainname) -                *domainname = lease->domainname; -        else -                return -ENOENT; +        if (!lease->domainname) +                return -ENODATA; +        *domainname = lease->domainname;          return 0;  } @@ -106,11 +137,10 @@ int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {          assert_return(lease, -EINVAL);          assert_return(hostname, -EINVAL); -        if (lease->hostname) -                *hostname = lease->hostname; -        else -                return -ENOENT; +        if (!lease->hostname) +                return -ENODATA; +        *hostname = lease->hostname;          return 0;  } @@ -118,11 +148,10 @@ int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {          assert_return(lease, -EINVAL);          assert_return(root_path, -EINVAL); -        if (lease->root_path) -                *root_path = lease->root_path; -        else -                return -ENOENT; +        if (!lease->root_path) +                return -ENODATA; +        *root_path = lease->root_path;          return 0;  } @@ -130,11 +159,10 @@ int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {          assert_return(lease, -EINVAL);          assert_return(addr, -EINVAL); -        if (lease->router != INADDR_ANY) -                addr->s_addr = lease->router; -        else -                return -ENOENT; +        if (lease->router == 0) +                return -ENODATA; +        addr->s_addr = lease->router;          return 0;  } @@ -142,8 +170,10 @@ int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {          assert_return(lease, -EINVAL);          assert_return(addr, -EINVAL); -        addr->s_addr = lease->subnet_mask; +        if (!lease->have_subnet_mask) +                return -ENODATA; +        addr->s_addr = lease->subnet_mask;          return 0;  } @@ -151,8 +181,10 @@ int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *ad          assert_return(lease, -EINVAL);          assert_return(addr, -EINVAL); -        addr->s_addr = lease->server_address; +        if (lease->server_address == 0) +                return -ENODATA; +        addr->s_addr = lease->server_address;          return 0;  } @@ -160,136 +192,134 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {          assert_return(lease, -EINVAL);          assert_return(addr, -EINVAL); -        addr->s_addr = lease->next_server; +        if (lease->next_server == 0) +                return -ENODATA; +        addr->s_addr = lease->next_server;          return 0;  }  int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) { -          assert_return(lease, -EINVAL);          assert_return(routes, -EINVAL); -        if (lease->static_route_size) { -                *routes = lease->static_route; -                return lease->static_route_size; -        } else -                return -ENOENT; +        if (lease->static_route_size <= 0) +                return -ENODATA; -        return 0; +        *routes = lease->static_route; +        return (int) lease->static_route_size;  } -int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data, -                                      size_t *data_len) { +int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) {          assert_return(lease, -EINVAL);          assert_return(data, -EINVAL);          assert_return(data_len, -EINVAL); -        if (!lease->vendor_specific) -                return -ENOENT; +        if (lease->vendor_specific_len <= 0) +                return -ENODATA;          *data = lease->vendor_specific;          *data_len = lease->vendor_specific_len; -          return 0;  }  sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) { -        if (lease) -                assert_se(REFCNT_INC(lease->n_ref) >= 2); + +        if (!lease) +                return NULL; + +        assert(lease->n_ref >= 1); +        lease->n_ref++;          return lease;  }  sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { -        if (lease && REFCNT_DEC(lease->n_ref) == 0) { -                while (lease->private_options) { -                        struct sd_dhcp_raw_option *option = lease->private_options; -                        LIST_REMOVE(options, lease->private_options, option); +        if (!lease) +                return NULL; -                        free(option->data); -                        free(option); -                } -                free(lease->hostname); -                free(lease->domainname); -                free(lease->dns); -                free(lease->ntp); -                free(lease->static_route); -                free(lease->client_id); -                free(lease->vendor_specific); -                free(lease); -        } +        assert(lease->n_ref >= 1); +        lease->n_ref--; -        return NULL; -} +        if (lease->n_ref > 0) +                return NULL; -static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { -        assert(option); -        assert(ret); +        while (lease->private_options) { +                struct sd_dhcp_raw_option *option = lease->private_options; -        if (len == 4) { -                *ret = unaligned_read_be32((be32_t*) option); +                LIST_REMOVE(options, lease->private_options, option); -                if (*ret < min) -                        *ret = min; +                free(option->data); +                free(option);          } -} -static void lease_parse_s32(const uint8_t *option, size_t len, int32_t *ret) { -        lease_parse_u32(option, len, (uint32_t *)ret, 0); +        free(lease->hostname); +        free(lease->domainname); +        free(lease->dns); +        free(lease->ntp); +        free(lease->static_route); +        free(lease->client_id); +        free(lease->vendor_specific); +        free(lease); + +        return NULL;  } -static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) { +static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {          assert(option);          assert(ret); -        if (len == 2) { -                *ret = unaligned_read_be16((be16_t*) option); +        if (len != 4) +                return -EINVAL; -                if (*ret < min) -                        *ret = min; -        } +        *ret = unaligned_read_be32((be32_t*) option); +        if (*ret < min) +                *ret = min; + +        return 0;  } -static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) { +static int lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {          assert(option);          assert(ret); -        if (len == 4) -                memcpy(ret, option, 4); -} +        if (len != 2) +                return -EINVAL; -static void lease_parse_bool(const uint8_t *option, size_t len, bool *ret) { -        assert(option); -        assert(ret); +        *ret = unaligned_read_be16((be16_t*) option); +        if (*ret < min) +                *ret = min; -        if (len == 1) -                *ret = !!(*option); +        return 0;  } -static void lease_parse_u8(const uint8_t *option, size_t len, uint8_t *ret, uint8_t min) { +static int lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {          assert(option);          assert(ret); -        if (len == 1) { -                *ret = *option; +        if (len != 4) +                return -EINVAL; -                if (*ret < min) -                        *ret = min; -        } +        memcpy(ret, option, 4); +        return 0;  }  static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {          assert(option);          assert(ret); -        if (len >= 1) { +        if (len <= 0) +                *ret = mfree(*ret); +        else {                  char *string; +                if (memchr(option, 0, len)) +                        return -EINVAL; +                  string = strndup((const char *)option, len);                  if (!string) -                        return -errno; +                        return -ENOMEM;                  free(*ret);                  *ret = string; @@ -298,48 +328,47 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {          return 0;  } -static int lease_parse_in_addrs_aux(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size, size_t mult) { +static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {          assert(option);          assert(ret); -        assert(ret_size); +        assert(n_ret); -        if (len && !(len % (4 * mult))) { -                size_t size; +        if (len <= 0) { +                *ret = mfree(*ret); +                *n_ret = 0; +        } else { +                size_t n_addresses;                  struct in_addr *addresses; -                size = len / 4; +                if (len % 4 != 0) +                        return -EINVAL; + +                n_addresses = len / 4; -                addresses = newdup(struct in_addr, option, size); +                addresses = newdup(struct in_addr, option, n_addresses);                  if (!addresses)                          return -ENOMEM;                  free(*ret);                  *ret = addresses; -                *ret_size = size; +                *n_ret = n_addresses;          }          return 0;  } -static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) { -        return lease_parse_in_addrs_aux(option, len, ret, ret_size, 1); -} - -static int lease_parse_in_addrs_pairs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) { -        return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2); -} - -static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes, -        size_t *routes_size, size_t *routes_allocated) { +static int lease_parse_routes( +                const uint8_t *option, size_t len, +                struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) {          struct in_addr addr; -        assert(option); +        assert(option || len <= 0);          assert(routes);          assert(routes_size);          assert(routes_allocated); -        if (!len) +        if (len <= 0)                  return 0;          if (len % 8 != 0) @@ -354,15 +383,15 @@ static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_                  r = in_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen);                  if (r < 0) { -                        log_error("Failed to determine destination prefix length from class based IP, ignoring"); +                        log_debug("Failed to determine destination prefix length from class based IP, ignoring");                          continue;                  } -                lease_parse_be32(option, 4, &addr.s_addr); +                assert_se(lease_parse_be32(option, 4, &addr.s_addr) >= 0);                  route->dst_addr = inet_makeaddr(inet_netof(addr), 0);                  option += 4; -                lease_parse_be32(option, 4, &route->gw_addr.s_addr); +                assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0);                  option += 4;                  len -= 8; @@ -373,14 +402,18 @@ static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_  }  /* parses RFC3442 Classless Static Route Option */ -static int lease_parse_classless_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes, -        size_t *routes_size, size_t *routes_allocated) { +static int lease_parse_classless_routes( +                const uint8_t *option, size_t len, +                struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { -        assert(option); +        assert(option || len <= 0);          assert(routes);          assert(routes_size);          assert(routes_allocated); +        if (len <= 0) +                return 0; +          /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)*  */          while (len > 0) { @@ -388,7 +421,7 @@ static int lease_parse_classless_routes(const uint8_t *option, size_t len, struc                  struct sd_dhcp_route *route;                  if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1)) -                    return -ENOMEM; +                        return -ENOMEM;                  route = *routes + *routes_size; @@ -419,223 +452,222 @@ static int lease_parse_classless_routes(const uint8_t *option, size_t len, struc          return 0;  } -int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, -                              void *user_data) { -        sd_dhcp_lease *lease = user_data; +int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) { +        sd_dhcp_lease *lease = userdata;          int r;          assert(lease);          switch(code) { -        case DHCP_OPTION_TIME_OFFSET: -                lease_parse_s32(option, len, &lease->time_offset); - -                break; - -        case DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT: -                lease_parse_u32(option, len, &lease->mtu_aging_timeout, 0); - -                break; -          case DHCP_OPTION_IP_ADDRESS_LEASE_TIME: -                lease_parse_u32(option, len, &lease->lifetime, 1); +                r = lease_parse_u32(option, len, &lease->lifetime, 1); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse lease time, ignoring: %m");                  break;          case DHCP_OPTION_SERVER_IDENTIFIER: -                lease_parse_be32(option, len, &lease->server_address); +                r = lease_parse_be32(option, len, &lease->server_address); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse server identifier, ignoring: %m");                  break;          case DHCP_OPTION_SUBNET_MASK: -                lease_parse_be32(option, len, &lease->subnet_mask); - +                r = lease_parse_be32(option, len, &lease->subnet_mask); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m"); +                else +                        lease->have_subnet_mask = true;                  break;          case DHCP_OPTION_BROADCAST: -                lease_parse_be32(option, len, &lease->broadcast); - +                r = lease_parse_be32(option, len, &lease->broadcast); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m"); +                else +                        lease->have_broadcast = true;                  break;          case DHCP_OPTION_ROUTER: -                if(len >= 4) -                        lease_parse_be32(option, 4, &lease->router); - +                if (len >= 4) { +                        r = lease_parse_be32(option, 4, &lease->router); +                        if (r < 0) +                                log_debug_errno(r, "Failed to parse router address, ignoring: %m"); +                }                  break;          case DHCP_OPTION_DOMAIN_NAME_SERVER:                  r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);                  if (r < 0) -                        return r; - +                        log_debug_errno(r, "Failed to parse DNS server, ignoring: %m");                  break;          case DHCP_OPTION_NTP_SERVER:                  r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);                  if (r < 0) -                        return r; - -                break; - -        case DHCP_OPTION_POLICY_FILTER: -                r = lease_parse_in_addrs_pairs(option, len, &lease->policy_filter, &lease->policy_filter_size); -                if (r < 0) -                        return r; - +                        log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");                  break;          case DHCP_OPTION_STATIC_ROUTE: -                r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, -                        &lease->static_route_allocated); +                r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);                  if (r < 0) -                        return r; - +                        log_debug_errno(r, "Failed to parse static routes, ignoring: %m");                  break;          case DHCP_OPTION_INTERFACE_MTU: -                lease_parse_u16(option, len, &lease->mtu, 68); - -                break; - -        case DHCP_OPTION_INTERFACE_MDR: -                lease_parse_u16(option, len, &lease->mdr, 576); - -                break; - -        case DHCP_OPTION_INTERFACE_TTL: -                lease_parse_u8(option, len, &lease->ttl, 1); - -                break; - -        case DHCP_OPTION_BOOT_FILE_SIZE: -                lease_parse_u16(option, len, &lease->boot_file_size, 0); - +                r = lease_parse_u16(option, len, &lease->mtu, 68); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse MTU, ignoring: %m");                  break; -        case DHCP_OPTION_DOMAIN_NAME: -        { -                _cleanup_free_ char *domainname = NULL; -                char *e; +        case DHCP_OPTION_DOMAIN_NAME: { +                _cleanup_free_ char *domainname = NULL, *normalized = NULL;                  r = lease_parse_string(option, len, &domainname); -                if (r < 0) -                        return r; - -                /* Chop off trailing dot of domain name that some DHCP -                 * servers send us back. Internally we want to store -                 * host names without trailing dots and -                 * host_name_is_valid() doesn't accept them. */ -                e = endswith(domainname, "."); -                if (e) -                        *e = 0; +                if (r < 0) { +                        log_debug_errno(r, "Failed to parse domain name, ignoring: %m"); +                        return 0; +                } -                if (is_localhost(domainname)) -                        break; +                r = dns_name_normalize(domainname, &normalized); +                if (r < 0) { +                        log_debug_errno(r, "Failed to normalize domain name '%s': %m", domainname); +                        return 0; +                } -                r = dns_name_is_valid(domainname); -                if (r <= 0) { -                        if (r < 0) -                                log_error_errno(r, "Failed to validate domain name: %s: %m", domainname); -                        if (r == 0) -                                log_warning("Domain name is not valid, ignoring: %s", domainname); +                if (is_localhost(normalized)) { +                        log_debug_errno(r, "Detected 'localhost' as suggested domain name, ignoring.");                          break;                  }                  free(lease->domainname); -                lease->domainname = domainname; -                domainname = NULL; +                lease->domainname = normalized; +                normalized = NULL;                  break;          } -        case DHCP_OPTION_HOST_NAME: -        { -                _cleanup_free_ char *hostname = NULL; -                char *e; + +        case DHCP_OPTION_HOST_NAME: { +                _cleanup_free_ char *hostname = NULL, *normalized = NULL;                  r = lease_parse_string(option, len, &hostname); -                if (r < 0) -                        return r; +                if (r < 0) { +                        log_debug_errno(r, "Failed to parse host name, ignoring: %m"); +                        return 0; +                } -                e = endswith(hostname, "."); -                if (e) -                        *e = 0; +                r = dns_name_normalize(hostname, &normalized); +                if (r < 0) { +                        log_debug_errno(r, "Failed to normalize host name '%s', ignoring: %m", hostname); +                        return 0; +                } -                if (!hostname_is_valid(hostname, false) || is_localhost(hostname)) -                        break; +                if (is_localhost(normalized)) { +                        log_debug_errno(r, "Detected 'localhost' as suggested host name, ignoring."); +                        return 0; +                } -                free_and_replace(&lease->hostname, hostname); -                hostname = NULL; +                free(lease->hostname); +                lease->hostname = normalized; +                normalized = NULL;                  break;          } +          case DHCP_OPTION_ROOT_PATH:                  r = lease_parse_string(option, len, &lease->root_path);                  if (r < 0) -                        return r; - +                        log_debug_errno(r, "Failed to parse root path, ignoring: %m");                  break;          case DHCP_OPTION_RENEWAL_T1_TIME: -                lease_parse_u32(option, len, &lease->t1, 1); - +                r = lease_parse_u32(option, len, &lease->t1, 1); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse T1 time, ignoring: %m");                  break;          case DHCP_OPTION_REBINDING_T2_TIME: -                lease_parse_u32(option, len, &lease->t2, 1); - +                r = lease_parse_u32(option, len, &lease->t2, 1); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse T2 time, ignoring: %m");                  break; -        case DHCP_OPTION_ENABLE_IP_FORWARDING: -                lease_parse_bool(option, len, &lease->ip_forward); - +        case DHCP_OPTION_CLASSLESS_STATIC_ROUTE: +                r = lease_parse_classless_routes( +                                option, len, +                                &lease->static_route, +                                &lease->static_route_size, +                                &lease->static_route_allocated); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");                  break; -        case DHCP_OPTION_ENABLE_IP_FORWARDING_NL: -                lease_parse_bool(option, len, &lease->ip_forward_non_local); +        case DHCP_OPTION_NEW_TZDB_TIMEZONE: { +                _cleanup_free_ char *tz = NULL; -                break; +                r = lease_parse_string(option, len, &tz); +                if (r < 0) { +                        log_debug_errno(r, "Failed to parse timezone option, ignoring: %m"); +                        return 0; +                } -        case DHCP_OPTION_CLASSLESS_STATIC_ROUTE: -                r = lease_parse_classless_routes(option, len, &lease->static_route, &lease->static_route_size, -                        &lease->static_route_allocated); -                if (r < 0) -                        return r; +                if (!timezone_is_valid(tz)) { +                        log_debug_errno(r, "Timezone is not valid, ignoring: %m"); +                        return 0; +                } + +                free(lease->timezone); +                lease->timezone = tz; +                tz = NULL;                  break; +        }          case DHCP_OPTION_VENDOR_SPECIFIC: -                if (len >= 1) { -                        free(lease->vendor_specific); -                        lease->vendor_specific = memdup(option, len); -                        if (!lease->vendor_specific) + +                if (len <= 0) +                        lease->vendor_specific = mfree(lease->vendor_specific); +                else { +                        void *p; + +                        p = memdup(option, len); +                        if (!p)                                  return -ENOMEM; -                        lease->vendor_specific_len = len; -                } -               break; +                        free(lease->vendor_specific); +                        lease->vendor_specific = p; +                } -        default: -                if (code < DHCP_OPTION_PRIVATE_BASE || code > DHCP_OPTION_PRIVATE_LAST) -                    break; +                lease->vendor_specific_len = len; +                break; +        case DHCP_OPTION_PRIVATE_BASE ... DHCP_OPTION_PRIVATE_LAST:                  r = dhcp_lease_insert_private_option(lease, code, option, len);                  if (r < 0)                          return r; + +                break; + +        default: +                log_debug("Ignoring option DHCP option %i while parsing.", code); +                break;          }          return 0;  } -int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, -                                     const uint8_t *data, uint8_t len) { +int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len) {          struct sd_dhcp_raw_option *cur, *option; +        assert(lease); +          LIST_FOREACH(options, cur, lease->private_options) {                  if (tag < cur->tag)                          break; -                else if (tag == cur->tag) { -                        log_error("Ignoring duplicate option, tagged %d.", tag); +                if (tag == cur->tag) { +                        log_debug("Ignoring duplicate option, tagged %i.", tag);                          return 0;                  }          } @@ -653,7 +685,6 @@ int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag,          }          LIST_INSERT_BEFORE(options, lease->private_options, cur, option); -          return 0;  } @@ -665,24 +696,24 @@ int dhcp_lease_new(sd_dhcp_lease **ret) {                  return -ENOMEM;          lease->router = INADDR_ANY; -        lease->n_ref = REFCNT_INIT; -        LIST_HEAD_INIT(lease->private_options); +        lease->n_ref = 1;          *ret = lease;          return 0;  } -int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { +int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {          _cleanup_free_ char *temp_path = NULL;          _cleanup_fclose_ FILE *f = NULL;          struct sd_dhcp_raw_option *option;          struct in_addr address;          const struct in_addr *addresses; -        const uint8_t *client_id, *data; +        const void *client_id, *data;          size_t client_id_len, data_len;          const char *string;          uint16_t mtu;          struct sd_dhcp_route *routes; +        uint32_t t1, t2, lifetime;          int r;          assert(lease); @@ -694,19 +725,16 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {          fchmod(fileno(f), 0644); -        r = sd_dhcp_lease_get_address(lease, &address); -        if (r < 0) -                goto fail; -          fprintf(f, -                "# This is private data. Do not parse.\n" -                "ADDRESS=%s\n", inet_ntoa(address)); +                "# This is private data. Do not parse.\n"); -        r = sd_dhcp_lease_get_netmask(lease, &address); -        if (r < 0) -                goto fail; +        r = sd_dhcp_lease_get_address(lease, &address); +        if (r >= 0) +                fprintf(f, "ADDRESS=%s\n", inet_ntoa(address)); -        fprintf(f, "NETMASK=%s\n", inet_ntoa(address)); +        r = sd_dhcp_lease_get_netmask(lease, &address); +        if (r >= 0) +                fprintf(f, "NETMASK=%s\n", inet_ntoa(address));          r = sd_dhcp_lease_get_router(lease, &address);          if (r >= 0) @@ -714,28 +742,45 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {          r = sd_dhcp_lease_get_server_identifier(lease, &address);          if (r >= 0) -                fprintf(f, "SERVER_ADDRESS=%s\n", -                        inet_ntoa(address)); +                fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntoa(address));          r = sd_dhcp_lease_get_next_server(lease, &address);          if (r >= 0)                  fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address)); +        r = sd_dhcp_lease_get_broadcast(lease, &address); +        if (r >= 0) +                fprintf(f, "BROADCAST=%s\n", inet_ntoa(address)); +          r = sd_dhcp_lease_get_mtu(lease, &mtu);          if (r >= 0)                  fprintf(f, "MTU=%" PRIu16 "\n", mtu); -        fputs("DNS=", f); -        r = sd_dhcp_lease_get_dns(lease, &addresses); +        r = sd_dhcp_lease_get_t1(lease, &t1); +        if (r >= 0) +                fprintf(f, "T1=%" PRIu32 "\n", t1); + +        r = sd_dhcp_lease_get_t2(lease, &t2); +        if (r >= 0) +                fprintf(f, "T2=%" PRIu32 "\n", t2); + +        r = sd_dhcp_lease_get_lifetime(lease, &lifetime);          if (r >= 0) +                fprintf(f, "LIFETIME=%" PRIu32 "\n", lifetime); + +        r = sd_dhcp_lease_get_dns(lease, &addresses); +        if (r > 0) { +                fputs("DNS=", f);                  serialize_in_addrs(f, addresses, r); -        fputs("\n", f); +                fputs("\n", f); +        } -        fputs("NTP=", f);          r = sd_dhcp_lease_get_ntp(lease, &addresses); -        if (r >= 0) +        if (r > 0) { +                fputs("NTP=", f);                  serialize_in_addrs(f, addresses, r); -        fputs("\n", f); +                fputs("\n", f); +        }          r = sd_dhcp_lease_get_domainname(lease, &string);          if (r >= 0) @@ -750,9 +795,13 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {                  fprintf(f, "ROOT_PATH=%s\n", string);          r = sd_dhcp_lease_get_routes(lease, &routes); -        if (r >= 0) +        if (r > 0)                  serialize_dhcp_routes(f, "ROUTES", routes, r); +        r = sd_dhcp_lease_get_timezone(lease, &string); +        if (r >= 0) +                fprintf(f, "TIMEZONE=%s\n", string); +          r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);          if (r >= 0) {                  _cleanup_free_ char *client_id_hex; @@ -779,6 +828,7 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {          LIST_FOREACH(options, option, lease->private_options) {                  char key[strlen("OPTION_000")+1]; +                  snprintf(key, sizeof(key), "OPTION_%"PRIu8, option->tag);                  r = serialize_dhcp_option(f, key, option->data, option->length);                  if (r < 0) @@ -803,16 +853,27 @@ fail:          return log_error_errno(r, "Failed to save lease data %s: %m", lease_file);  } -int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { +int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { +          _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL; -        _cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL, -                            *server_address = NULL, *next_server = NULL, -                            *dns = NULL, *ntp = NULL, *mtu = NULL, -                            *routes = NULL, *client_id_hex = NULL, -                            *vendor_specific_hex = NULL, -                            *options[DHCP_OPTION_PRIVATE_LAST - -                                     DHCP_OPTION_PRIVATE_BASE + 1] = { NULL }; -        struct in_addr addr; +        _cleanup_free_ char +                *address = NULL, +                *router = NULL, +                *netmask = NULL, +                *server_address = NULL, +                *next_server = NULL, +                *broadcast = NULL, +                *dns = NULL, +                *ntp = NULL, +                *mtu = NULL, +                *routes = NULL, +                *client_id_hex = NULL, +                *vendor_specific_hex = NULL, +                *lifetime = NULL, +                *t1 = NULL, +                *t2 = NULL, +                *options[DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE + 1] = {}; +          int r, i;          assert(lease_file); @@ -828,6 +889,7 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {                             "NETMASK", &netmask,                             "SERVER_IDENTIFIER", &server_address,                             "NEXT_SERVER", &next_server, +                           "BROADCAST", &broadcast,                             "DNS", &dns,                             "NTP", &ntp,                             "MTU", &mtu, @@ -836,7 +898,11 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {                             "ROOT_PATH", &lease->root_path,                             "ROUTES", &routes,                             "CLIENTID", &client_id_hex, +                           "TIMEZONE", &lease->timezone,                             "VENDOR_SPECIFIC", &vendor_specific_hex, +                           "LIFETIME", &lifetime, +                           "T1", &t1, +                           "T2", &t2,                             "OPTION_224", &options[0],                             "OPTION_225", &options[1],                             "OPTION_226", &options[2], @@ -869,100 +935,123 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {                             "OPTION_253", &options[29],                             "OPTION_254", &options[30],                             NULL); -        if (r < 0) { -                if (r == -ENOENT) -                        return 0; - -                return log_error_errno(r, "Failed to read %s: %m", lease_file); -        } - -        r = inet_pton(AF_INET, address, &addr);          if (r < 0)                  return r; -        lease->address = addr.s_addr; +        if (address) { +                r = inet_pton(AF_INET, address, &lease->address); +                if (r <= 0) +                        log_debug_errno(errno, "Failed to parse address %s, ignoring: %m", address); +        }          if (router) { -                r = inet_pton(AF_INET, router, &addr); -                if (r < 0) -                        return r; - -                lease->router = addr.s_addr; +                r = inet_pton(AF_INET, router, &lease->router); +                if (r <= 0) +                        log_debug_errno(errno, "Failed to parse router %s, ignoring: %m", router);          } -        r = inet_pton(AF_INET, netmask, &addr); -        if (r < 0) -                return r; - -        lease->subnet_mask = addr.s_addr; +        if (netmask) { +                r = inet_pton(AF_INET, netmask, &lease->subnet_mask); +                if (r <= 0) +                        log_debug_errno(errno, "Failed to parse netmask %s, ignoring: %m", netmask); +                else +                        lease->have_subnet_mask = true; +        }          if (server_address) { -                r = inet_pton(AF_INET, server_address, &addr); -                if (r < 0) -                        return r; - -                lease->server_address = addr.s_addr; +                r = inet_pton(AF_INET, server_address, &lease->server_address); +                if (r <= 0) +                        log_debug_errno(errno, "Failed to parse netmask %s, ignoring: %m", server_address);          }          if (next_server) { -                r = inet_pton(AF_INET, next_server, &addr); -                if (r < 0) -                        return r; +                r = inet_pton(AF_INET, next_server, &lease->next_server); +                if (r <= 0) +                        log_debug_errno(errno, "Failed to parse next server %s, ignoring: %m", next_server); +        } -                lease->next_server = addr.s_addr; +        if (broadcast) { +                r = inet_pton(AF_INET, broadcast, &lease->broadcast); +                if (r <= 0) +                        log_debug_errno(errno, "Failed to parse broadcast address %s, ignoring: %m", broadcast); +                else +                        lease->have_broadcast = true;          }          if (dns) {                  r = deserialize_in_addrs(&lease->dns, dns);                  if (r < 0) -                        return r; - -                lease->dns_size = r; +                        log_debug_errno(r, "Failed to deserialize DNS servers %s, ignoring: %m", dns); +                else +                        lease->dns_size = r;          }          if (ntp) {                  r = deserialize_in_addrs(&lease->ntp, ntp);                  if (r < 0) -                        return r; - -                lease->ntp_size = r; +                        log_debug_errno(r, "Failed to deserialize NTP servers %s, ignoring: %m", ntp); +                else +                        lease->ntp_size = r;          }          if (mtu) { -                uint16_t u; -                if (sscanf(mtu, "%" SCNu16, &u) > 0) -                        lease->mtu = u; +                r = safe_atou16(mtu, &lease->mtu); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu);          }          if (routes) { -                r = deserialize_dhcp_routes(&lease->static_route, &lease->static_route_size, -                                &lease->static_route_allocated, routes); +                r = deserialize_dhcp_routes( +                                &lease->static_route, +                                &lease->static_route_size, +                                &lease->static_route_allocated, +                                routes); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse DHCP routes %s, ignoring: %m", routes); +        } + +        if (lifetime) { +                r = safe_atou32(lifetime, &lease->lifetime); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse lifetime %s, ignoring: %m", lifetime); +        } + +        if (t1) { +                r = safe_atou32(t1, &lease->t1); +                if (r < 0) +                        log_debug_errno(r, "Failed to parse T1 %s, ignoring: %m", t1); +        } + +        if (t2) { +                r = safe_atou32(t2, &lease->t2);                  if (r < 0) -                    return r; +                        log_debug_errno(r, "Failed to parse T2 %s, ignoring: %m", t2);          }          if (client_id_hex) {                  r = deserialize_dhcp_option(&lease->client_id, &lease->client_id_len, client_id_hex);                  if (r < 0) -                        return r; +                        log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex);          }          if (vendor_specific_hex) {                  r = deserialize_dhcp_option(&lease->vendor_specific, &lease->vendor_specific_len, vendor_specific_hex);                  if (r < 0) -                        return r; +                        log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);          }          for (i = 0; i <= DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE; i++) { -                _cleanup_free_ uint8_t *data = NULL; +                _cleanup_free_ void *data = NULL;                  size_t len;                  if (!options[i])                          continue;                  r = deserialize_dhcp_option(&data, &len, options[i]); -                if (r < 0) -                        return r; +                if (r < 0) { +                        log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]); +                        continue; +                }                  r = dhcp_lease_insert_private_option(lease, DHCP_OPTION_PRIVATE_BASE + i, data, len);                  if (r < 0) @@ -976,12 +1065,14 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {  }  int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) { -        struct in_addr address; -        struct in_addr mask; +        struct in_addr address, mask;          int r;          assert(lease); +        if (lease->address == 0) +                return -ENODATA; +          address.s_addr = lease->address;          /* fall back to the default subnet masks based on address class */ @@ -990,35 +1081,53 @@ int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {                  return r;          lease->subnet_mask = mask.s_addr; +        lease->have_subnet_mask = true;          return 0;  } -int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id, -                                size_t *client_id_len) { +int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) {          assert_return(lease, -EINVAL);          assert_return(client_id, -EINVAL);          assert_return(client_id_len, -EINVAL); +        if (!lease->client_id) +                return -ENODATA; +          *client_id = lease->client_id;          *client_id_len = lease->client_id_len; +          return 0;  } -int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id, -                             size_t client_id_len) { +int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len) {          assert_return(lease, -EINVAL); -        assert_return((!client_id && !client_id_len) || -                      (client_id && client_id_len), -EINVAL); +        assert_return(client_id || client_id_len <= 0, -EINVAL); + +        if (client_id_len <= 0) +                lease->client_id = mfree(lease->client_id); +        else { +                void *p; -        free (lease->client_id); -        lease->client_id = NULL; -        lease->client_id_len = 0; +                p = memdup(client_id, client_id_len); +                if (!p) +                        return -ENOMEM; -        if (client_id) { -                lease->client_id = memdup (client_id, client_id_len); +                free(lease->client_id); +                lease->client_id = p;                  lease->client_id_len = client_id_len;          }          return 0;  } + +int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone) { +        assert_return(lease, -EINVAL); +        assert_return(timezone, -EINVAL); + +        if (!lease->timezone) +                return -ENODATA; + +        *timezone = lease->timezone; +        return 0; +} diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index faeab0fd30..a46858258b 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -28,7 +28,8 @@  #include "dhcp-server-internal.h"  #include "dhcp-internal.h" -#define DHCP_DEFAULT_LEASE_TIME         3600 /* one hour */ +#define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR +#define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)  int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server,                                    struct in_addr *address, @@ -73,8 +74,12 @@ bool sd_dhcp_server_is_running(sd_dhcp_server *server) {  }  sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server) { -        if (server) -                assert_se(REFCNT_INC(server->n_ref) >= 2); + +        if (!server) +                return NULL; + +        assert(server->n_ref >= 1); +        server->n_ref++;          return server;  } @@ -127,7 +132,10 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {          if (!server)                  return NULL; -        if (REFCNT_DEC(server->n_ref) > 0) +        assert(server->n_ref >= 1); +        server->n_ref--; + +        if (server->n_ref > 0)                  return NULL;          log_dhcp_server(server, "UNREF"); @@ -136,6 +144,10 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {          sd_event_unref(server->event); +        free(server->timezone); +        free(server->dns); +        free(server->ntp); +          while ((lease = hashmap_steal_first(server->leases_by_client_id)))                  dhcp_lease_free(lease);          hashmap_free(server->leases_by_client_id); @@ -156,13 +168,15 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {          if (!server)                  return -ENOMEM; -        server->n_ref = REFCNT_INIT; +        server->n_ref = 1;          server->fd_raw = -1;          server->fd = -1;          server->address = htobe32(INADDR_ANY);          server->netmask = htobe32(INADDR_ANY); -        server->index = ifindex; +        server->ifindex = ifindex;          server->leases_by_client_id = hashmap_new(&client_id_hash_ops); +        server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC); +        server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC);          *ret = server;          server = NULL; @@ -223,13 +237,12 @@ static int dhcp_server_send_unicast_raw(sd_dhcp_server *server,          union sockaddr_union link = {                  .ll.sll_family = AF_PACKET,                  .ll.sll_protocol = htons(ETH_P_IP), -                .ll.sll_ifindex = server->index, +                .ll.sll_ifindex = server->ifindex,                  .ll.sll_halen = ETH_ALEN,          }; -        int r;          assert(server); -        assert(server->index > 0); +        assert(server->ifindex > 0);          assert(server->address);          assert(packet);          assert(len > sizeof(DHCPPacket)); @@ -240,11 +253,7 @@ static int dhcp_server_send_unicast_raw(sd_dhcp_server *server,                                        packet->dhcp.yiaddr,                                        DHCP_PORT_CLIENT, len); -        r = dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len); -        if (r < 0) -                return r; - -        return 0; +        return dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len);  }  static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination, @@ -290,7 +299,7 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,          pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);          assert(pktinfo); -        pktinfo->ipi_ifindex = server->index; +        pktinfo->ipi_ifindex = server->ifindex;          pktinfo->ipi_spec_dst.s_addr = server->address;          r = sendmsg(server->fd, &msg, 0); @@ -474,6 +483,33 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,          if (r < 0)                  return r; +        if (server->n_dns > 0) { +                r = dhcp_option_append( +                                &packet->dhcp, req->max_optlen, &offset, 0, +                                DHCP_OPTION_DOMAIN_NAME_SERVER, +                                sizeof(struct in_addr) * server->n_dns, server->dns); +                if (r < 0) +                        return r; +        } + +        if (server->n_ntp > 0) { +                r = dhcp_option_append( +                                &packet->dhcp, req->max_optlen, &offset, 0, +                                DHCP_OPTION_NTP_SERVER, +                                sizeof(struct in_addr) * server->n_ntp, server->ntp); +                if (r < 0) +                        return r; +        } + +        if (server->timezone) { +                r = dhcp_option_append( +                                &packet->dhcp, req->max_optlen, &offset, 0, +                                DHCP_OPTION_NEW_TZDB_TIMEZONE, +                                strlen(server->timezone), server->timezone); +                if (r < 0) +                        return r; +        } +          r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset);          if (r < 0)                  return r; @@ -490,11 +526,7 @@ static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) {          if (r < 0)                  return r; -        r = dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset); -        if (r < 0) -                return r; - -        return 0; +        return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);  }  static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, @@ -532,9 +564,8 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,          return 0;  } -static int parse_request(uint8_t code, uint8_t len, const uint8_t *option, -                         void *user_data) { -        DHCPRequest *req = user_data; +static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) { +        DHCPRequest *req = userdata;          assert(req); @@ -590,7 +621,7 @@ static void dhcp_request_free(DHCPRequest *req) {  DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);  #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep) -static int ensure_sane_request(DHCPRequest *req, DHCPMessage *message) { +static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) {          assert(req);          assert(message); @@ -599,23 +630,27 @@ static int ensure_sane_request(DHCPRequest *req, DHCPMessage *message) {          /* set client id based on MAC address if client did not send an explicit             one */          if (!req->client_id.data) { -                uint8_t *data; +                void *data; -                data = new0(uint8_t, ETH_ALEN + 1); +                data = malloc0(ETH_ALEN + 1);                  if (!data)                          return -ENOMEM; +                ((uint8_t*) data)[0] = 0x01; +                memcpy((uint8_t*) data + 1, &message->chaddr, ETH_ALEN); +                  req->client_id.length = ETH_ALEN + 1;                  req->client_id.data = data; -                req->client_id.data[0] = 0x01; -                memcpy(&req->client_id.data[1], &message->chaddr, ETH_ALEN);          }          if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE)                  req->max_optlen = DHCP_MIN_OPTIONS_SIZE; -        if (!req->lifetime) -                req->lifetime = DHCP_DEFAULT_LEASE_TIME; +        if (req->lifetime <= 0) +                req->lifetime = MAX(1ULL, server->default_lease_time); + +        if (server->max_lease_time > 0 && req->lifetime > server->max_lease_time) +                req->lifetime = server->max_lease_time;          return 0;  } @@ -656,7 +691,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,          if (type < 0)                  return 0; -        r = ensure_sane_request(req, message); +        r = ensure_sane_request(server, req, message);          if (r < 0)                  /* this only fails on critical errors */                  return r; @@ -665,8 +700,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,                                       &req->client_id);          switch(type) { -        case DHCP_DISCOVER: -        { + +        case DHCP_DISCOVER: {                  be32_t address = INADDR_ANY;                  unsigned i; @@ -716,9 +751,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,                  return 1; -                break; -        case DHCP_REQUEST: -        { +        case DHCP_REQUEST: {                  be32_t address;                  bool init_reboot = false;                  int pool_offset; @@ -840,6 +873,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,                  break;          } +          case DHCP_RELEASE: {                  int pool_offset; @@ -883,13 +917,12 @@ static int server_receive_message(sd_event_source *s, int fd,                  .msg_controllen = sizeof(cmsgbuf),          };          struct cmsghdr *cmsg; -        int buflen = 0, len, r; +        int buflen = 0, len;          assert(server); -        r = ioctl(fd, FIONREAD, &buflen); -        if (r < 0) -                return r; +        if (ioctl(fd, FIONREAD, &buflen) < 0) +                return -errno;          if (buflen < 0)                  return -EIO; @@ -914,7 +947,7 @@ static int server_receive_message(sd_event_source *s, int fd,                          /* TODO figure out if this can be done as a filter on                           * the socket, like for IPv6 */ -                        if (server->index != info->ipi_ifindex) +                        if (server->ifindex != info->ipi_ifindex)                                  return 0;                          break; @@ -993,3 +1026,91 @@ int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {          return r;  } + +int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone) { +        int r; + +        assert_return(server, -EINVAL); +        assert_return(timezone_is_valid(timezone), -EINVAL); + +        if (streq_ptr(timezone, server->timezone)) +                return 0; + +        r = free_and_strdup(&server->timezone, timezone); +        if (r < 0) +                return r; + +        return 1; +} + +int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t) { +        assert_return(server, -EINVAL); + +        if (t == server->max_lease_time) +                return 0; + +        server->max_lease_time = t; +        return 1; +} + +int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) { +        assert_return(server, -EINVAL); + +        if (t == server->default_lease_time) +                return 0; + +        server->default_lease_time = t; +        return 1; +} + +int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n) { +        assert_return(server, -EINVAL); +        assert_return(dns || n <= 0, -EINVAL); + +        if (server->n_dns == n && +            memcmp(server->dns, dns, sizeof(struct in_addr) * n) == 0) +                return 0; + +        if (n <= 0) { +                server->dns = mfree(server->dns); +                server->n_dns = 0; +        } else { +                struct in_addr *c; + +                c = newdup(struct in_addr, dns, n); +                if (!c) +                        return -ENOMEM; + +                free(server->dns); +                server->dns = c; +                server->n_dns = n; +        } + +        return 1; +} + +int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n) { +        assert_return(server, -EINVAL); +        assert_return(ntp || n <= 0, -EINVAL); + +        if (server->n_ntp == n && +            memcmp(server->ntp, ntp, sizeof(struct in_addr) * n) == 0) +                return 0; + +        if (n <= 0) { +                server->ntp = mfree(server->ntp); +                server->n_ntp = 0; +        } else { +                struct in_addr *c; + +                c = newdup(struct in_addr, ntp, n); +                if (!c) +                        return -ENOMEM; + +                free(server->ntp); +                server->ntp = c; +                server->n_ntp = n; +        } + +        return 1; +} diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 10c3654020..5489c77864 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -27,7 +27,6 @@  #include "udev.h"  #include "udev-util.h"  #include "util.h" -#include "refcnt.h"  #include "random-util.h"  #include "network-internal.h" @@ -40,7 +39,7 @@  #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN  struct sd_dhcp6_client { -        RefCount n_ref; +        unsigned n_ref;          enum DHCP6State state;          sd_event *event; @@ -113,9 +112,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);  static int client_start(sd_dhcp6_client *client, enum DHCP6State state); -int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, -                                 sd_dhcp6_client_cb_t cb, void *userdata) -{ +int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {          assert_return(client, -EINVAL);          client->cb = cb; @@ -124,8 +121,7 @@ int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,          return 0;  } -int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) -{ +int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {          assert_return(client, -EINVAL);          assert_return(interface_index >= -1, -EINVAL); @@ -134,9 +130,11 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)          return 0;  } -int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr, -                            size_t addr_len, uint16_t arp_type) -{ +int sd_dhcp6_client_set_mac( +                sd_dhcp6_client *client, +                const uint8_t *addr, size_t addr_len, +                uint16_t arp_type) { +          assert_return(client, -EINVAL);          assert_return(addr, -EINVAL);          assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); @@ -160,16 +158,17 @@ int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,          return 0;  } -static int client_ensure_duid(sd_dhcp6_client *client) -{ +static int client_ensure_duid(sd_dhcp6_client *client) {          if (client->duid_len != 0)                  return 0; +          return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);  } -int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid, -                             size_t duid_len) -{ +int sd_dhcp6_client_set_duid( +                sd_dhcp6_client *client, +                uint16_t type, +                uint8_t *duid, size_t duid_len) {          assert_return(client, -EINVAL);          assert_return(duid, -EINVAL);          assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL); @@ -203,8 +202,7 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du          return 0;  } -int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, -                                            bool enabled) { +int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, bool enabled) {          assert_return(client, -EINVAL);          client->information_request = enabled; @@ -212,8 +210,7 @@ int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client,          return 0;  } -int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, -                                            bool *enabled) { +int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, bool *enabled) {          assert_return(client, -EINVAL);          assert_return(enabled, -EINVAL); @@ -222,8 +219,7 @@ int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client,          return 0;  } -int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, -                                       uint16_t option) { +int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {          size_t t;          assert_return(client, -EINVAL); @@ -805,9 +801,7 @@ static int client_parse_message(sd_dhcp6_client *client,          return r;  } -static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, -                                size_t len) -{ +static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {          int r;          _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;          bool rapid_commit; @@ -843,8 +837,7 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,          return DHCP6_STATE_BOUND;  } -static int client_receive_advertise(sd_dhcp6_client *client, -                                    DHCP6Message *advertise, size_t len) { +static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {          int r;          _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;          uint8_t pref_advertise = 0, pref_lease = 0; @@ -879,8 +872,7 @@ static int client_receive_advertise(sd_dhcp6_client *client,          return r;  } -static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, -                                  void *userdata) { +static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {          sd_dhcp6_client *client = userdata;          DHCP6_CLIENT_DONT_DESTROY(client);          _cleanup_free_ DHCP6Message *message; @@ -991,8 +983,7 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,          return 0;  } -static int client_start(sd_dhcp6_client *client, enum DHCP6State state) -{ +static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {          int r;          usec_t timeout, time_now;          char time_string[FORMAT_TIMESPAN_MAX]; @@ -1121,15 +1112,13 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)          return 0;  } -int sd_dhcp6_client_stop(sd_dhcp6_client *client) -{ +int sd_dhcp6_client_stop(sd_dhcp6_client *client) {          client_stop(client, DHCP6_EVENT_STOP);          return 0;  } -int sd_dhcp6_client_start(sd_dhcp6_client *client) -{ +int sd_dhcp6_client_start(sd_dhcp6_client *client) {          int r = 0;          enum DHCP6State state = DHCP6_STATE_SOLICITATION; @@ -1185,9 +1174,7 @@ error:          return r;  } -int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, -                                 int priority) -{ +int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority) {          int r;          assert_return(client, -EINVAL); @@ -1222,30 +1209,39 @@ sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {  }  sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) { -        if (client) -                assert_se(REFCNT_INC(client->n_ref) >= 2); + +        if (!client) +                return NULL; + +        assert(client->n_ref >= 1); +        client->n_ref++;          return client;  }  sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) { -        if (client && REFCNT_DEC(client->n_ref) == 0) { -                client_reset(client); -                sd_dhcp6_client_detach_event(client); -                sd_dhcp6_lease_unref(client->lease); +        if (!client) +                return NULL; -                free(client->req_opts); -                free(client); +        assert(client->n_ref >= 1); +        client->n_ref--; +        if (client->n_ref > 0)                  return NULL; -        } -        return client; +        client_reset(client); + +        sd_dhcp6_client_detach_event(client); +        sd_dhcp6_lease_unref(client->lease); + +        free(client->req_opts); +        free(client); + +        return NULL;  } -int sd_dhcp6_client_new(sd_dhcp6_client **ret) -{ +int sd_dhcp6_client_new(sd_dhcp6_client **ret) {          _cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;          size_t t; @@ -1255,7 +1251,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret)          if (!client)                  return -ENOMEM; -        client->n_ref = REFCNT_INIT; +        client->n_ref = 1;          client->ia_na.type = DHCP6_OPTION_IA_NA; diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index f0494b3c91..f34af6eaba 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -247,8 +247,7 @@ int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) {          return -ENOENT;  } -int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) -{ +int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {          int r;          uint16_t subopt;          size_t sublen; @@ -361,26 +360,38 @@ int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {  }  sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) { -        if (lease) -                assert_se(REFCNT_INC(lease->n_ref) >= 2); + +        if (!lease) +                return NULL; + +        assert(lease->n_ref >= 1); +        lease->n_ref++;          return lease;  }  sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) { -        if (lease && REFCNT_DEC(lease->n_ref) == 0) { -                free(lease->serverid); -                dhcp6_lease_free_ia(&lease->ia); -                free(lease->dns); +        if (!lease) +                return NULL; -                lease->domains = strv_free(lease->domains); +        assert(lease->n_ref >= 1); +        lease->n_ref--; -                free(lease->ntp); +        if (lease->n_ref > 0) +                return NULL; -                lease->ntp_fqdn = strv_free(lease->ntp_fqdn); -                free(lease); -        } +        free(lease->serverid); +        dhcp6_lease_free_ia(&lease->ia); + +        free(lease->dns); + +        lease->domains = strv_free(lease->domains); + +        free(lease->ntp); + +        lease->ntp_fqdn = strv_free(lease->ntp_fqdn); +        free(lease);          return NULL;  } @@ -392,7 +403,7 @@ int dhcp6_lease_new(sd_dhcp6_lease **ret) {          if (!lease)                  return -ENOMEM; -        lease->n_ref = REFCNT_INIT; +        lease->n_ref = 1;          LIST_HEAD_INIT(lease->ia.addresses); diff --git a/src/libsystemd-network/sd-icmp6-nd.c b/src/libsystemd-network/sd-icmp6-nd.c index 2f867e8562..e80232a7e0 100644 --- a/src/libsystemd-network/sd-icmp6-nd.c +++ b/src/libsystemd-network/sd-icmp6-nd.c @@ -25,7 +25,6 @@  #include <sys/ioctl.h>  #include "socket-util.h" -#include "refcnt.h"  #include "async.h"  #include "dhcp6-internal.h" @@ -47,7 +46,7 @@ enum icmp6_nd_state {  typedef struct ICMP6Prefix ICMP6Prefix;  struct ICMP6Prefix { -        RefCount n_ref; +        unsigned n_ref;          LIST_FIELDS(ICMP6Prefix, prefixes); @@ -57,7 +56,7 @@ struct ICMP6Prefix {  };  struct sd_icmp6_nd { -        RefCount n_ref; +        unsigned n_ref;          enum icmp6_nd_state state;          sd_event *event; @@ -78,13 +77,18 @@ struct sd_icmp6_nd {  #define log_icmp6_nd(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "ICMPv6 CLIENT: " fmt, ##__VA_ARGS__)  static ICMP6Prefix *icmp6_prefix_unref(ICMP6Prefix *prefix) { -        if (prefix && REFCNT_DEC(prefix->n_ref) <= 0) { -                prefix->timeout_valid = -                        sd_event_source_unref(prefix->timeout_valid); -                free(prefix); -        } +        if (!prefix) +                return NULL; + +        assert(prefix->n_ref > 0); +        prefix->n_ref--; +        if (prefix->n_ref > 0) +                return NULL; + +        prefix->timeout_valid = sd_event_source_unref(prefix->timeout_valid); +        free(prefix);          return NULL;  } @@ -97,7 +101,7 @@ static int icmp6_prefix_new(ICMP6Prefix **ret) {          if (!prefix)                  return -ENOMEM; -        prefix->n_ref = REFCNT_INIT; +        prefix->n_ref = 1;          LIST_INIT(prefixes, prefix);          *ret = prefix; @@ -106,8 +110,7 @@ static int icmp6_prefix_new(ICMP6Prefix **ret) {          return 0;  } -static void icmp6_nd_notify(sd_icmp6_nd *nd, int event) -{ +static void icmp6_nd_notify(sd_icmp6_nd *nd, int event) {          if (nd->callback)                  nd->callback(nd, event, nd->userdata);  } @@ -177,9 +180,12 @@ sd_event *sd_icmp6_nd_get_event(sd_icmp6_nd *nd) {  }  sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd) { -        assert (nd); -        assert_se(REFCNT_INC(nd->n_ref) >= 2); +        if (!nd) +                return NULL; + +        assert(nd->n_ref > 0); +        nd->n_ref++;          return nd;  } @@ -195,21 +201,28 @@ static int icmp6_nd_init(sd_icmp6_nd *nd) {  }  sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd) { -        if (nd && REFCNT_DEC(nd->n_ref) == 0) { -                ICMP6Prefix *prefix, *p; +        ICMP6Prefix *prefix, *p; -                icmp6_nd_init(nd); -                sd_icmp6_nd_detach_event(nd); +        if (!nd) +                return NULL; -                LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) { -                        LIST_REMOVE(prefixes, nd->prefixes, prefix); +        assert(nd->n_ref > 0); +        nd->n_ref--; -                        prefix = icmp6_prefix_unref(prefix); -                } +        if (nd->n_ref > 0) +                return NULL; + +        icmp6_nd_init(nd); +        sd_icmp6_nd_detach_event(nd); -                free(nd); +        LIST_FOREACH_SAFE(prefixes, prefix, p, nd->prefixes) { +                LIST_REMOVE(prefixes, nd->prefixes, prefix); + +                prefix = icmp6_prefix_unref(prefix);          } +        free(nd); +          return NULL;  } @@ -225,7 +238,7 @@ int sd_icmp6_nd_new(sd_icmp6_nd **ret) {          if (!nd)                  return -ENOMEM; -        nd->n_ref = REFCNT_INIT; +        nd->n_ref = 1;          nd->index = -1;          nd->fd = -1; @@ -376,9 +389,7 @@ int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,          return 0;  } -int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr, -                                uint8_t *prefixlen) -{ +int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr, uint8_t *prefixlen) {          assert_return(nd, -EINVAL);          assert_return(addr, -EINVAL);          assert_return(prefixlen, -EINVAL); @@ -525,9 +536,7 @@ static int icmp6_ra_parse(sd_icmp6_nd *nd, struct nd_router_advert *ra,          return 0;  } -static int icmp6_router_advertisment_recv(sd_event_source *s, int fd, -                                          uint32_t revents, void *userdata) -{ +static int icmp6_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {          sd_icmp6_nd *nd = userdata;          int r, buflen = 0;          ssize_t len; @@ -586,9 +595,7 @@ static int icmp6_router_advertisment_recv(sd_event_source *s, int fd,          return 0;  } -static int icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec, -                                             void *userdata) -{ +static int icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec, void *userdata) {          sd_icmp6_nd *nd = userdata;          uint64_t time_now, next_timeout;          struct ether_addr unset = { }; diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index f080c5c0a7..0fc05e1484 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -26,7 +26,6 @@  #include "util.h"  #include "siphash24.h"  #include "list.h" -#include "refcnt.h"  #include "random-util.h"  #include "ipv4ll-internal.h" @@ -68,7 +67,7 @@ typedef enum IPv4LLState {  } IPv4LLState;  struct sd_ipv4ll { -        RefCount n_ref; +        unsigned n_ref;          IPv4LLState state;          int index; @@ -598,30 +597,39 @@ int sd_ipv4ll_stop(sd_ipv4ll *ll) {  }  sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) { -        if (ll) -                assert_se(REFCNT_INC(ll->n_ref) >= 2); + +        if (!ll) +                return NULL; + +        assert(ll->n_ref >= 1); +        ll->n_ref++;          return ll;  }  sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) { -        if (ll && REFCNT_DEC(ll->n_ref) == 0) { -                ll->receive_message = -                        sd_event_source_unref(ll->receive_message); -                ll->fd = safe_close(ll->fd); -                ll->timer = sd_event_source_unref(ll->timer); +        if (!ll) +                return NULL; -                sd_ipv4ll_detach_event(ll); +        assert(ll->n_ref >= 1); +        ll->n_ref--; -                free(ll->random_data); -                free(ll->random_data_state); -                free(ll); +        if (ll->n_ref > 0) +                return ll; -                return NULL; -        } +        ll->receive_message = sd_event_source_unref(ll->receive_message); +        ll->fd = safe_close(ll->fd); -        return ll; +        ll->timer = sd_event_source_unref(ll->timer); + +        sd_ipv4ll_detach_event(ll); + +        free(ll->random_data); +        free(ll->random_data_state); +        free(ll); + +        return NULL;  }  DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_unref); @@ -636,7 +644,7 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) {          if (!ll)                  return -ENOMEM; -        ll->n_ref = REFCNT_INIT; +        ll->n_ref = 1;          ll->state = IPV4LL_STATE_INIT;          ll->index = -1;          ll->fd = -1; diff --git a/src/libsystemd-network/sd-pppoe.c b/src/libsystemd-network/sd-pppoe.c index ff064f563f..c6c9da812b 100644 --- a/src/libsystemd-network/sd-pppoe.c +++ b/src/libsystemd-network/sd-pppoe.c @@ -36,7 +36,6 @@  #include "random-util.h"  #include "socket-util.h"  #include "async.h" -#include "refcnt.h"  #include "utf8.h"  #define PPPOE_MAX_PACKET_SIZE 1484 @@ -68,7 +67,7 @@ typedef struct PPPoETags {  } PPPoETags;  struct sd_pppoe { -        RefCount n_ref; +        unsigned n_ref;          PPPoEState state;          uint64_t host_uniq; @@ -202,23 +201,34 @@ int sd_pppoe_detach_event(sd_pppoe *ppp) {  }  sd_pppoe *sd_pppoe_ref(sd_pppoe *ppp) { -        if (ppp) -                assert_se(REFCNT_INC(ppp->n_ref) >= 2); + +        if (!ppp) +                return NULL; + +        assert(ppp->n_ref > 0); +        ppp->n_ref++;          return ppp;  }  sd_pppoe *sd_pppoe_unref(sd_pppoe *ppp) { -        if (ppp && REFCNT_DEC(ppp->n_ref) <= 0) { -                pppoe_tags_clear(&ppp->tags); -                free(ppp->ifname); -                free(ppp->service_name); -                sd_pppoe_stop(ppp); -                sd_pppoe_detach_event(ppp); - -                free(ppp); -        } +        if (!ppp) +                return NULL; + +        assert(ppp->n_ref > 0); +        ppp->n_ref--; + +        if (ppp->n_ref > 0) +                return NULL; + +        pppoe_tags_clear(&ppp->tags); +        free(ppp->ifname); +        free(ppp->service_name); +        sd_pppoe_stop(ppp); +        sd_pppoe_detach_event(ppp); + +        free(ppp);          return NULL;  } @@ -231,7 +241,7 @@ int sd_pppoe_new (sd_pppoe **ret) {          if (!ppp)                  return -ENOMEM; -        ppp->n_ref = REFCNT_INIT; +        ppp->n_ref = 1;          ppp->state = _PPPOE_STATE_INVALID;          ppp->ifindex = -1;          ppp->fd = -1; diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c index 200499d613..29c20b77e3 100644 --- a/src/libsystemd-network/test-dhcp-client.c +++ b/src/libsystemd-network/test-dhcp-client.c @@ -43,16 +43,13 @@ static test_callback_recv_t callback_recv;  static be32_t xid;  static sd_event_source *test_hangcheck; -static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec, -                               void *userdata) -{ +static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {          assert_not_reached("Test case should have completed in 2 seconds");          return 0;  } -static void test_request_basic(sd_event *e) -{ +static void test_request_basic(sd_event *e) {          int r;          sd_dhcp_client *client; @@ -87,10 +84,7 @@ static void test_request_basic(sd_event *e)          assert_se(sd_dhcp_client_set_request_option(client,                                          DHCP_OPTION_DOMAIN_NAME) == -EEXIST);          assert_se(sd_dhcp_client_set_request_option(client, -                                        DHCP_OPTION_DOMAIN_NAME_SERVER) -                        == -EEXIST); -        assert_se(sd_dhcp_client_set_request_option(client, -                                        DHCP_OPTION_NTP_SERVER) == -EEXIST); +                                        DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);          assert_se(sd_dhcp_client_set_request_option(client,                                          DHCP_OPTION_PAD) == -EINVAL); @@ -112,8 +106,7 @@ static void test_request_basic(sd_event *e)          sd_dhcp_client_unref(client);  } -static void test_checksum(void) -{ +static void test_checksum(void) {          uint8_t buf[20] = {                  0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,                  0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -126,9 +119,7 @@ static void test_checksum(void)          assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae));  } -static int check_options(uint8_t code, uint8_t len, const uint8_t *option, -                void *user_data) -{ +static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {          switch(code) {          case DHCP_OPTION_CLIENT_IDENTIFIER:          { @@ -141,10 +132,10 @@ static int check_options(uint8_t code, uint8_t len, const uint8_t *option,                  assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);                  assert_se(len == 19); -                assert_se(option[0] == 0xff); +                assert_se(((uint8_t*) option)[0] == 0xff); -                assert_se(memcmp(&option[1], &iaid, sizeof(iaid)) == 0); -                assert_se(memcmp(&option[5], &duid, duid_len) == 0); +                assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0); +                assert_se(memcmp((uint8_t*) option + 5, &duid, duid_len) == 0);                  break;          } @@ -155,9 +146,7 @@ static int check_options(uint8_t code, uint8_t len, const uint8_t *option,          return 0;  } -int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, -                                 const void *packet, size_t len) -{ +int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) {          size_t size;          _cleanup_free_ DHCPPacket *discover;          uint16_t ip_check, udp_check; @@ -202,18 +191,20 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,          return 575;  } -int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, -                                 uint32_t id, const uint8_t *addr, -                                 size_t addr_len, uint16_t arp_type) -{ +int dhcp_network_bind_raw_socket( +                int index, +                union sockaddr_union *link, +                uint32_t id, +                const uint8_t *addr, size_t addr_len, +                uint16_t arp_type) { +          if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)                  return -errno;          return test_fd[0];  } -int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) -{ +int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {          int fd;          fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0); @@ -223,14 +214,11 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port)          return fd;  } -int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, -                                 const void *packet, size_t len) -{ +int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) {          return 0;  } -static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) -{ +static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {          int res;          res = dhcp_option_parse(dhcp, size, check_options, NULL); @@ -242,8 +230,7 @@ static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp)          return 0;  } -static void test_discover_message(sd_event *e) -{ +static void test_discover_message(sd_event *e) {          sd_dhcp_client *client;          int res, r; diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c index a63a4ea738..b1ef174849 100644 --- a/src/libsystemd-network/test-dhcp-option.c +++ b/src/libsystemd-network/test-dhcp-option.c @@ -145,8 +145,8 @@ static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen) {          }  } -static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option, void *user_data) { -        struct option_desc *desc = user_data; +static int test_options_cb(uint8_t code, uint8_t len, const void *option, void *userdata) { +        struct option_desc *desc = userdata;          uint8_t *descoption = NULL;          int *desclen = NULL, *descpos = NULL;          uint8_t optcode = 0; @@ -207,10 +207,10 @@ static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option, voi          for (i = 0; i < len; i++) {                  if (verbose) -                        printf("0x%02x(0x%02x) ", option[i], +                        printf("0x%02x(0x%02x) ", ((uint8_t*) option)[i],                                          descoption[*descpos + 2 + i]); -                assert_se(option[i] == descoption[*descpos + 2 + i]); +                assert_se(((uint8_t*) option)[i] == descoption[*descpos + 2 + i]);          }          if (verbose) diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c index 6e62262443..12daac3211 100644 --- a/src/libsystemd-network/test-dhcp6-client.c +++ b/src/libsystemd-network/test-dhcp6-client.c @@ -501,8 +501,7 @@ static int test_client_verify_request(DHCP6Message *request, uint8_t *option,          return 0;  } -static int test_client_send_advertise(DHCP6Message *solicit) -{ +static int test_client_send_advertise(DHCP6Message *solicit) {          DHCP6Message advertise;          advertise.transaction_id = solicit->transaction_id; diff --git a/src/libsystemd-network/test-ipv4ll.c b/src/libsystemd-network/test-ipv4ll.c index 5677bfb2d2..d60ee98b25 100644 --- a/src/libsystemd-network/test-ipv4ll.c +++ b/src/libsystemd-network/test-ipv4ll.c @@ -39,9 +39,9 @@ static int test_fd[2];  static int basic_request_handler_bind = 0;  static int basic_request_handler_stop = 0; -static void* basic_request_handler_user_data = (void*)0xCABCAB; +static void* basic_request_handler_userdata = (void*)0xCABCAB;  static void basic_request_handler(sd_ipv4ll *ll, int event, void *userdata) { -        assert_se(userdata == basic_request_handler_user_data); +        assert_se(userdata == basic_request_handler_userdata);          switch(event) {                  case IPV4LL_EVENT_STOP: @@ -175,7 +175,7 @@ static void test_basic_request(sd_event *e) {          assert_se(sd_ipv4ll_start(ll) == -EINVAL);          assert_se(sd_ipv4ll_set_callback(ll, basic_request_handler, -                                         basic_request_handler_user_data) == 0); +                                         basic_request_handler_userdata) == 0);          assert_se(sd_ipv4ll_start(ll) == -EINVAL);          assert_se(sd_ipv4ll_set_index(ll, 1) == 0); diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index a21ed8cb62..366a026426 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -1024,7 +1024,9 @@ _public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {  _public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {          assert_return(m, NULL); -        assert_return(sd_bus_error_is_set(&m->error), NULL); + +        if (!sd_bus_error_is_set(&m->error)) +                return NULL;          return &m->error;  } diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 40aa77ee5c..06c98314e8 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -79,8 +79,7 @@ static bool linebuf_add(struct linebuf *buf, const char *s, size_t len) {          return true;  } -static bool linebuf_add_char(struct linebuf *buf, char c) -{ +static bool linebuf_add_char(struct linebuf *buf, char c) {          if (buf->len + 1 >= sizeof(buf->bytes))                  return false;          buf->bytes[buf->len++] = c; @@ -269,13 +268,13 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) {  }  static const char hwdb_bin_paths[] = -    "/etc/systemd/hwdb/hwdb.bin\0" -    "/etc/udev/hwdb.bin\0" -    "/usr/lib/systemd/hwdb/hwdb.bin\0" +        "/etc/systemd/hwdb/hwdb.bin\0" +        "/etc/udev/hwdb.bin\0" +        "/usr/lib/systemd/hwdb/hwdb.bin\0"  #ifdef HAVE_SPLIT_USR -    "/lib/systemd/hwdb/hwdb.bin\0" +        "/lib/systemd/hwdb/hwdb.bin\0"  #endif -    UDEVLIBEXECDIR "/hwdb.bin\0"; +        UDEVLIBEXECDIR "/hwdb.bin\0";  _public_ int sd_hwdb_new(sd_hwdb **ret) {          _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL; diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index b63fdf8fcb..87d87359b8 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -214,6 +214,28 @@ _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {          return 0;  } +int sd_network_link_get_timezone(int ifindex, char **ret) { +        _cleanup_free_ char *s = NULL, *p = NULL; +        int r; + +        assert_return(ifindex > 0, -EINVAL); +        assert_return(ret, -EINVAL); + +        if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) +                return -ENOMEM; + +        r = parse_env_file(p, NEWLINE, "TIMEZONE", &s, NULL); +        if (r == -ENOENT) +                return -ENODATA; +        if (r < 0) +                return r; +        if (isempty(s)) +                return -ENODATA; + +        *ret = s; +        s = NULL; +        return 0; +}  static int network_get_link_strv(const char *key, int ifindex, char ***ret) {          _cleanup_free_ char *p = NULL, *s = NULL; diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c index b0dc822591..888b372c99 100644 --- a/src/libsystemd/sd-resolve/sd-resolve.c +++ b/src/libsystemd/sd-resolve/sd-resolve.c @@ -48,9 +48,6 @@ typedef enum {          RESPONSE_ADDRINFO,          REQUEST_NAMEINFO,          RESPONSE_NAMEINFO, -        REQUEST_RES_QUERY, -        REQUEST_RES_SEARCH, -        RESPONSE_RES,          REQUEST_TERMINATE,          RESPONSE_DIED  } QueryType; @@ -104,12 +101,10 @@ struct sd_resolve_query {          int _h_errno;          struct addrinfo *addrinfo;          char *serv, *host; -        unsigned char *answer;          union {                  sd_resolve_getaddrinfo_handler_t getaddrinfo_handler;                  sd_resolve_getnameinfo_handler_t getnameinfo_handler; -                sd_resolve_res_handler_t res_handler;          };          void *userdata; @@ -166,33 +161,16 @@ typedef struct NameInfoResponse {          int _h_errno;  } NameInfoResponse; -typedef struct ResRequest { -        struct RHeader header; -        int class; -        int type; -        size_t dname_len; -} ResRequest; - -typedef struct ResResponse { -        struct RHeader header; -        int ret; -        int _errno; -        int _h_errno; -} ResResponse; -  typedef union Packet {          RHeader rheader;          AddrInfoRequest addrinfo_request;          AddrInfoResponse addrinfo_response;          NameInfoRequest nameinfo_request;          NameInfoResponse nameinfo_response; -        ResRequest res_request; -        ResResponse res_response;  } Packet;  static int getaddrinfo_done(sd_resolve_query* q);  static int getnameinfo_done(sd_resolve_query *q); -static int res_query_done(sd_resolve_query* q);  static void resolve_query_disconnect(sd_resolve_query *q); @@ -343,38 +321,6 @@ static int send_nameinfo_reply(          return 0;  } -static int send_res_reply(int out_fd, unsigned id, const unsigned char *answer, int ret, int _errno, int _h_errno) { - -        ResResponse resp = { -                .header.type = RESPONSE_RES, -                .header.id = id, -                .ret = ret, -                ._errno = _errno, -                ._h_errno = _h_errno, -        }; - -        struct msghdr mh = {}; -        struct iovec iov[2]; -        size_t l; - -        assert(out_fd >= 0); - -        l = ret > 0 ? (size_t) ret : 0; - -        resp.header.length = sizeof(ResResponse) + l; - -        iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(ResResponse) }; -        iov[1] = (struct iovec) { .iov_base = (void*) answer, .iov_len = l }; - -        mh.msg_iov = iov; -        mh.msg_iovlen = ELEMENTSOF(iov); - -        if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0) -                return -errno; - -        return 0; -} -  static int handle_request(int out_fd, const Packet *packet, size_t length) {          const RHeader *req; @@ -437,29 +383,6 @@ static int handle_request(int out_fd, const Packet *packet, size_t length) {                                 errno, h_errno);          } -        case REQUEST_RES_QUERY: -        case REQUEST_RES_SEARCH: { -                 const ResRequest *res_req = &packet->res_request; -                 union { -                         HEADER header; -                         uint8_t space[BUFSIZE]; -                 } answer; -                 const char *dname; -                 int ret; - -                 assert(length >= sizeof(ResRequest)); -                 assert(length == sizeof(ResRequest) + res_req->dname_len); - -                 dname = (const char *) res_req + sizeof(ResRequest); - -                 if (req->type == REQUEST_RES_QUERY) -                         ret = res_query(dname, res_req->class, res_req->type, (unsigned char *) &answer, BUFSIZE); -                 else -                         ret = res_search(dname, res_req->class, res_req->type, (unsigned char *) &answer, BUFSIZE); - -                 return send_res_reply(out_fd, req->id, (unsigned char *) &answer, ret, errno, h_errno); -        } -          case REQUEST_TERMINATE:                   /* Quit */                   return -ECONNRESET; @@ -752,11 +675,6 @@ static int complete_query(sd_resolve *resolve, sd_resolve_query *q) {                  r = getnameinfo_done(q);                  break; -        case REQUEST_RES_QUERY: -        case REQUEST_RES_SEARCH: -                r = res_query_done(q); -                break; -          default:                  assert_not_reached("Cannot complete unknown query type");          } @@ -923,28 +841,6 @@ static int handle_response(sd_resolve *resolve, const Packet *packet, size_t len                  return complete_query(resolve, q);          } -        case RESPONSE_RES: { -                const ResResponse *res_resp = &packet->res_response; - -                assert(length >= sizeof(ResResponse)); -                assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH); - -                q->ret = res_resp->ret; -                q->_errno = res_resp->_errno; -                q->_h_errno = res_resp->_h_errno; - -                if (res_resp->ret >= 0)  { -                        q->answer = memdup((const char *)resp + sizeof(ResResponse), res_resp->ret); -                        if (!q->answer) { -                                q->ret = -1; -                                q->_errno = ENOMEM; -                                q->_h_errno = 0; -                        } -                } - -                return complete_query(resolve, q); -        } -          default:                  return 0;          } @@ -1181,79 +1077,6 @@ static int getnameinfo_done(sd_resolve_query *q) {          return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);  } -static int resolve_res( -                sd_resolve *resolve, -                sd_resolve_query **_q, -                QueryType qtype, -                const char *dname, -                int class, int type, -                sd_resolve_res_handler_t callback, void *userdata) { - -        struct msghdr mh = {}; -        struct iovec iov[2]; -        ResRequest req = {}; -        sd_resolve_query *q; -        int r; - -        assert_return(resolve, -EINVAL); -        assert_return(dname, -EINVAL); -        assert_return(callback, -EINVAL); -        assert_return(!resolve_pid_changed(resolve), -ECHILD); - -        r = alloc_query(resolve, !_q, &q); -        if (r < 0) -                return r; - -        q->type = qtype; -        q->res_handler = callback; -        q->userdata = userdata; - -        req.dname_len = strlen(dname) + 1; -        req.class = class; -        req.type = type; - -        req.header.id = q->id; -        req.header.type = qtype; -        req.header.length = sizeof(ResRequest) + req.dname_len; - -        iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(ResRequest) }; -        iov[1] = (struct iovec) { .iov_base = (void*) dname, .iov_len = req.dname_len }; - -        mh.msg_iov = iov; -        mh.msg_iovlen = 2; - -        if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) { -                sd_resolve_query_unref(q); -                return -errno; -        } - -        resolve->n_outstanding++; - -        if (_q) -                *_q = q; - -        return 0; -} - -_public_ int sd_resolve_res_query(sd_resolve *resolve, sd_resolve_query** q, const char *dname, int class, int type, sd_resolve_res_handler_t callback, void *userdata) { -        return resolve_res(resolve, q, REQUEST_RES_QUERY, dname, class, type, callback, userdata); -} - -_public_ int sd_resolve_res_search(sd_resolve *resolve, sd_resolve_query** q, const char *dname, int class, int type, sd_resolve_res_handler_t callback, void *userdata) { -        return resolve_res(resolve, q, REQUEST_RES_SEARCH, dname, class, type, callback, userdata); -} - -static int res_query_done(sd_resolve_query* q) { -        assert(q); -        assert(q->done); -        assert(q->res_handler); - -        errno = q->_errno; -        h_errno = q->_h_errno; - -        return q->res_handler(q, q->ret, q->answer, q->userdata); -} -  _public_ sd_resolve_query* sd_resolve_query_ref(sd_resolve_query *q) {          assert_return(q, NULL); @@ -1310,7 +1133,6 @@ static void resolve_query_free(sd_resolve_query *q) {          resolve_freeaddrinfo(q->addrinfo);          free(q->host);          free(q->serv); -        free(q->answer);          free(q);  } diff --git a/src/libsystemd/sd-resolve/test-resolve.c b/src/libsystemd/sd-resolve/test-resolve.c index 354a4071b7..e8056529f5 100644 --- a/src/libsystemd/sd-resolve/test-resolve.c +++ b/src/libsystemd/sd-resolve/test-resolve.c @@ -67,59 +67,8 @@ static int getnameinfo_handler(sd_resolve_query *q, int ret, const char *host, c          return 0;  } -static int res_handler(sd_resolve_query *q, int ret, unsigned char *answer, void *userdata) { -        int qdcount, ancount, len; -        const unsigned char *pos = answer + sizeof(HEADER); -        unsigned char *end = answer + ret; -        HEADER *head = (HEADER *) answer; -        char name[256]; -        assert_se(q); - -        if (ret < 0) { -                log_error("res_query() error: %s %i", strerror(errno), errno); -                return 0; -        } - -        if (ret == 0) { -                log_error("No reply for SRV lookup"); -                return 0; -        } - -        qdcount = ntohs(head->qdcount); -        ancount = ntohs(head->ancount); - -        printf("%d answers for srv lookup:\n", ancount); - -        /* Ignore the questions */ -        while (qdcount-- > 0 && (len = dn_expand(answer, end, pos, name, 255)) >= 0) { -                assert_se(len >= 0); -                pos += len + QFIXEDSZ; -        } - -        /* Parse the answers */ -        while (ancount-- > 0 && (len = dn_expand(answer, end, pos, name, 255)) >= 0) { -                /* Ignore the initial string */ -                uint16_t pref, weight, port; -                assert_se(len >= 0); -                pos += len; -                /* Ignore type, ttl, class and dlen */ -                pos += 10; - -                GETSHORT(pref, pos); -                GETSHORT(weight, pos); -                GETSHORT(port, pos); -                len = dn_expand(answer, end, pos, name, 255); -                printf("\tpreference: %2d weight: %2d port: %d host: %s\n", -                       pref, weight, port, name); - -                pos += len; -        } - -        return 0; -} -  int main(int argc, char *argv[]) { -        _cleanup_resolve_query_unref_ sd_resolve_query *q1 = NULL, *q2 = NULL, *q3 = NULL; +        _cleanup_resolve_query_unref_ sd_resolve_query *q1 = NULL, *q2 = NULL;          _cleanup_resolve_unref_ sd_resolve *resolve = NULL;          int r = 0; @@ -150,15 +99,9 @@ int main(int argc, char *argv[]) {          if (r < 0)                  log_error_errno(r, "sd_resolve_getnameinfo(): %m"); -        /* Make a res_query() call */ -        r = sd_resolve_res_query(resolve, &q3, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV, res_handler, NULL); -        if (r < 0) -                log_error_errno(r, "sd_resolve_res_query(): %m"); - -        /* Wait until the three queries are completed */ +        /* Wait until the two queries are completed */          while (sd_resolve_query_is_done(q1) == 0 || -               sd_resolve_query_is_done(q2) == 0 || -               sd_resolve_query_is_done(q3) == 0) { +               sd_resolve_query_is_done(q2) == 0) {                  r = sd_resolve_wait(resolve, (uint64_t) -1);                  if (r < 0) { diff --git a/src/network/networkctl.c b/src/network/networkctl.c index c9b53dc3f6..2281d4b718 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -497,7 +497,7 @@ static int link_status_one(                  sd_hwdb *hwdb,                  const char *name) {          _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL; -        _cleanup_free_ char *setup_state = NULL, *operational_state = NULL; +        _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *timezone = NULL;          _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;          _cleanup_device_unref_ sd_device *d = NULL;          char devid[2 + DECIMAL_STR_MAX(int)]; @@ -570,7 +570,6 @@ static int link_status_one(          setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);          sd_network_link_get_dns(ifindex, &dns); -        sd_network_link_get_ntp(ifindex, &ntp);          sd_network_link_get_domains(ifindex, &domains);          r = sd_network_link_get_wildcard_domain(ifindex);          if (r > 0) { @@ -652,6 +651,8 @@ static int link_status_one(                  dump_list("             DNS: ", dns);          if (!strv_isempty(domains))                  dump_list("          Domain: ", domains); + +        (void) sd_network_link_get_ntp(ifindex, &ntp);          if (!strv_isempty(ntp))                  dump_list("             NTP: ", ntp); @@ -661,6 +662,10 @@ static int link_status_one(          if (!strv_isempty(carrier_bound_by))                  dump_list("Carrier Bound By: ", carrier_bound_by); +        (void) sd_network_link_get_timezone(ifindex, &timezone); +        if (timezone) +                printf("       Time Zone: %s", timezone); +          return 0;  } diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index 584a956a7e..d609daafde 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -19,9 +19,8 @@    along with systemd; If not, see <http://www.gnu.org/licenses/>.  ***/ -  #include "networkd.h" -#include "networkd-link.h" +#include "networkd-address-pool.h"  int address_pool_new(                  Manager *m, diff --git a/src/network/networkd-address-pool.h b/src/network/networkd-address-pool.h new file mode 100644 index 0000000000..e6207ccce6 --- /dev/null +++ b/src/network/networkd-address-pool.h @@ -0,0 +1,43 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** +  This file is part of systemd. + +  Copyright 2014 Lennart Poettering + +  systemd is free software; you can redistribute it and/or modify it +  under the terms of the GNU Lesser General Public License as published by +  the Free Software Foundation; either version 2.1 of the License, or +  (at your option) any later version. + +  systemd is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public License +  along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +typedef struct AddressPool AddressPool; + +#include "networkd.h" + +struct AddressPool { +        Manager *manager; + +        int family; +        unsigned prefixlen; + +        union in_addr_union in_addr; + +        LIST_FIELDS(AddressPool, address_pools); +}; + +int address_pool_new(Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen); +int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen); +void address_pool_free(AddressPool *p); + +int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 172ca43a7d..b0d296941e 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -25,8 +25,10 @@  #include "util.h"  #include "conf-parser.h"  #include "firewall-util.h" +#include "netlink-util.h" +  #include "networkd.h" -#include "networkd-link.h" +#include "networkd-address.h"  static void address_init(Address *address) {          assert(address); diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h new file mode 100644 index 0000000000..39789a2382 --- /dev/null +++ b/src/network/networkd-address.h @@ -0,0 +1,73 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** +  This file is part of systemd. + +  Copyright 2013 Tom Gundersen <teg@jklm.no> + +  systemd is free software; you can redistribute it and/or modify it +  under the terms of the GNU Lesser General Public License as published by +  the Free Software Foundation; either version 2.1 of the License, or +  (at your option) any later version. + +  systemd is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public License +  along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <inttypes.h> +#include <stdbool.h> + +#include "in-addr-util.h" + +typedef struct Address Address; + +#include "networkd.h" +#include "networkd-network.h" +#include "networkd-link.h" + +#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU + +struct Address { +        Network *network; +        unsigned section; + +        int family; +        unsigned char prefixlen; +        unsigned char scope; +        uint32_t flags; +        char *label; + +        struct in_addr broadcast; +        struct ifa_cacheinfo cinfo; + +        union in_addr_union in_addr; +        union in_addr_union in_addr_peer; + +        bool ip_masquerade_done; + +        LIST_FIELDS(Address, addresses); +}; + +int address_new_static(Network *network, unsigned section, Address **ret); +int address_new_dynamic(Address **ret); +void address_free(Address *address); +int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback); +int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback); +int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback); +int address_establish(Address *address, Link *link); +int address_release(Address *address, Link *link); +bool address_equal(Address *a1, Address *a2); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free); +#define _cleanup_address_free_ _cleanup_(address_freep) + +int config_parse_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_broadcast(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 1b2ff7c769..36601367bf 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -39,8 +39,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,          r = sd_netlink_message_get_errno(m);          if (r < 0 && r != -EEXIST) { -                log_link_error(link, "could not set DHCPv4 route: %s", -                               strerror(-r)); +                log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");                  link_enter_failed(link);          } @@ -61,40 +60,25 @@ static int link_set_dhcp_routes(Link *link) {          assert(link->dhcp_lease);          r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); -        if (r < 0 && r != -ENOENT) { -                log_link_warning(link, -                                 "DHCP error: could not get gateway: %s", -                                 strerror(-r)); -                return r; -        } +        if (r < 0 && r != -ENOENT) +                return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); +          if (r >= 0) {                  struct in_addr address;                  _cleanup_route_free_ Route *route = NULL;                  _cleanup_route_free_ Route *route_gw = NULL;                  r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); -                if (r < 0) { -                        log_link_warning(link, -                                         "DHCP error: could not get address: %s", -                                         strerror(-r)); -                        return r; -                } +                if (r < 0) +                        return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");                  r = route_new_dynamic(&route, RTPROT_DHCP); -                if (r < 0) { -                        log_link_error(link, -                                       "Could not allocate route: %s", -                                       strerror(-r)); -                        return r; -                } +                if (r < 0) +                        return log_link_error_errno(link, r, "Could not allocate route: %m");                  r = route_new_dynamic(&route_gw, RTPROT_DHCP); -                if (r < 0) { -                log_link_error(link, -                               "Could not allocate route: %s", -                               strerror(-r)); -                               return r; -                } +                if (r < 0) +                        return log_link_error_errno(link, r,  "Could not allocate route: %m");                  /* The dhcp netmask may mask out the gateway. Add an explicit                   * route for the gw host so that we can route no matter the @@ -107,12 +91,8 @@ static int link_set_dhcp_routes(Link *link) {                  route_gw->metrics = link->network->dhcp_route_metric;                  r = route_configure(route_gw, link, &dhcp4_route_handler); -                if (r < 0) { -                        log_link_warning(link, -                                         "could not set host route: %s", -                                         strerror(-r)); -                        return r; -                } +                if (r < 0) +                        return log_link_warning_errno(link, r, "Could not set host route: %m");                  link->dhcp4_messages ++; @@ -123,9 +103,7 @@ static int link_set_dhcp_routes(Link *link) {                  r = route_configure(route, link, &dhcp4_route_handler);                  if (r < 0) { -                        log_link_warning(link, -                                         "could not set routes: %s", -                                         strerror(-r)); +                        log_link_warning_errno(link, r, "Could not set routes: %m");                          link_enter_failed(link);                          return r;                  } @@ -136,23 +114,15 @@ static int link_set_dhcp_routes(Link *link) {          n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);          if (n == -ENOENT)                  return 0; -        if (n < 0) { -                log_link_warning(link, -                                 "DHCP error: could not get routes: %s", -                                 strerror(-n)); - -                return n; -        } +        if (n < 0) +                return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m");          for (i = 0; i < n; i++) {                  _cleanup_route_free_ Route *route = NULL;                  r = route_new_dynamic(&route, RTPROT_DHCP); -                if (r < 0) { -                        log_link_error(link, "Could not allocate route: %s", -                                       strerror(-r)); -                        return r; -                } +                if (r < 0) +                        return log_link_error_errno(link, r, "Could not allocate route: %m");                  route->family = AF_INET;                  route->in_addr.in = static_routes[i].gw_addr; @@ -161,12 +131,8 @@ static int link_set_dhcp_routes(Link *link) {                  route->metrics = link->network->dhcp_route_metric;                  r = route_configure(route, link, &dhcp4_route_handler); -                if (r < 0) { -                        log_link_warning(link, -                                         "could not set host route: %s", -                                         strerror(-r)); -                        return r; -                } +                if (r < 0) +                        return log_link_warning_errno(link, r, "Could not set host route: %m");                  link->dhcp4_messages ++;          } @@ -270,18 +236,16 @@ static int dhcp_lease_lost(Link *link) {          if (link->network->dhcp_hostname) {                  const char *hostname = NULL; -                if (!link->network->hostname) -                        r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname); -                else +                if (link->network->hostname)                          hostname = link->network->hostname; +                else +                        (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname); -                if (r >= 0 || hostname) { -                        r = link_set_hostname(link, hostname); +                if (hostname) { +                        /* If a hostname was set due to the lease, then unset it now. */ +                        r = link_set_hostname(link, NULL);                          if (r < 0) -                                log_link_error_errno(link, r, -                                                     "Failed to set transient hostname to '%s': %m", -                                                     hostname); - +                                log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");                  }          } @@ -300,8 +264,7 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,          r = sd_netlink_message_get_errno(m);          if (r < 0 && r != -EEXIST) { -                log_link_error(link, "could not set DHCPv4 address: %s", -                               strerror(-r)); +                log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");                  link_enter_failed(link);          } else if (r >= 0)                  link_rtnl_process_address(rtnl, m, link->manager); @@ -357,45 +320,30 @@ static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {          assert(link->network);          r = sd_dhcp_client_get_lease(client, &lease); -        if (r < 0) { -                log_link_warning(link, "DHCP error: no lease %s", -                                 strerror(-r)); -                return r; -        } +        if (r < 0) +                return log_link_warning_errno(link, r, "DHCP error: no lease: %m");          sd_dhcp_lease_unref(link->dhcp_lease);          link->dhcp4_configured = false;          link->dhcp_lease = sd_dhcp_lease_ref(lease);          r = sd_dhcp_lease_get_address(lease, &address); -        if (r < 0) { -                log_link_warning(link, "DHCP error: no address: %s", -                                 strerror(-r)); -                return r; -        } +        if (r < 0) +                return log_link_warning_errno(link, r, "DHCP error: no address: %m");          r = sd_dhcp_lease_get_netmask(lease, &netmask); -        if (r < 0) { -                log_link_warning(link, "DHCP error: no netmask: %s", -                                 strerror(-r)); -                return r; -        } +        if (r < 0) +                return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");          if (!link->network->dhcp_critical) { -                r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, -                                               &lifetime); -                if (r < 0) { -                        log_link_warning(link, -                                         "DHCP error: no lifetime: %s", -                                         strerror(-r)); -                        return r; -                } +                r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); +                if (r < 0) +                        return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");          }          r = dhcp4_update_address(link, &address, &netmask, lifetime);          if (r < 0) { -                log_link_warning(link, "could not update IP address: %s", -                                 strerror(-r)); +                log_link_warning_errno(link, r, "Could not update IP address: %m");                  link_enter_failed(link);                  return r;          } @@ -417,21 +365,21 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {          r = sd_dhcp_client_get_lease(client, &lease);          if (r < 0) -                return log_link_error_errno(link, r, "DHCP error: no lease: %m"); +                return log_link_error_errno(link, r, "DHCP error: No lease: %m");          r = sd_dhcp_lease_get_address(lease, &address);          if (r < 0) -                return log_link_error_errno(link, r, "DHCP error: no address: %m"); +                return log_link_error_errno(link, r, "DHCP error: No address: %m");          r = sd_dhcp_lease_get_netmask(lease, &netmask);          if (r < 0) -                return log_link_error_errno(link, r, "DHCP error: no netmask: %m"); +                return log_link_error_errno(link, r, "DHCP error: No netmask: %m");          prefixlen = in_addr_netmask_to_prefixlen(&netmask);          r = sd_dhcp_lease_get_router(lease, &gateway);          if (r < 0 && r != -ENOENT) -                return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m"); +                return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");          if (r >= 0)                  log_struct(LOG_INFO, @@ -470,18 +418,30 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {          if (link->network->dhcp_hostname) {                  const char *hostname = NULL; -                if (!link->network->hostname) -                        r = sd_dhcp_lease_get_hostname(lease, &hostname); -                else +                if (link->network->hostname)                          hostname = link->network->hostname; +                else +                        (void) sd_dhcp_lease_get_hostname(lease, &hostname); -                if (r >= 0 || hostname) { +                if (hostname) {                          r = link_set_hostname(link, hostname);                          if (r < 0)                                  log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);                  }          } +        if (link->network->dhcp_timezone) { +                const char *tz = NULL; + +                (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); + +                if (tz) { +                        r = link_set_timezone(link, tz); +                        if (r < 0) +                                log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz); +                } +        } +          if (!link->network->dhcp_critical) {                  r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);                  if (r < 0) { @@ -515,8 +475,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {                  case DHCP_EVENT_STOP:                  case DHCP_EVENT_IP_CHANGE:                          if (link->network->dhcp_critical) { -                                log_link_error(link, -                                               "DHCPv4 connection considered system critical, ignoring request to reconfigure it."); +                                log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");                                  return;                          } @@ -553,13 +512,9 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {                          break;                  default:                          if (event < 0) -                                log_link_warning(link, -                                                 "DHCP error: client failed: %s", -                                                 strerror(-event)); +                                log_link_warning_errno(link, event, "DHCP error: Client failed: %m");                          else -                                log_link_warning(link, -                                                 "DHCP unknown event: %d", -                                                 event); +                                log_link_warning(link, "DHCP unknown event: %i", event);                          break;          } @@ -607,10 +562,10 @@ int dhcp4_configure(Link *link) {          }          if (link->network->dhcp_mtu) { -             r = sd_dhcp_client_set_request_option(link->dhcp_client, -                                                   DHCP_OPTION_INTERFACE_MTU); -             if (r < 0) -                return r; +                r = sd_dhcp_client_set_request_option(link->dhcp_client, +                                                      DHCP_OPTION_INTERFACE_MTU); +                if (r < 0) +                        return r;          }          if (link->network->dhcp_routes) { @@ -624,6 +579,15 @@ int dhcp4_configure(Link *link) {                          return r;          } +        /* Always acquire the timezone and NTP*/ +        r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NTP_SERVER); +        if (r < 0) +                return r; + +        r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NEW_TZDB_TIMEZONE); +        if (r < 0) +                return r; +          if (link->network->dhcp_sendhost) {                  _cleanup_free_ char *hostname = NULL;                  const char *hn = NULL; diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 0f2510e904..22efadb843 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -22,10 +22,12 @@  #include <net/if.h>  #include <net/ethernet.h> -#include "networkd.h" -#include "networkd-link.h"  #include "conf-parser.h"  #include "util.h" +#include "netlink-util.h" + +#include "networkd.h" +#include "networkd-fdb.h"  /* create a new FDB entry or get an existing one. */  int fdb_entry_new_static(Network *const network, diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h new file mode 100644 index 0000000000..f0efb902d0 --- /dev/null +++ b/src/network/networkd-fdb.h @@ -0,0 +1,47 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** +  This file is part of systemd. + +  Copyright (C) 2014 Intel Corporation. All rights reserved. + +  systemd is free software; you can redistribute it and/or modify it +  under the terms of the GNU Lesser General Public License as published by +  the Free Software Foundation; either version 2.1 of the License, or +  (at your option) any later version. + +  systemd is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public License +  along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +typedef struct FdbEntry FdbEntry; + +#include "networkd.h" +#include "networkd-network.h" + +struct FdbEntry { +        Network *network; +        unsigned section; + +        struct ether_addr *mac_addr; +        uint16_t vlan_id; + +        LIST_FIELDS(FdbEntry, static_fdb_entries); +}; + +int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret); +void fdb_entry_free(FdbEntry *fdb_entry); +int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry); + +DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free); +#define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep) + +int config_parse_fdb_hwaddr(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_fdb_vlan_id(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index cc9dc393c6..ff693ed0fd 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -29,7 +29,10 @@  #include "socket-util.h"  #include "bus-util.h"  #include "udev-util.h" +#include "netlink-util.h" +#include "dhcp-lease-internal.h"  #include "network-internal.h" +  #include "networkd-link.h"  #include "networkd-netdev.h" @@ -613,6 +616,96 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda          return 1;  } +static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { +        _cleanup_free_ struct in_addr *addresses = NULL; +        size_t n_addresses = 0, n_allocated = 0; +        char **a; + +        log_debug("Copying DNS server information from %s", link->ifname); + +        if (!link->network) +                return 0; + +        STRV_FOREACH(a, link->network->dns) { +                struct in_addr ia; + +                /* Only look for IPv4 addresses */ +                if (inet_pton(AF_INET, *a, &ia) <= 0) +                        continue; + +                if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) +                        return log_oom(); + +                addresses[n_addresses++] = ia; +        } + +        if (link->network->dhcp_dns && +            link->dhcp_lease) { +                const struct in_addr *da = NULL; +                int n; + +                n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da); +                if (n > 0) { + +                        if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) +                                return log_oom(); + +                        memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr)); +                        n_addresses += n; +                } +        } + +        if (n_addresses <= 0) +                return 0; + +        return sd_dhcp_server_set_dns(s, addresses, n_addresses); +} + +static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { +        _cleanup_free_ struct in_addr *addresses = NULL; +        size_t n_addresses = 0, n_allocated = 0; +        char **a; + +        if (!link->network) +                return 0; + +        log_debug("Copying NTP server information from %s", link->ifname); + +        STRV_FOREACH(a, link->network->ntp) { +                struct in_addr ia; + +                /* Only look for IPv4 addresses */ +                if (inet_pton(AF_INET, *a, &ia) <= 0) +                        continue; + +                if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) +                        return log_oom(); + +                addresses[n_addresses++] = ia; +        } + +        if (link->network->dhcp_ntp && +            link->dhcp_lease) { +                const struct in_addr *da = NULL; +                int n; + +                n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da); +                if (n > 0) { + +                        if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) +                                return log_oom(); + +                        memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr)); +                        n_addresses += n; +                } +        } + +        if (n_addresses <= 0) +                return 0; + +        return sd_dhcp_server_set_ntp(s, addresses, n_addresses); +} +  static int link_enter_set_addresses(Link *link) {          Address *ad;          int r; @@ -639,6 +732,8 @@ static int link_enter_set_addresses(Link *link) {          if (link_dhcp4_server_enabled(link)) {                  struct in_addr pool_start;                  Address *address; +                Link *uplink = NULL; +                bool acquired_uplink = false;                  address = link_find_dhcp_server_address(link);                  if (!address) { @@ -672,6 +767,81 @@ static int link_enter_set_addresses(Link *link) {                          return r;                  */ +                if (link->network->dhcp_server_max_lease_time_usec > 0) { +                        r = sd_dhcp_server_set_max_lease_time( +                                        link->dhcp_server, +                                        DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC)); +                        if (r < 0) +                                return r; +                } + +                if (link->network->dhcp_server_default_lease_time_usec > 0) { +                        r = sd_dhcp_server_set_default_lease_time( +                                        link->dhcp_server, +                                        DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC)); +                        if (r < 0) +                                return r; +                } + +                if (link->network->dhcp_server_emit_dns) { + +                        if (link->network->n_dhcp_server_dns > 0) +                                r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns); +                        else { +                                uplink = manager_find_uplink(link->manager, link); +                                acquired_uplink = true; + +                                if (!uplink) { +                                        log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink."); +                                        r = 0; +                                } else +                                        r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server); +                        } +                        if (r < 0) +                                log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m"); +                } + + +                if (link->network->dhcp_server_emit_ntp) { + +                        if (link->network->n_dhcp_server_ntp > 0) +                                r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp); +                        else { +                                if (!acquired_uplink) +                                        uplink = manager_find_uplink(link->manager, link); + +                                if (!uplink) { +                                        log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink."); +                                        r = 0; +                                } else +                                        r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server); + +                        } +                        if (r < 0) +                                log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m"); +                } + +                if (link->network->dhcp_server_emit_timezone) { +                        _cleanup_free_ char *buffer = NULL; +                        const char *tz; + +                        if (link->network->dhcp_server_timezone) +                                tz = link->network->dhcp_server_timezone; +                        else { +                                r = get_timezone(&buffer); +                                if (r < 0) +                                        log_warning_errno(r, "Failed to determine timezone: %m"); +                                else +                                        tz = buffer; +                        } + +                        if (tz) { +                                r = sd_dhcp_server_set_timezone(link->dhcp_server, tz); +                                if (r < 0) +                                        return r; +                        } +                } +                  r = sd_dhcp_server_start(link->dhcp_server);                  if (r < 0) {                          log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m"); @@ -743,7 +913,7 @@ static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userd  static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {          _cleanup_link_unref_ Link *link = userdata; -        int r; +        const sd_bus_error *e;          assert(m);          assert(link); @@ -751,21 +921,20 @@ static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error          if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))                  return 1; -        r = sd_bus_message_get_errno(m); -        if (r > 0) -                log_link_warning_errno(link, r, "Could not set hostname: %m"); +        e = sd_bus_message_get_error(m); +        if (e) +                log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);          return 1;  }  int link_set_hostname(Link *link, const char *hostname) { -        int r = 0; +        int r;          assert(link);          assert(link->manager); -        assert(hostname); -        log_link_debug(link, "Setting transient hostname: '%s'", hostname); +        log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));          if (!link->manager->bus) {                  /* TODO: replace by assert when we can rely on kdbus */ @@ -794,6 +963,57 @@ int link_set_hostname(Link *link, const char *hostname) {          return 0;  } +static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { +        _cleanup_link_unref_ Link *link = userdata; +        const sd_bus_error *e; + +        assert(m); +        assert(link); + +        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) +                return 1; + +        e = sd_bus_message_get_error(m); +        if (e) +                log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message); + +        return 1; +} + +int link_set_timezone(Link *link, const char *timezone) { +        int r; + +        assert(link); +        assert(link->manager); +        assert(timezone); + +        log_link_debug(link, "Setting system timezone: '%s'", timezone); + +        if (!link->manager->bus) { +                log_link_info(link, "Not connected to system bus, ignoring timezone."); +                return 0; +        } + +        r = sd_bus_call_method_async( +                        link->manager->bus, +                        NULL, +                        "org.freedesktop.timedate1", +                        "/org/freedesktop/timedate1", +                        "org.freedesktop.timedate1", +                        "SetTimezone", +                        set_timezone_handler, +                        link, +                        "sb", +                        timezone, +                        false); +        if (r < 0) +                return log_link_error_errno(link, r, "Could not set timezone: %m"); + +        link_ref(link); + +        return 0; +} +  static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {          _cleanup_link_unref_ Link *link = userdata;          int r; @@ -2414,9 +2634,17 @@ int link_save(Link *link) {          }          if (link->dhcp_lease) { +                const char *tz = NULL; + +                r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); +                if (r >= 0) +                        fprintf(f, "TIMEZONE=%s\n", tz); +        } + +        if (link->dhcp_lease) {                  assert(link->network); -                r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file); +                r = dhcp_lease_save(link->dhcp_lease, link->lease_file);                  if (r < 0)                          goto fail; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 2dcbbda607..f588faf209 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -1,5 +1,7 @@  /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ +#pragma once +  /***    This file is part of systemd. @@ -19,11 +21,16 @@    along with systemd; If not, see <http://www.gnu.org/licenses/>.  ***/ -#pragma once -  #include <endian.h> -#include "networkd.h" +#include "sd-dhcp-client.h" +#include "sd-dhcp-server.h" +#include "sd-ipv4ll.h" +#include "sd-icmp6-nd.h" +#include "sd-dhcp6-client.h" +#include "sd-lldp.h" + +typedef struct Link Link;  typedef enum LinkState {          LINK_STATE_PENDING, @@ -38,6 +45,21 @@ typedef enum LinkState {          _LINK_STATE_INVALID = -1  } LinkState; +typedef enum LinkOperationalState { +        LINK_OPERSTATE_OFF, +        LINK_OPERSTATE_NO_CARRIER, +        LINK_OPERSTATE_DORMANT, +        LINK_OPERSTATE_CARRIER, +        LINK_OPERSTATE_DEGRADED, +        LINK_OPERSTATE_ROUTABLE, +        _LINK_OPERSTATE_MAX, +        _LINK_OPERSTATE_INVALID = -1 +} LinkOperationalState; + +#include "networkd.h" +#include "networkd-network.h" +#include "networkd-address.h" +  struct Link {          Manager *manager; @@ -115,6 +137,7 @@ bool link_has_carrier(Link *link);  int link_set_mtu(Link *link, uint32_t mtu);  int link_set_hostname(Link *link, const char *hostname); +int link_set_timezone(Link *link, const char *timezone);  int ipv4ll_configure(Link *link);  int dhcp4_configure(Link *link); @@ -130,6 +153,9 @@ bool link_dhcp6_enabled(Link *link);  const char* link_state_to_string(LinkState s) _const_;  LinkState link_state_from_string(const char *s) _pure_; +const char* link_operstate_to_string(LinkOperationalState s) _const_; +LinkOperationalState link_operstate_from_string(const char *s) _pure_; +  extern const sd_bus_vtable link_vtable[];  int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 09a929e0da..16f732f244 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -22,20 +22,21 @@  #include <sys/socket.h>  #include <linux/if.h> +#include "sd-netlink.h" +#include "sd-daemon.h" +  #include "conf-parser.h"  #include "path-util.h" -#include "networkd.h" -#include "networkd-netdev.h" -#include "networkd-link.h"  #include "libudev-private.h"  #include "udev-util.h"  #include "netlink-util.h"  #include "bus-util.h"  #include "def.h"  #include "virt.h" +#include "set.h" +#include "local-addresses.h" -#include "sd-netlink.h" -#include "sd-daemon.h" +#include "networkd.h"  /* use 8 MB for receive socket kernel queue. */  #define RCVBUF_SIZE    (8*1024*1024) @@ -99,7 +100,7 @@ static int manager_reset_all(Manager *m) {          HASHMAP_FOREACH(link, m->links, i) {                  r = link_carrier_reset(link);                  if (r < 0) -                        log_link_warning_errno(link, r, "could not reset carrier: %m"); +                        log_link_warning_errno(link, r, "Could not reset carrier: %m");          }          return 0; @@ -204,7 +205,7 @@ static int manager_udev_process_link(Manager *m, struct udev_device *device) {          ifindex = udev_device_get_ifindex(device);          if (ifindex <= 0) { -                log_debug("ignoring udev ADD event for device with invalid ifindex"); +                log_debug("Ignoring udev ADD event for device with invalid ifindex");                  return 0;          } @@ -291,23 +292,23 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa          if (sd_netlink_message_is_error(message)) {                  r = sd_netlink_message_get_errno(message);                  if (r < 0) -                        log_warning_errno(r, "rtnl: could not receive link: %m"); +                        log_warning_errno(r, "rtnl: Could not receive link: %m");                  return 0;          }          r = sd_netlink_message_get_type(message, &type);          if (r < 0) { -                log_warning_errno(r, "rtnl: could not get message type: %m"); +                log_warning_errno(r, "rtnl: Could not get message type: %m");                  return 0;          } else if (type != RTM_NEWLINK && type != RTM_DELLINK) { -                log_warning("rtnl: received unexpected message type when processing link"); +                log_warning("rtnl: Received unexpected message type when processing link");                  return 0;          }          r = sd_rtnl_message_link_get_ifindex(message, &ifindex);          if (r < 0) { -                log_warning_errno(r, "rtnl: could not get ifindex from link: %m"); +                log_warning_errno(r, "rtnl: Could not get ifindex from link: %m");                  return 0;          } else if (ifindex <= 0) {                  log_warning("rtnl: received link message with invalid ifindex: %d", ifindex); @@ -317,7 +318,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa          r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);          if (r < 0) { -                log_warning_errno(r, "rtnl: received link message without ifname: %m"); +                log_warning_errno(r, "rtnl: Received link message without ifname: %m");                  return 0;          } else                  netdev_get(m, name, &netdev); @@ -328,7 +329,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa                          /* link is new, so add it */                          r = link_add(m, message, &link);                          if (r < 0) { -                                log_warning_errno(r, "could not add new link: %m"); +                                log_warning_errno(r, "Could not add new link: %m");                                  return 0;                          }                  } @@ -337,7 +338,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa                          /* netdev exists, so make sure the ifindex matches */                          r = netdev_set_ifindex(netdev, message);                          if (r < 0) { -                                log_warning_errno(r, "could not set ifindex on netdev: %m"); +                                log_warning_errno(r, "Could not set ifindex on netdev: %m");                                  return 0;                          }                  } @@ -476,13 +477,13 @@ void manager_free(Manager *m) {          free(m->state_file); +        sd_event_source_unref(m->udev_event_source);          udev_monitor_unref(m->udev_monitor);          udev_unref(m->udev); +          sd_bus_unref(m->bus);          sd_bus_slot_unref(m->prepare_for_sleep_slot); -        sd_event_source_unref(m->udev_event_source);          sd_event_source_unref(m->bus_retry_event_source); -        sd_event_unref(m->event);          while ((link = hashmap_first(m->links)))                  link_unref(link); @@ -501,6 +502,7 @@ void manager_free(Manager *m) {                  address_pool_free(pool);          sd_netlink_unref(m->rtnl); +        sd_event_unref(m->event);          free(m);  } @@ -846,36 +848,39 @@ int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, uni          return 0;  } -const char *address_family_boolean_to_string(AddressFamilyBoolean b) { -        if (b == ADDRESS_FAMILY_YES || -            b == ADDRESS_FAMILY_NO) -                return yes_no(b == ADDRESS_FAMILY_YES); +Link* manager_find_uplink(Manager *m, Link *exclude) { +        _cleanup_free_ struct local_address *gateways = NULL; +        int n, i; -        if (b == ADDRESS_FAMILY_IPV4) -                return "ipv4"; -        if (b == ADDRESS_FAMILY_IPV6) -                return "ipv6"; +        assert(m); -        return NULL; -} +        /* Looks for a suitable "uplink", via black magic: an +         * interface that is up and where the default route with the +         * highest priority points to. */ -AddressFamilyBoolean address_family_boolean_from_string(const char *s) { -        int r; +        n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways); +        if (n < 0) { +                log_warning_errno(n, "Failed to determine list of default gateways: %m"); +                return NULL; +        } + +        for (i = 0; i < n; i++) { +                Link *link; + +                link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex)); +                if (!link) { +                        log_debug("Weird, found a gateway for a link we don't know. Ignoring."); +                        continue; +                } -        /* Make this a true superset of a boolean */ +                if (link == exclude) +                        continue; -        r = parse_boolean(s); -        if (r > 0) -                return ADDRESS_FAMILY_YES; -        if (r == 0) -                return ADDRESS_FAMILY_NO; +                if (link->operstate < LINK_OPERSTATE_ROUTABLE) +                        continue; -        if (streq(s, "ipv4")) -                return ADDRESS_FAMILY_IPV4; -        if (streq(s, "ipv6")) -                return ADDRESS_FAMILY_IPV6; +                return link; +        } -        return _ADDRESS_FAMILY_BOOLEAN_INVALID; +        return NULL;  } - -DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option"); diff --git a/src/network/networkd-netdev-bond.h b/src/network/networkd-netdev-bond.h index 9991fa731f..0cdce1605e 100644 --- a/src/network/networkd-netdev-bond.h +++ b/src/network/networkd-netdev-bond.h @@ -1,5 +1,7 @@  /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ +#pragma once +  /***    This file is part of systemd. @@ -19,7 +21,7 @@    along with systemd; If not, see <http://www.gnu.org/licenses/>.  ***/ -#pragma once +#include "in-addr-util.h"  typedef struct Bond Bond; diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index cd31387b41..ff1edf2c39 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -21,15 +21,18 @@  #include <net/if.h> -#include "networkd-netdev.h" -#include "networkd-link.h" -#include "network-internal.h"  #include "conf-files.h"  #include "conf-parser.h"  #include "list.h"  #include "siphash24.h" +#include "netlink-util.h" +#include "network-internal.h" + +#include "networkd.h" +#include "networkd-netdev.h"  const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { +          [NETDEV_KIND_BRIDGE] = &bridge_vtable,          [NETDEV_KIND_BOND] = &bond_vtable,          [NETDEV_KIND_VLAN] = &vlan_vtable, diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h index 19fb5bb185..1f8510c4f7 100644 --- a/src/network/networkd-netdev.h +++ b/src/network/networkd-netdev.h @@ -21,11 +21,14 @@  #pragma once -#include "networkd.h"  #include "list.h" +typedef struct NetDev NetDev;  typedef struct NetDevVTable NetDevVTable; +#include "networkd.h" +#include "networkd-link.h" +  typedef struct netdev_join_callback netdev_join_callback;  struct netdev_join_callback { diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 7ac7ef1ea3..108e892fb8 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -73,6 +73,15 @@ DHCP.RequestBroadcast,         config_parse_bool,                              0  DHCP.CriticalConnection,       config_parse_bool,                              0,                             offsetof(Network, dhcp_critical)  DHCP.VendorClassIdentifier,    config_parse_string,                            0,                             offsetof(Network, dhcp_vendor_class_identifier)  DHCP.RouteMetric,              config_parse_unsigned,                          0,                             offsetof(Network, dhcp_route_metric) +DHCP.UseTimezone,              config_parse_bool,                              0,                             offsetof(Network, dhcp_timezone) +DHCPServer.MaxLeaseTimeSec,    config_parse_sec,                               0,                             offsetof(Network, dhcp_server_max_lease_time_usec) +DHCPServer.DefaultLeaseTimeSec,config_parse_sec,                               0,                             offsetof(Network, dhcp_server_default_lease_time_usec) +DHCPServer.EmitDNS,            config_parse_bool,                              0,                             offsetof(Network, dhcp_server_emit_dns) +DHCPServer.DNS,                config_parse_dhcp_server_dns,                   0,                             0 +DHCPServer.EmitNTP,            config_parse_bool,                              0,                             offsetof(Network, dhcp_server_emit_ntp) +DHCPServer.NTP,                config_parse_dhcp_server_ntp,                   0,                             0 +DHCPServer.EmitTimezone,       config_parse_bool,                              0,                             offsetof(Network, dhcp_server_emit_timezone) +DHCPServer.Timezone,           config_parse_timezone,                          0,                             offsetof(Network, dhcp_server_timezone)  Bridge.Cost,                   config_parse_unsigned,                          0,                             offsetof(Network, cost)  Bridge.UseBPDU,                config_parse_bool,                              0,                             offsetof(Network, use_bpdu)  Bridge.HairPin,                config_parse_bool,                              0,                             offsetof(Network, hairpin) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 6587ea994c..2a77242013 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -26,11 +26,11 @@  #include "conf-parser.h"  #include "util.h"  #include "hostname-util.h" -#include "networkd.h" -#include "networkd-netdev.h" -#include "networkd-link.h" -#include "network-internal.h"  #include "dns-domain.h" +#include "network-internal.h" + +#include "networkd.h" +#include "networkd-network.h"  static int network_load_one(Manager *manager, const char *filename) {          _cleanup_network_free_ Network *network = NULL; @@ -107,6 +107,10 @@ static int network_load_one(Manager *manager, const char *filename) {          network->dhcp_route_metric = DHCP_ROUTE_METRIC;          network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID; +        network->dhcp_server_emit_dns = true; +        network->dhcp_server_emit_ntp = true; +        network->dhcp_server_emit_timezone = true; +          network->use_bpdu = true;          network->allow_port_to_be_root = true;          network->unicast_flood = true; @@ -124,7 +128,8 @@ static int network_load_one(Manager *manager, const char *filename) {                           "Address\0"                           "Route\0"                           "DHCP\0" -                         "DHCPv4\0" +                         "DHCPv4\0" /* compat */ +                         "DHCPServer\0"                           "Bridge\0"                           "BridgeFDB\0",                           config_item_perf_lookup, network_network_gperf_lookup, @@ -258,6 +263,10 @@ void network_free(Network *network) {          condition_free_list(network->match_kernel);          condition_free_list(network->match_arch); +        free(network->dhcp_server_timezone); +        free(network->dhcp_server_dns); +        free(network->dhcp_server_ntp); +          free(network);  } @@ -632,57 +641,6 @@ static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {  DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DCHPClientIdentifier);  DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type"); -static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = { -        [RESOLVE_SUPPORT_NO] = "no", -        [RESOLVE_SUPPORT_YES] = "yes", -        [RESOLVE_SUPPORT_RESOLVE] = "resolve", -}; - -DEFINE_STRING_TABLE_LOOKUP(resolve_support, ResolveSupport); - -int config_parse_resolve( -                const char* unit, -                const char *filename, -                unsigned line, -                const char *section, -                unsigned section_line, -                const char *lvalue, -                int ltype, -                const char *rvalue, -                void *data, -                void *userdata) { - -        ResolveSupport *resolve = data; -        int k; - -        assert(filename); -        assert(lvalue); -        assert(rvalue); -        assert(resolve); - -        /* Our enum shall be a superset of booleans, hence first try -         * to parse as boolean, and then as enum */ - -        k = parse_boolean(rvalue); -        if (k > 0) -                *resolve = RESOLVE_SUPPORT_YES; -        else if (k == 0) -                *resolve = RESOLVE_SUPPORT_NO; -        else { -                ResolveSupport s; - -                s = resolve_support_from_string(rvalue); -                if (s < 0){ -                        log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse %s option, ignoring: %s", lvalue, rvalue); -                        return 0; -                } - -                *resolve = s; -        } - -        return 0; -} -  int config_parse_ipv6token(                  const char* unit,                  const char *filename, @@ -726,40 +684,6 @@ int config_parse_ipv6token(          return 0;  } -int config_parse_address_family_boolean_with_kernel( -                const char* unit, -                const char *filename, -                unsigned line, -                const char *section, -                unsigned section_line, -                const char *lvalue, -                int ltype, -                const char *rvalue, -                void *data, -                void *userdata) { - -        AddressFamilyBoolean *fwd = data, s; - -        assert(filename); -        assert(lvalue); -        assert(rvalue); -        assert(data); - -        s = address_family_boolean_from_string(rvalue); -        if (s < 0) { -                if (streq(rvalue, "kernel")) -                        s = _ADDRESS_FAMILY_BOOLEAN_INVALID; -                else { -                        log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPForwarding option, ignoring: %s", rvalue); -                        return 0; -                } -        } - -        *fwd = s; - -        return 0; -} -  static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {          [IPV6_PRIVACY_EXTENSIONS_NO] = "no",          [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", @@ -816,37 +740,165 @@ int config_parse_ipv6_privacy_extensions(          return 0;  } -int config_parse_hostname(const char *unit, -                          const char *filename, -                          unsigned line, -                          const char *section, -                          unsigned section_line, -                          const char *lvalue, -                          int ltype, -                          const char *rvalue, -                          void *data, -                          void *userdata) { -        char **hostname = data; -        char *hn = NULL; +int config_parse_hostname( +                const char *unit, +                const char *filename, +                unsigned line, +                const char *section, +                unsigned section_line, +                const char *lvalue, +                int ltype, +                const char *rvalue, +                void *data, +                void *userdata) { + +        char **hostname = data, *hn = NULL;          int r;          assert(filename);          assert(lvalue);          assert(rvalue); -        r = config_parse_string(unit, filename, line, section, section_line, -                                lvalue, ltype, rvalue, &hn, userdata); +        r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);          if (r < 0)                  return r; -        if (!hostname_is_valid(hn, true)) { -                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "hostname is not valid, ignoring assignment: %s", rvalue); - +        if (!hostname_is_valid(hn, false)) { +                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Hostname is not valid, ignoring assignment: %s", rvalue);                  free(hn);                  return 0;          } +        free(*hostname);          *hostname = hostname_cleanup(hn); +        return 0; +} + +int config_parse_timezone( +                const char *unit, +                const char *filename, +                unsigned line, +                const char *section, +                unsigned section_line, +                const char *lvalue, +                int ltype, +                const char *rvalue, +                void *data, +                void *userdata) { + +        char **timezone = data, *tz = NULL; +        int r; + +        assert(filename); +        assert(lvalue); +        assert(rvalue); + +        r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata); +        if (r < 0) +                return r; + +        if (!timezone_is_valid(tz)) { +                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Timezone is not valid, ignoring assignment: %s", rvalue); +                free(tz); +                return 0; +        } + +        free(*timezone); +        *timezone = tz;          return 0;  } + +int config_parse_dhcp_server_dns( +                const char *unit, +                const char *filename, +                unsigned line, +                const char *section, +                unsigned section_line, +                const char *lvalue, +                int ltype, +                const char *rvalue, +                void *data, +                void *userdata) { + +        Network *n = data; +        const char *p = rvalue; +        int r; + +        assert(filename); +        assert(lvalue); +        assert(rvalue); + +        for (;;) { +                _cleanup_free_ char *w = NULL; +                struct in_addr a, *m; + +                r = extract_first_word(&p, &w, NULL, 0); +                if (r < 0) { +                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue); +                        return 0; +                } + +                if (r == 0) +                        return 0; + +                if (inet_pton(AF_INET, w, &a) <= 0) { +                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server address, ignoring: %s", w); +                        continue; +                } + +                m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr)); +                if (!m) +                        return log_oom(); + +                m[n->n_dhcp_server_dns++] = a; +                n->dhcp_server_dns = m; +        } +} + +int config_parse_dhcp_server_ntp( +                const char *unit, +                const char *filename, +                unsigned line, +                const char *section, +                unsigned section_line, +                const char *lvalue, +                int ltype, +                const char *rvalue, +                void *data, +                void *userdata) { + +        Network *n = data; +        const char *p = rvalue; +        int r; + +        assert(filename); +        assert(lvalue); +        assert(rvalue); + +        for (;;) { +                _cleanup_free_ char *w = NULL; +                struct in_addr a, *m; + +                r = extract_first_word(&p, &w, NULL, 0); +                if (r < 0) { +                        log_syntax(unit, LOG_ERR, filename, r, line, "Failed to extract word, ignoring: %s", rvalue); +                        return 0; +                } + +                if (r == 0) +                        return 0; + +                if (inet_pton(AF_INET, w, &a) <= 0) { +                        log_syntax(unit, LOG_ERR, filename, r, line, "Failed to parse NTP server address, ignoring: %s", w); +                        continue; +                } + +                m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr)); +                if (!m) +                        return log_oom(); + +                m[n->n_dhcp_server_ntp++] = a; +                n->dhcp_server_ntp = m; +        } +} diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h new file mode 100644 index 0000000000..d691cc3a45 --- /dev/null +++ b/src/network/networkd-network.h @@ -0,0 +1,179 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** +  This file is part of systemd. + +  Copyright 2013 Tom Gundersen <teg@jklm.no> + +  systemd is free software; you can redistribute it and/or modify it +  under the terms of the GNU Lesser General Public License as published by +  the Free Software Foundation; either version 2.1 of the License, or +  (at your option) any later version. + +  systemd is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public License +  along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "condition.h" + +typedef struct Network Network; + +#include "networkd.h" +#include "networkd-netdev.h" +#include "networkd-address.h" +#include "networkd-route.h" +#include "networkd-fdb.h" +#include "networkd-util.h" + +#define DHCP_ROUTE_METRIC 1024 +#define IPV4LL_ROUTE_METRIC 2048 + +typedef enum DCHPClientIdentifier { +        DHCP_CLIENT_ID_MAC, +        DHCP_CLIENT_ID_DUID, +        _DHCP_CLIENT_ID_MAX, +        _DHCP_CLIENT_ID_INVALID = -1, +} DCHPClientIdentifier; + +typedef enum IPv6PrivacyExtensions { +        /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ +        IPV6_PRIVACY_EXTENSIONS_NO, +        IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, +        IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ +        _IPV6_PRIVACY_EXTENSIONS_MAX, +        _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, +} IPv6PrivacyExtensions; + +struct Network { +        Manager *manager; + +        char *filename; +        char *name; + +        struct ether_addr *match_mac; +        char **match_path; +        char **match_driver; +        char **match_type; +        char **match_name; + +        Condition *match_host; +        Condition *match_virt; +        Condition *match_kernel; +        Condition *match_arch; + +        char *description; + +        NetDev *bridge; +        NetDev *bond; +        Hashmap *stacked_netdevs; + +        /* DHCP Client Support */ +        AddressFamilyBoolean dhcp; +        DCHPClientIdentifier dhcp_client_identifier; +        char *dhcp_vendor_class_identifier; +        char *hostname; +        bool dhcp_dns; +        bool dhcp_ntp; +        bool dhcp_mtu; +        bool dhcp_hostname; +        bool dhcp_domains; +        bool dhcp_sendhost; +        bool dhcp_broadcast; +        bool dhcp_critical; +        bool dhcp_routes; +        bool dhcp_timezone; +        unsigned dhcp_route_metric; + +        /* DHCP Server Support */ +        bool dhcp_server; +        bool dhcp_server_emit_dns; +        struct in_addr *dhcp_server_dns; +        unsigned n_dhcp_server_dns; +        bool dhcp_server_emit_ntp; +        struct in_addr *dhcp_server_ntp; +        unsigned n_dhcp_server_ntp; +        bool dhcp_server_emit_timezone; +        char *dhcp_server_timezone; +        usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec; + +        /* IPV4LL Support */ +        AddressFamilyBoolean link_local; +        bool ipv4ll_route; + +        /* Bridge Support */ +        bool use_bpdu; +        bool hairpin; +        bool fast_leave; +        bool allow_port_to_be_root; +        bool unicast_flood; +        unsigned cost; + +        AddressFamilyBoolean ip_forward; +        bool ip_masquerade; + +        union in_addr_union ipv6_token; +        IPv6PrivacyExtensions ipv6_privacy_extensions; + +        struct ether_addr *mac; +        unsigned mtu; + +        bool lldp; + +        LIST_HEAD(Address, static_addresses); +        LIST_HEAD(Route, static_routes); +        LIST_HEAD(FdbEntry, static_fdb_entries); + +        Hashmap *addresses_by_section; +        Hashmap *routes_by_section; +        Hashmap *fdb_entries_by_section; + +        bool wildcard_domain; +        char **domains, **dns, **ntp, **bind_carrier; + +        ResolveSupport llmnr; + +        LIST_FIELDS(Network, networks); +}; + +void network_free(Network *network); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free); +#define _cleanup_network_free_ _cleanup_(network_freep) + +int network_load(Manager *manager); + +int network_get_by_name(Manager *manager, const char *name, Network **ret); +int network_get(Manager *manager, struct udev_device *device, const char *ifname, const struct ether_addr *mac, Network **ret); +int network_apply(Manager *manager, Network *network, Link *link); + +int config_parse_netdev(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_tunnel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_dhcp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_dhcp_client_identifier(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_ipv6token(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_ipv6_privacy_extensions(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_timezone(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_dhcp_server_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); + +/* Legacy IPv4LL support */ +int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); + +const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length); + +extern const sd_bus_vtable network_vtable[]; + +int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); + +const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; +IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 31b10c458d..fbaad40579 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -19,12 +19,12 @@    along with systemd; If not, see <http://www.gnu.org/licenses/>.  ***/ - -#include "networkd.h" -#include "networkd-link.h" -  #include "util.h"  #include "conf-parser.h" +#include "netlink-util.h" + +#include "networkd.h" +#include "networkd-route.h"  int route_new_static(Network *network, unsigned section, Route **ret) {          _cleanup_route_free_ Route *route = NULL; diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h new file mode 100644 index 0000000000..d090b9c91e --- /dev/null +++ b/src/network/networkd-route.h @@ -0,0 +1,60 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** +  This file is part of systemd. + +  Copyright 2013 Tom Gundersen <teg@jklm.no> + +  systemd is free software; you can redistribute it and/or modify it +  under the terms of the GNU Lesser General Public License as published by +  the Free Software Foundation; either version 2.1 of the License, or +  (at your option) any later version. + +  systemd is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public License +  along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +typedef struct Route Route; + +#include "networkd.h" +#include "networkd-network.h" + +struct Route { +        Network *network; +        unsigned section; + +        int family; +        unsigned char dst_prefixlen; +        unsigned char src_prefixlen; +        unsigned char scope; +        uint32_t metrics; +        unsigned char protocol;  /* RTPROT_* */ + +        union in_addr_union in_addr; +        union in_addr_union dst_addr; +        union in_addr_union src_addr; +        union in_addr_union prefsrc_addr; + +        LIST_FIELDS(Route, routes); +}; + +int route_new_static(Network *network, unsigned section, Route **ret); +int route_new_dynamic(Route **ret, unsigned char rtm_protocol); +void route_free(Route *route); +int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback); +int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free); +#define _cleanup_route_free_ _cleanup_(route_freep) + +int config_parse_gateway(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_destination(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_route_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_route_scope(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c new file mode 100644 index 0000000000..a41cd86239 --- /dev/null +++ b/src/network/networkd-util.c @@ -0,0 +1,144 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** +  This file is part of systemd. + +  Copyright 2013 Tom Gundersen <teg@jklm.no> + +  systemd is free software; you can redistribute it and/or modify it +  under the terms of the GNU Lesser General Public License as published by +  the Free Software Foundation; either version 2.1 of the License, or +  (at your option) any later version. + +  systemd is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public License +  along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "util.h" +#include "conf-parser.h" + +#include "networkd-util.h" + +const char *address_family_boolean_to_string(AddressFamilyBoolean b) { +        if (b == ADDRESS_FAMILY_YES || +            b == ADDRESS_FAMILY_NO) +                return yes_no(b == ADDRESS_FAMILY_YES); + +        if (b == ADDRESS_FAMILY_IPV4) +                return "ipv4"; +        if (b == ADDRESS_FAMILY_IPV6) +                return "ipv6"; + +        return NULL; +} + +AddressFamilyBoolean address_family_boolean_from_string(const char *s) { +        int r; + +        /* Make this a true superset of a boolean */ + +        r = parse_boolean(s); +        if (r > 0) +                return ADDRESS_FAMILY_YES; +        if (r == 0) +                return ADDRESS_FAMILY_NO; + +        if (streq(s, "ipv4")) +                return ADDRESS_FAMILY_IPV4; +        if (streq(s, "ipv6")) +                return ADDRESS_FAMILY_IPV6; + +        return _ADDRESS_FAMILY_BOOLEAN_INVALID; +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option"); + +int config_parse_address_family_boolean_with_kernel( +                const char* unit, +                const char *filename, +                unsigned line, +                const char *section, +                unsigned section_line, +                const char *lvalue, +                int ltype, +                const char *rvalue, +                void *data, +                void *userdata) { + +        AddressFamilyBoolean *fwd = data, s; + +        assert(filename); +        assert(lvalue); +        assert(rvalue); +        assert(data); + +        s = address_family_boolean_from_string(rvalue); +        if (s < 0) { +                if (streq(rvalue, "kernel")) +                        s = _ADDRESS_FAMILY_BOOLEAN_INVALID; +                else { +                        log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPForwarding= option, ignoring: %s", rvalue); +                        return 0; +                } +        } + +        *fwd = s; + +        return 0; +} + +static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = { +        [RESOLVE_SUPPORT_NO] = "no", +        [RESOLVE_SUPPORT_YES] = "yes", +        [RESOLVE_SUPPORT_RESOLVE] = "resolve", +}; + +DEFINE_STRING_TABLE_LOOKUP(resolve_support, ResolveSupport); + +int config_parse_resolve( +                const char* unit, +                const char *filename, +                unsigned line, +                const char *section, +                unsigned section_line, +                const char *lvalue, +                int ltype, +                const char *rvalue, +                void *data, +                void *userdata) { + +        ResolveSupport *resolve = data; +        int k; + +        assert(filename); +        assert(lvalue); +        assert(rvalue); +        assert(resolve); + +        /* Our enum shall be a superset of booleans, hence first try +         * to parse as boolean, and then as enum */ + +        k = parse_boolean(rvalue); +        if (k > 0) +                *resolve = RESOLVE_SUPPORT_YES; +        else if (k == 0) +                *resolve = RESOLVE_SUPPORT_NO; +        else { +                ResolveSupport s; + +                s = resolve_support_from_string(rvalue); +                if (s < 0){ +                        log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse %s= option, ignoring: %s", lvalue, rvalue); +                        return 0; +                } + +                *resolve = s; +        } + +        return 0; +} diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h new file mode 100644 index 0000000000..cc41aae85a --- /dev/null +++ b/src/network/networkd-util.h @@ -0,0 +1,52 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** +  This file is part of systemd. + +  Copyright 2013 Tom Gundersen <teg@jklm.no> + +  systemd is free software; you can redistribute it and/or modify it +  under the terms of the GNU Lesser General Public License as published by +  the Free Software Foundation; either version 2.1 of the License, or +  (at your option) any later version. + +  systemd is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public License +  along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "macro.h" + +typedef enum AddressFamilyBoolean { +        /* This is a bitmask, though it usually doesn't feel that way! */ +        ADDRESS_FAMILY_NO = 0, +        ADDRESS_FAMILY_IPV4 = 1, +        ADDRESS_FAMILY_IPV6 = 2, +        ADDRESS_FAMILY_YES = 3, +        _ADDRESS_FAMILY_BOOLEAN_MAX, +        _ADDRESS_FAMILY_BOOLEAN_INVALID = -1, +} AddressFamilyBoolean; + +typedef enum ResolveSupport { +        RESOLVE_SUPPORT_NO, +        RESOLVE_SUPPORT_YES, +        RESOLVE_SUPPORT_RESOLVE, +        _RESOLVE_SUPPORT_MAX, +        _RESOLVE_SUPPORT_INVALID = -1, +} ResolveSupport; + +int config_parse_resolve(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_address_family_boolean_with_kernel(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); + +const char* resolve_support_to_string(ResolveSupport i) _const_; +ResolveSupport resolve_support_from_string(const char *s) _pure_; + +const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_; +AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_; diff --git a/src/network/networkd.h b/src/network/networkd.h index 5340922bf1..eea57ac158 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -26,213 +26,17 @@  #include "sd-event.h"  #include "sd-netlink.h"  #include "sd-bus.h" -#include "sd-dhcp-client.h" -#include "sd-dhcp-server.h" -#include "sd-ipv4ll.h" -#include "sd-icmp6-nd.h" -#include "sd-dhcp6-client.h"  #include "udev.h" -#include "sd-lldp.h" -#include "netlink-util.h"  #include "hashmap.h"  #include "list.h" -#include "set.h" -#include "condition.h" -#include "in-addr-util.h" -#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU -#define DHCP_ROUTE_METRIC 1024 -#define IPV4LL_ROUTE_METRIC 2048 - -typedef struct NetDev NetDev; -typedef struct Network Network; -typedef struct Link Link; -typedef struct Address Address; -typedef struct Route Route;  typedef struct Manager Manager; -typedef struct AddressPool AddressPool; -typedef struct FdbEntry FdbEntry; - -typedef enum AddressFamilyBoolean { -        /* This is a bitmask, though it usually doesn't feel that way! */ -        ADDRESS_FAMILY_NO = 0, -        ADDRESS_FAMILY_IPV4 = 1, -        ADDRESS_FAMILY_IPV6 = 2, -        ADDRESS_FAMILY_YES = 3, -        _ADDRESS_FAMILY_BOOLEAN_MAX, -        _ADDRESS_FAMILY_BOOLEAN_INVALID = -1, -} AddressFamilyBoolean; - -typedef enum ResolveSupport { -        RESOLVE_SUPPORT_NO, -        RESOLVE_SUPPORT_YES, -        RESOLVE_SUPPORT_RESOLVE, -        _RESOLVE_SUPPORT_MAX, -        _RESOLVE_SUPPORT_INVALID = -1, -} ResolveSupport; - -typedef enum LinkOperationalState { -        LINK_OPERSTATE_OFF, -        LINK_OPERSTATE_NO_CARRIER, -        LINK_OPERSTATE_DORMANT, -        LINK_OPERSTATE_CARRIER, -        LINK_OPERSTATE_DEGRADED, -        LINK_OPERSTATE_ROUTABLE, -        _LINK_OPERSTATE_MAX, -        _LINK_OPERSTATE_INVALID = -1 -} LinkOperationalState; - -typedef enum DCHPClientIdentifier { -        DHCP_CLIENT_ID_MAC, -        DHCP_CLIENT_ID_DUID, -        _DHCP_CLIENT_ID_MAX, -        _DHCP_CLIENT_ID_INVALID = -1, -} DCHPClientIdentifier; - -typedef enum IPv6PrivacyExtensions { -        /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ -        IPV6_PRIVACY_EXTENSIONS_NO, -        IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, -        IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ -        _IPV6_PRIVACY_EXTENSIONS_MAX, -        _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, -} IPv6PrivacyExtensions; - -struct FdbEntry { -        Network *network; -        unsigned section; - -        struct ether_addr *mac_addr; -        uint16_t vlan_id; - -        LIST_FIELDS(FdbEntry, static_fdb_entries); -}; - -struct Network { -        Manager *manager; - -        char *filename; -        char *name; - -        struct ether_addr *match_mac; -        char **match_path; -        char **match_driver; -        char **match_type; -        char **match_name; - -        Condition *match_host; -        Condition *match_virt; -        Condition *match_kernel; -        Condition *match_arch; - -        char *description; -        NetDev *bridge; -        NetDev *bond; -        Hashmap *stacked_netdevs; -        AddressFamilyBoolean dhcp; -        DCHPClientIdentifier dhcp_client_identifier; -        char *dhcp_vendor_class_identifier; -        char *hostname; -        bool dhcp_dns; -        bool dhcp_ntp; -        bool dhcp_mtu; -        bool dhcp_hostname; -        bool dhcp_domains; -        bool dhcp_sendhost; -        bool dhcp_broadcast; -        bool dhcp_critical; -        bool dhcp_routes; -        unsigned dhcp_route_metric; -        AddressFamilyBoolean link_local; -        bool ipv4ll_route; -        union in_addr_union ipv6_token; - -        bool dhcp_server; - -        bool use_bpdu; -        bool hairpin; -        bool fast_leave; -        bool allow_port_to_be_root; -        bool unicast_flood; -        unsigned cost; - -        AddressFamilyBoolean ip_forward; -        bool ip_masquerade; - -        IPv6PrivacyExtensions ipv6_privacy_extensions; - -        struct ether_addr *mac; -        unsigned mtu; - -        bool lldp; - -        LIST_HEAD(Address, static_addresses); -        LIST_HEAD(Route, static_routes); -        LIST_HEAD(FdbEntry, static_fdb_entries); - -        Hashmap *addresses_by_section; -        Hashmap *routes_by_section; -        Hashmap *fdb_entries_by_section; -        bool wildcard_domain; -        char **domains, **dns, **ntp, **bind_carrier; - -        ResolveSupport llmnr; - -        LIST_FIELDS(Network, networks); -}; - -struct Address { -        Network *network; -        unsigned section; - -        int family; -        unsigned char prefixlen; -        unsigned char scope; -        uint32_t flags; -        char *label; - -        struct in_addr broadcast; -        struct ifa_cacheinfo cinfo; - -        union in_addr_union in_addr; -        union in_addr_union in_addr_peer; - -        bool ip_masquerade_done; - -        LIST_FIELDS(Address, addresses); -}; - -struct Route { -        Network *network; -        unsigned section; - -        int family; -        unsigned char dst_prefixlen; -        unsigned char src_prefixlen; -        unsigned char scope; -        uint32_t metrics; -        unsigned char protocol;  /* RTPROT_* */ - -        union in_addr_union in_addr; -        union in_addr_union dst_addr; -        union in_addr_union src_addr; -        union in_addr_union prefsrc_addr; - -        LIST_FIELDS(Route, routes); -}; - -struct AddressPool { -        Manager *manager; - -        int family; -        unsigned prefixlen; - -        union in_addr_union in_addr; - -        LIST_FIELDS(AddressPool, address_pools); -}; +#include "networkd-network.h" +#include "networkd-address-pool.h" +#include "networkd-link.h" +#include "networkd-util.h"  struct Manager {          sd_netlink *rtnl; @@ -281,183 +85,7 @@ int manager_save(Manager *m);  int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); +Link* manager_find_uplink(Manager *m, Link *exclude); +  DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);  #define _cleanup_manager_free_ _cleanup_(manager_freep) - -/* Network */ - -int network_load(Manager *manager); - -void network_free(Network *network); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free); -#define _cleanup_network_free_ _cleanup_(network_freep) - -int network_get_by_name(Manager *manager, const char *name, Network **ret); -int network_get(Manager *manager, struct udev_device *device, -                const char *ifname, const struct ether_addr *mac, -                Network **ret); -int network_apply(Manager *manager, Network *network, Link *link); - -int config_parse_netdev(const char *unit, const char *filename, unsigned line, -                        const char *section, unsigned section_line, const char *lvalue, -                        int ltype, const char *rvalue, void *data, void *userdata); - -int config_parse_domains(const char *unit, -                         const char *filename, -                         unsigned line, -                         const char *section, -                         unsigned section_line, -                         const char *lvalue, -                         int ltype, -                         const char *rvalue, -                         void *data, -                         void *userdata); - -int config_parse_tunnel(const char *unit, -                        const char *filename, -                        unsigned line, -                        const char *section, -                        unsigned section_line, -                        const char *lvalue, -                        int ltype, -                        const char *rvalue, -                        void *data, -                        void *userdata); - -extern const sd_bus_vtable network_vtable[]; - -int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); -int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); - -/* gperf */ -const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length); - -/* Route */ -int route_new_static(Network *network, unsigned section, Route **ret); -int route_new_dynamic(Route **ret, unsigned char rtm_protocol); -void route_free(Route *route); -int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback); -int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback); - - -DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free); -#define _cleanup_route_free_ _cleanup_(route_freep) - -int config_parse_gateway(const char *unit, const char *filename, unsigned line, -                         const char *section, unsigned section_line, const char *lvalue, -                         int ltype, const char *rvalue, void *data, void *userdata); - -int config_parse_destination(const char *unit, const char *filename, unsigned line, -                             const char *section, unsigned section_line, const char *lvalue, -                             int ltype, const char *rvalue, void *data, void *userdata); - -int config_parse_route_priority(const char *unit, const char *filename, unsigned line, -                                const char *section, unsigned section_line, const char *lvalue, -                                int ltype, const char *rvalue, void *data, void *userdata); - -int config_parse_route_scope(const char *unit, const char *filename, unsigned line, -                             const char *section, unsigned section_line, const char *lvalue, -                             int ltype, const char *rvalue, void *data, void *userdata); -/* Address */ -int address_new_static(Network *network, unsigned section, Address **ret); -int address_new_dynamic(Address **ret); -void address_free(Address *address); -int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback); -int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback); -int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback); -int address_establish(Address *address, Link *link); -int address_release(Address *address, Link *link); -bool address_equal(Address *a1, Address *a2); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free); -#define _cleanup_address_free_ _cleanup_(address_freep) - -int config_parse_address(const char *unit, const char *filename, unsigned line, -                         const char *section, unsigned section_line, const char *lvalue, -                         int ltype, const char *rvalue, void *data, void *userdata); - -int config_parse_broadcast(const char *unit, const char *filename, unsigned line, -                           const char *section, unsigned section_line, const char *lvalue, -                           int ltype, const char *rvalue, void *data, void *userdata); - -int config_parse_label(const char *unit, const char *filename, unsigned line, -                       const char *section, unsigned section_line, const char *lvalue, -                       int ltype, const char *rvalue, void *data, void *userdata); - -/* Forwarding database table. */ -int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry); -void fdb_entry_free(FdbEntry *fdb_entry); -int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret); - -DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free); -#define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep) - -int config_parse_fdb_hwaddr(const char *unit, const char *filename, unsigned line, -                            const char *section, unsigned section_line, const char *lvalue, -                            int ltype, const char *rvalue, void *data, void *userdata); - -int config_parse_fdb_vlan_id(const char *unit, const char *filename, unsigned line, -                             const char *section, unsigned section_line, const char *lvalue, -                             int ltype, const char *rvalue, void *data, void *userdata); - -/* DHCP support */ - -int config_parse_dhcp(const char *unit, const char *filename, unsigned line, -                      const char *section, unsigned section_line, const char *lvalue, -                      int ltype, const char *rvalue, void *data, void *userdata); -int config_parse_dhcp_client_identifier(const char *unit, const char *filename, unsigned line, -                                        const char *section, unsigned section_line, const char *lvalue, -                                        int ltype, const char *rvalue, void *data, void *userdata); - -/* IPv4LL support (legacy) */ - -int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, -                        const char *section, unsigned section_line, const char *lvalue, -                        int ltype, const char *rvalue, void *data, void *userdata); - -/* IPv6 support */ -int config_parse_ipv6token(const char *unit, const char *filename, unsigned line, -                           const char *section, unsigned section_line, const char *lvalue, -                           int ltype, const char *rvalue, void *data, void *userdata); - -/* Resolve protocols support */ - -const char* resolve_support_to_string(ResolveSupport i) _const_; -ResolveSupport resolve_support_from_string(const char *s) _pure_; - -int config_parse_resolve(const char *unit, const char *filename, unsigned line, -                         const char *section, unsigned section_line, const char *lvalue, -                         int ltype, const char *rvalue, void *data, void *userdata); - -/* Address Pool */ - -int address_pool_new(Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen); -int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen); -void address_pool_free(AddressPool *p); - -int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found); - -const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_; -AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_; - -int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); - -/* IPForwarding parser */ -int config_parse_address_family_boolean_with_kernel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); - -/* Operational State */ - -const char* link_operstate_to_string(LinkOperationalState s) _const_; -LinkOperationalState link_operstate_from_string(const char *s) _pure_; - -/* IPv6 privacy extensions support */ - -const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; -IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; - -int config_parse_ipv6_privacy_extensions(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); - - -/* Hostname */ -int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h index 5afa50a9d0..ed5bceecdd 100644 --- a/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/sd-dhcp-lease.h @@ -34,6 +34,9 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease);  int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr);  int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime); +int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1); +int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2); +int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr);  int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr);  int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr);  int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); @@ -44,13 +47,9 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);  int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);  int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname);  int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path); -int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routesgn); -int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data, -                                      size_t *data_len); -int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id, -                                size_t *client_id_len); - -int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); -int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file); +int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes); +int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len); +int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len); +int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);  #endif diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index 9af3b6532d..7e4f2ffb30 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -30,11 +30,11 @@  typedef struct sd_dhcp_server sd_dhcp_server; +int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex); +  sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server);  sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server); -int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex); -  int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int priority);  int sd_dhcp_server_detach_event(sd_dhcp_server *client);  sd_event *sd_dhcp_server_get_event(sd_dhcp_server *client); @@ -47,5 +47,13 @@ int sd_dhcp_server_stop(sd_dhcp_server *server);  int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen);  int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server, struct in_addr *start, size_t size); +int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone); +int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n); +int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr dns[], unsigned n); + +int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t); +int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t); +  int sd_dhcp_server_forcerenew(sd_dhcp_server *server); +  #endif diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index 4d96c867d9..4179015fbf 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -122,6 +122,9 @@ int sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers);  /* Get the CARRIERS that are bound to current link. */  int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers); +/* Get the timezone that was learnt on a specific link. */ +int sd_network_link_get_timezone(int ifindex, char **timezone); +  /* Returns whether or not domains that don't match any link should be resolved   * on this link. 1 for yes, 0 for no and negative value for error */  int sd_network_link_get_wildcard_domain(int ifindex); diff --git a/src/systemd/sd-resolve.h b/src/systemd/sd-resolve.h index 36cedcd6b5..80c5852e45 100644 --- a/src/systemd/sd-resolve.h +++ b/src/systemd/sd-resolve.h @@ -40,7 +40,6 @@ typedef struct sd_resolve_query sd_resolve_query;  /* A callback on completion */  typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata);  typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata); -typedef int (*sd_resolve_res_handler_t)(sd_resolve_query* q, int ret, unsigned char *answer, void *userdata);  enum {          SD_RESOLVE_GET_HOST = 1ULL, @@ -99,18 +98,6 @@ int sd_resolve_getaddrinfo(sd_resolve *resolve, sd_resolve_query **q, const char   * if you want to query the hostname (resp. the service name). */  int sd_resolve_getnameinfo(sd_resolve *resolve, sd_resolve_query **q, const struct sockaddr *sa, socklen_t salen, int flags, uint64_t get, sd_resolve_getnameinfo_handler_t callback, void *userdata); -/* Issue a resolver query on the specified session. The arguments are - * compatible with those of libc's res_query(3). The function returns a new - * query object. When the query is completed, you may retrieve the results using - * sd_resolve_res_done(). */ -int sd_resolve_res_query(sd_resolve *resolve, sd_resolve_query **q, const char *dname, int clazz, int type, sd_resolve_res_handler_t callback, void *userdata); - -/* Issue a resolver query on the specified session. The arguments are - * compatible with those of libc's res_search(3). The function returns a new - * query object. When the query is completed, you may retrieve the results using - * sd_resolve_res_done(). */ -int sd_resolve_res_search(sd_resolve *resolve, sd_resolve_query **q, const char *dname, int clazz, int type, sd_resolve_res_handler_t callback, void *userdata); -  sd_resolve_query *sd_resolve_query_ref(sd_resolve_query* q);  sd_resolve_query *sd_resolve_query_unref(sd_resolve_query* q); diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 21d6ee4c0c..42ae70fd1d 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -68,32 +68,15 @@ static int context_read_data(Context *c) {          assert(c); -        r = readlink_malloc("/etc/localtime", &t); -        if (r < 0) { -                if (r == -EINVAL) -                        log_warning("/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."); -                else -                        log_warning_errno(r, "Failed to get target of /etc/localtime: %m"); -        } else { -                const char *e; +        r = get_timezone(&t); +        if (r == -EINVAL) +                log_warning_errno(r, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."); +        else if (r < 0) +                log_warning_errno(r, "Failed to get target of /etc/localtime: %m"); -                e = path_startswith(t, "/usr/share/zoneinfo/"); -                if (!e) -                        e = path_startswith(t, "../usr/share/zoneinfo/"); - -                if (!e) -                        log_warning("/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."); -                else { -                        c->zone = strdup(e); -                        if (!c->zone) -                                return log_oom(); -                } -        } - -        if (isempty(c->zone)) { -                free(c->zone); -                c->zone = NULL; -        } +        free(c->zone); +        c->zone = t; +        t = NULL;          c->local_rtc = clock_is_localtime() > 0; | 
