Change the IP address wrappers to include the version. Makes comparing

easier. Hard-coded some IPv6 localhost tests.
This commit is contained in:
John Safranek 2019-09-06 16:12:09 -07:00
parent d1d2eb0edd
commit a5bfb8a18b
2 changed files with 103 additions and 80 deletions

View File

@ -317,9 +317,12 @@ typedef struct NamedKey {
#endif
typedef union IpAddrInfo {
word32 ip4;
word32 ip6[4];
typedef struct IpAddrInfo {
int version;
union {
word32 ip4;
byte ip6[16];
};
} IpAddrInfo;
@ -328,7 +331,6 @@ typedef struct SnifferServer {
SSL_CTX* ctx; /* SSL context */
char address[MAX_SERVER_ADDRESS]; /* passed in server address */
IpAddrInfo server; /* network order address */
int version; /* IP version */
int port; /* server port */
#ifdef HAVE_SNI
NamedKey* namedKeys; /* mapping of names and keys */
@ -392,7 +394,6 @@ typedef struct SnifferSession {
SSL* sslClient; /* SSL client side decode */
IpAddrInfo server; /* server address in network byte order */
IpAddrInfo client; /* client address in network byte order */
int version;
word16 srvPort; /* server port */
word16 cliPort; /* client port */
word32 cliSeqStart; /* client start sequence */
@ -782,7 +783,6 @@ static void InitSession(SnifferSession* session)
/* IP Info from IP Header */
typedef struct IpInfo {
int version; /* IP version */
int length; /* length of this header */
int total; /* total length of fragment */
IpAddrInfo src; /* network order source address */
@ -855,8 +855,8 @@ typedef struct Ip6Hdr {
word16 length; /* payload length */
byte next_header; /* next header (6 for TCP, any other skip) */
byte hl; /* hop limit */
word32 src[4]; /* source address */
word32 dst[4]; /* destination address */
byte src[16]; /* source address */
byte dst[16]; /* destination address */
} Ip6Hdr;
@ -960,12 +960,12 @@ static char* IpToS(word32 addr, char* str)
/* Convert network byte order address into human readable */
static char* Ip6ToS(word32* addr, char* str)
static char* Ip6ToS(byte* addr, char* str)
{
byte* p = (byte*)addr;
/* Very incorrect. XXX */
SNPRINTF(str, TRACE_MSG_SZ, "::%d", p[127]);
SNPRINTF(str, TRACE_MSG_SZ, "::%d", p[15]);
return str;
}
@ -989,7 +989,7 @@ static void TraceIP6(Ip6Hdr* iphdr)
if (TraceOn) {
char src[TRACE_MSG_SZ];
char dst[TRACE_MSG_SZ];
fprintf(TraceFile, "\tdst:%s src:%s\n", Ip6ToS(iphdr->dst, dst),
fprintf(TraceFile, "\tdst: %s src: %s\n", Ip6ToS(iphdr->dst, dst),
Ip6ToS(iphdr->src, src));
}
}
@ -1166,6 +1166,19 @@ static void SetError(int idx, char* error, SnifferSession* session, int fatal)
}
/* Compare IpAddrInfo structs */
static inline int MatchAddr(IpAddrInfo l, IpAddrInfo r)
{
if (l.version == r.version) {
if (l.version == IPV4)
return (l.ip4 == r.ip4);
else if (l.version == IPV6)
return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6)));
}
return 0;
}
#ifndef WOLFSSL_SNIFFER_WATCH
/* See if this IPV4 network order address has been registered */
@ -1195,7 +1208,7 @@ static int IsServerRegistered(word32 addr)
/* See if this port has been registered to watch */
/* See if this IPV4 network order address has been registered */
/* return 1 is true, 0 is false */
static int IsServerRegistered6(word32* addr)
static int IsServerRegistered6(byte* addr)
{
int ret = 0; /* false */
SnifferServer* sniffer;
@ -1204,7 +1217,8 @@ static int IsServerRegistered6(word32* addr)
sniffer = ServerList;
while (sniffer) {
if (XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) {
if (sniffer->server.version == IPV6 &&
0 == XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) {
ret = 1;
break;
}
@ -1254,24 +1268,12 @@ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
#ifndef WOLFSSL_SNIFFER_WATCH
while (sniffer) {
if (ipInfo->version == IPV4) {
if (sniffer->port == tcpInfo->srcPort &&
sniffer->server.ip4 == ipInfo->src.ip4)
break;
if (sniffer->port == tcpInfo->dstPort &&
sniffer->server.ip4 == ipInfo->dst.ip4)
break;
}
else if (ipInfo->version == IPV6) {
if (sniffer->port == tcpInfo->srcPort &&
XMEMCMP(sniffer->server.ip6, ipInfo->src.ip6,
sizeof(sniffer->server.ip6)) == 0)
break;
if (sniffer->port == tcpInfo->dstPort &&
XMEMCMP(sniffer->server.ip6, ipInfo->dst.ip6,
sizeof(sniffer->server.ip6)) == 0)
break;
}
if (sniffer->port == tcpInfo->srcPort &&
MatchAddr(sniffer->server, ipInfo->src))
break;
if (sniffer->port == tcpInfo->dstPort &&
MatchAddr(sniffer->server, ipInfo->dst))
break;
sniffer = sniffer->next;
}
@ -1291,17 +1293,18 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
{
word32 hash = 1;
if (ipInfo->version == IPV4) {
if (ipInfo->src.version == IPV4) {
hash *= ipInfo->src.ip4 * ipInfo->dst.ip4;
}
else if (ipInfo->version == IPV6) {
word32 x;
x = ipInfo->src.ip6[0] ^ ipInfo->src.ip6[1] ^
ipInfo->src.ip6[2] ^ ipInfo->src.ip6[3];
hash *= x;
x = ipInfo->dst.ip6[0] ^ ipInfo->dst.ip6[1] ^
ipInfo->dst.ip6[2] ^ ipInfo->dst.ip6[3];
hash *= x;
else if (ipInfo->src.version == IPV6) {
word32* x;
word32 y;
x = (word32*)ipInfo->src.ip6;
y = x[0] ^ x[1] ^ x[2] ^ x[3];
hash *= y;
x = (word32*)ipInfo->dst.ip6;
y = x[0] ^ x[1] ^ x[2] ^ x[3];
hash *= y;
}
hash *= tcpInfo->srcPort * tcpInfo->dstPort;
@ -1309,15 +1312,6 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
}
static inline int MatchAddr(int version, IpAddrInfo l, IpAddrInfo r)
{
if (version == IPV4)
return (l.ip4 == r.ip4);
else
return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6)));
}
/* Get Exisiting SnifferSession from IP and Port */
static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
{
@ -1331,14 +1325,14 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
session = SessionTable[row];
while (session) {
if (MatchAddr(session->version, session->server, ipInfo->src) &&
MatchAddr(session->version, session->client, ipInfo->dst) &&
if (MatchAddr(session->server, ipInfo->src) &&
MatchAddr(session->client, ipInfo->dst) &&
session->srvPort == tcpInfo->srcPort &&
session->cliPort == tcpInfo->dstPort)
break;
if (MatchAddr(session->version, session->client, ipInfo->src) &&
MatchAddr(session->version, session->server, ipInfo->dst) &&
if (MatchAddr(session->client, ipInfo->src) &&
MatchAddr(session->server, ipInfo->dst) &&
session->cliPort == tcpInfo->srcPort &&
session->srvPort == tcpInfo->dstPort)
break;
@ -1353,7 +1347,7 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
/* determine side */
if (session) {
if (MatchAddr(ipInfo->version, ipInfo->dst, session->server) &&
if (MatchAddr(ipInfo->dst, session->server) &&
tcpInfo->dstPort == session->srvPort) {
session->flags.side = WOLFSSL_SERVER_END;
@ -1451,7 +1445,8 @@ static int CreateWatchSnifferServer(char* error)
{
SnifferServer* sniffer;
sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL,
DYNAMIC_TYPE_SNIFFER_SERVER);
if (sniffer == NULL) {
SetError(MEMORY_STR, error, NULL, 0);
return -1;
@ -1482,7 +1477,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
int type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
WOLFSSL_FILETYPE_ASN1;
int isNew = 0;
word32 serverIp;
IpAddrInfo serverIp;
#ifdef HAVE_SNI
NamedKey* namedKey = NULL;
@ -1515,10 +1510,18 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
}
#endif
serverIp = inet_addr(address);
serverIp.version = IPV4;
serverIp.ip4 = inet_addr(address);
if (serverIp.ip4 == INADDR_NONE) {
if (inet_pton(AF_INET6, address, serverIp.ip6) == 1) {
serverIp.version = IPV6;
serverIp.ip6[0] = 0;
serverIp.ip6[1] = 0;
}
}
sniffer = ServerList;
while (sniffer != NULL &&
(sniffer->server.ip4 != serverIp || sniffer->port != port)) {
(!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) {
sniffer = sniffer->next;
}
@ -1537,7 +1540,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
sniffer->server.ip4 = serverIp;
sniffer->server = serverIp;
sniffer->port = port;
sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method());
@ -1665,10 +1668,13 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
}
#endif
info->total = ntohs(iphdr->length);
info->version = IPV6;
info->length = 40;
info->total = ntohs(iphdr->length) + info->length;
/* IPv6 doesn't include its own header size in the length like v4. */
info->src.version = IPV6;
XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6));
XMEMCPY(info->dst.ip6, iphdr->src, sizeof(info->dst.ip6));
info->dst.version = IPV6;
XMEMCPY(info->dst.ip6, iphdr->dst, sizeof(info->dst.ip6));
/* This needs to massage the length and size to match what the sniffer
* expects. IPv4 and IPv6 treat the length parameter differently. */
@ -1686,12 +1692,12 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
{
int version = IP_V(iphdr);
TraceIP(iphdr);
Trace(IP_CHECK_STR);
if (version == IPV6)
return CheckIp6Hdr((Ip6Hdr*)iphdr, info, length, error);
TraceIP(iphdr);
Trace(IP_CHECK_STR);
if (version != IPV4) {
SetError(BAD_IPVER_STR, error, NULL, 0);
return -1;
@ -1711,8 +1717,9 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
info->length = IP_HL(iphdr);
info->total = ntohs(iphdr->length);
info->version = IPV4;
info->src.version = IPV4;
info->src.ip4 = iphdr->src;
info->dst.version = IPV4;
info->dst.ip4 = iphdr->dst;
if (info->total == 0)

View File

@ -184,7 +184,23 @@ static char* iptos(unsigned int addr)
static char output[32];
byte *p = (byte*)&addr;
SNPRINTF(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
snprintf(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output;
}
static char* ip6tos(const unsigned char* addr)
{
static char output[42];
snprintf(output, sizeof(output),
"%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
"%02x%02x:%02x%02x:%02x%02x:%02x%02x",
addr[0], addr[1], addr[2], addr[3],
addr[4], addr[5], addr[6], addr[7],
addr[8], addr[9], addr[10], addr[11],
addr[12], addr[13], addr[14], addr[15]);
return output;
}
@ -347,22 +363,21 @@ int main(int argc, char** argv)
if (pcap == NULL) printf("pcap_create failed %s\n", err);
/* get an IPv4 address */
/* get an IPv4 or IPv6 address */
for (a = d->addresses; a; a = a->next) {
switch(a->addr->sa_family)
{
case AF_INET:
server =
iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr);
printf("server = %s\n", server);
break;
default:
break;
}
if (a->addr->sa_family == AF_INET)
server =
iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr);
else if (a->addr->sa_family == AF_INET6)
server =
ip6tos(((struct sockaddr_in6 *)a->addr)->sin6_addr.s6_addr);
else
server = NULL;
}
if (server == NULL)
err_sys("Unable to get device IPv4 address");
err_sys("Unable to get device IPv4 or IPv6 address");
else
printf("server = %s\n", server);
ret = pcap_set_snaplen(pcap, 65536);
if (ret != 0) printf("pcap_set_snaplen failed %s\n", pcap_geterr(pcap));
@ -395,6 +410,7 @@ int main(int argc, char** argv)
if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap));
#ifndef WOLFSSL_SNIFFER_WATCH
server = "::1";
ret = ssl_SetPrivateKey(server, port, "../../certs/server-key.pem",
FILETYPE_PEM, NULL, err);
if (ret != 0) {