]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: support setting dhcp client listen port (#4631)
authorSusant Sahani <ssahani@users.noreply.github.com>
Thu, 10 Nov 2016 23:34:19 +0000 (05:04 +0530)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 10 Nov 2016 23:34:19 +0000 (18:34 -0500)
Allow setting custom port for the DHCP client to listen on in networkd.

[DHCP]
ListenPort=6677

man/systemd.network.xml
src/libsystemd-network/dhcp-internal.h
src/libsystemd-network/dhcp-network.c
src/libsystemd-network/dhcp-packet.c
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/test-dhcp-client.c
src/network/networkd-dhcp4.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.h
src/systemd/sd-dhcp-client.h

index 2fb4907634bf6356a492b01ef45662201a7922e2..99283813fd46fa5e0ac777a2e5ec0367a1aa3a21 100644 (file)
             </para>
           </listitem>
         </varlistentry>
+
+        <varlistentry>
+          <term><varname>ListenPort=</varname></term>
+          <listitem>
+            <para>Allow setting custom port for the DHCP client to listen on.</para>
+          </listitem>
+        </varlistentry>
       </variablelist>
     </refsect1>
 
index 99f690897df9f11894fe87d31cfaa6db0d885bfc..5aa8aca42610bb522689a385c921dc4f6f6bcda1 100644 (file)
@@ -32,7 +32,8 @@
 
 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);
+                                 size_t mac_addr_len, uint16_t arp_type,
+                                 uint16_t port);
 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);
@@ -57,7 +58,7 @@ 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);
 
-int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum);
+int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port);
 
 /* If we are invoking callbacks of a dhcp-client, ensure unreffing the
  * client from the callback doesn't destroy the object we are working
index a9f5a0a5de01973e560518ab277106949f0494f6..3c85bb0b54b56e5e2250031974a65b61348a3a95 100644 (file)
@@ -36,7 +36,8 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
                             size_t mac_addr_len,
                             const uint8_t *bcast_addr,
                             const struct ether_addr *eth_mac,
-                            uint16_t arp_type, uint8_t dhcp_hlen) {
+                            uint16_t arp_type, uint8_t dhcp_hlen,
+                            uint16_t port) {
         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 ? */
@@ -53,7 +54,7 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
                 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_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_JUMP(BPF_JMP + BPF_JEQ + BPF_K, port, 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 ? */
@@ -125,7 +126,8 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
 
 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) {
+                                 size_t mac_addr_len, uint16_t arp_type,
+                                 uint16_t port) {
         static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
         /* Default broadcast address for IPoIB */
         static const uint8_t ib_bcast[] = {
@@ -151,7 +153,7 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
                 return -EINVAL;
 
         return _bind_raw_socket(ifindex, link, xid, mac_addr, mac_addr_len,
-                                bcast_addr, &eth_mac, arp_type, dhcp_hlen);
+                                bcast_addr, &eth_mac, arp_type, dhcp_hlen, port);
 }
 
 int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
index 8be774061d67ff7f542c126c0a93a6e206ce5bb9..40442b3636c3a50f2763e0fc5b02cd6dfe2004c6 100644 (file)
@@ -114,7 +114,7 @@ void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
         packet->ip.check = dhcp_packet_checksum((uint8_t*)&packet->ip, DHCP_IP_SIZE);
 }
 
-int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) {
+int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port) {
         size_t hdrlen;
 
         assert(packet);
@@ -160,10 +160,10 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) {
                 return -EINVAL;
         }
 
-        if (be16toh(packet->udp.dest) != DHCP_PORT_CLIENT) {
+        if (be16toh(packet->udp.dest) != port) {
                 log_debug("ignoring packet: to port %u, which "
                           "is not the DHCP client port (%u)",
-                          be16toh(packet->udp.dest), DHCP_PORT_CLIENT);
+                          be16toh(packet->udp.dest), port);
                 return -EINVAL;
         }
 
