bb2d391712fb0208347ffc0b88abe146df14dc0a
galt
  Fri Jun 21 18:21:50 2019 -0700
Adding Support for CIDR specification of subnets, e.g. 192.168.1.255/31. It still supports the older subnet format too, e.g. 192.168

diff --git src/lib/net.c src/lib/net.c
index 75dcea1..60689c4 100644
--- src/lib/net.c
+++ src/lib/net.c
@@ -1,27 +1,26 @@
 /* net.c some stuff to wrap around net communications. 
  *
  * This file is copyright 2002 Jim Kent, but license is hereby
  * granted for all use - public, private or commercial. */
 
 #include "common.h"
 #include <signal.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/time.h>
 #include <pthread.h>
-#include "internet.h"
 #include "errAbort.h"
 #include "hash.h"
 #include "net.h"
 #include "linefile.h"
 #include "base64.h"
 #include "cheapcgi.h"
 #include "https.h"
 #include "sqlNum.h"
 #include "obscure.h"
 
 /* Brought errno in to get more useful error messages */
 extern int errno;
 
 static int netStreamSocket()
 /* Create a TCP/IP streaming socket.  Complain and return something
@@ -273,52 +272,52 @@
 
 int netAcceptingSocket(int port, int queueSize)
 /* Create a socket that can accept connections from
  * anywhere. */
 {
 return netAcceptingSocketFrom(port, queueSize, NULL);
 }
 
 int netAccept(int sd)
 /* Accept incoming connection from socket descriptor. */
 {
 socklen_t fromLen;
 return accept(sd, NULL, &fromLen);
 }
 
-int netAcceptFrom(int acceptor, unsigned char subnet[4])
+int netAcceptFrom(int acceptor, struct cidr *subnet)
 /* Wait for incoming connection from socket descriptor
  * from IP address in subnet.  Subnet is something
  * returned from netParseSubnet or internetParseDottedQuad. 
  * Subnet may be NULL. */
 {
 struct sockaddr_in sai;		/* Some system socket info. */
 ZeroVar(&sai);
 sai.sin_family = AF_INET;
 for (;;)
     {
     socklen_t addrSize = sizeof(sai);
     int sd = accept(acceptor, (struct sockaddr *)&sai, &addrSize);
     if (sd >= 0)
 	{
 	if (subnet == NULL)
 	    return sd;
 	else
 	    {
 	    unsigned char unpacked[4]; 
 	    internetUnpackIp(ntohl(sai.sin_addr.s_addr), unpacked);
-	    if (internetIpInSubnet(unpacked, subnet))
+	    if (internetIpInSubnetCidr(unpacked, subnet))
 		{
 		return sd;
 		}
 	    else
 		{
 		close(sd);
 		}
 	    }
 	}
     }
 }
 
 FILE *netFileFromSocket(int socket)
 /* Wrap a FILE around socket.  This should be fclose'd
  * and separately the socket close'd. */
@@ -364,86 +363,51 @@
     totalRead += oneRead;
     }
 return totalRead;
 }
 
 ssize_t netMustReadAll(int sd, void *vBuf, ssize_t size)
 /* Read given number of bytes into buffer or die.
  * Don't give up if first read is short! */
 {
 ssize_t ret = netReadAll(sd, vBuf, size);
 if (ret < 0)
     errnoAbort("Couldn't finish netReadAll");
 return ret;
 }
 
