Skip to content

Instantly share code, notes, and snippets.

@danintel
Last active April 18, 2018 16:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danintel/a15fa70e94b28dee96a77c9d1bb70387 to your computer and use it in GitHub Desktop.
Save danintel/a15fa70e94b28dee96a77c9d1bb70387 to your computer and use it in GitHub Desktop.
Patch to add IPv6 Support to the Microsoft/IBM TPM 2.0 Simulator on SourceForge
--- src/TcpServerPosix.c.ori 2016-11-16 10:31:54.000000000 -0800
+++ src/TcpServerPosix.c 2018-04-18 09:10:00.000000000 -0700
@@ -82,6 +82,9 @@
#include "TcpServerPosix_fp.h"
#include "Simulator_fp.h"
+#define IPVER(len) ((len) == sizeof(struct sockaddr_in6) ? 6 : \
+ ((len) == sizeof(struct sockaddr_in) ? 4 : 0))
+
#ifndef __IGNORE_STATE__
static UINT32 ServerVersion = 1;
#define MAX_BUFFER 1048576
@@ -104,28 +107,57 @@
static int
CreateSocket(
int PortNumber,
- SOCKET *listenSocket
+ SOCKET *listenSocket,
+ socklen_t *addr_len,
+ int domain // AF_INET or AF_INET6
)
{
- struct sockaddr_in MyAddress;
+ struct sockaddr_storage MyAddress;
int opt;
int res;
// create listening socket
- *listenSocket = socket(PF_INET, SOCK_STREAM, 0);
+ *listenSocket = socket(domain, SOCK_STREAM, 0);
if(*listenSocket == -1)
{
- printf("Cannot create server listen socket. Erroris %d %s\n",
- errno, strerror(errno));
+ printf("Cannot create server listen %s socket. Error is %d %s\n",
+ domain == AF_INET6 ? "IPv6" :
+ (domain == AF_INET) ? "IPv4" : "?", errno, strerror(errno));
return -1;
}
- // bind the listening socket to the specified port
+ // bind the listening socket to the specified port, any address (0s)
memset((char *)&MyAddress, 0, sizeof(MyAddress));
- MyAddress.sin_port=htons((short) PortNumber);
- MyAddress.sin_family=AF_INET;
- MyAddress.sin_addr.s_addr = htonl(INADDR_ANY); /* host to network byte order for long */
+ MyAddress.ss_family = domain;
+ switch (domain) {
+ case AF_INET:
+ ((struct sockaddr_in *)&MyAddress)->sin_port =
+ htons((short) PortNumber);
+ if (addr_len != NULL)
+ *addr_len = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&MyAddress)->sin6_port =
+ htons((short) PortNumber);
+ if (addr_len != NULL)
+ *addr_len = sizeof(struct sockaddr_in6);
+
+ opt = 1;
+ // Set IPPROTO_IPV6 so that it's just for IPv6 and not both IPv4/IPv6.
+ res = setsockopt(*listenSocket, IPPROTO_IPV6, IPV6_V6ONLY, &opt,
+ sizeof(opt));
+ if (res != 0) {
+ printf("setsockopt IPV6_V6ONLY error. Error is %d %s\n", errno,
+ strerror(errno));
+ return -1;
+ }
+ break;
+ default:
+ printf("Address family %d not supported\n", domain);
+ return -1;
+ }
+
opt = 1;
/* Set SO_REUSEADDR before calling bind() for servers that bind to a fixed port number. */
res = setsockopt(*listenSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
@@ -253,43 +285,79 @@
)
{
int PortNumber = *(int *)port;
- SOCKET listenSocket, serverSocket;
- struct sockaddr_in HerAddress;
- int res;
- socklen_t length;
+ SOCKET listenSocket[2], maxListenSocket, serverSocket;
+ struct sockaddr_storage HerAddress;
+ fd_set sockSet;
+ int res, i;
+ int nSock = 0;
+ socklen_t length[2];
BOOL continueServing;
-
- res = CreateSocket(PortNumber, &listenSocket);
- if(res != 0)
- {
+
+ if (CreateSocket(PortNumber, &listenSocket[nSock], &length[nSock],
+ AF_INET) == 0) {
+ nSock++;
+
+ }
+ if (CreateSocket(PortNumber, &listenSocket[nSock], &length[nSock],
+ AF_INET6) == 0) {
+ nSock++;
+ }
+ if (nSock == 0) {
printf("Create platform service socket fail\n");
- return res;
+ return -1;
}
+ maxListenSocket = listenSocket[0];
+ if (nSock == 2 && listenSocket[1] > maxListenSocket) {
+ maxListenSocket = listenSocket[1];
+ }
// Loop accepting connections one-by-one until we are killed or asked to stop
// Note the platform service is single-threaded so we don't listen for a new
// connection until the prior connection drops.
do
{
- printf("Platform server listening on port %d\n", PortNumber);
-
- // blocking accept
- length = sizeof(HerAddress);
- serverSocket = accept(listenSocket,
- (struct sockaddr*) &HerAddress,
- &length);
- if(serverSocket < 0)
- {
- printf("Accept error. Error is %d %s\n", errno, strerror(errno));
- return -1;
- };
- printf("Client accepted\n");
+
+ printf("Platform server listening on port %d\n", PortNumber);
+
+ // Select both IPv4 and IPv6 sockets or whatever is available
+ FD_ZERO(&sockSet);
+ FD_SET(listenSocket[0], &sockSet);
+ if (nSock == 2)
+ FD_SET(listenSocket[1], &sockSet);
+ do {
+ res = select(maxListenSocket + 1, &sockSet, NULL, NULL, NULL);
+ } while ((res == -1) && (errno == EINTR));
+ if (res == -1) {
+ printf("Platform server select error. Error is %d %s\n", errno,
+ strerror(errno));
+ return -1;
+ }
+
+ for (i = 0; i < nSock; i++) {
+ int ipver = IPVER(length[i]);
+
+ if (!FD_ISSET(listenSocket[i], &sockSet))
+ {
+ continue;
+ }
+ // blocking accept
+ serverSocket = accept(listenSocket[i],
+ (struct sockaddr*) &HerAddress,
+ &length[i]);
+ if(serverSocket < 0)
+ {
+ printf("Platform server IPv%d Accept error. Error is %d %s\n",
+ ipver, errno, strerror(errno));
+ return -1;
+ };
+ printf("Platform IPv%d client accepted\n", ipver);
- // normal behavior on client disconnection is to wait for a new client
- // to connect
- continueServing = PlatformServer(serverSocket);
- close(serverSocket);
- serverSocket = -1;
+ // normal behavior on client disconnection is to wait for a new
+ // client to connect
+ continueServing = PlatformServer(serverSocket);
+ close(serverSocket);
+ serverSocket = -1;
+ }
}
while(continueServing);
@@ -348,45 +416,78 @@
int *PortNumber
)
{
- SOCKET listenSocket;
+ SOCKET listenSocket[2], maxListenSocket;
SOCKET serverSocket;
- struct sockaddr_in HerAddress;
-
- int res;
- socklen_t length;
+ struct sockaddr_storage HerAddress;
+ fd_set sockSet;
+ int res, i;
+ int nSock = 0;
+ socklen_t length[2];
BOOL continueServing;
-
- res = CreateSocket(*PortNumber, &listenSocket);
- if(res != 0)
- {
- printf("Create platform service socket fail\n");
- return res;
- }
+
+ if (CreateSocket(*PortNumber, &listenSocket[nSock], &length[nSock],
+ AF_INET) == 0) {
+ nSock++;
+
+ }
+ if (CreateSocket(*PortNumber, &listenSocket[nSock], &length[nSock],
+ AF_INET6) == 0) {
+ nSock++;
+ }
+ if (nSock == 0) {
+ printf("Create TPM command service socket fail\n");
+ return -1;
+ }
+ maxListenSocket = listenSocket[0];
+ if (nSock == 2 && listenSocket[1] > maxListenSocket) {
+ maxListenSocket = listenSocket[1];
+ }
// Loop accepting connections one-by-one until we are killed or asked to stop
// Note the TPM command service is single-threaded so we don't listen for
// a new connection until the prior connection drops.
do
{
- printf("TPM command server listening on port %d\n", *PortNumber);
-
- // blocking accept
- length = sizeof(HerAddress);
- serverSocket = accept(listenSocket,
- (struct sockaddr*) &HerAddress,
- &length);
- if(serverSocket < 0)
- {
- printf("Accept error. Error is %d %s\n", errno, strerror(errno));
- return -1;
- };
- printf("Client accepted\n");
+
+ printf("TPM command server listening on port %d\n", *PortNumber);
+
+ // Select both IPv4 and IPv6 sockets or whatever is available
+ FD_ZERO(&sockSet);
+ FD_SET(listenSocket[0], &sockSet);
+ if (nSock == 2)
+ FD_SET(listenSocket[1], &sockSet);
+ do {
+ res = select(maxListenSocket + 1, &sockSet, NULL, NULL, NULL);
+ } while ((res == -1) && (errno == EINTR));
+ if (res == -1) {
+ printf("TPM command server select error. Error is %d %s\n", errno,
+ strerror(errno));
+ return -1;
+ }
+
+ for (i = 0; i < nSock; i++) {
+ int ipver = IPVER(length[i]);
+
+ if (!FD_ISSET(listenSocket[i], &sockSet))
+ continue;
+ // blocking accept
+ serverSocket = accept(listenSocket[i],
+ (struct sockaddr*) &HerAddress,
+ &length[i]);
+ if(serverSocket < 0)
+ {
+ printf("TPM server IPv%d Accept error. Error is %d %s\n",
+ ipver, errno, strerror(errno));
+ return -1;
+ };
+ printf("Command IPv%d client accepted\n", ipver);
- // normal behavior on client disconnection is to wait for a new client
- // to connect
- continueServing = TpmServer(serverSocket);
- close(serverSocket);
- serverSocket = -1;
+ // normal behavior on client disconnection is to wait for a new
+ // client to connect
+ continueServing = TpmServer(serverSocket);
+ close(serverSocket);
+ serverSocket = -1;
+ }
}
while(continueServing);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment