close down of the connection), set errno to zero; otherwise leave it alone. */
#ifdef SUPPORT_TLS
-if (tls_active == sock)
- rc = tls_read(buffer, buffsize);
+if (tls_out.active == sock)
+ rc = tls_read(FALSE, buffer, buffsize);
+else if (tls_in.active == sock)
+ rc = tls_read(TRUE, buffer, buffsize);
else
#endif
rc = recv(sock, buffer, buffsize, 0);
+/*************************************************
+* Lookup address family of potential socket *
+*************************************************/
+
+/* Given a file-descriptor, check to see if it's a socket and, if so,
+return the address family; detects IPv4 vs IPv6. If not a socket then
+return -1.
+
+The value 0 is typically AF_UNSPEC, which should not be seen on a connected
+fd. If the return is -1, the errno will be from getsockname(); probably
+ENOTSOCK or ECONNRESET.
+
+Arguments: socket-or-not fd
+Returns: address family or -1
+*/
+
+int
+ip_get_address_family(int fd)
+{
+struct sockaddr_storage ss;
+socklen_t sslen = sizeof(ss);
+
+if (getsockname(fd, (struct sockaddr *) &ss, &sslen) < 0)
+ return -1;
+
+return (int) ss.ss_family;
+}
+
+
+
+
/*************************************************
* Lookup DSCP settings for a socket *
*************************************************/
/* Keep both of these tables sorted! */
static struct dscp_name_tableentry dscp_table[] = {
#ifdef IPTOS_DSCP_AF11
- { "af11", IPTOS_DSCP_AF11 },
- { "af12", IPTOS_DSCP_AF12 },
- { "af13", IPTOS_DSCP_AF13 },
- { "af21", IPTOS_DSCP_AF21 },
- { "af22", IPTOS_DSCP_AF22 },
- { "af23", IPTOS_DSCP_AF23 },
- { "af31", IPTOS_DSCP_AF31 },
- { "af32", IPTOS_DSCP_AF32 },
- { "af33", IPTOS_DSCP_AF33 },
- { "af41", IPTOS_DSCP_AF41 },
- { "af42", IPTOS_DSCP_AF42 },
- { "af43", IPTOS_DSCP_AF43 },
- { "ef", IPTOS_DSCP_EF },
+ { CUS"af11", IPTOS_DSCP_AF11 },
+ { CUS"af12", IPTOS_DSCP_AF12 },
+ { CUS"af13", IPTOS_DSCP_AF13 },
+ { CUS"af21", IPTOS_DSCP_AF21 },
+ { CUS"af22", IPTOS_DSCP_AF22 },
+ { CUS"af23", IPTOS_DSCP_AF23 },
+ { CUS"af31", IPTOS_DSCP_AF31 },
+ { CUS"af32", IPTOS_DSCP_AF32 },
+ { CUS"af33", IPTOS_DSCP_AF33 },
+ { CUS"af41", IPTOS_DSCP_AF41 },
+ { CUS"af42", IPTOS_DSCP_AF42 },
+ { CUS"af43", IPTOS_DSCP_AF43 },
+ { CUS"ef", IPTOS_DSCP_EF },
#endif
#ifdef IPTOS_LOWCOST
- { "lowcost", IPTOS_LOWCOST },
+ { CUS"lowcost", IPTOS_LOWCOST },
#endif
- { "lowdelay", IPTOS_LOWDELAY },
+ { CUS"lowdelay", IPTOS_LOWDELAY },
#ifdef IPTOS_MINCOST
- { "mincost", IPTOS_MINCOST },
+ { CUS"mincost", IPTOS_MINCOST },
#endif
- { "reliability", IPTOS_RELIABILITY },
- { "throughput", IPTOS_THROUGHPUT }
+ { CUS"reliability", IPTOS_RELIABILITY },
+ { CUS"throughput", IPTOS_THROUGHPUT }
};
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
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)
{
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)
return FALSE;
}
+void
+dscp_list_to_stream(FILE *stream)
+{
+int i;
+for (i=0; i < dscp_table_size; ++i)
+ fprintf(stream, "%s\n", dscp_table[i].name);
+}
+
/* End of ip.c */