ntopng/third-party/snmp/net.c
2018-09-04 20:20:46 +02:00

151 lines
3.2 KiB
C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef WIN32
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#endif
#ifndef __USE_GNU
#define __USE_GNU
#endif
#ifdef WIN32
#define gethostbyname2(a, b) gethostbyname(a)
#else
#include <unistd.h>
#endif
#define BUFLEN 65535
void diep(char *s)
{
perror(s);
exit(1);
}
int split_host_port(char *input, int default_port, char **host, int *port)
{
char *p;
*host = strdup(input);
if ((p = strchr(*host, ':')))
{
*port = strtol(p+1, NULL, 0);
*p = 0;
}
else
{
*port = default_port;
}
return 1;
}
int open_udp_socket(int port)
{
struct sockaddr_in si_me;
int s;
int reuse = 1;
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return(-1); // diep("socket");
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) != 0)
return(-1); //diep("setsockaopt");
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (::bind(s, (struct sockaddr *) &si_me, sizeof(si_me)) != 0)
return(-1); //diep("bind");
return s;
}
void send_udp_datagram(void *buf, int len, int socket, char *target_host, int target_port)
{
struct sockaddr_in target_si;
struct addrinfo hints, *res = NULL, *p;
int errcode;
memset(&target_si, 0, sizeof(target_si));
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; /* IPv4 */
// hints.ai_socktype = SOCK_STREAM;
// hints.ai_flags |= AI_CANONNAME;
if((errcode = getaddrinfo(target_host, NULL, &hints, &res))
|| !res)
return;
for (p = res; p != NULL; p = p->ai_next) {
memcpy(&target_si, res->ai_addr, res->ai_addrlen);
break;
}
freeaddrinfo(res);
target_si.sin_port = htons(target_port);
if (sendto(socket, (const char*)buf, len, 0, (struct sockaddr *) &target_si, sizeof(target_si)) == -1)
return; //diep("sendto");
}
int receive_udp_datagram(void *buf, int max, int socket, char **sender_host, int *sender_port)
{
struct sockaddr_in sender_si;
int slen = sizeof(sender_si);
int nr;
nr = recvfrom(socket, (char*)buf, BUFLEN,
#ifdef WIN32
0,
#else
MSG_DONTWAIT, // TODO: add select() to avoid waiting forever
#endif
(struct sockaddr *) &sender_si, (socklen_t*)&slen);
if (nr == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
return 0;
return(-1); //diep("recvfrom");
}
if (sender_host)
*sender_host = inet_ntoa(sender_si.sin_addr);
if (sender_port)
*sender_port = ntohs(sender_si.sin_port);
return nr;
}
/* Borrowed from the GNU libc manual. */
int input_timeout(int filedes, unsigned int seconds)
{
fd_set set;
struct timeval timeout;
/* Initialize the file descriptor set. */
FD_ZERO(&set);
FD_SET(filedes, &set);
/* Initialize the timeout data structure. */
timeout.tv_sec = seconds;
timeout.tv_usec = 0;
/* `select' returns 0 if timeout, 1 if input available, -1 if error. */
return /* TEMP_FAILURE_RETRY*/(select(FD_SETSIZE,
&set, NULL, NULL,
&timeout));
}