|
Packit Service |
4684c1 |
/* This example code is placed in the public domain. */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
4684c1 |
#include <config.h>
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <stdio.h>
|
|
Packit Service |
4684c1 |
#include <stdlib.h>
|
|
Packit Service |
4684c1 |
#include <errno.h>
|
|
Packit Service |
4684c1 |
#include <sys/types.h>
|
|
Packit Service |
4684c1 |
#include <sys/socket.h>
|
|
Packit Service |
4684c1 |
#include <arpa/inet.h>
|
|
Packit Service |
4684c1 |
#include <netinet/in.h>
|
|
Packit Service |
4684c1 |
#include <sys/select.h>
|
|
Packit Service |
4684c1 |
#include <netdb.h>
|
|
Packit Service |
4684c1 |
#include <string.h>
|
|
Packit Service |
4684c1 |
#include <unistd.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/gnutls.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/dtls.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define KEYFILE "key.pem"
|
|
Packit Service |
4684c1 |
#define CERTFILE "cert.pem"
|
|
Packit Service |
4684c1 |
#define CAFILE "/etc/ssl/certs/ca-certificates.crt"
|
|
Packit Service |
4684c1 |
#define CRLFILE "crl.pem"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* This is a sample DTLS echo server, using X.509 authentication.
|
|
Packit Service |
4684c1 |
* Note that error checking is minimal to simplify the example.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define LOOP_CHECK(rval, cmd) \
|
|
Packit Service |
4684c1 |
do { \
|
|
Packit Service |
4684c1 |
rval = cmd; \
|
|
Packit Service |
4684c1 |
} while(rval == GNUTLS_E_AGAIN || rval == GNUTLS_E_INTERRUPTED)
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define MAX_BUFFER 1024
|
|
Packit Service |
4684c1 |
#define PORT 5557
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
typedef struct {
|
|
Packit Service |
4684c1 |
gnutls_session_t session;
|
|
Packit Service |
4684c1 |
int fd;
|
|
Packit Service |
4684c1 |
struct sockaddr *cli_addr;
|
|
Packit Service |
4684c1 |
socklen_t cli_addr_size;
|
|
Packit Service |
4684c1 |
} priv_data_st;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms);
|
|
Packit Service |
4684c1 |
static ssize_t push_func(gnutls_transport_ptr_t p, const void *data,
|
|
Packit Service |
4684c1 |
size_t size);
|
|
Packit Service |
4684c1 |
static ssize_t pull_func(gnutls_transport_ptr_t p, void *data,
|
|
Packit Service |
4684c1 |
size_t size);
|
|
Packit Service |
4684c1 |
static const char *human_addr(const struct sockaddr *sa, socklen_t salen,
|
|
Packit Service |
4684c1 |
char *buf, size_t buflen);
|
|
Packit Service |
4684c1 |
static int wait_for_connection(int fd);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Use global credentials and parameters to simplify
|
|
Packit Service |
4684c1 |
* the example. */
|
|
Packit Service |
4684c1 |
static gnutls_certificate_credentials_t x509_cred;
|
|
Packit Service |
4684c1 |
static gnutls_priority_t priority_cache;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int main(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int listen_sd;
|
|
Packit Service |
4684c1 |
int sock, ret;
|
|
Packit Service |
4684c1 |
struct sockaddr_in sa_serv;
|
|
Packit Service |
4684c1 |
struct sockaddr_in cli_addr;
|
|
Packit Service |
4684c1 |
socklen_t cli_addr_size;
|
|
Packit Service |
4684c1 |
gnutls_session_t session;
|
|
Packit Service |
4684c1 |
char buffer[MAX_BUFFER];
|
|
Packit Service |
4684c1 |
priv_data_st priv;
|
|
Packit Service |
4684c1 |
gnutls_datum_t cookie_key;
|
|
Packit Service |
4684c1 |
gnutls_dtls_prestate_st prestate;
|
|
Packit Service |
4684c1 |
int mtu = 1400;
|
|
Packit Service |
4684c1 |
unsigned char sequence[8];
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* this must be called once in the program
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
gnutls_global_init();
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_certificate_allocate_credentials(&x509_cred);
|
|
Packit Service |
4684c1 |
gnutls_certificate_set_x509_trust_file(x509_cred, CAFILE,
|
|
Packit Service |
4684c1 |
GNUTLS_X509_FMT_PEM);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_certificate_set_x509_crl_file(x509_cred, CRLFILE,
|
|
Packit Service |
4684c1 |
GNUTLS_X509_FMT_PEM);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_certificate_set_x509_key_file(x509_cred, CERTFILE,
|
|
Packit Service |
4684c1 |
KEYFILE,
|
|
Packit Service |
4684c1 |
GNUTLS_X509_FMT_PEM);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
printf("No certificate or key were found\n");
|
|
Packit Service |
4684c1 |
exit(1);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_certificate_set_known_dh_params(x509_cred, GNUTLS_SEC_PARAM_MEDIUM);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* pre-3.6.3 equivalent:
|
|
Packit Service |
4684c1 |
* gnutls_priority_init(&priority_cache,
|
|
Packit Service |
4684c1 |
* "NORMAL:-VERS-TLS-ALL:+VERS-DTLS1.0:%SERVER_PRECEDENCE",
|
|
Packit Service |
4684c1 |
* NULL);
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
gnutls_priority_init2(&priority_cache,
|
|
Packit Service |
4684c1 |
"%SERVER_PRECEDENCE",
|
|
Packit Service |
4684c1 |
NULL, GNUTLS_PRIORITY_INIT_DEF_APPEND);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Socket operations
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
listen_sd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(&sa_serv, '\0', sizeof(sa_serv));
|
|
Packit Service |
4684c1 |
sa_serv.sin_family = AF_INET;
|
|
Packit Service |
4684c1 |
sa_serv.sin_addr.s_addr = INADDR_ANY;
|
|
Packit Service |
4684c1 |
sa_serv.sin_port = htons(PORT);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
{ /* DTLS requires the IP don't fragment (DF) bit to be set */
|
|
Packit Service |
4684c1 |
#if defined(IP_DONTFRAG)
|
|
Packit Service |
4684c1 |
int optval = 1;
|
|
Packit Service |
4684c1 |
setsockopt(listen_sd, IPPROTO_IP, IP_DONTFRAG,
|
|
Packit Service |
4684c1 |
(const void *) &optval, sizeof(optval));
|
|
Packit Service |
4684c1 |
#elif defined(IP_MTU_DISCOVER)
|
|
Packit Service |
4684c1 |
int optval = IP_PMTUDISC_DO;
|
|
Packit Service |
4684c1 |
setsockopt(listen_sd, IPPROTO_IP, IP_MTU_DISCOVER,
|
|
Packit Service |
4684c1 |
(const void *) &optval, sizeof(optval));
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bind(listen_sd, (struct sockaddr *) &sa_serv, sizeof(sa_serv));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf("UDP server ready. Listening to port '%d'.\n\n", PORT);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (;;) {
|
|
Packit Service |
4684c1 |
printf("Waiting for connection...\n");
|
|
Packit Service |
4684c1 |
sock = wait_for_connection(listen_sd);
|
|
Packit Service |
4684c1 |
if (sock < 0)
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cli_addr_size = sizeof(cli_addr);
|
|
Packit Service |
4684c1 |
ret = recvfrom(sock, buffer, sizeof(buffer), MSG_PEEK,
|
|
Packit Service |
4684c1 |
(struct sockaddr *) &cli_addr,
|
|
Packit Service |
4684c1 |
&cli_addr_size);
|
|
Packit Service |
4684c1 |
if (ret > 0) {
|
|
Packit Service |
4684c1 |
memset(&prestate, 0, sizeof(prestate));
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
gnutls_dtls_cookie_verify(&cookie_key,
|
|
Packit Service |
4684c1 |
&cli_addr,
|
|
Packit Service |
4684c1 |
sizeof(cli_addr),
|
|
Packit Service |
4684c1 |
buffer, ret,
|
|
Packit Service |
4684c1 |
&prestate);
|
|
Packit Service |
4684c1 |
if (ret < 0) { /* cookie not valid */
|
|
Packit Service |
4684c1 |
priv_data_st s;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(&s, 0, sizeof(s));
|
|
Packit Service |
4684c1 |
s.fd = sock;
|
|
Packit Service |
4684c1 |
s.cli_addr = (void *) &cli_addr;
|
|
Packit Service |
4684c1 |
s.cli_addr_size = sizeof(cli_addr);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf
|
|
Packit Service |
4684c1 |
("Sending hello verify request to %s\n",
|
|
Packit Service |
4684c1 |
human_addr((struct sockaddr *)
|
|
Packit Service |
4684c1 |
&cli_addr,
|
|
Packit Service |
4684c1 |
sizeof(cli_addr), buffer,
|
|
Packit Service |
4684c1 |
sizeof(buffer)));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_dtls_cookie_send(&cookie_key,
|
|
Packit Service |
4684c1 |
&cli_addr,
|
|
Packit Service |
4684c1 |
sizeof(cli_addr),
|
|
Packit Service |
4684c1 |
&prestate,
|
|
Packit Service |
4684c1 |
(gnutls_transport_ptr_t)
|
|
Packit Service |
4684c1 |
& s, push_func);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* discard peeked data */
|
|
Packit Service |
4684c1 |
recvfrom(sock, buffer, sizeof(buffer), 0,
|
|
Packit Service |
4684c1 |
(struct sockaddr *) &cli_addr,
|
|
Packit Service |
4684c1 |
&cli_addr_size);
|
|
Packit Service |
4684c1 |
usleep(100);
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
printf("Accepted connection from %s\n",
|
|
Packit Service |
4684c1 |
human_addr((struct sockaddr *)
|
|
Packit Service |
4684c1 |
&cli_addr, sizeof(cli_addr),
|
|
Packit Service |
4684c1 |
buffer, sizeof(buffer)));
|
|
Packit Service |
4684c1 |
} else
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
|
|
Packit Service |
4684c1 |
gnutls_priority_set(session, priority_cache);
|
|
Packit Service |
4684c1 |
gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
|
|
Packit Service |
4684c1 |
x509_cred);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_dtls_prestate_set(session, &prestate);
|
|
Packit Service |
4684c1 |
gnutls_dtls_set_mtu(session, mtu);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
priv.session = session;
|
|
Packit Service |
4684c1 |
priv.fd = sock;
|
|
Packit Service |
4684c1 |
priv.cli_addr = (struct sockaddr *) &cli_addr;
|
|
Packit Service |
4684c1 |
priv.cli_addr_size = sizeof(cli_addr);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_transport_set_ptr(session, &priv;;
|
|
Packit Service |
4684c1 |
gnutls_transport_set_push_function(session, push_func);
|
|
Packit Service |
4684c1 |
gnutls_transport_set_pull_function(session, pull_func);
|
|
Packit Service |
4684c1 |
gnutls_transport_set_pull_timeout_function(session,
|
|
Packit Service |
4684c1 |
pull_timeout_func);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
LOOP_CHECK(ret, gnutls_handshake(session));
|
|
Packit Service |
4684c1 |
/* Note that DTLS may also receive GNUTLS_E_LARGE_PACKET.
|
|
Packit Service |
4684c1 |
* In that case the MTU should be adjusted.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Error in handshake(): %s\n",
|
|
Packit Service |
4684c1 |
gnutls_strerror(ret));
|
|
Packit Service |
4684c1 |
gnutls_deinit(session);
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf("- Handshake was completed\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (;;) {
|
|
Packit Service |
4684c1 |
LOOP_CHECK(ret,
|
|
Packit Service |
4684c1 |
gnutls_record_recv_seq(session, buffer,
|
|
Packit Service |
4684c1 |
MAX_BUFFER,
|
|
Packit Service |
4684c1 |
sequence));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0 && gnutls_error_is_fatal(ret) == 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "*** Warning: %s\n",
|
|
Packit Service |
4684c1 |
gnutls_strerror(ret));
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
} else if (ret < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Error in recv(): %s\n",
|
|
Packit Service |
4684c1 |
gnutls_strerror(ret));
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret == 0) {
|
|
Packit Service |
4684c1 |
printf("EOF\n\n");
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
buffer[ret] = 0;
|
|
Packit Service |
4684c1 |
printf
|
|
Packit Service |
4684c1 |
("received[%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x]: %s\n",
|
|
Packit Service |
4684c1 |
sequence[0], sequence[1], sequence[2],
|
|
Packit Service |
4684c1 |
sequence[3], sequence[4], sequence[5],
|
|
Packit Service |
4684c1 |
sequence[6], sequence[7], buffer);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* reply back */
|
|
Packit Service |
4684c1 |
LOOP_CHECK(ret, gnutls_record_send(session, buffer, ret));
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
fprintf(stderr, "Error in send(): %s\n",
|
|
Packit Service |
4684c1 |
gnutls_strerror(ret));
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
LOOP_CHECK(ret, gnutls_bye(session, GNUTLS_SHUT_WR));
|
|
Packit Service |
4684c1 |
gnutls_deinit(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
close(listen_sd);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_certificate_free_credentials(x509_cred);
|
|
Packit Service |
4684c1 |
gnutls_priority_deinit(priority_cache);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_global_deinit();
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int wait_for_connection(int fd)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fd_set rd, wr;
|
|
Packit Service |
4684c1 |
int n;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FD_ZERO(&rd);
|
|
Packit Service |
4684c1 |
FD_ZERO(&wr);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FD_SET(fd, &rd);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* waiting part */
|
|
Packit Service |
4684c1 |
n = select(fd + 1, &rd, &wr, NULL, NULL);
|
|
Packit Service |
4684c1 |
if (n == -1 && errno == EINTR)
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
if (n < 0) {
|
|
Packit Service |
4684c1 |
perror("select()");
|
|
Packit Service |
4684c1 |
exit(1);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return fd;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Wait for data to be received within a timeout period in milliseconds
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fd_set rfds;
|
|
Packit Service |
4684c1 |
struct timeval tv;
|
|
Packit Service |
4684c1 |
priv_data_st *priv = ptr;
|
|
Packit Service |
4684c1 |
struct sockaddr_in cli_addr;
|
|
Packit Service |
4684c1 |
socklen_t cli_addr_size;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
char c;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FD_ZERO(&rfds);
|
|
Packit Service |
4684c1 |
FD_SET(priv->fd, &rfds);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
tv.tv_sec = ms / 1000;
|
|
Packit Service |
4684c1 |
tv.tv_usec = (ms % 1000) * 1000;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = select(priv->fd + 1, &rfds, NULL, NULL, &tv;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret <= 0)
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* only report ok if the next message is from the peer we expect
|
|
Packit Service |
4684c1 |
* from
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
cli_addr_size = sizeof(cli_addr);
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
recvfrom(priv->fd, &c, 1, MSG_PEEK,
|
|
Packit Service |
4684c1 |
(struct sockaddr *) &cli_addr, &cli_addr_size);
|
|
Packit Service |
4684c1 |
if (ret > 0) {
|
|
Packit Service |
4684c1 |
if (cli_addr_size == priv->cli_addr_size
|
|
Packit Service |
4684c1 |
&& memcmp(&cli_addr, priv->cli_addr,
|
|
Packit Service |
4684c1 |
sizeof(cli_addr)) == 0)
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static ssize_t
|
|
Packit Service |
4684c1 |
push_func(gnutls_transport_ptr_t p, const void *data, size_t size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
priv_data_st *priv = p;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return sendto(priv->fd, data, size, 0, priv->cli_addr,
|
|
Packit Service |
4684c1 |
priv->cli_addr_size);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static ssize_t pull_func(gnutls_transport_ptr_t p, void *data, size_t size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
priv_data_st *priv = p;
|
|
Packit Service |
4684c1 |
struct sockaddr_in cli_addr;
|
|
Packit Service |
4684c1 |
socklen_t cli_addr_size;
|
|
Packit Service |
4684c1 |
char buffer[64];
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cli_addr_size = sizeof(cli_addr);
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
recvfrom(priv->fd, data, size, 0,
|
|
Packit Service |
4684c1 |
(struct sockaddr *) &cli_addr, &cli_addr_size);
|
|
Packit Service |
4684c1 |
if (ret == -1)
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (cli_addr_size == priv->cli_addr_size
|
|
Packit Service |
4684c1 |
&& memcmp(&cli_addr, priv->cli_addr, sizeof(cli_addr)) == 0)
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf("Denied connection from %s\n",
|
|
Packit Service |
4684c1 |
human_addr((struct sockaddr *)
|
|
Packit Service |
4684c1 |
&cli_addr, sizeof(cli_addr), buffer,
|
|
Packit Service |
4684c1 |
sizeof(buffer)));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_transport_set_errno(priv->session, EAGAIN);
|
|
Packit Service |
4684c1 |
return -1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static const char *human_addr(const struct sockaddr *sa, socklen_t salen,
|
|
Packit Service |
4684c1 |
char *buf, size_t buflen)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const char *save_buf = buf;
|
|
Packit Service |
4684c1 |
size_t l;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!buf || !buflen)
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*buf = '\0';
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
switch (sa->sa_family) {
|
|
Packit Service |
4684c1 |
#if HAVE_IPV6
|
|
Packit Service |
4684c1 |
case AF_INET6:
|
|
Packit Service |
4684c1 |
snprintf(buf, buflen, "IPv6 ");
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
case AF_INET:
|
|
Packit Service |
4684c1 |
snprintf(buf, buflen, "IPv4 ");
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
l = strlen(buf);
|
|
Packit Service |
4684c1 |
buf += l;
|
|
Packit Service |
4684c1 |
buflen -= l;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (getnameinfo(sa, salen, buf, buflen, NULL, 0, NI_NUMERICHOST) !=
|
|
Packit Service |
4684c1 |
0)
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
l = strlen(buf);
|
|
Packit Service |
4684c1 |
buf += l;
|
|
Packit Service |
4684c1 |
buflen -= l;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
strncat(buf, " port ", buflen);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
l = strlen(buf);
|
|
Packit Service |
4684c1 |
buf += l;
|
|
Packit Service |
4684c1 |
buflen -= l;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (getnameinfo(sa, salen, NULL, 0, buf, buflen, NI_NUMERICSERV) !=
|
|
Packit Service |
4684c1 |
0)
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return save_buf;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|