[systemd-devel] [PATCH] sd-dhcp-client: support non-Ethernet hardware addresses

Tom Gundersen teg at jklm.no
Thu Oct 2 07:39:43 PDT 2014


On Fri, Sep 26, 2014 at 10:15 PM, Dan Williams <dcbw at redhat.com> wrote:
> Like Infiniband.  See RFC 4390 section 2.1 for details on DHCP
> and Infiniband; chaddr is zeroed, hlen is set to 0, and htype
> is set to ARPHRD_INFINIBAND because IB hardware addresses
> are 20 bytes in length.

Sorry for taking time with this. Overall looks good, just minor comments inline.

> ---
>  src/libsystemd-network/dhcp-internal.h    | 10 +++--
>  src/libsystemd-network/dhcp-network.c     | 54 ++++++++++++++++++++-----
>  src/libsystemd-network/dhcp-packet.c      |  8 ++--
>  src/libsystemd-network/sd-dhcp-client.c   | 66 +++++++++++++++++++++++--------
>  src/libsystemd-network/sd-dhcp-server.c   |  8 ++--
>  src/libsystemd-network/test-dhcp-client.c | 14 +++++--
>  src/libsystemd-network/test-dhcp-option.c |  2 +-
>  src/network/networkd-dhcp4.c              |  4 +-
>  src/network/networkd-link.c               |  4 +-
>  src/systemd/sd-dhcp-client.h              |  4 +-
>  10 files changed, 130 insertions(+), 44 deletions(-)
>
> *** Testing appreciated....
>
> diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
> index 1069c8a..d358a49 100644
> --- a/src/libsystemd-network/dhcp-internal.h
> +++ b/src/libsystemd-network/dhcp-internal.h
> @@ -20,22 +20,25 @@
>
>    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 <stdint.h>
>  #include <linux/if_packet.h>
> +#include <net/if_arp.h>
>  #include <net/ethernet.h>
>
>  #include "socket-util.h"
>
>  #include "sd-dhcp-client.h"
>  #include "dhcp-protocol.h"
>
> -int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t xid, struct ether_addr mac_addr);
> +int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
> +                                 uint32_t xid, const uint8_t *mac_addr,
> +                                 size_t mac_addr_len, uint16_t arp_type);
>  int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
>  int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
>                                   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);
>
>  int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload,
> @@ -43,16 +46,17 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_
>
>  typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len,
>                                  const uint8_t *option, void *user_data);
>
>  int dhcp_option_parse(DHCPMessage *message, size_t len,
>                        dhcp_option_cb_t cb, void *user_data);
>
> -int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type,
> -                      size_t optlen, size_t *optoffset);
> +int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
> +                      uint8_t type, uint16_t arp_type, size_t optlen,
> +                      size_t *optoffset);
>
>  uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len);
>
>  void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
>                                     uint16_t source, be32_t destination_addr,
>                                     uint16_t destination, uint16_t len);
>
> diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c
> index 1ced5cf..29e9993 100644
> --- a/src/libsystemd-network/dhcp-network.c
> +++ b/src/libsystemd-network/dhcp-network.c
> @@ -18,27 +18,31 @@
>  ***/
>
>  #include <errno.h>
>  #include <sys/types.h>
>  #include <sys/socket.h>
>  #include <string.h>
>  #include <linux/if_packet.h>
> +#include <linux/if_infiniband.h>
>  #include <net/ethernet.h>
>  #include <net/if_arp.h>
>  #include <stdio.h>
>  #include <unistd.h>
>  #include <linux/filter.h>
>
>  #include "socket-util.h"
>
>  #include "dhcp-internal.h"
>
> -int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
> -                                 uint32_t xid, struct ether_addr mac_addr) {
> -
> +static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
> +                            uint32_t xid, const uint8_t *mac_addr,
> +                            size_t mac_addr_len,
> +                            const uint8_t *bcast_addr,
> +                            const struct ether_addr *eth_mac,
> +                            uint16_t arp_type, uint8_t dhcp_hlen) {
>          struct sock_filter filter[] = {
>                  BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),                                 /* A <- packet length */
>                  BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0),         /* packet >= DHCPPacket ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
>                  BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.protocol)), /* A <- IP protocol */
>                  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0),                /* IP protocol == UDP ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
> @@ -53,29 +57,29 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
>                  BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, udp.dest)),    /* A <- UDP destination port */
>                  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_PORT_CLIENT, 1, 0),           /* UDP destination port == DHCP client port ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
>                  BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.op)),     /* A <- DHCP op */
>                  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0),                  /* op == BOOTREPLY ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
>                  BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.htype)),  /* A <- DHCP header type */
> -                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0),               /* header type == ARPHRD_ETHER ? */
> +                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arp_type, 1, 0),                   /* header type == arp_type ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
>                  BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.hlen)),   /* A <- mac address length */
> -                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHER_ADDR_LEN, 1, 0),             /* address length == ETHER_ADDR_LEN ? */
> +                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, dhcp_hlen, 1, 0),                  /* address length == dhcp_hlen ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
>                  BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.xid)),    /* A <- client identifier */
>                  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0),                        /* client identifier == xid ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */

