introduce-network-connect-filter-callback.patch

Signed-off-by: Andy Green <andy.green@linaro.org>
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index 49913b7..59c954a 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -133,6 +133,70 @@
 	free(wsi);
 }
 
+/**
+ * libwebsockets_get_peer_addresses() - Get client address information
+ * @fd:		Connection socket descriptor
+ * @name:	Buffer to take client address name
+ * @name_len:	Length of client address name buffer
+ * @rip:	Buffer to take client address IP qotted quad
+ * @rip_len:	Length of client address IP buffer
+ *
+ *	This function fills in @name and @rip with the name and IP of
+ * 	the client connected with socket descriptor @fd.  Names may be
+ * 	truncated if there is not enough room.  If either cannot be
+ * 	determined, they will be returned as valid zero-length strings.
+ */
+
+void
+libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
+					char *rip, int rip_len)
+{
+	unsigned int len;
+	struct sockaddr_in sin;
+	struct hostent *host;
+	struct hostent *host1;
+	char ip[128];
+	char *p;
+	int n;
+
+	rip[0] = '\0';
+	name[0] = '\0';
+
+	len = sizeof sin;
+	if (getpeername(fd, (struct sockaddr *) &sin, &len) < 0) {
+		perror("getpeername");
+		return;
+	}
+		
+	host = gethostbyaddr((char *) &sin.sin_addr, sizeof sin.sin_addr,
+								       AF_INET);
+	if (host == NULL) {
+		perror("gethostbyaddr");
+		return;
+	}
+
+	strncpy(name, host->h_name, name_len);
+	name[name_len - 1] = '\0';
+
+	host1 = gethostbyname(host->h_name);
+	if (host1 == NULL)
+		return;
+	p = (char *)host1;
+	n = 0;
+	while (p != NULL) {
+		p = host1->h_addr_list[n++];
+		if (p == NULL)
+			continue;
+		if (host1->h_addrtype != AF_INET)
+			continue;
+
+		sprintf(ip, "%d.%d.%d.%d",
+				p[0], p[1], p[2], p[3]);
+		p = NULL;
+		strncpy(rip, ip, rip_len);
+		rip[rip_len - 1] = '\0';
+	}
+}
 
 /**
  * libwebsocket_service_fd() - Service polled socket with something waiting
@@ -187,6 +251,20 @@
 			break;
 		}
 
+		/*
+		 * look at who we connected to and give user code a chance
+		 * to reject based on client IP.  There's no protocol selected
+		 * yet so we issue this to protocols[0]
+		 */
+
+		if ((this->protocols[0].callback)(wsi,
+				LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
+					     (void*)(long)accept_fd, NULL, 0)) {
+			fprintf(stderr, "Callback denied network connection\n");
+			close(accept_fd);
+			break;
+		}
+
 		/* accepting connection to main listener */
 
 		new_wsi = malloc(sizeof(struct libwebsocket));
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index 72962f9..31f28e9 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -41,6 +41,7 @@
 	LWS_CALLBACK_CLIENT_WRITEABLE,
 	LWS_CALLBACK_HTTP,
 	LWS_CALLBACK_BROADCAST,
+	LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
 	LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
 
 	/* external poll() management support */
@@ -180,6 +181,16 @@
  *		was able to take another packet without blocking, you'll get
  *		this callback at the next call to the service loop function.
  *
+ *	LWS_CALLBACK_FILTER_NETWORK_CONNECTION: called when a client connects to
+ *		the server at network level; the connection is accepted but then
+ *		passed to this callback to decide whether to hang up immediately
+ *		or not, based on the client IP.  @user contains the connection
+ *		socket's descriptor.  Return non-zero to terminate
+ *		the connection before sending or receiving anything.
+ * 		Because this happens immediately after the network connection
+ *		from the client, there's no websocket protocol selected yet so
+ *		this callback is issued only to protocol 0.
+ *
  * 	LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has
  * 		been received and parsed from the client, but the response is
  * 		not sent yet.  Return non-zero to disallow the connection.
