From 07034092357547f8c1ff55f30de9052335eab4f3 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 13 Feb 2011 08:37:12 +0000 Subject: [PATCH] introduce-network-connect-filter-callback.patch Signed-off-by: Andy Green --- lib/libwebsockets.c | 78 +++++++++++++++++++++++++++++++++++++++ lib/libwebsockets.h | 15 ++++++++ libwebsockets-api-doc.html | 47 ++++++++++++++++++++++- test-server/test-server-extpoll.c | 4 +- 4 files changed, 142 insertions(+), 2 deletions(-) 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 @@ libwebsocket_close_and_free_session(struct libwebsocket *wsi) 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 @@ libwebsocket_service_fd(struct libwebsocket_context *this, 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 @@ enum libwebsocket_callback_reasons { 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 @@ struct libwebsocket_context; * 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 @@ libwebsocket_canonical_hostname(struct libwebsocket_context *this); 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 @@ +

libwebsockets_get_peer_addresses - Get client address information

+void +libwebsockets_get_peer_addresses +(int fd, +char * name, +int name_len, +char * rip, +int rip_len) +

Arguments

+
+
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 +
+

Description

+
+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. +
+

libwebsocket_service_fd - Service polled socket with something waiting

int libwebsocket_service_fd @@ -485,12 +514,28 @@ accept another write packet without blocking. If it already 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. -user is a pointer to an array of +user 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.

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 @@ static int callback_http(struct libwebsocket *wsi, 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 @@ static int callback_http(struct libwebsocket *wsi, /* * callbacks for managing the external poll() array appear in - * protocl 0 callback + * protocol 0 callback */ case LWS_CALLBACK_ADD_POLL_FD: -- 2.7.4