-static void notGoodSubnet(char *sns)
-/* Complain about subnet format. */
-{
-errAbort("'%s' is not a properly formatted subnet.  Subnets must consist of\n"
-         "one to three dot-separated numbers between 0 and 255", sns);
-}
-
-void netParseSubnet(char *in, unsigned char out[4])
-/* Parse subnet, which is a prefix of a normal dotted quad form.
- * Out will contain 255's for the don't care bits. */
-{
-out[0] = out[1] = out[2] = out[3] = 255;
-if (in != NULL)
-    {
-    char *snsCopy = strdup(in);
-    char *words[5];
-    int wordCount, i;
-    wordCount = chopString(snsCopy, ".", words, ArraySize(words));
-    if (wordCount > 3 || wordCount < 1)
-        notGoodSubnet(in);
-    for (i=0; i<wordCount; ++i)
-	{
-	char *s = words[i];
-	int x;
-	if (!isdigit(s[0]))
-	    notGoodSubnet(in);
-	x = atoi(s);
-	if (x > 255)
-	    notGoodSubnet(in);
-	out[i] = x;
-	}
-    freez(&snsCopy);
-    }
-}
 
 static void parseByteRange(char *url, ssize_t *rangeStart, ssize_t *rangeEnd, boolean terminateAtByteRange)
 /* parse the byte range information from url */
 {
 char *x;
 /* default to no byte range specified */
 *rangeStart = -1;
 *rangeEnd = -1;
 x = strrchr(url, ';');
 if (x)
     {
     if (startsWith(";byterange=", x))
 	{
 	char *y=strchr(x, '=');
 	++y;
 	char *z=strchr(y, '-');
 	if (z)
 	    {
 	    ++z;
 	    if (terminateAtByteRange)
 		*x = 0;
-	    // TODO: use something better than atoll() ?
 	    *rangeStart = atoll(y); 
 	    if (z[0] != '\0')
 		*rangeEnd = atoll(z);
 	    }    
 	}
     }
 
 }
 
 void netParseUrl(char *url, struct netParsedUrl *parsed)
 /* Parse a URL into components.   A full URL is made up as so:
  *   http://user:password@hostName:port/file;byterange=0-499
  * User and password may be cgi-encoded.
  * This is set up so that the http:// and the port are optional. 
  */
@@ -855,31 +819,30 @@
     }
 /* 200 Type set to I */
 /* (send the data as binary, so can support compressed files) */
 return sd;
 }
 
 boolean netGetFtpInfo(char *url, long long *retSize, time_t *retTime)
 /* Return date in UTC and size of ftp url file */
 {
 /* Parse the URL and connect. */
 struct netParsedUrl npu;
 netParseUrl(url, &npu);
 if (!sameString(npu.protocol, "ftp"))
     errAbort("netGetFtpInfo: url (%s) is not for ftp.", url);
 
-// TODO maybe remove this workaround where udc cache wants info on URL "/" ?
 if (sameString(npu.file,"/"))
     {
     *retSize = 0;
     *retTime = time(NULL);
     return TRUE;
     }
 
 int sd = openFtpControlSocket(npu.host, atoi(npu.port), npu.user, npu.password);
 if (sd < 0)
     return FALSE;
 char cmd[256];
 safef(cmd,sizeof(cmd),"SIZE %s\r\n", npu.file);
 struct dyString *rs = NULL;
 if (!sendFtpCommand(sd, cmd, &rs, NULL))
     {
@@ -1362,31 +1325,30 @@
 /* parse the content range information from response header value 
 	"bytes 763400000-763400112/763400113"
  */
 {
 /* default to no byte range specified */
 *rangeStart = -1;
 *rangeEnd = -1;
 if (startsWith("bytes ", x))
     {
     char *y=strchr(x, ' ');
     ++y;
     char *z=strchr(y, '-');
     if (z)
 	{
 	++z;
-	// TODO: use something better than atoll() ?
 	*rangeStart = atoll(y); 
 	if (z[0] != '\0')
 	    *rangeEnd = atoll(z);
 	}    
     }
 
 }
 
 
 boolean netSkipHttpHeaderLinesWithRedirect(int sd, char *url, char **redirectedUrl)
 /* Skip http header lines. Return FALSE if there's a problem.
  * The input is a standard sd or fd descriptor.
  * This is meant to be able work even with a re-passable stream handle,
  * e.g. can pass it to the pipes routines, which means we can't
  * attach a linefile since filling its buffer reads in more than just the http header.