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

View File

@ -184,7 +184,23 @@ static char* iptos(unsigned int addr)
static char output[32]; static char output[32];
byte *p = (byte*)&addr; 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; return output;
} }
@ -347,22 +363,21 @@ int main(int argc, char** argv)
if (pcap == NULL) printf("pcap_create failed %s\n", err); 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) { for (a = d->addresses; a; a = a->next) {
switch(a->addr->sa_family) if (a->addr->sa_family == AF_INET)
{ server =
case AF_INET: iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr);
server = else if (a->addr->sa_family == AF_INET6)
iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr); server =
printf("server = %s\n", server); ip6tos(((struct sockaddr_in6 *)a->addr)->sin6_addr.s6_addr);
break; else
server = NULL;
default:
break;
}
} }
if (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); ret = pcap_set_snaplen(pcap, 65536);
if (ret != 0) printf("pcap_set_snaplen failed %s\n", pcap_geterr(pcap)); 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)); if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap));
#ifndef WOLFSSL_SNIFFER_WATCH #ifndef WOLFSSL_SNIFFER_WATCH
server = "::1";
ret = ssl_SetPrivateKey(server, port, "../../certs/server-key.pem", ret = ssl_SetPrivateKey(server, port, "../../certs/server-key.pem",
FILETYPE_PEM, NULL, err); FILETYPE_PEM, NULL, err);
if (ret != 0) { if (ret != 0) {