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: