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 #include #include #include #include -#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 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.