mirror of
https://github.com/curl/curl.git
synced 2025-09-13 07:32:38 +03:00
curl: support IP Type of Service / Traffic Class: --ip-tos
Add --ip-tos option to the command line tool for setting TOS for IPv4 or Traffic Class for IPv6. Closes #13606
This commit is contained in:
parent
f786fce914
commit
3c20ae08b9
6
.github/scripts/spellcheck.words
vendored
6
.github/scripts/spellcheck.words
vendored
|
@ -214,6 +214,8 @@ ECHConfigList
|
||||||
ecl
|
ecl
|
||||||
ECONNREFUSED
|
ECONNREFUSED
|
||||||
eCOS
|
eCOS
|
||||||
|
ECT
|
||||||
|
EF
|
||||||
EFnet
|
EFnet
|
||||||
EGD
|
EGD
|
||||||
EHLO
|
EHLO
|
||||||
|
@ -457,6 +459,8 @@ LOGDIR
|
||||||
logfile
|
logfile
|
||||||
lookups
|
lookups
|
||||||
loopback
|
loopback
|
||||||
|
LOWCOST
|
||||||
|
LOWDELAY
|
||||||
LPRT
|
LPRT
|
||||||
LSB
|
LSB
|
||||||
lseek
|
lseek
|
||||||
|
@ -488,6 +492,7 @@ Micrium
|
||||||
MicroBlaze
|
MicroBlaze
|
||||||
MicroOS
|
MicroOS
|
||||||
middlebox
|
middlebox
|
||||||
|
MINCOST
|
||||||
mingw
|
mingw
|
||||||
MinGW
|
MinGW
|
||||||
MINIX
|
MINIX
|
||||||
|
@ -837,6 +842,7 @@ toolchain
|
||||||
toolchains
|
toolchains
|
||||||
toolset
|
toolset
|
||||||
toplevel
|
toplevel
|
||||||
|
TOS
|
||||||
TPF
|
TPF
|
||||||
TrackMemory
|
TrackMemory
|
||||||
transcode
|
transcode
|
||||||
|
|
|
@ -136,6 +136,7 @@ DPAGES = \
|
||||||
include.md \
|
include.md \
|
||||||
insecure.md \
|
insecure.md \
|
||||||
interface.md \
|
interface.md \
|
||||||
|
ip-tos.md \
|
||||||
ipfs-gateway.md \
|
ipfs-gateway.md \
|
||||||
ipv4.md \
|
ipv4.md \
|
||||||
ipv6.md \
|
ipv6.md \
|
||||||
|
|
54
docs/cmdline-opts/ip-tos.md
Normal file
54
docs/cmdline-opts/ip-tos.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
---
|
||||||
|
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
|
SPDX-License-Identifier: curl
|
||||||
|
Long: ip-tos
|
||||||
|
Arg: <string>
|
||||||
|
Help: Set IP Type of Service or Traffic Class
|
||||||
|
Added: 8.9.0
|
||||||
|
Category: connection
|
||||||
|
Protocols: All
|
||||||
|
Multi: single
|
||||||
|
See-also:
|
||||||
|
- tcp-nodelay
|
||||||
|
Example:
|
||||||
|
- --ip-tos CS5 $URL
|
||||||
|
---
|
||||||
|
|
||||||
|
# `--ip-tos`
|
||||||
|
|
||||||
|
Set Type of Service (TOS) for IPv4 or Traffic Class for IPv6. (Added in 8.9.0).
|
||||||
|
|
||||||
|
The values allowed for \<string\> can be a numeric value between 1 and 255
|
||||||
|
or one of the following:
|
||||||
|
|
||||||
|
* CS0
|
||||||
|
* CS1
|
||||||
|
* CS2
|
||||||
|
* CS3
|
||||||
|
* CS4
|
||||||
|
* CS5
|
||||||
|
* CS6
|
||||||
|
* CS7
|
||||||
|
* AF11
|
||||||
|
* AF12
|
||||||
|
* AF13
|
||||||
|
* AF21
|
||||||
|
* AF22
|
||||||
|
* AF23
|
||||||
|
* AF31
|
||||||
|
* AF32
|
||||||
|
* AF33
|
||||||
|
* AF41
|
||||||
|
* AF42
|
||||||
|
* AF43
|
||||||
|
* EF
|
||||||
|
* VOICE-ADMIT
|
||||||
|
* ECT1
|
||||||
|
* ECT0
|
||||||
|
* CE
|
||||||
|
* LE
|
||||||
|
* LOWCOST
|
||||||
|
* LOWDELAY
|
||||||
|
* THROUGHPUT
|
||||||
|
* RELIABILITY
|
||||||
|
* MINCOST
|
|
@ -98,6 +98,7 @@
|
||||||
--http3 7.66.0
|
--http3 7.66.0
|
||||||
--http3-only 7.88.0
|
--http3-only 7.88.0
|
||||||
--ignore-content-length 7.14.1
|
--ignore-content-length 7.14.1
|
||||||
|
--ip-tos 8.9.0
|
||||||
--ipfs-gateway 8.4.0
|
--ipfs-gateway 8.4.0
|
||||||
--include (-i) 4.8
|
--include (-i) 4.8
|
||||||
--insecure (-k) 7.10
|
--insecure (-k) 7.10
|
||||||
|
|
|
@ -85,6 +85,7 @@ struct OperationConfig {
|
||||||
char *range;
|
char *range;
|
||||||
long low_speed_limit;
|
long low_speed_limit;
|
||||||
long low_speed_time;
|
long low_speed_time;
|
||||||
|
long ip_tos; /* IP Type of Service */
|
||||||
char *dns_servers; /* dot notation: 1.1.1.1;2.2.2.2 */
|
char *dns_servers; /* dot notation: 1.1.1.1;2.2.2.2 */
|
||||||
char *dns_interface; /* interface name */
|
char *dns_interface; /* interface name */
|
||||||
char *dns_ipv4_addr; /* dot notation */
|
char *dns_ipv4_addr; /* dot notation */
|
||||||
|
|
|
@ -328,6 +328,7 @@ typedef enum {
|
||||||
C_TRACE_CONFIG,
|
C_TRACE_CONFIG,
|
||||||
C_TRACE_IDS,
|
C_TRACE_IDS,
|
||||||
C_TRACE_TIME,
|
C_TRACE_TIME,
|
||||||
|
C_IP_TOS,
|
||||||
C_UNIX_SOCKET,
|
C_UNIX_SOCKET,
|
||||||
C_UPLOAD_FILE,
|
C_UPLOAD_FILE,
|
||||||
C_URL,
|
C_URL,
|
||||||
|
@ -455,6 +456,7 @@ static const struct LongShort aliases[]= {
|
||||||
{"include", ARG_BOOL, 'i', C_INCLUDE},
|
{"include", ARG_BOOL, 'i', C_INCLUDE},
|
||||||
{"insecure", ARG_BOOL, 'k', C_INSECURE},
|
{"insecure", ARG_BOOL, 'k', C_INSECURE},
|
||||||
{"interface", ARG_STRG, ' ', C_INTERFACE},
|
{"interface", ARG_STRG, ' ', C_INTERFACE},
|
||||||
|
{"ip-tos", ARG_STRG, ' ', C_IP_TOS},
|
||||||
{"ipfs-gateway", ARG_STRG, ' ', C_IPFS_GATEWAY},
|
{"ipfs-gateway", ARG_STRG, ' ', C_IPFS_GATEWAY},
|
||||||
{"ipv4", ARG_NONE, '4', C_IPV4},
|
{"ipv4", ARG_NONE, '4', C_IPV4},
|
||||||
{"ipv6", ARG_NONE, '6', C_IPV6},
|
{"ipv6", ARG_NONE, '6', C_IPV6},
|
||||||
|
@ -1027,6 +1029,52 @@ static const struct LongShort *single(char letter)
|
||||||
return singles[letter - ' '];
|
return singles[letter - ' '];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TOSEntry {
|
||||||
|
const char *name;
|
||||||
|
unsigned char value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct TOSEntry tos_entries[] = {
|
||||||
|
{"AF11", 0x28},
|
||||||
|
{"AF12", 0x30},
|
||||||
|
{"AF13", 0x38},
|
||||||
|
{"AF21", 0x48},
|
||||||
|
{"AF22", 0x50},
|
||||||
|
{"AF23", 0x58},
|
||||||
|
{"AF31", 0x68},
|
||||||
|
{"AF32", 0x70},
|
||||||
|
{"AF33", 0x78},
|
||||||
|
{"AF41", 0x88},
|
||||||
|
{"AF42", 0x90},
|
||||||
|
{"AF43", 0x98},
|
||||||
|
{"CE", 0x03},
|
||||||
|
{"CS0", 0x00},
|
||||||
|
{"CS1", 0x20},
|
||||||
|
{"CS2", 0x40},
|
||||||
|
{"CS3", 0x60},
|
||||||
|
{"CS4", 0x80},
|
||||||
|
{"CS5", 0xa0},
|
||||||
|
{"CS6", 0xc0},
|
||||||
|
{"CS7", 0xe0},
|
||||||
|
{"ECT0", 0x02},
|
||||||
|
{"ECT1", 0x01},
|
||||||
|
{"EF", 0xb8},
|
||||||
|
{"LE", 0x04},
|
||||||
|
{"LOWCOST", 0x02},
|
||||||
|
{"LOWDELAY", 0x10},
|
||||||
|
{"MINCOST", 0x02},
|
||||||
|
{"RELIABILITY", 0x04},
|
||||||
|
{"THROUGHPUT", 0x08},
|
||||||
|
{"VOICE-ADMIT", 0xb0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int find_tos(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const struct TOSEntry *aa = a;
|
||||||
|
const struct TOSEntry *bb = b;
|
||||||
|
return strcmp(aa->name, bb->name);
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
|
#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
|
||||||
static ParameterError url_query(char *nextarg,
|
static ParameterError url_query(char *nextarg,
|
||||||
struct GlobalConfig *global,
|
struct GlobalConfig *global,
|
||||||
|
@ -1630,6 +1678,16 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
|
||||||
case C_TCP_NODELAY: /* --tcp-nodelay */
|
case C_TCP_NODELAY: /* --tcp-nodelay */
|
||||||
config->tcp_nodelay = toggle;
|
config->tcp_nodelay = toggle;
|
||||||
break;
|
break;
|
||||||
|
case C_IP_TOS: { /* --ip-tos */
|
||||||
|
const struct TOSEntry *entry = bsearch(
|
||||||
|
&nextarg, tos_entries, sizeof(tos_entries)/sizeof(*tos_entries),
|
||||||
|
sizeof(*tos_entries), find_tos);
|
||||||
|
if(entry)
|
||||||
|
config->ip_tos = entry->value;
|
||||||
|
else /* numeric tos value */
|
||||||
|
err = str2unummax(&config->ip_tos, nextarg, 0xFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case C_PROXY_DIGEST: /* --proxy-digest */
|
case C_PROXY_DIGEST: /* --proxy-digest */
|
||||||
config->proxydigest = toggle;
|
config->proxydigest = toggle;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -306,6 +306,9 @@ const struct helptxt helptext[] = {
|
||||||
{" --interface <name>",
|
{" --interface <name>",
|
||||||
"Use network interface",
|
"Use network interface",
|
||||||
CURLHELP_CONNECTION},
|
CURLHELP_CONNECTION},
|
||||||
|
{" --ip-tos <string>",
|
||||||
|
"Set IP Type of Service or Traffic Class",
|
||||||
|
CURLHELP_CONNECTION},
|
||||||
{" --ipfs-gateway <URL>",
|
{" --ipfs-gateway <URL>",
|
||||||
"Gateway for IPFS",
|
"Gateway for IPFS",
|
||||||
CURLHELP_IPFS},
|
CURLHELP_IPFS},
|
||||||
|
|
|
@ -45,6 +45,10 @@
|
||||||
# include <proto/dos.h>
|
# include <proto/dos.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
# include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ENABLE_CURLX_PRINTF
|
#define ENABLE_CURLX_PRINTF
|
||||||
/* use our own printf() functions */
|
/* use our own printf() functions */
|
||||||
#include "curlx.h"
|
#include "curlx.h"
|
||||||
|
@ -95,6 +99,10 @@
|
||||||
# define O_BINARY 0
|
# define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SOL_IP
|
||||||
|
# define SOL_IP IPPROTO_IP
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CURL_CA_CERT_ERRORMSG \
|
#define CURL_CA_CERT_ERRORMSG \
|
||||||
"More details here: https://curl.se/docs/sslcerts.html\n\n" \
|
"More details here: https://curl.se/docs/sslcerts.html\n\n" \
|
||||||
"curl failed to verify the legitimacy of the server and therefore " \
|
"curl failed to verify the legitimacy of the server and therefore " \
|
||||||
|
@ -142,6 +150,55 @@ static bool is_pkcs11_uri(const char *string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef IP_TOS
|
||||||
|
static int get_address_family(curl_socket_t sockfd)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
if(getsockname(sockfd, (struct sockaddr *)&addr, &addrlen) == 0)
|
||||||
|
return addr.ss_family;
|
||||||
|
return AF_UNSPEC;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(IP_TOS) || defined(IPV6_TCLASS)
|
||||||
|
static int sockopt_callback(void *clientp, curl_socket_t curlfd,
|
||||||
|
curlsocktype purpose)
|
||||||
|
{
|
||||||
|
struct OperationConfig *config = (struct OperationConfig *)clientp;
|
||||||
|
if(purpose != CURLSOCKTYPE_IPCXN)
|
||||||
|
return CURL_SOCKOPT_OK;
|
||||||
|
(void)config;
|
||||||
|
(void)curlfd;
|
||||||
|
if(config->ip_tos > 0) {
|
||||||
|
int tos = (int)config->ip_tos;
|
||||||
|
int result = 0;
|
||||||
|
switch(get_address_family(curlfd)) {
|
||||||
|
case AF_INET:
|
||||||
|
#ifdef IP_TOS
|
||||||
|
result = setsockopt(curlfd, SOL_IP, IP_TOS,
|
||||||
|
(const char *)&tos, sizeof(tos));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
#ifdef IPV6_TCLASS
|
||||||
|
result = setsockopt(curlfd, IPPROTO_IPV6, IPV6_TCLASS,
|
||||||
|
(const char *)&tos, sizeof(tos));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(result < 0) {
|
||||||
|
int error = errno;
|
||||||
|
warnf(config->global,
|
||||||
|
"Setting type of service to %d failed with errno %d: %s;\n",
|
||||||
|
tos, error, strerror(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CURL_SOCKOPT_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __VMS
|
#ifdef __VMS
|
||||||
/*
|
/*
|
||||||
* get_vms_file_size does what it takes to get the real size of the file
|
* get_vms_file_size does what it takes to get the real size of the file
|
||||||
|
@ -2189,6 +2246,17 @@ static CURLcode single_transfer(struct GlobalConfig *global,
|
||||||
my_setopt_str(curl, CURLOPT_ECH, config->ech_config);
|
my_setopt_str(curl, CURLOPT_ECH, config->ech_config);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* new in 8.9.0 */
|
||||||
|
if(config->ip_tos > 0) {
|
||||||
|
#if defined(IP_TOS) || defined(IPV6_TCLASS)
|
||||||
|
my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
|
||||||
|
my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
|
||||||
|
#else
|
||||||
|
warnf(config->global,
|
||||||
|
"Type of service is not supported in this build.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize retry vars for loop below */
|
/* initialize retry vars for loop below */
|
||||||
per->retry_sleep_default = (config->retry_delay) ?
|
per->retry_sleep_default = (config->retry_delay) ?
|
||||||
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
|
config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user