summaryrefslogtreecommitdiff
path: root/src/udp-serv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/udp-serv.c')
-rw-r--r--src/udp-serv.c456
1 files changed, 244 insertions, 212 deletions
diff --git a/src/udp-serv.c b/src/udp-serv.c
index 08d2677a88..f9cb420ffe 100644
--- a/src/udp-serv.c
+++ b/src/udp-serv.c
@@ -21,13 +21,13 @@
#include <stdio.h>
#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
+#include <sys/socket.h>
#elif HAVE_WS2TCPIP_H
-# include <ws2tcpip.h>
+#include <ws2tcpip.h>
#endif
#include <arpa/inet.h>
#ifndef _WIN32
-# include <netinet/in.h>
+#include <netinet/in.h>
#endif
#include <sys/select.h>
#include <stdlib.h>
@@ -39,232 +39,264 @@
#include "list.h"
typedef struct {
- gnutls_session_t session;
- int fd;
- struct sockaddr * cli_addr;
- socklen_t cli_addr_size;
+ gnutls_session_t session;
+ int fd;
+ struct sockaddr *cli_addr;
+ socklen_t cli_addr_size;
} priv_data_st;
static int pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms);
-static ssize_t push_func (gnutls_transport_ptr_t p, const void * data, size_t size);
-static ssize_t pull_func(gnutls_transport_ptr_t p, void * data, size_t size);
+static ssize_t push_func(gnutls_transport_ptr_t p, const void *data,
+ size_t size);
+static ssize_t pull_func(gnutls_transport_ptr_t p, void *data,
+ size_t size);
-#define MAX_BUFFER 255 /* Longest string to echo */
+#define MAX_BUFFER 255 /* Longest string to echo */
-void udp_server(const char* name, int port, int mtu)
+void udp_server(const char *name, int port, int mtu)
{
- int sock, ret;
- struct sockaddr_in cli_addr;
- socklen_t cli_addr_size;
- char buffer[MAX_BUFFER];
- priv_data_st priv;
- gnutls_session_t session;
- gnutls_datum_t cookie_key;
- gnutls_dtls_prestate_st prestate;
- unsigned char sequence[8];
-
- ret = gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE);
- if (ret < 0)
- {
- fprintf(stderr, "Cannot generate key\n");
- exit(1);
- }
-
- ret = listen_socket (name, port, SOCK_DGRAM);
- if (ret < 0)
- {
- fprintf(stderr, "Cannot listen\n");
- exit (1);
- }
-
- for (;;)
- {
- printf("Waiting for connection...\n");
- sock = wait_for_connection();
- if (sock < 0)
- continue;
-
- cli_addr_size = sizeof(cli_addr);
- ret = recvfrom(sock, buffer, sizeof(buffer), MSG_PEEK, (struct sockaddr*)&cli_addr, &cli_addr_size);
- if (ret > 0)
- {
- memset(&prestate, 0, sizeof(prestate));
- ret = gnutls_dtls_cookie_verify(&cookie_key, &cli_addr, sizeof(cli_addr), buffer, ret, &prestate);
- if (ret < 0) /* cookie not valid */
- {
- priv_data_st s;
-
- memset(&s,0,sizeof(s));
- s.fd = sock;
- s.cli_addr = (void*)&cli_addr;
- s.cli_addr_size = sizeof(cli_addr);
-
- printf("Sending hello verify request to %s\n", human_addr ((struct sockaddr *)
- &cli_addr, sizeof(cli_addr), buffer, sizeof(buffer)));
- gnutls_dtls_cookie_send(&cookie_key, &cli_addr, sizeof(cli_addr), &prestate, (gnutls_transport_ptr_t)&s, push_func);
-
- /* discard peeked data*/
- recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&cli_addr, &cli_addr_size);
- continue;
- }
- printf ("Accepted connection from %s\n",
- human_addr ((struct sockaddr *)
- &cli_addr, sizeof(cli_addr), buffer,
- sizeof (buffer)));
- }
- else
- continue;
-
- session = initialize_session(1);
- gnutls_dtls_prestate_set(session, &prestate);
- if (mtu) gnutls_dtls_set_mtu(session, mtu);
-
- priv.session = session;
- priv.fd = sock;
- priv.cli_addr = (struct sockaddr *)&cli_addr;
- priv.cli_addr_size = sizeof(cli_addr);
-
- gnutls_transport_set_ptr (session, &priv);
- gnutls_transport_set_push_function (session, push_func);
- gnutls_transport_set_pull_function (session, pull_func);
- gnutls_transport_set_pull_timeout_function (session, pull_timeout_func);
-
- do
- {
- ret = gnutls_handshake(session);
- }
- while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
-
- if (ret < 0)
- {
- fprintf(stderr, "Error in handshake(): %s\n", gnutls_strerror(ret));
- gnutls_deinit(session);
- continue;
- }
-
- for(;;)
- {
- do
- {
- ret = gnutls_record_recv_seq(session, buffer, MAX_BUFFER, sequence);
- if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED)
- gnutls_heartbeat_pong(session, 0);
- }
- while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);
-
- if (ret == GNUTLS_E_REHANDSHAKE)
- {
- fprintf (stderr, "*** Received hello message\n");
- do
- {
- ret = gnutls_handshake (session);
- }
- while (ret == GNUTLS_E_INTERRUPTED ||
- ret == GNUTLS_E_AGAIN);
-
- if (ret == 0) continue;
- }
- if (ret < 0)
- {
- fprintf(stderr, "Error in recv(): %s\n", gnutls_strerror(ret));
- break;
- }
- if (ret == 0)
- {
- printf("EOF\n\n");
- break;
- }
-
- buffer[ret] = 0;
- printf("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n", sequence[0], sequence[1], sequence[2],
- sequence[3], sequence[4], sequence[5], sequence[6], sequence[7], buffer);
-
- if (check_command(session, buffer) == 0)
- {
- /* reply back */
- ret = gnutls_record_send(session, buffer, ret);
- if (ret < 0)
- {
- fprintf(stderr, "Error in send(): %s\n", gnutls_strerror(ret));
- break;
- }
- }
- }
- }
- gnutls_deinit(session);
+ int sock, ret;
+ struct sockaddr_in cli_addr;
+ socklen_t cli_addr_size;
+ char buffer[MAX_BUFFER];
+ priv_data_st priv;
+ gnutls_session_t session;
+ gnutls_datum_t cookie_key;
+ gnutls_dtls_prestate_st prestate;
+ unsigned char sequence[8];
+
+ ret = gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE);
+ if (ret < 0) {
+ fprintf(stderr, "Cannot generate key\n");
+ exit(1);
+ }
+
+ ret = listen_socket(name, port, SOCK_DGRAM);
+ if (ret < 0) {
+ fprintf(stderr, "Cannot listen\n");
+ exit(1);
+ }
+
+ for (;;) {
+ printf("Waiting for connection...\n");
+ sock = wait_for_connection();
+ if (sock < 0)
+ continue;
+
+ cli_addr_size = sizeof(cli_addr);
+ ret =
+ recvfrom(sock, buffer, sizeof(buffer), MSG_PEEK,
+ (struct sockaddr *) &cli_addr,
+ &cli_addr_size);
+ if (ret > 0) {
+ memset(&prestate, 0, sizeof(prestate));
+ ret =
+ gnutls_dtls_cookie_verify(&cookie_key,
+ &cli_addr,
+ sizeof(cli_addr),
+ buffer, ret,
+ &prestate);
+ if (ret < 0) { /* cookie not valid */
+ priv_data_st s;
+
+ memset(&s, 0, sizeof(s));
+ s.fd = sock;
+ s.cli_addr = (void *) &cli_addr;
+ s.cli_addr_size = sizeof(cli_addr);
+
+ printf
+ ("Sending hello verify request to %s\n",
+ human_addr((struct sockaddr *)
+ &cli_addr,
+ sizeof(cli_addr), buffer,
+ sizeof(buffer)));
+ gnutls_dtls_cookie_send(&cookie_key,
+ &cli_addr,
+ sizeof(cli_addr),
+ &prestate,
+ (gnutls_transport_ptr_t)
+ & s, push_func);
+
+ /* discard peeked data */
+ recvfrom(sock, buffer, sizeof(buffer), 0,
+ (struct sockaddr *) &cli_addr,
+ &cli_addr_size);
+ continue;
+ }
+ printf("Accepted connection from %s\n",
+ human_addr((struct sockaddr *)
+ &cli_addr, sizeof(cli_addr),
+ buffer, sizeof(buffer)));
+ } else
+ continue;
+
+ session = initialize_session(1);
+ gnutls_dtls_prestate_set(session, &prestate);
+ if (mtu)
+ gnutls_dtls_set_mtu(session, mtu);
+
+ priv.session = session;
+ priv.fd = sock;
+ priv.cli_addr = (struct sockaddr *) &cli_addr;
+ priv.cli_addr_size = sizeof(cli_addr);
+
+ gnutls_transport_set_ptr(session, &priv);
+ gnutls_transport_set_push_function(session, push_func);
+ gnutls_transport_set_pull_function(session, pull_func);
+ gnutls_transport_set_pull_timeout_function(session,
+ pull_timeout_func);
+
+ do {
+ ret = gnutls_handshake(session);
+ }
+ while (ret == GNUTLS_E_AGAIN
+ || ret == GNUTLS_E_INTERRUPTED);
+
+ if (ret < 0) {
+ fprintf(stderr, "Error in handshake(): %s\n",
+ gnutls_strerror(ret));
+ gnutls_deinit(session);
+ continue;
+ }
+
+ for (;;) {
+ do {
+ ret =
+ gnutls_record_recv_seq(session, buffer,
+ MAX_BUFFER,
+ sequence);
+ if (ret ==
+ GNUTLS_E_HEARTBEAT_PING_RECEIVED)
+ gnutls_heartbeat_pong(session, 0);
+ }
+ while (ret == GNUTLS_E_INTERRUPTED
+ || ret == GNUTLS_E_AGAIN
+ || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);
+
+ if (ret == GNUTLS_E_REHANDSHAKE) {
+ fprintf(stderr,
+ "*** Received hello message\n");
+ do {
+ ret = gnutls_handshake(session);
+ }
+ while (ret == GNUTLS_E_INTERRUPTED ||
+ ret == GNUTLS_E_AGAIN);
+
+ if (ret == 0)
+ continue;
+ }
+ if (ret < 0) {
+ fprintf(stderr, "Error in recv(): %s\n",
+ gnutls_strerror(ret));
+ break;
+ }
+ if (ret == 0) {
+ printf("EOF\n\n");
+ break;
+ }
+
+ buffer[ret] = 0;
+ printf
+ ("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n",
+ sequence[0], sequence[1], sequence[2],
+ sequence[3], sequence[4], sequence[5],
+ sequence[6], sequence[7], buffer);
+
+ if (check_command(session, buffer) == 0) {
+ /* reply back */
+ ret =
+ gnutls_record_send(session, buffer,
+ ret);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Error in send(): %s\n",
+ gnutls_strerror(ret));
+ break;
+ }
+ }
+ }
+ }
+ gnutls_deinit(session);
}
/* Wait for data to be received within a timeout period in milliseconds
*/
static int pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms)
{
-fd_set rfds;
-struct timeval tv;
-priv_data_st *priv = ptr;
-struct sockaddr_in cli_addr;
-socklen_t cli_addr_size;
-int ret;
-char c;
-
- FD_ZERO(&rfds);
- FD_SET(priv->fd, &rfds);
-
- tv.tv_sec = 0;
- tv.tv_usec = ms * 1000;
-
- while(tv.tv_usec >= 1000000)
- {
- tv.tv_usec -= 1000000;
- tv.tv_sec++;
- }
-
- ret = select(priv->fd+1, &rfds, NULL, NULL, &tv);
-
- if (ret <= 0)
- return ret;
-
- /* only report ok if the next message is from the peer we expect
- * from
- */
- cli_addr_size = sizeof(cli_addr);
- ret = recvfrom(priv->fd, &c, 1, MSG_PEEK, (struct sockaddr*)&cli_addr, &cli_addr_size);
- if (ret > 0)
- {
- if (cli_addr_size == priv->cli_addr_size && memcmp(&cli_addr, priv->cli_addr, sizeof(cli_addr))==0)
- return 1;
- }
-
- return 0;
+ fd_set rfds;
+ struct timeval tv;
+ priv_data_st *priv = ptr;
+ struct sockaddr_in cli_addr;
+ socklen_t cli_addr_size;
+ int ret;
+ char c;
+
+ FD_ZERO(&rfds);
+ FD_SET(priv->fd, &rfds);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = ms * 1000;
+
+ while (tv.tv_usec >= 1000000) {
+ tv.tv_usec -= 1000000;
+ tv.tv_sec++;
+ }
+
+ ret = select(priv->fd + 1, &rfds, NULL, NULL, &tv);
+
+ if (ret <= 0)
+ return ret;
+
+ /* only report ok if the next message is from the peer we expect
+ * from
+ */
+ cli_addr_size = sizeof(cli_addr);
+ ret =
+ recvfrom(priv->fd, &c, 1, MSG_PEEK,
+ (struct sockaddr *) &cli_addr, &cli_addr_size);
+ if (ret > 0) {
+ if (cli_addr_size == priv->cli_addr_size
+ && memcmp(&cli_addr, priv->cli_addr,
+ sizeof(cli_addr)) == 0)
+ return 1;
+ }
+
+ return 0;
}
-static ssize_t push_func (gnutls_transport_ptr_t p, const void * data, size_t size)
+static ssize_t push_func(gnutls_transport_ptr_t p, const void *data,
+ size_t size)
{
-priv_data_st *priv = p;
+ priv_data_st *priv = p;
- return sendto(priv->fd, data, size, 0, priv->cli_addr, priv->cli_addr_size);
+ return sendto(priv->fd, data, size, 0, priv->cli_addr,
+ priv->cli_addr_size);
}
-static ssize_t pull_func(gnutls_transport_ptr_t p, void * data, size_t size)
+static ssize_t pull_func(gnutls_transport_ptr_t p, void *data, size_t size)
{
-priv_data_st *priv = p;
-struct sockaddr_in cli_addr;
-socklen_t cli_addr_size;
-char buffer[64];
-int ret;
-
- cli_addr_size = sizeof(cli_addr);
- ret = recvfrom(priv->fd, data, size, 0, (struct sockaddr*)&cli_addr, &cli_addr_size);
- if (ret == -1)
- return ret;
-
- if (cli_addr_size == priv->cli_addr_size && memcmp(&cli_addr, priv->cli_addr, sizeof(cli_addr))==0)
- return ret;
-
- printf ("Denied connection from %s\n",
- human_addr ((struct sockaddr *)
- &cli_addr, sizeof(cli_addr), buffer,
- sizeof (buffer)));
-
- gnutls_transport_set_errno(priv->session, EAGAIN);
- return -1;
+ priv_data_st *priv = p;
+ struct sockaddr_in cli_addr;
+ socklen_t cli_addr_size;
+ char buffer[64];
+ int ret;
+
+ cli_addr_size = sizeof(cli_addr);
+ ret =
+ recvfrom(priv->fd, data, size, 0,
+ (struct sockaddr *) &cli_addr, &cli_addr_size);
+ if (ret == -1)
+ return ret;
+
+ if (cli_addr_size == priv->cli_addr_size
+ && memcmp(&cli_addr, priv->cli_addr, sizeof(cli_addr)) == 0)
+ return ret;
+
+ printf("Denied connection from %s\n",
+ human_addr((struct sockaddr *)
+ &cli_addr, sizeof(cli_addr), buffer,
+ sizeof(buffer)));
+
+ gnutls_transport_set_errno(priv->session, EAGAIN);
+ return -1;
}