diff --git a/src/n-dhcp4/src/n-dhcp4-c-connection.c b/src/n-dhcp4/src/n-dhcp4-c-connection.c index dd1a573a6..7cb4f23fe 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 284aa428e..b7fe1c4f3 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]; @@ -190,6 +191,19 @@ _c_public_ void n_dhcp4_client_probe_config_set_init_reboot(NDhcp4ClientProbeCon config->init_reboot = init_reboot; } +/** + * 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 diff --git a/src/n-dhcp4/src/n-dhcp4-private.h b/src/n-dhcp4/src/n-dhcp4-private.h index 8b17a1a25..4bbb03d48 100644 --- a/src/n-dhcp4/src/n-dhcp4-private.h +++ b/src/n-dhcp4/src/n-dhcp4-private.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -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 474a7b63c..5ed190a8e 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 3e703b4fc..ec2a48e34 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 8493a487d..f6c87a8d8 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 7d1756534..2b9303afe 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 48f2c85eb..cbf09c06c 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 98dabf7fb..ec06a2137 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 0f5cba63a..44dbc3004 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); }