summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2023-12-20 17:48:20 +0100
committerBeniamino Galvani <bgalvani@redhat.com>2024-02-06 14:24:38 +0100
commit2f543f1154a0cfdbf0f9ef269e02f308a35108e4 (patch)
tree4745a62b1df384f88d049e477f36a9f403c759b1
parent2370a9005f1e55ef92533223247fae5fc4987185 (diff)
n-dhcp4: support setting the DSCP value
The client currently always sets the DSCP value in the DS field (formerly known as "TOS") to CS6. Some network equipment drops packets with such DSCP value; provide a way to change it.
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-connection.c4
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-probe.c14
-rw-r--r--src/n-dhcp4/src/n-dhcp4-private.h9
-rw-r--r--src/n-dhcp4/src/n-dhcp4-s-connection.c1
-rw-r--r--src/n-dhcp4/src/n-dhcp4-socket.c14
-rw-r--r--src/n-dhcp4/src/n-dhcp4.h1
-rw-r--r--src/n-dhcp4/src/test-socket.c5
-rw-r--r--src/n-dhcp4/src/util/packet.c6
-rw-r--r--src/n-dhcp4/src/util/packet.h3
-rw-r--r--src/n-dhcp4/src/util/test-packet.c4
10 files changed, 50 insertions, 11 deletions
diff --git a/src/n-dhcp4/src/n-dhcp4-c-connection.c b/src/n-dhcp4/src/n-dhcp4-c-connection.c
index dd1a573a67..7cb4f23fe0 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-connection.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-connection.c
@@ -191,7 +191,8 @@ int n_dhcp4_c_connection_connect(NDhcp4CConnection *connection,
r = n_dhcp4_c_socket_udp_new(&fd_udp,
connection->client_config->ifindex,
client,
- server);
+ server,
+ connection->probe_config->dscp);
if (r)
return r;
@@ -388,6 +389,7 @@ static int n_dhcp4_c_connection_packet_broadcast(NDhcp4CConnection *connection,
connection->client_config->ifindex,
connection->client_config->broadcast_mac,
connection->client_config->n_broadcast_mac,
+ connection->probe_config->dscp,
message);
if (r)
return r;
diff --git a/src/n-dhcp4/src/n-dhcp4-c-probe.c b/src/n-dhcp4/src/n-dhcp4-c-probe.c
index 284aa428e9..b7fe1c4f38 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-probe.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-probe.c
@@ -118,6 +118,7 @@ int n_dhcp4_client_probe_config_dup(NDhcp4ClientProbeConfig *config,
dup->init_reboot = config->init_reboot;
dup->requested_ip = config->requested_ip;
dup->ms_start_delay = config->ms_start_delay;
+ dup->dscp = config->dscp;
for (unsigned int i = 0; i < config->n_request_parameters; ++i)
dup->request_parameters[dup->n_request_parameters++] = config->request_parameters[i];
@@ -191,6 +192,19 @@ _c_public_ void n_dhcp4_client_probe_config_set_init_reboot(NDhcp4ClientProbeCon
}
/**
+ * n_dhcp4_client_probe_config_set_dscp() - set the IP DSCP value
+ * @config: configuration to operate on
+ * @dscp: value to set
+ *
+ * This sets the DSCP property of the configuration object, which specifies
+ * the DSCP value to set in the first six bits of the DS field in the IPv4
+ * header. If this function is not called, the DSCP will be set to CS6.
+ */
+_c_public_ void n_dhcp4_client_probe_config_set_dscp(NDhcp4ClientProbeConfig *config, uint8_t dscp) {
+ config->dscp = dscp & 0x3F;
+}
+
+/**
* n_dhcp4_client_probe_config_set_requested_ip() - set requested-ip property
* @config: configuration to operate on
* @ip: value to set
diff --git a/src/n-dhcp4/src/n-dhcp4-private.h b/src/n-dhcp4/src/n-dhcp4-private.h
index 8b17a1a25f..4bbb03d482 100644
--- a/src/n-dhcp4/src/n-dhcp4-private.h
+++ b/src/n-dhcp4/src/n-dhcp4-private.h
@@ -7,6 +7,7 @@
#include <endian.h>
#include <inttypes.h>
#include <limits.h>
+#include <netinet/ip.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
@@ -34,6 +35,7 @@ typedef struct NDhcp4LogQueue NDhcp4LogQueue;
#define N_DHCP4_NETWORK_CLIENT_PORT (68)
#define N_DHCP4_MESSAGE_MAGIC ((uint32_t)(0x63825363))
#define N_DHCP4_MESSAGE_FLAG_BROADCAST (htons(0x8000))
+#define N_DHCP4_DSCP_DEFAULT (IPTOS_CLASS_CS6 >> 2)
enum {
N_DHCP4_OP_BOOTREQUEST = 1,
@@ -263,6 +265,7 @@ struct NDhcp4ClientProbeOption {
struct NDhcp4ClientProbeConfig {
bool inform_only;
bool init_reboot;
+ uint8_t dscp;
struct in_addr requested_ip;
unsigned short int entropy[3];
uint64_t ms_start_delay; /* max ms to wait before starting probe */
@@ -273,6 +276,7 @@ struct NDhcp4ClientProbeConfig {
#define N_DHCP4_CLIENT_PROBE_CONFIG_NULL(_x) { \
.ms_start_delay = N_DHCP4_CLIENT_START_DELAY_RFC2131, \
+ .dscp = N_DHCP4_DSCP_DEFAULT, \
}
struct NDhcp4CEventNode {
@@ -536,7 +540,8 @@ int n_dhcp4_c_socket_packet_new(int *sockfdp, int ifindex);
int n_dhcp4_c_socket_udp_new(int *sockfdp,
int ifindex,
const struct in_addr *client_addr,
- const struct in_addr *server_addr);
+ const struct in_addr *server_addr,
+ uint8_t dscp);
int n_dhcp4_s_socket_packet_new(int *sockfdp);
int n_dhcp4_s_socket_udp_new(int *sockfdp, int ifindex);
@@ -544,6 +549,7 @@ int n_dhcp4_c_socket_packet_send(int sockfd,
int ifindex,
const unsigned char *dest_haddr,
unsigned char halen,
+ uint8_t dscp,
NDhcp4Outgoing *message);
int n_dhcp4_c_socket_udp_send(int sockfd, NDhcp4Outgoing *message);
int n_dhcp4_c_socket_udp_broadcast(int sockfd, NDhcp4Outgoing *message);
@@ -553,6 +559,7 @@ int n_dhcp4_s_socket_packet_send(int sockfd,
const unsigned char *dest_haddr,
unsigned char halen,
const struct in_addr *dest_inaddr,
+ uint8_t dscp,
NDhcp4Outgoing *message);
int n_dhcp4_s_socket_udp_send(int sockfd,
const struct in_addr *inaddr_src,
diff --git a/src/n-dhcp4/src/n-dhcp4-s-connection.c b/src/n-dhcp4/src/n-dhcp4-s-connection.c
index 474a7b63c8..5ed190a8ef 100644
--- a/src/n-dhcp4/src/n-dhcp4-s-connection.c
+++ b/src/n-dhcp4/src/n-dhcp4-s-connection.c
@@ -202,6 +202,7 @@ int n_dhcp4_s_connection_send_reply(NDhcp4SConnection *connection,
header->chaddr,
header->hlen,
&(struct in_addr){header->yiaddr},
+ N_DHCP4_DSCP_DEFAULT,
message);
if (r)
return r;
diff --git a/src/n-dhcp4/src/n-dhcp4-socket.c b/src/n-dhcp4/src/n-dhcp4-socket.c
index 3e703b4fcb..ec2a48e344 100644
--- a/src/n-dhcp4/src/n-dhcp4-socket.c
+++ b/src/n-dhcp4/src/n-dhcp4-socket.c
@@ -133,6 +133,7 @@ int n_dhcp4_c_socket_packet_new(int *sockfdp, int ifindex) {
* @ifindex: interface index to bind to
* @client_addr: client address to bind to
* @server_addr: server address to connect to
+ * @dscp: the DSCP value
*
* Create a new AF_INET/SOCK_DGRAM socket usable to listen to and send DHCP client
* packets.
@@ -145,7 +146,8 @@ int n_dhcp4_c_socket_packet_new(int *sockfdp, int ifindex) {
int n_dhcp4_c_socket_udp_new(int *sockfdp,
int ifindex,
const struct in_addr *client_addr,
- const struct in_addr *server_addr) {
+ const struct in_addr *server_addr,
+ uint8_t dscp) {
_c_cleanup_(c_closep) int sockfd = -1;
struct sock_filter filter[] = {
/*
@@ -189,7 +191,8 @@ int n_dhcp4_c_socket_udp_new(int *sockfdp,
.sin_addr = *server_addr,
.sin_port = htons(N_DHCP4_NETWORK_SERVER_PORT),
};
- int r, tos = IPTOS_CLASS_CS6, on = 1;
+ int r, on = 1;
+ int tos = dscp << 2;
sockfd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (sockfd < 0)
@@ -340,6 +343,7 @@ static int n_dhcp4_socket_packet_send(int sockfd,
const unsigned char *dest_haddr,
unsigned char halen,
const struct sockaddr_in *dest_paddr,
+ uint8_t dscp,
NDhcp4Outgoing *message) {
struct packet_sockaddr_ll haddr = {
.sll_family = AF_PACKET,
@@ -357,7 +361,7 @@ static int n_dhcp4_socket_packet_send(int sockfd,
n_buf = n_dhcp4_outgoing_get_raw(message, &buf);
- r = packet_sendto_udp(sockfd, buf, n_buf, &len, src_paddr, &haddr, dest_paddr);
+ r = packet_sendto_udp(sockfd, buf, n_buf, &len, src_paddr, &haddr, dest_paddr, dscp);
if (r < 0) {
if (r == -EAGAIN || r == -ENOBUFS)
return N_DHCP4_E_DROPPED;
@@ -379,6 +383,7 @@ int n_dhcp4_c_socket_packet_send(int sockfd,
int ifindex,
const unsigned char *dest_haddr,
unsigned char halen,
+ uint8_t dscp,
NDhcp4Outgoing *message) {
struct sockaddr_in src_paddr = {
.sin_family = AF_INET,
@@ -397,6 +402,7 @@ int n_dhcp4_c_socket_packet_send(int sockfd,
dest_haddr,
halen,
&dest_paddr,
+ dscp,
message);
}
@@ -468,6 +474,7 @@ int n_dhcp4_s_socket_packet_send(int sockfd,
const unsigned char *dest_haddr,
unsigned char halen,
const struct in_addr *dest_inaddr,
+ uint8_t dscp,
NDhcp4Outgoing *message) {
struct sockaddr_in src_paddr = {
.sin_family = AF_INET,
@@ -486,6 +493,7 @@ int n_dhcp4_s_socket_packet_send(int sockfd,
dest_haddr,
halen,
&dest_paddr,
+ dscp,
message);
}
diff --git a/src/n-dhcp4/src/n-dhcp4.h b/src/n-dhcp4/src/n-dhcp4.h
index 8493a487dd..f6c87a8d80 100644
--- a/src/n-dhcp4/src/n-dhcp4.h
+++ b/src/n-dhcp4/src/n-dhcp4.h
@@ -128,6 +128,7 @@ NDhcp4ClientProbeConfig *n_dhcp4_client_probe_config_free(NDhcp4ClientProbeConfi
void n_dhcp4_client_probe_config_set_inform_only(NDhcp4ClientProbeConfig *config, bool inform_only);
void n_dhcp4_client_probe_config_set_init_reboot(NDhcp4ClientProbeConfig *config, bool init_reboot);
+void n_dhcp4_client_probe_config_set_dscp(NDhcp4ClientProbeConfig *config, uint8_t dscp);
void n_dhcp4_client_probe_config_set_requested_ip(NDhcp4ClientProbeConfig *config, struct in_addr ip);
void n_dhcp4_client_probe_config_set_start_delay(NDhcp4ClientProbeConfig *config, uint64_t msecs);
void n_dhcp4_client_probe_config_request_option(NDhcp4ClientProbeConfig *config, uint8_t option);
diff --git a/src/n-dhcp4/src/test-socket.c b/src/n-dhcp4/src/test-socket.c
index 7d17565346..2b9303afe3 100644
--- a/src/n-dhcp4/src/test-socket.c
+++ b/src/n-dhcp4/src/test-socket.c
@@ -46,7 +46,7 @@ static void test_client_udp_socket_new(Link *link,
netns_get(&oldns);
netns_set(link->netns);
- r = n_dhcp4_c_socket_udp_new(skp, link->ifindex, addr_client, addr_server);
+ r = n_dhcp4_c_socket_udp_new(skp, link->ifindex, addr_client, addr_server, N_DHCP4_DSCP_DEFAULT);
c_assert(r >= 0);
netns_set(oldns);
@@ -95,6 +95,7 @@ static void test_client_server_packet(Link *link_server, Link *link_client) {
link_client->ifindex,
(const unsigned char[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
ETH_ALEN,
+ -1,
outgoing);
c_assert(!r);
@@ -178,6 +179,7 @@ static void test_server_client_packet(Link *link_server, Link *link_client) {
link_client->mac.ether_addr_octet,
ETH_ALEN,
&addr_client,
+ N_DHCP4_DSCP_DEFAULT,
outgoing);
c_assert(!r);
r = n_dhcp4_s_socket_packet_send(sk_server,
@@ -188,6 +190,7 @@ static void test_server_client_packet(Link *link_server, Link *link_client) {
},
ETH_ALEN,
&addr_client,
+ N_DHCP4_DSCP_DEFAULT,
outgoing);
c_assert(!r);
diff --git a/src/n-dhcp4/src/util/packet.c b/src/n-dhcp4/src/util/packet.c
index 48f2c85eb9..cbf09c06ce 100644
--- a/src/n-dhcp4/src/util/packet.c
+++ b/src/n-dhcp4/src/util/packet.c
@@ -150,6 +150,7 @@ uint16_t packet_internet_checksum_udp(const struct in_addr *src_addr,
* @src_paddr: source protocol address, see ip(7)
* @dest_haddr: destination hardware address, see packet(7)
* @dest_paddr: destination protocol address, see ip(7)
+ * @dscp: the DSCP value
*
* Sends an UDP packet on a AF_PACKET socket directly to a hardware
* address. The difference between this and sendto() on an AF_INET
@@ -165,11 +166,12 @@ int packet_sendto_udp(int sockfd,
size_t *n_transmittedp,
const struct sockaddr_in *src_paddr,
const struct packet_sockaddr_ll *dest_haddr,
- const struct sockaddr_in *dest_paddr) {
+ const struct sockaddr_in *dest_paddr,
+ uint8_t dscp) {
struct iphdr ip_hdr = {
.version = IPVERSION,
.ihl = sizeof(ip_hdr) / 4, /* Length of header in multiples of four bytes */
- .tos = IPTOS_CLASS_CS6, /* Class Selector for network control */
+ .tos = dscp << 2,
.tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + n_buf),
.frag_off = htons(IP_DF), /* Do not fragment */
.ttl = IPDEFTTL,
diff --git a/src/n-dhcp4/src/util/packet.h b/src/n-dhcp4/src/util/packet.h
index 98dabf7fbe..ec06a21374 100644
--- a/src/n-dhcp4/src/util/packet.h
+++ b/src/n-dhcp4/src/util/packet.h
@@ -42,7 +42,8 @@ int packet_sendto_udp(int sockfd,
size_t *n_transmittedp,
const struct sockaddr_in *src_paddr,
const struct packet_sockaddr_ll *dest_haddr,
- const struct sockaddr_in *dest_paddr);
+ const struct sockaddr_in *dest_paddr,
+ uint8_t dscp);
int packet_recvfrom_udp(int sockfd,
void *buf,
size_t n_buf,
diff --git a/src/n-dhcp4/src/util/test-packet.c b/src/n-dhcp4/src/util/test-packet.c
index 0f5cba63a7..44dbc3004b 100644
--- a/src/n-dhcp4/src/util/test-packet.c
+++ b/src/n-dhcp4/src/util/test-packet.c
@@ -123,7 +123,7 @@ static void test_packet_unicast(int ifindex, int sk, void *buf, size_t n_buf,
memcpy(addr.sll_addr, haddr_dst, ETH_ALEN);
- r = packet_sendto_udp(sk, buf, n_buf, &len, paddr_src, &addr, paddr_dst);
+ r = packet_sendto_udp(sk, buf, n_buf, &len, paddr_src, &addr, paddr_dst, N_DHCP4_DSCP_DEFAULT);
c_assert(!r);
c_assert(len == n_buf);
}
@@ -142,7 +142,7 @@ static void test_packet_broadcast(int ifindex, int sk, void *buf, size_t n_buf,
memcpy(addr.sll_addr, (unsigned char[]){ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, ETH_ALEN);
- r = packet_sendto_udp(sk, buf, n_buf, &len, paddr_src, &addr, paddr_dst);
+ r = packet_sendto_udp(sk, buf, n_buf, &len, paddr_src, &addr, paddr_dst, N_DHCP4_DSCP_DEFAULT);
c_assert(!r);
c_assert(len == n_buf);
}