Moved SLPD related code to slpd.c

- Added setup_slpd()
This commit is contained in:
thorkill 2016-05-25 19:18:32 +02:00
parent 62b63fff8b
commit 26a7e51cbe
4 changed files with 145 additions and 136 deletions

View file

@ -60,7 +60,6 @@
int keylifetime = 0; int keylifetime = 0;
int edgeupdateinterval = 0; int edgeupdateinterval = 0;
int slpdinterval = 0;
#ifdef HAVE_LZO #ifdef HAVE_LZO
static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS]; static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS];
#endif #endif
@ -1592,25 +1591,6 @@ void handle_incoming_vpn_data(void *data, int flags) {
#endif #endif
} }
void handle_incoming_slpd_data(void *data, int flags) {
listen_socket_t *ls = data;
char pkt[MAXSIZE];
struct sockaddr_in6 addr;
socklen_t addrlen = sizeof(addr);
size_t len = recvfrom(ls->udp.fd, pkt, MAXSIZE, 0, (struct sockaddr *)&addr, &addrlen);
if(len <= 0 || len > MAXSIZE) {
if(!sockwouldblock(sockerrno))
logger(DEBUG_ALWAYS, LOG_ERR, "Receiving SLPD packet failed: %s", sockstrerror(sockerrno));
return;
}
handle_incoming_slpd_packet(ls, &pkt, &addr, len);
}
void handle_device_data(void *data, int flags) { void handle_device_data(void *data, int flags) {
vpn_packet_t packet; vpn_packet_t packet;
UNUSED(data); UNUSED(data);

View file

@ -39,6 +39,7 @@
#include "route.h" #include "route.h"
#include "rsa.h" #include "rsa.h"
#include "script.h" #include "script.h"
#include "slpd.h"
#include "splay_tree.h" #include "splay_tree.h"
#include "subnet.h" #include "subnet.h"
#include "utils.h" #include "utils.h"
@ -49,9 +50,6 @@
#endif #endif
char *myport; char *myport;
char *my_slpd_port;
char *my_slpd_group;
int my_slpd_expire;
static char *myname; static char *myname;
static io_t device_io; static io_t device_io;
devops_t devops; devops_t devops;
@ -325,7 +323,7 @@ static void slpdupdate_handler(void *data) {
while(c_iface) { while(c_iface) {
logger(DEBUG_STATUS, LOG_NOTICE, "Sending SLPD out on %s", c_iface->value); logger(DEBUG_STATUS, LOG_NOTICE, "Sending SLPD out on %s", c_iface->value);
send_slpd_broadcast(c_iface->value); send_slpd_broadcast(myself, c_iface->value);
c_iface = lookup_config_next(config_tree, c_iface); c_iface = lookup_config_next(config_tree, c_iface);
} }
@ -342,105 +340,6 @@ static void edgeupdate_handler(void *data) {
timeout_set(data, &(struct timeval){edgeupdateinterval + (rand() % 10), rand() % 100000}); timeout_set(data, &(struct timeval){edgeupdateinterval + (rand() % 10), rand() % 100000});
} }
void send_slpd_broadcast(char *iface) {
int sd;
struct addrinfo *mcast_addr;
struct addrinfo hints;
sockaddr_t r;
char slpd_msg[MAXSIZE] = "";
/* Check if interface is up */
struct ifreq ifr;
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, iface);
if (ioctl(sd, SIOCGIFFLAGS, &ifr) < 0) {
logger(DEBUG_ALWAYS, LOG_INFO, "ioctl() on %s error: [%s:%d]", iface, strerror(errno), errno);
}
close(sd);
// Requested interface is down
if (!(ifr.ifr_flags & IFF_UP) || !(ifr.ifr_flags & IFF_RUNNING))
return;
bzero(&hints, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
int status;
if ((status = getaddrinfo(my_slpd_group, my_slpd_port, &hints, &mcast_addr)) != 0 ) {
logger(DEBUG_ALWAYS, LOG_INFO, "getaddrinfo() error: [%s:%d]", strerror(errno), errno);
return;
}
if ((sd = socket(mcast_addr->ai_family, mcast_addr->ai_socktype, 0)) < 0 ) {
logger(DEBUG_ALWAYS, LOG_INFO, "socket() error: [%s:%d]", strerror(errno), errno);
freeaddrinfo(mcast_addr);
return;
}
int on = 1;
if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "setsockopt() IPV6_V6ONLY failed [%s:%d]", strerror(errno), errno);
return;
}
/* Send SLPD only on this Interface */
unsigned int ifindex;
ifindex = if_nametoindex(iface);
if(setsockopt (sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) != 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "setsockopt() IPV6_MULTICAST_IF failed [%s:%d]", strerror(errno), errno);
freeaddrinfo(mcast_addr);
return;
}
unsigned int reuse = 1;
if(setsockopt (sd, IPPROTO_IPV6, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) != 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "setsockopt() SO_REUSEADDR failed: [%s:%d]", strerror(errno), errno);
freeaddrinfo(mcast_addr);
return;
}
snprintf(slpd_msg, MAXSIZE, "sLPD 0 2 %s %d", myname, atoi(myport));
char signature[87];
char b64sig[255];
char pkt[MAXSIZE];
if (!node_read_ecdsa_public_key(myself)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can not load public key for SLPD");
return;
}
if (!read_ecdsa_private_key()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can not load private key for SLPD");
return;
}
slpd_msg[MAXSIZE-1] = '\00';
if (!ecdsa_sign(myself->connection->ecdsa, slpd_msg, strlen(slpd_msg), &signature)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can not sign payload for SLPD");
return;
}
if (b64encode(signature, b64sig, 64) != 86) {
logger(DEBUG_ALWAYS, LOG_ERR, "b64encode() failed!");
return;
}
int l = snprintf(pkt, strlen(slpd_msg) + strlen(b64sig) + 2, "%s %s", slpd_msg, b64sig);
pkt[l] = '\00';
if (sendto(sd, pkt, strlen(pkt), 0, mcast_addr->ai_addr, mcast_addr->ai_addrlen) != strlen(pkt) ) {
logger(DEBUG_ALWAYS, LOG_ERR, "SLPD send() error: [%s:%d]", strerror(errno), errno);
}
close(sd);
return;
}
void regenerate_key(void) { void regenerate_key(void) {
logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys"); logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys");
send_key_changed(); send_key_changed();
@ -923,17 +822,7 @@ static bool setup_myself(void) {
else else
port_specified = true; port_specified = true;
if(!get_config_string(lookup_config(config_tree, "SLPDPort"), &my_slpd_port)) setup_slpd();
my_slpd_port = xstrdup(DEFAULT_SLPD_PORT);
if(!get_config_string(lookup_config(config_tree, "SLPDGroup"), &my_slpd_group))
my_slpd_group = xstrdup(DEFAULT_SLPD_GROUP);
char *tmp_expire;
if(!get_config_string(lookup_config(config_tree, "SLPDExpire"), &tmp_expire))
my_slpd_expire = DEFAULT_SLPD_EXPIRE;
else
my_slpd_expire = atoi(tmp_expire);
myself->connection->options = 0; myself->connection->options = 0;
myself->connection->protocol_major = PROT_MAJOR; myself->connection->protocol_major = PROT_MAJOR;

View file

@ -19,10 +19,14 @@
#include "slpd.h" #include "slpd.h"
extern int my_slpd_expire; char *my_slpd_port;
char *my_slpd_group;
int my_slpd_expire;
int slpdinterval = 0;
extern char *myname;
void periodic_slpd_handler(void) { void periodic_slpd_handler(void) {
// expire SLPD addresses // expire SLPD addresses
for splay_each(node_t, n, node_tree) { for splay_each(node_t, n, node_tree) {
if (!n->slpd_address) if (!n->slpd_address)
@ -36,6 +40,20 @@ void periodic_slpd_handler(void) {
} }
} }
void setup_slpd(void) {
if(!get_config_string(lookup_config(config_tree, "SLPDPort"), &my_slpd_port))
my_slpd_port = xstrdup(DEFAULT_SLPD_PORT);
if(!get_config_string(lookup_config(config_tree, "SLPDGroup"), &my_slpd_group))
my_slpd_group = xstrdup(DEFAULT_SLPD_GROUP);
char *tmp_expire;
if(!get_config_string(lookup_config(config_tree, "SLPDExpire"), &tmp_expire))
my_slpd_expire = DEFAULT_SLPD_EXPIRE;
else
my_slpd_expire = atoi(tmp_expire);
}
int setup_slpd_in_socket(void) { int setup_slpd_in_socket(void) {
int nfd; int nfd;
char *my_slpd_port; char *my_slpd_port;
@ -202,3 +220,123 @@ void handle_incoming_slpd_packet(listen_socket_t *ls, void *pkt, struct sockaddr
} }
return; return;
} }
void send_slpd_broadcast(node_t *myself, char *iface) {
int sd;
char *myname = myself->name;
struct addrinfo *mcast_addr;
struct addrinfo hints;
sockaddr_t r;
char slpd_msg[MAXSIZE] = "";
/* Check if interface is up */
struct ifreq ifr;
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, iface);
if (ioctl(sd, SIOCGIFFLAGS, &ifr) < 0) {
logger(DEBUG_ALWAYS, LOG_INFO, "ioctl() on %s error: [%s:%d]", iface, strerror(errno), errno);
}
close(sd);
// Requested interface is down
if (!(ifr.ifr_flags & IFF_UP) || !(ifr.ifr_flags & IFF_RUNNING))
return;
bzero(&hints, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
int status;
if ((status = getaddrinfo(my_slpd_group, my_slpd_port, &hints, &mcast_addr)) != 0 ) {
logger(DEBUG_ALWAYS, LOG_INFO, "getaddrinfo() error: [%s:%d]", strerror(errno), errno);
return;
}
if ((sd = socket(mcast_addr->ai_family, mcast_addr->ai_socktype, 0)) < 0 ) {
logger(DEBUG_ALWAYS, LOG_INFO, "socket() error: [%s:%d]", strerror(errno), errno);
freeaddrinfo(mcast_addr);
return;
}
int on = 1;
if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "setsockopt() IPV6_V6ONLY failed [%s:%d]", strerror(errno), errno);
return;
}
/* Send SLPD only on this Interface */
unsigned int ifindex;
ifindex = if_nametoindex(iface);
if(setsockopt (sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) != 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "setsockopt() IPV6_MULTICAST_IF failed [%s:%d]", strerror(errno), errno);
freeaddrinfo(mcast_addr);
return;
}
unsigned int reuse = 1;
if(setsockopt (sd, IPPROTO_IPV6, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) != 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "setsockopt() SO_REUSEADDR failed: [%s:%d]", strerror(errno), errno);
freeaddrinfo(mcast_addr);
return;
}
snprintf(slpd_msg, MAXSIZE, "sLPD 0 2 %s %d", myname, atoi(myport));
char signature[87];
char b64sig[255];
char pkt[MAXSIZE];
/*
if (!node_read_ecdsa_public_key(myself)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can not load public key for SLPD");
return;
}
if (!read_ecdsa_private_key()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can not load private key for SLPD");
return;
}
*/
slpd_msg[MAXSIZE-1] = '\00';
if (!ecdsa_sign(myself->connection->ecdsa, slpd_msg, strlen(slpd_msg), &signature)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can not sign payload for SLPD");
return;
}
if (b64encode(signature, b64sig, 64) != 86) {
logger(DEBUG_ALWAYS, LOG_ERR, "b64encode() failed!");
return;
}
int l = snprintf(pkt, strlen(slpd_msg) + strlen(b64sig) + 2, "%s %s", slpd_msg, b64sig);
pkt[l] = '\00';
if (sendto(sd, pkt, strlen(pkt), 0, mcast_addr->ai_addr, mcast_addr->ai_addrlen) != strlen(pkt) ) {
logger(DEBUG_ALWAYS, LOG_ERR, "SLPD send() error: [%s:%d]", strerror(errno), errno);
}
close(sd);
return;
}
void handle_incoming_slpd_data(void *data, int flags) {
listen_socket_t *ls = data;
char pkt[MAXSIZE];
struct sockaddr_in6 addr;
socklen_t addrlen = sizeof(addr);
size_t len = recvfrom(ls->udp.fd, pkt, MAXSIZE, 0, (struct sockaddr *)&addr, &addrlen);
if(len == 0 || len > MAXSIZE) {
if(!sockwouldblock(sockerrno))
logger(DEBUG_ALWAYS, LOG_ERR, "Receiving SLPD packet failed: %s", sockstrerror(sockerrno));
return;
}
handle_incoming_slpd_packet(ls, &pkt, &addr, len);
}

View file

@ -25,5 +25,7 @@
#include "xalloc.h" #include "xalloc.h"
void periodic_slpd_handler(void); void periodic_slpd_handler(void);
void setup_slpd(void);
int setup_slpd_in_socket(void); int setup_slpd_in_socket(void);
void handle_incoming_slpd_packet(listen_socket_t *, void *, struct sockaddr_in6 *, size_t); void handle_incoming_slpd_packet(listen_socket_t *, void *, struct sockaddr_in6 *, size_t);
void send_slpd_broadcast(node_t *, char *);