Won't the following be all wrong in case hlen != ETHER_ADDR_LEN? I
mean we are here hard-coding it to compare 6 bytes... Or am I missing
something?

If there is no way to do this nicely using BPF we can just move the
mac addr check to userspace (as we are already doing for received UDP
packets).

Cheers,

Tom

> -                BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) &mac_addr))),                    /* A <- 4 bytes of client's MAC */
> +                BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) eth_mac))),                     /* A <- 4 bytes of client's MAC */
>                  BPF_STMT(BPF_MISC + BPF_TAX, 0),                                                       /* X <- A */
>                  BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)),                 /* A <- 4 bytes of MAC from dhcp.chaddr */
>                  BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),                                                /* A xor X */
>                  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),                                          /* A == 0 ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                                          /* ignore */
> -                BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) (((char *) &mac_addr) + 4)))), /* A <- remainder of client's MAC */
> +                BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) (((char *) eth_mac) + 4)))),   /* A <- remainder of client's MAC */
>                  BPF_STMT(BPF_MISC + BPF_TAX, 0),                                                       /* X <- A */
>                  BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4),             /* A <- remainder of MAC from dhcp.chaddr */
>                  BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),                                                /* A xor X */
>                  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),                                          /* A == 0 ? */
>                  BPF_STMT(BPF_RET + BPF_K, 0),                                                          /* ignore */
>                  BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)),  /* A <- DHCP magic cookie */
>                  BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0),          /* cookie == DHCP magic cookie ? */
> @@ -103,27 +107,59 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
>          r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
>          if (r < 0)
>                  return -errno;
>
>          link->ll.sll_family = AF_PACKET;
>          link->ll.sll_protocol = htons(ETH_P_IP);
>          link->ll.sll_ifindex = ifindex;
> -        link->ll.sll_halen = ETH_ALEN;
> -        memset(link->ll.sll_addr, 0xff, ETH_ALEN);
> +        link->ll.sll_hatype = htons(arp_type);
> +        link->ll.sll_halen = mac_addr_len;
> +        memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len);
>
>          r = bind(s, &link->sa, sizeof(link->ll));
>          if (r < 0)
>                  return -errno;
>
>          r = s;
>          s = -1;
>
>          return r;
>  }
>
> +int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
> +                                 uint32_t xid, const uint8_t *mac_addr,
> +                                 size_t mac_addr_len, uint16_t arp_type) {
> +        static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
> +        /* Default broadcast address for IPoIB */
> +        static const uint8_t ib_bcast[] = {
> +                0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b,
> +                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +                0xff, 0xff, 0xff, 0xff
> +          };
> +        struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } };
> +        const uint8_t *bcast_addr = NULL;
> +        uint8_t dhcp_hlen = 0;
> +
> +        assert_return(mac_addr_len > 0, -EINVAL);
> +
> +        if (arp_type == ARPHRD_ETHER) {
> +                assert_return(mac_addr_len == ETH_ALEN, -EINVAL);
> +                memcpy(&eth_mac, mac_addr, ETH_ALEN);
> +                bcast_addr = eth_bcast;
> +                dhcp_hlen = ETH_ALEN;
> +        } else if (arp_type == ARPHRD_INFINIBAND) {
> +                assert_return(mac_addr_len == INFINIBAND_ALEN, -EINVAL);
> +                bcast_addr = ib_bcast;
> +        } else
> +                return -EINVAL;
> +
> +        return _bind_raw_socket(ifindex, link, xid, mac_addr, mac_addr_len,
> +                                bcast_addr, &eth_mac, arp_type, dhcp_hlen);
> +}
> +
>  int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
>          union sockaddr_union src = {
>                  .in.sin_family = AF_INET,
>                  .in.sin_port = htobe16(port),
>                  .in.sin_addr.s_addr = address,
>          };
>          _cleanup_close_ int s = -1;
> diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
> index 9f850fd..7581dae 100644
> --- a/src/libsystemd-network/dhcp-packet.c
> +++ b/src/libsystemd-network/dhcp-packet.c
> @@ -34,23 +34,25 @@
>  #include "dhcp-internal.h"
>  #include "sd-dhcp-lease.h"
>  #include "sd-dhcp-client.h"
>
>  #define DHCP_CLIENT_MIN_OPTIONS_SIZE            312
>
>  int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
> -                      uint8_t type, size_t optlen, size_t *optoffset) {
> +                      uint8_t type, uint16_t arp_type, size_t optlen,
> +                      size_t *optoffset) {
>          size_t offset = 0;
>          int r;
>
>          assert(op == BOOTREQUEST || op == BOOTREPLY);
> +        assert(arp_type == ARPHRD_ETHER || arp_type == ARPHRD_INFINIBAND);
>
>          message->op = op;
> -        message->htype = ARPHRD_ETHER;
> -        message->hlen = ETHER_ADDR_LEN;
> +        message->htype = arp_type;
> +        message->hlen = (arp_type == ARPHRD_ETHER) ? ETHER_ADDR_LEN : 0;
>          message->xid = htobe32(xid);
>          message->magic = htobe32(DHCP_MAGIC_COOKIE);
>
>          r = dhcp_option_append(message, optlen, &offset, 0,
>                                 DHCP_OPTION_MESSAGE_TYPE, 1, &type);
>          if (r < 0)
>                  return r;
> diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
> index 2f94c16..ad04f98 100644
> --- a/src/libsystemd-network/sd-dhcp-client.c
> +++ b/src/libsystemd-network/sd-dhcp-client.c
> @@ -33,14 +33,16 @@
>  #include "async.h"
>
>  #include "dhcp-protocol.h"
>  #include "dhcp-internal.h"
>  #include "dhcp-lease-internal.h"
>  #include "sd-dhcp-client.h"
>
> +#define MAX_MAC_ADDR_LEN  20  /* INFINIBAND_ALEN */
> +
>  struct sd_dhcp_client {
>          RefCount n_ref;
>
>          DHCPState state;
>          sd_event *event;
>          int event_priority;
>          sd_event_source *timeout_resend;
> @@ -53,14 +55,17 @@ struct sd_dhcp_client {
>          size_t req_opts_allocated;
>          size_t req_opts_size;
>          be32_t last_addr;
>          struct {
>                  uint8_t type;
>                  struct ether_addr mac_addr;
>          } _packed_ client_id;
> +        uint8_t mac_addr[MAX_MAC_ADDR_LEN];
> +        size_t mac_addr_len;
> +        uint16_t arp_type;
>          char *hostname;
>          char *vendor_class_identifier;
>          uint32_t mtu;
>          uint32_t xid;
>          usec_t start_time;
>          uint16_t secs;
>          unsigned int attempt;
> @@ -159,32 +164,39 @@ int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
>          assert_return(interface_index > 0, -EINVAL);
>
>          client->index = interface_index;
>
>          return 0;
>  }
>
> -int sd_dhcp_client_set_mac(sd_dhcp_client *client,
> -                           const struct ether_addr *addr) {
> +int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
> +                           size_t addr_len, uint16_t arp_type) {
>          DHCP_CLIENT_DONT_DESTROY(client);
>          bool need_restart = false;
>
>          assert_return(client, -EINVAL);
>          assert_return(addr, -EINVAL);
> +        assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
> +        assert_return(arp_type > 0, -EINVAL);
>
> -        if (memcmp(&client->client_id.mac_addr, addr, ETH_ALEN) == 0)
> +        if (client->mac_addr_len == addr_len &&
> +            memcmp(&client->mac_addr, addr, addr_len) == 0)
>                  return 0;
>
>          if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
>                  log_dhcp_client(client, "Changing MAC address on running DHCP "
>                                  "client, restarting");
>                  need_restart = true;
>                  client_stop(client, DHCP_EVENT_STOP);
>          }
>
> +        memcpy(&client->mac_addr, addr, addr_len);
> +        client->mac_addr_len = addr_len;
> +        client->arp_type = arp_type;
> +
>          memcpy(&client->client_id.mac_addr, addr, ETH_ALEN);
>          client->client_id.type = 0x01;
>
>          if (need_restart && client->state != DHCP_STATE_STOPPED)
>                  sd_dhcp_client_start(client);
>
>          return 0;
> @@ -314,15 +326,15 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
>          size = sizeof(DHCPPacket) + optlen;
>
>          packet = malloc0(size);
>          if (!packet)
>                  return -ENOMEM;
>
>          r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
> -                              optlen, &optoffset);
> +                              client->arp_type, optlen, &optoffset);
>          if (r < 0)
>                  return r;
>
>          /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
>             refuse to issue an DHCP lease if 'secs' is set to zero */
>          packet->dhcp.secs = htobe16(client->secs);
>
> @@ -333,22 +345,25 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
>             DHCPREQUEST messages that client sends.  The BROADCAST bit will
>             provide a hint to the DHCP server and BOOTP relay agent to broadcast
>             any messages to the client on the client's subnet.
>
>             Note: some interfaces needs this to be enabled, but some networks
>             needs this to be disabled as broadcasts are filteretd, so this
>             needs to be configurable */
> -        if (client->request_broadcast)
> +        if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
>                  packet->dhcp.flags = htobe16(0x8000);
>
>          /* RFC2132 section 4.1.1:
>             The client MUST include its hardware address in the ’chaddr’ field, if
> -           necessary for delivery of DHCP reply messages.
> +           necessary for delivery of DHCP reply messages.  Non-Ethernet
> +           interfaces will leave 'chaddr' empty and use the client identifier
> +           instead (eg, RFC 4390 section 2.1).
>           */
> -        memcpy(&packet->dhcp.chaddr, &client->client_id.mac_addr, ETH_ALEN);
> +        if (client->mac_addr_len == ETH_ALEN)
> +                memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
>
>          /* Some DHCP servers will refuse to issue an DHCP lease if the Client
>             Identifier option is not set */
>          r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
>                                 DHCP_OPTION_CLIENT_IDENTIFIER,
>                                 sizeof(client->client_id), &client->client_id);
>          if (r < 0)
> @@ -839,15 +854,17 @@ static int client_start(sd_dhcp_client *client) {
>          assert_return(client->fd < 0, -EBUSY);
>          assert_return(client->xid == 0, -EINVAL);
>          assert_return(client->state == DHCP_STATE_INIT ||
>                        client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
>
>          client->xid = random_u32();
>
> -        r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
> +        r = dhcp_network_bind_raw_socket(client->index, &client->link,
> +                                         client->xid, client->mac_addr,
> +                                         client->mac_addr_len, client->arp_type);
>          if (r < 0) {
>                  client_stop(client, r);
>                  return r;
>          }
>          client->fd = r;
>
>          if (client->state == DHCP_STATE_INIT) {
> @@ -883,15 +900,17 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
>
>          client->receive_message = sd_event_source_unref(client->receive_message);
>          client->fd = asynchronous_close(client->fd);
>
>          client->state = DHCP_STATE_REBINDING;
>          client->attempt = 1;
>
> -        r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
> +        r = dhcp_network_bind_raw_socket(client->index, &client->link,
> +                                         client->xid, client->mac_addr,
> +                                         client->mac_addr_len, client->arp_type);
>          if (r < 0) {
>                  client_stop(client, r);
>                  return 0;
>          }
>          client->fd = r;
>
>          return client_initialize_events(client, client_receive_message_raw);
> @@ -1327,14 +1346,17 @@ error:
>  }
>
>  static int client_receive_message_udp(sd_event_source *s, int fd,
>                                        uint32_t revents, void *userdata) {
>          sd_dhcp_client *client = userdata;
>          _cleanup_free_ DHCPMessage *message = NULL;
>          int buflen = 0, len, r;
> +        const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
> +        const struct ether_addr *expected_chaddr = NULL;
> +        uint8_t expected_hlen = 0;
>
>          assert(s);
>          assert(client);
>
>          r = ioctl(fd, FIONREAD, &buflen);
>          if (r < 0)
>                  return r;
> @@ -1363,21 +1385,34 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
>          }
>
>          if (message->op != BOOTREPLY) {
>                  log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
>                  return 0;
>          }
>
> -        if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
> -                log_dhcp_client(client, "not an ethernet packet");
> +        if (message->htype != client->arp_type) {
> +                log_dhcp_client(client, "packet type does not match client type");
>                  return 0;
>          }
>
> -        if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
> -                   ETH_ALEN)) {
> +        if (client->arp_type == ARPHRD_ETHER) {
> +                expected_hlen = ETH_ALEN;
> +                expected_chaddr = (const struct ether_addr *) &client->mac_addr;
> +        } else {
> +               /* Non-ethernet links expect zero chaddr */
> +               expected_hlen = 0;
> +               expected_chaddr = &zero_mac;
> +        }
> +
> +        if (message->hlen != expected_hlen) {
> +                log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
> +                return 0;
> +        }
> +
> +        if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
>                  log_dhcp_client(client, "received chaddr does not match "
>                                  "expected: ignoring");
>                  return 0;
>          }
>
>          if (client->state != DHCP_STATE_BOUND &&
>              be32toh(message->xid) != client->xid) {
> @@ -1451,31 +1486,28 @@ static int client_receive_message_raw(sd_event_source *s, int fd,
>
>          len -= DHCP_IP_UDP_SIZE;
>
>          return client_handle_message(client, &packet->dhcp, len);
>  }
>
>  int sd_dhcp_client_start(sd_dhcp_client *client) {
> -        char buffer[ETHER_ADDR_TO_STRING_MAX];
>          int r;
>
>          assert_return(client, -EINVAL);
>
>          r = client_initialize(client);
>          if (r < 0)
>                  return r;
>
>          if (client->last_addr)
>                  client->state = DHCP_STATE_INIT_REBOOT;
>
>          r = client_start(client);
>          if (r >= 0)
> -                log_dhcp_client(client, "STARTED on ifindex %u with address %s",
> -                                client->index,
> -                                ether_addr_to_string(&client->client_id.mac_addr, buffer));
> +                log_dhcp_client(client, "STARTED on ifindex %u", client->index);
>
>          return r;
>  }
>
>  int sd_dhcp_client_stop(sd_dhcp_client *client) {
>          DHCP_CLIENT_DONT_DESTROY(client);
>
> diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
> index a6d6178..24fedd2 100644
> --- a/src/libsystemd-network/sd-dhcp-server.c
> +++ b/src/libsystemd-network/sd-dhcp-server.c
> @@ -388,16 +388,16 @@ static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
>          assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK));
>
>          packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
>          if (!packet)
>                  return -ENOMEM;
>
>          r = dhcp_message_init(&packet->dhcp, BOOTREPLY,
> -                              be32toh(req->message->xid), type, req->max_optlen,
> -                              &optoffset);
> +                              be32toh(req->message->xid), type, ARPHRD_ETHER,
> +                              req->max_optlen, &optoffset);
>          if (r < 0)
>                  return r;
>
>          packet->dhcp.flags = req->message->flags;
>          packet->dhcp.giaddr = req->message->giaddr;
>          memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN);
>
> @@ -509,16 +509,16 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
>          assert(chaddr);
>
>          packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE);
>          if (!packet)
>                  return -ENOMEM;
>
>          r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0,
> -                              DHCP_FORCERENEW, DHCP_MIN_OPTIONS_SIZE,
> -                              &optoffset);
> +                              DHCP_FORCERENEW, ARPHRD_ETHER,
> +                              DHCP_MIN_OPTIONS_SIZE, &optoffset);
>          if (r < 0)
>                  return r;
>
>          r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE,
>                                 &optoffset, 0, DHCP_OPTION_END, 0, NULL);
>          if (r < 0)
>                  return r;
> diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
> index c48aa04..7dab97d 100644
> --- a/src/libsystemd-network/test-dhcp-client.c
> +++ b/src/libsystemd-network/test-dhcp-client.c
> @@ -192,15 +192,17 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
>
>          assert_se(callback_recv);
>          callback_recv(size, &discover->dhcp);
>
>          return 575;
>  }
>
> -int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t id, struct ether_addr mac)
> +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];
>  }
>
> @@ -240,15 +242,18 @@ static void test_discover_message(sd_event *e)
>          assert_se(r >= 0);
>          assert_se(client);
>
>          r = sd_dhcp_client_attach_event(client, e, 0);
>          assert_se(r >= 0);
>
>          assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
> -        assert_se(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
> +        assert_se(sd_dhcp_client_set_mac(client,
> +                                         (const uint8_t *) &mac_addr,
> +                                         sizeof (mac_addr),
> +                                         ARPHRD_ETHER) >= 0);
>
>          assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
>
>          callback_recv = test_discover_message_verify;
>
>          res = sd_dhcp_client_start(client);
>
> @@ -458,15 +463,18 @@ static void test_addr_acq(sd_event *e) {
>          assert_se(r >= 0);
>          assert_se(client);
>
>          r = sd_dhcp_client_attach_event(client, e, 0);
>          assert_se(r >= 0);
>
>          assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
> -        assert_se(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
> +        assert_se(sd_dhcp_client_set_mac(client,
> +                                         (const uint8_t *) &mac_addr,
> +                                         sizeof (mac_addr),
> +                                         ARPHRD_ETHER) >= 0);
>
>          assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e)
>                  >= 0);
>
>          callback_recv = test_addr_acq_recv_discover;
>
>          assert_se(sd_event_add_time(e, &test_hangcheck,
> diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c
> index 63cdc7a..eac3844 100644
> --- a/src/libsystemd-network/test-dhcp-option.c
> +++ b/src/libsystemd-network/test-dhcp-option.c
> @@ -88,15 +88,15 @@ static void test_message_init(void)
>          size_t optlen = 4, optoffset;
>          size_t len = sizeof(DHCPMessage) + optlen;
>          uint8_t *magic;
>
>          message = malloc0(len);
>
>          assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678,
> -                  DHCP_DISCOVER, optlen, &optoffset) >= 0);
> +                  DHCP_DISCOVER, ARPHRD_ETHER, optlen, &optoffset) >= 0);
>
>          assert_se(message->xid == htobe32(0x12345678));
>          assert_se(message->op == BOOTREQUEST);
>
>          magic = (uint8_t*)&message->magic;
>
>          assert_se(magic[0] == 99);
> diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
> index e451af8..63bfa86 100644
> --- a/src/network/networkd-dhcp4.c
> +++ b/src/network/networkd-dhcp4.c
> @@ -595,15 +595,17 @@ int dhcp4_configure(Link *link) {
>          if (r < 0)
>                  return r;
>
>          r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
>          if (r < 0)
>                  return r;
>
> -        r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
> +        r = sd_dhcp_client_set_mac(link->dhcp_client,
> +                                   (const uint8_t *) &link->mac,
> +                                   sizeof (link->mac), ARPHRD_ETHER);
>          if (r < 0)
>                  return r;
>
>          r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
>          if (r < 0)
>                  return r;
>
> diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
> index 427f695..0cc7231 100644
> --- a/src/network/networkd-link.c
> +++ b/src/network/networkd-link.c
> @@ -1647,15 +1647,17 @@ int link_update(Link *link, sd_rtnl_message *m) {
>                                                           strerror(-r));
>                                          return r;
>                                  }
>                          }
>
>                          if (link->dhcp_client) {
>                                  r = sd_dhcp_client_set_mac(link->dhcp_client,
> -                                                           &link->mac);
> +                                                           (const uint8_t *) &link->mac,
> +                                                           sizeof (link->mac),
> +                                                           ARPHRD_ETHER);
>                                  if (r < 0) {
>                                          log_warning_link(link,
>                                                           "Could not update MAC address in DHCP client: %s",
>                                                           strerror(-r));
>                                          return r;
>                                  }
>                          }
> diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
> index 98c6782..7416f82 100644
> --- a/src/systemd/sd-dhcp-client.h
> +++ b/src/systemd/sd-dhcp-client.h
> @@ -45,16 +45,16 @@ int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb,
>
>
>  int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option);
>  int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
>                                         const struct in_addr *last_address);
>  int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast);
>  int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
> -int sd_dhcp_client_set_mac(sd_dhcp_client *client,
> -                           const struct ether_addr *addr);
> +int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
> +                           size_t addr_len, uint16_t arp_type);
>  int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
>  int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname);
>  int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci);
>  int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret);
>
>  int sd_dhcp_client_stop(sd_dhcp_client *client);
>  int sd_dhcp_client_start(sd_dhcp_client *client);
> --
> 1.9.3
>
>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel


More information about the systemd-devel mailing list