index 5ccb23922c9499d91cd55675afa023df90993526..6475da2c2a0add476aec75800711ebabc4bf8461 100644 (file)
@@ -55,6 +55,7 @@ struct sd_dhcp_client {
         sd_event_source *timeout_resend;
         int ifindex;
         int fd;
+        uint16_t port;
         union sockaddr_union link;
         sd_event_source *receive_message;
         bool request_broadcast;
@@ -426,6 +427,17 @@ int sd_dhcp_client_set_vendor_class_identifier(
         return 0;
 }
 
+int sd_dhcp_client_set_client_port(
+                sd_dhcp_client *client,
+                uint16_t port) {
+
+        assert_return(client, -EINVAL);
+
+        client->port = port;
+
+        return 0;
+}
+
 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
         assert_return(client, -EINVAL);
         assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
@@ -668,7 +680,7 @@ static int dhcp_client_send_raw(
                 DHCPPacket *packet,
                 size_t len) {
 
-        dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
+        dhcp_packet_append_ip_headers(packet, INADDR_ANY, client->port,
                                       INADDR_BROADCAST, DHCP_PORT_SERVER, len);
 
         return dhcp_network_send_raw_socket(client->fd, &client->link,
@@ -1120,7 +1132,7 @@ static int client_start_delayed(sd_dhcp_client *client) {
 
         r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
                                          client->xid, client->mac_addr,
-                                         client->mac_addr_len, client->arp_type);
+                                         client->mac_addr_len, client->arp_type, client->port);
         if (r < 0) {
                 client_stop(client, r);
                 return r;
@@ -1170,7 +1182,8 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
 
         r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
                                          client->xid, client->mac_addr,
-                                         client->mac_addr_len, client->arp_type);
+                                         client->mac_addr_len, client->arp_type,
+                                         client->port);
         if (r < 0) {
                 client_stop(client, r);
                 return 0;
@@ -1555,8 +1568,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
                                 goto error;
                         }
 
-                        r = dhcp_network_bind_udp_socket(client->lease->address,
-                                                         DHCP_PORT_CLIENT);
+                        r = dhcp_network_bind_udp_socket(client->lease->address, client->port);
                         if (r < 0) {
                                 log_dhcp_client(client, "could not bind UDP socket");
                                 goto error;
@@ -1766,7 +1778,7 @@ static int client_receive_message_raw(
                 }
         }
 
-        r = dhcp_packet_verify_headers(packet, len, checksum);
+        r = dhcp_packet_verify_headers(packet, len, checksum, client->port);
         if (r < 0)
                 return 0;
 
@@ -1891,6 +1903,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) {
         client->fd = -1;
         client->attempt = 1;
         client->mtu = DHCP_DEFAULT_MIN_SIZE;
+        client->port = DHCP_PORT_CLIENT;
 
         client->req_opts_size = ELEMENTSOF(default_req_opts);
         client->req_opts = memdup(default_req_opts, client->req_opts_size);
index 2a101cb1fe0bd5bd8c9f2b4eb5b6c72063f07a47..c10ca74b863bc316d82b519d6a9ac2e46e471016 100644 (file)
@@ -195,7 +195,7 @@ int dhcp_network_bind_raw_socket(
                 union sockaddr_union *link,
                 uint32_t id,
                 const uint8_t *addr, size_t addr_len,
-                uint16_t arp_type) {
+                uint16_t arp_type, uint16_t port) {
 
         if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
                 return -errno;
index 76d3d132ea28e93dff671e0f81317046c254b46c..3feb158642566eef1ea389d6026332763cba36e2 100644 (file)
@@ -630,6 +630,12 @@ int dhcp4_configure(Link *link) {
                         return r;
         }
 
+        if (link->network->dhcp_client_port) {
+                r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
+                if (r < 0)
+                        return r;
+        }
+
         switch (link->network->dhcp_client_identifier) {
         case DHCP_CLIENT_ID_DUID: {
                 /* If configured, apply user specified DUID and/or IAID */
index bcf8186c33f5e385132511b44505301d3eef39f3..814f435fc10e71cc74adea58599e00360e447b6d 100644 (file)
@@ -100,6 +100,7 @@ DHCP.RouteMetric,                       config_parse_unsigned,
 DHCP.RouteTable,                        config_parse_dhcp_route_table,                  0,                             offsetof(Network, dhcp_route_table)
 DHCP.UseTimezone,                       config_parse_bool,                              0,                             offsetof(Network, dhcp_use_timezone)
 DHCP.IAID,                              config_parse_iaid,                              0,                             offsetof(Network, iaid)
+DHCP.ListenPort,                        config_parse_uint32,                            0,                             offsetof(Network, dhcp_client_port)
 IPv6AcceptRA.UseDNS,                    config_parse_bool,                              0,                             offsetof(Network, ipv6_accept_ra_use_dns)
 IPv6AcceptRA.UseDomains,                config_parse_dhcp_use_domains,                  0,                             offsetof(Network, ipv6_accept_ra_use_domains)
 IPv6AcceptRA.RouteTable,                config_parse_dhcp_route_table,                  0,                             offsetof(Network, ipv6_accept_ra_route_table)
index 42fc82d39228091853e7368a7f8d40b210a654b5..4df8c37979fa39816b978ad833a51d32c06d23e7 100644 (file)
@@ -124,6 +124,7 @@ struct Network {
         bool dhcp_use_timezone;
         unsigned dhcp_route_metric;
         uint32_t dhcp_route_table;
+        uint32_t dhcp_client_port;
 
         /* DHCP Server Support */
         bool dhcp_server;
index 9a90c2ed42138941f57b2f282472bd6f46848ee1..ffe7f836de0c87d0459c11b1e4013361738002c5 100644 (file)
@@ -126,6 +126,9 @@ int sd_dhcp_client_get_client_id(
 int sd_dhcp_client_set_mtu(
                 sd_dhcp_client *client,
                 uint32_t mtu);
+int sd_dhcp_client_set_client_port(
+                sd_dhcp_client *client,
+                uint16_t port);
 int sd_dhcp_client_set_hostname(
                 sd_dhcp_client *client,
                 const char *hostname);