@@ -373,4 +384,8 @@
 extern void
 libwebsocket_client_close(struct libwebsocket *wsi);
 
+extern void
+libwebsockets_get_peer_addresses(int fd, char *name, int name_len,
+					char *rip, int rip_len);
+
 #endif
diff --git a/libwebsockets-api-doc.html b/libwebsockets-api-doc.html
index 2c08d1f..487b942 100644
--- a/libwebsockets-api-doc.html
+++ b/libwebsockets-api-doc.html
@@ -1,3 +1,32 @@
+<h2>libwebsockets_get_peer_addresses - Get client address information</h2>
+<i>void</i>
+<b>libwebsockets_get_peer_addresses</b>
+(<i>int</i> <b>fd</b>,
+<i>char *</i> <b>name</b>,
+<i>int</i> <b>name_len</b>,
+<i>char *</i> <b>rip</b>,
+<i>int</i> <b>rip_len</b>)
+<h3>Arguments</h3>
+<dl>
+<dt><b>fd</b>
+<dd>Connection socket descriptor
+<dt><b>name</b>
+<dd>Buffer to take client address name
+<dt><b>name_len</b>
+<dd>Length of client address name buffer
+<dt><b>rip</b>
+<dd>Buffer to take client address IP qotted quad
+<dt><b>rip_len</b>
+<dd>Length of client address IP buffer
+</dl>
+<h3>Description</h3>
+<blockquote>
+This function fills in <tt><b>name</b></tt> and <tt><b>rip</b></tt> with the name and IP of
+the client connected with socket descriptor <tt><b>fd</b></tt>.  Names may be
+truncated if there is not enough room.  If either cannot be
+determined, they will be returned as valid zero-length strings.
+</blockquote>
+<hr>
 <h2>libwebsocket_service_fd - Service polled socket with something waiting</h2>
 <i>int</i>
 <b>libwebsocket_service_fd</b>
@@ -485,12 +514,28 @@
 was able to take another packet without blocking, you'll get
 this callback at the next call to the service loop function.
 </blockquote>
+<h3>LWS_CALLBACK_FILTER_NETWORK_CONNECTION</h3>
+<blockquote>
+called when a client connects to
+the server at network level; the connection is accepted but then
+passed to this callback to decide whether to hang up immediately
+or not, based on the client IP.  <tt><b>user</b></tt> contains the connection
+socket's descriptor.  Return non-zero to terminate
+the connection before sending or receiving anything.
+Because this happens immediately after the network connection
+from the client, there's no websocket protocol selected yet so
+this callback is issued only to protocol 0.
+</blockquote>
 <h3>LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION</h3>
 <blockquote>
 called when the handshake has
 been received and parsed from the client, but the response is
 not sent yet.  Return non-zero to disallow the connection.
-<tt><b>user</b></tt> is a pointer to an array of 
+<tt><b>user</b></tt> is a pointer to an array of struct lws_tokens, you can
+use the header enums lws_token_indexes from libwebsockets.h
+to check for and read the supported header presence and
+content before deciding to allow the handshake to proceed or
+to kill the connection.
 <p>
 <p>
 The next four reasons are optional and only need taking care of if you
diff --git a/test-server/test-server-extpoll.c b/test-server/test-server-extpoll.c
index d7ea10d..e0eced7 100644
--- a/test-server/test-server-extpoll.c
+++ b/test-server/test-server-extpoll.c
@@ -77,6 +77,8 @@
 							   void *in, size_t len)
 {
 	int n;
+	char client_name[128];
+	char client_ip[128];
 
 	switch (reason) {
 	case LWS_CALLBACK_HTTP:
@@ -98,7 +100,7 @@
 
 	/*
 	 * callbacks for managing the external poll() array appear in
-	 * protocl 0 callback
+	 * protocol 0 callback
 	 */
 
 	case LWS_CALLBACK_ADD_POLL_FD: