diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 79f58e9d3..e393429a9 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -132,14 +132,22 @@ config UDHCPC_DEFAULT_DECLINE_SCRIPT string "Absolute path to decline script" default "/usr/share/udhcpc/decline.script" depends on UDHCPC help The script is called after client receives offer from server. Decline script returns 0 when offer should be accepted. +config FEATURE_UDHCPC_COS + bool "Support Class of Service for DHCP Client" + default y + depends on UDHCPC + help + If selected, udhcpc will set -y socket priority. + script returns 1. + config UDHCP_DEBUG int "Maximum verbosity level (0..9)" default 2 range 0 9 depends on UDHCPD || UDHCPC || UDHCPC6 || DHCPRELAY help Verbosity can be increased with multiple -v options. diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 8d11a7539..43760a112 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -125,14 +125,15 @@ static const char udhcpc6_longopts[] ALIGN1 = "foreground\0" No_argument "f" "stateless\0" No_argument "l" USE_FOR_MMU( "background\0" No_argument "b" ) /// IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") + IF_FEATURE_UDHCPC_COS("cos\0" Required_argument "y") ; #endif /* Must match getopt32 option string order */ enum { OPT_i = 1 << 0, OPT_n = 1 << 1, OPT_p = 1 << 2, @@ -1147,14 +1148,17 @@ static void client_background(void) //usage: "\n -S Log to syslog too" //usage: IF_FEATURE_UDHCP_PORT( //usage: "\n -P PORT Use PORT (default 546)" //usage: ) ////usage: IF_FEATURE_UDHCPC_ARPING( ////usage: "\n -a Use arping to validate offered address" ////usage: ) +//usage: IF_FEATURE_UDHCPC_COS( +//usage: "\n -y PRIORITY CoS value 0 .. 7, default 0" +//usage: ) //usage: "\n -l Send 'information request' instead of 'solicit'" //usage: "\n (used for servers which do not assign IPv6 addresses)" //usage: "\n -r IPv6 Request this address ('no' to not request any IP)" //usage: "\n -d Request prefix" //usage: "\n -o Don't request any options (unless -O is given)" //usage: "\n -O OPT Request option OPT from server (cumulative)" //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" @@ -1208,23 +1212,25 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) /* Parse command line */ opt = getopt32long(argv, "^" /* O,x: list; -T,-t,-A take numeric param */ "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld" USE_FOR_MMU("b") ///IF_FEATURE_UDHCPC_ARPING("a") IF_FEATURE_UDHCP_PORT("P:") + IF_FEATURE_UDHCPC_COS("y:+") "v" "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ , udhcpc6_longopts , &client_data.interface, &client_data.pidfile, &str_r /* i,p */ , &client_data.script /* s */ , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ , &list_O , &list_x IF_FEATURE_UDHCP_PORT(, &str_P) + IF_FEATURE_UDHCPC_COS(, &sk_prio) IF_UDHCP_VERBOSE(, &dhcp_verbose) ); requested_ipv6 = NULL; option_mask32 |= OPT_r; if (opt & OPT_l) { /* for -l, do not require IPv6 assignment from server */ option_mask32 &= ~OPT_r; diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c index c1949f6e3..141cc5e59 100644 --- a/networking/udhcp/d6_packet.c +++ b/networking/udhcp/d6_packet.c @@ -107,14 +107,22 @@ int FAST_FUNC d6_send_raw_packet_from_client_data_ifindex( (uint8_t *)&packet + 4, offsetof(struct ip6_udp_d6_packet, data) - 4 + d6_pkt_size ); /* fix 'hop limit' and 'next header' after UDP checksumming */ packet.ip6.ip6_hlim = 1; /* observed Windows machines to use hlim=1 */ packet.ip6.ip6_nxt = IPPROTO_UDP; +IF_FEATURE_UDHCPC_COS( + if (sk_prio) { + if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &sk_prio, sizeof(sk_prio))) { + log1s("raw: SO_PRIORITY (dscp v6) setsockopt() failed"); + } + }) + + d6_dump_packet(d6_pkt); result = sendto(fd, &packet, offsetof(struct ip6_udp_d6_packet, data) + d6_pkt_size, /*flags:*/ 0, (struct sockaddr *) &dest_sll, sizeof(dest_sll) ); msg = "sendto"; ret_close: diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 2b75940fe..f8c0baceb 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -76,14 +76,15 @@ static const char udhcpc_longopts[] ALIGN1 = USE_FOR_MMU( "background\0" No_argument "b" ) "broadcast\0" No_argument "B" IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a") IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") IF_FEATURE_UDHCPC_DECLINE("decline-script\0" Required_argument "d") + IF_FEATURE_UDHCPC_COS("cos\0" Required_argument "y") ; #endif /* Must match getopt32 option string order */ enum { OPT_C = 1 << 0, OPT_V = 1 << 1, OPT_F = 1 << 2, @@ -1237,14 +1238,17 @@ static int udhcp_run_decline_script(struct dhcp_packet *packet) //usage: "\n -q Exit after obtaining lease" //usage: "\n -R Release IP on exit" //usage: "\n -f Run in foreground" //usage: "\n -S Log to syslog too" //usage: IF_FEATURE_UDHCPC_ARPING( //usage: "\n -a[MSEC] Validate offered address with ARP ping" //usage: ) +//usage: IF_FEATURE_UDHCPC_COS( +//usage: "\n -y PRIORITY CoS value 0 .. 7, default 0" +//usage: ) //usage: "\n -r IP Request this IP address" //usage: "\n -o Don't request any options (unless -O is given)" //usage: "\n -O OPT Request option OPT from server (cumulative)" //usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" //usage: "\n Examples of string, numeric, and hex byte opts:" //usage: "\n -x hostname:bbox - option 12" //usage: "\n -x lease:3600 - option 51 (lease time)" @@ -1303,27 +1307,29 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) opt = getopt32long(argv, "^" /* O,x: list; -T,-t,-A take numeric param */ "CV:F:i:np:qRr:s:T:+t:+SA:+O:*ox:*fB" USE_FOR_MMU("b") IF_FEATURE_UDHCPC_ARPING("a::") IF_FEATURE_UDHCP_PORT("P:") IF_FEATURE_UDHCPC_DECLINE("d:") + IF_FEATURE_UDHCPC_COS("y:+") "v" "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ , udhcpc_longopts , &str_V, &str_F , &client_data.interface, &client_data.pidfile /* i,p */ , &str_r /* r */ , &client_data.script /* s */ , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ , &list_O , &list_x IF_FEATURE_UDHCPC_ARPING(, &str_a) IF_FEATURE_UDHCP_PORT(, &str_P) IF_FEATURE_UDHCPC_DECLINE(, &client_data.decline_script) + IF_FEATURE_UDHCPC_COS(, &sk_prio) IF_UDHCP_VERBOSE(, &dhcp_verbose) ); if (opt & OPT_F) { char *p; unsigned len; /* FQDN option format: [0x51][len][flags][0][0] */ len = strlen(str_F); diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index ed51683dc..4b5659aef 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h @@ -3,14 +3,16 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ #ifndef UDHCP_DHCPC_H #define UDHCP_DHCPC_H 1 PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN +IF_FEATURE_UDHCPC_COS(extern uint32_t sk_prio;) + struct client_data_t { uint8_t client_mac[6]; /* Our mac address */ IF_FEATURE_UDHCP_PORT(uint16_t port;) int ifindex; /* Index number of the interface to use */ uint32_t xid; uint8_t opt_mask[256 / 8]; /* Bitmask of options to send (-O option) */ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO: DHCPv6 has 16-bit option numbers diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 78f580ce9..ef56e54d2 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -8,14 +8,16 @@ */ #include "common.h" #include "dhcpd.h" #include #include #include +IF_FEATURE_UDHCPC_COS(uint32_t sk_prio;) + #if ENABLE_UDHCPC || ENABLE_UDHCPD void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type) { memset(packet, 0, sizeof(*packet)); packet->op = BOOTREQUEST; /* if client to a server */ switch (type) { case DHCPOFFER: @@ -170,14 +172,21 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, /* but for sending, it is set to IP packet len */ packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); packet.ip.ihl = sizeof(packet.ip) >> 2; packet.ip.version = IPVERSION; packet.ip.ttl = IPDEFTTL; packet.ip.check = inet_cksum(&packet.ip, sizeof(packet.ip)); +IF_FEATURE_UDHCPC_COS( + if (sk_prio) { + if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &sk_prio, sizeof(sk_prio))) { + log1s("raw: SO_PRIORITY (dscp v6) setsockopt() failed"); + } + }) + udhcp_dump_packet(dhcp_pkt); result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0, (struct sockaddr *) &dest_sll, sizeof(dest_sll)); msg = "sendto"; ret_close: close(fd); if (result < 0) {