From 2a1b36b3082412c6723ec29c1fc1ef02589bd3b3 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Sat, 2 Jun 2012 14:45:26 -0400 Subject: [PATCH 1/1] DSCP: take numeric values too. Also fix doc claim that value is unexpanded. Also strip affix whitespace before numeric conversion and fixed string comparison. --- doc/doc-docbook/spec.xfpt | 9 +++++---- doc/doc-txt/NewStuff | 1 + src/src/ip.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 15a8f3550..d370cbc3f 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -22102,13 +22102,14 @@ details. .new -.option dscp smtp string unset +.option dscp smtp string&!! unset .cindex "DCSP" .cindex "DiffServ" This option causes the DSCP value associated with a socket to be set to one -of a number of fixed strings. The &%-bI:dscp%& option may be used to ask -Exim which values it knows of. Common values include &`throughput`&, -&`mincost`&, and on newer systems &`ef`&, &`af41`&, ... +of a number of fixed strings or to numeric value. +The &%-bI:dscp%& option may be used to ask Exim which names it knows of. +Common values include &`throughput`&, &`mincost`&, and on newer systems +&`ef`&, &`af41`&, etc. Numeric values may be in the range 0 to 0x3F. The outbound packets from Exim will be marked with this value in the header (for IPv4, the TOS field; for IPv6, the TCLASS field); there is no guarantee diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 2aaf56232..e33d2858c 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -43,6 +43,7 @@ Version 4.81 set "dscp = ef", for instance, to cause the connections to have the relevant DSCP (IPv4 TOS or IPv6 TCLASS) value in the header. Supported values depend upon system libraries. "exim -bI:dscp" to list the ones Exim knows of. + You can also set a raw number 0..0x3F. Version 4.80 diff --git a/src/src/ip.c b/src/src/ip.c index be4511dfa..2be68240c 100644 --- a/src/src/ip.c +++ b/src/src/ip.c @@ -400,7 +400,11 @@ static int dscp_table_size = sizeof(dscp_table) / sizeof(struct dscp_name_tableentry); /* DSCP values change by protocol family, and so do the options used for -setsockopt(); this utility does all the lookups. +setsockopt(); this utility does all the lookups. It takes an unexpanded +option string, expands it, strips off affix whitespace, then checks if it's +a number. If all of what's left is a number, then that's how the option will +be parsed and success/failure is a range check. If it's not all a number, +then it must be a supported keyword. Arguments: dscp_name a string, so far unvalidated @@ -410,14 +414,17 @@ Arguments: dscp_value value for dscp_name Returns: TRUE if okay to setsockopt(), else FALSE + +*level and *optname may be set even if FALSE is returned */ BOOL dscp_lookup(const uschar *dscp_name, int af, int *level, int *optname, int *dscp_value) { -uschar *dscp_lookup; +uschar *dscp_lookup, *p; int first, last; +long rawlong; if (af == AF_INET) { @@ -445,6 +452,27 @@ dscp_lookup = expand_string(US dscp_name); if (dscp_lookup == NULL || *dscp_lookup == '\0') return FALSE; +p = dscp_lookup + Ustrlen(dscp_lookup) - 1; +while (isspace(*p)) *p-- = '\0'; +while (isspace(*dscp_lookup) && dscp_lookup < p) dscp_lookup++; +if (*dscp_lookup == '\0') + return FALSE; + +rawlong = Ustrtol(dscp_lookup, &p, 0); +if (p != dscp_lookup && *p == '\0') + { + /* We have six bits available, which will end up shifted to fit in 0xFC mask. + RFC 2597 defines the values unshifted. */ + if (rawlong < 0 || rawlong > 0x3F) + { + DEBUG(D_transport) + debug_printf("DSCP value %ld out of range, ignored.\n", rawlong); + return FALSE; + } + *dscp_value = rawlong << 2; + return TRUE; + } + first = 0; last = dscp_table_size; while (last > first) -- 2.30.2