More compiler quietening.
[users/jgh/exim.git] / src / src / ip.c
index 66a750dfdadd460fdf5299c723c14ac1f37bb20f..b0c98878b6736b9f3365129d50a11ee10a22af4a 100644 (file)
@@ -347,8 +347,10 @@ for (;;)
 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);
@@ -361,6 +363,37 @@ return -1;
 
 
 
+/*************************************************
+*    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        *
 *************************************************/
@@ -372,35 +405,39 @@ struct dscp_name_tableentry {
 /* 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
@@ -410,14 +447,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 +485,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)
@@ -468,5 +529,13 @@ 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 */