On Thu, Oct 2, 2014 at 6:07 PM, Dan Williams <d...@redhat.com> wrote: > On Thu, 2014-10-02 at 16:39 +0200, Tom Gundersen wrote: >> On Fri, Sep 26, 2014 at 10:15 PM, Dan Williams <d...@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? > > The DHCPv4 header is the same format no matter what the LL address size, > but for non-ethernet the hlen is 0 and the chaddr is zeroed. The BPF is > seeded with an hlen of 0 and a valid ETH_ALEN sized buffer of all zeros. > So both the hlen and chaddr comparisons comparison should succeed. > > Does that make sense? I might have missed something too though...
So that sounds fine, but my concern was: are we guaranteed that all implementations properly zero out the remaining bytes past the hlen first ones? Sounds weird to reject a package if it has hlen == 0 and garbage in chaddr, or is the zeroing something we can rely on? (In that case I guess we should extend the check to check all 16 bytes, and not only the 6 first ones to make it truly agnostic). Patrik, any thoughts? >> 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(ð_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, ð_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@lists.freedesktop.org >> > http://lists.freedesktop.org/mailman/listinfo/systemd-devel > > _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel