|
|
|
|
@ -17,48 +17,30 @@
|
|
|
|
|
#include "udp_listener.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void control_udp_incoming(int fd, void *p, uintptr_t x) {
|
|
|
|
|
struct control_udp *u = p;
|
|
|
|
|
int ret, len;
|
|
|
|
|
char buf[8192];
|
|
|
|
|
struct sockaddr_in6 sin;
|
|
|
|
|
socklen_t sin_len;
|
|
|
|
|
static void control_udp_incoming(struct obj *obj, char *buf, int len, struct sockaddr_in6 *sin, char *addr) {
|
|
|
|
|
struct control_udp *u = (void *) obj;
|
|
|
|
|
int ret;
|
|
|
|
|
int ovec[100];
|
|
|
|
|
const char **out;
|
|
|
|
|
char *reply;
|
|
|
|
|
struct msghdr mh;
|
|
|
|
|
struct iovec iov[10];
|
|
|
|
|
char addr[64];
|
|
|
|
|
|
|
|
|
|
next:
|
|
|
|
|
sin_len = sizeof(sin);
|
|
|
|
|
len = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &sin, &sin_len);
|
|
|
|
|
if (len < 0) {
|
|
|
|
|
if (errno == EINTR)
|
|
|
|
|
goto next;
|
|
|
|
|
if (errno != EWOULDBLOCK && errno != EAGAIN)
|
|
|
|
|
mylog(LOG_WARNING, "Error reading from UDP socket");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf[len] = '\0';
|
|
|
|
|
smart_ntop_p(addr, &sin.sin6_addr, sizeof(addr));
|
|
|
|
|
|
|
|
|
|
ret = pcre_exec(u->parse_re, u->parse_ree, buf, len, 0, 0, ovec, G_N_ELEMENTS(ovec));
|
|
|
|
|
if (ret <= 0) {
|
|
|
|
|
ret = pcre_exec(u->fallback_re, NULL, buf, len, 0, 0, ovec, G_N_ELEMENTS(ovec));
|
|
|
|
|
if (ret <= 0) {
|
|
|
|
|
mylog(LOG_WARNING, "Unable to parse command line from udp:%s:%u: %s", addr, ntohs(sin.sin6_port), buf);
|
|
|
|
|
goto next;
|
|
|
|
|
mylog(LOG_WARNING, "Unable to parse command line from udp:%s:%u: %s", addr, ntohs(sin->sin6_port), buf);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mylog(LOG_WARNING, "Failed to properly parse UDP command line '%s' from %s:%u, using fallback RE", buf, addr, ntohs(sin.sin6_port));
|
|
|
|
|
mylog(LOG_WARNING, "Failed to properly parse UDP command line '%s' from %s:%u, using fallback RE", buf, addr, ntohs(sin->sin6_port));
|
|
|
|
|
|
|
|
|
|
pcre_get_substring_list(buf, ovec, ret, &out);
|
|
|
|
|
|
|
|
|
|
ZERO(mh);
|
|
|
|
|
mh.msg_name = &sin;
|
|
|
|
|
mh.msg_namelen = sizeof(sin);
|
|
|
|
|
mh.msg_name = sin;
|
|
|
|
|
mh.msg_namelen = sizeof(*sin);
|
|
|
|
|
mh.msg_iov = iov;
|
|
|
|
|
|
|
|
|
|
iov[0].iov_base = (void *) out[RE_UDP_COOKIE];
|
|
|
|
|
@ -78,21 +60,21 @@ next:
|
|
|
|
|
mh.msg_iovlen = 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sendmsg(fd, &mh, 0);
|
|
|
|
|
sendmsg(u->udp_listener.fd, &mh, 0);
|
|
|
|
|
|
|
|
|
|
pcre_free(out);
|
|
|
|
|
|
|
|
|
|
goto next;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mylog(LOG_INFO, "Got valid command from udp:%s:%u: %s", addr, ntohs(sin.sin6_port), buf);
|
|
|
|
|
mylog(LOG_INFO, "Got valid command from udp:%s:%u: %s", addr, ntohs(sin->sin6_port), buf);
|
|
|
|
|
|
|
|
|
|
pcre_get_substring_list(buf, ovec, ret, &out);
|
|
|
|
|
|
|
|
|
|
reply = cookie_cache_lookup(&u->cookie_cache, out[RE_UDP_COOKIE]);
|
|
|
|
|
if (reply) {
|
|
|
|
|
mylog(LOG_INFO, "Detected command from udp:%s:%u as a duplicate", addr, ntohs(sin.sin6_port));
|
|
|
|
|
sendto(fd, reply, strlen(reply), 0, (struct sockaddr *) &sin, sin_len);
|
|
|
|
|
mylog(LOG_INFO, "Detected command from udp:%s:%u as a duplicate", addr, ntohs(sin->sin6_port));
|
|
|
|
|
sendto(u->udp_listener.fd, reply, strlen(reply), 0, (struct sockaddr *) sin, sizeof(*sin));
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -106,8 +88,8 @@ next:
|
|
|
|
|
reply = call_query_udp(out, u->callmaster);
|
|
|
|
|
else if (chrtoupper(out[RE_UDP_V_CMD][0]) == 'V') {
|
|
|
|
|
ZERO(mh);
|
|
|
|
|
mh.msg_name = &sin;
|
|
|
|
|
mh.msg_namelen = sizeof(sin);
|
|
|
|
|
mh.msg_name = sin;
|
|
|
|
|
mh.msg_namelen = sizeof(*sin);
|
|
|
|
|
mh.msg_iov = iov;
|
|
|
|
|
mh.msg_iovlen = 2;
|
|
|
|
|
|
|
|
|
|
@ -133,12 +115,12 @@ next:
|
|
|
|
|
iov[2].iov_len = 9;
|
|
|
|
|
mh.msg_iovlen++;
|
|
|
|
|
}
|
|
|
|
|
sendmsg(fd, &mh, 0);
|
|
|
|
|
sendmsg(u->udp_listener.fd, &mh, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (reply) {
|
|
|
|
|
len = strlen(reply);
|
|
|
|
|
sendto(fd, reply, len, 0, (struct sockaddr *) &sin, sin_len);
|
|
|
|
|
sendto(u->udp_listener.fd, reply, len, 0, (struct sockaddr *) sin, sizeof(*sin));
|
|
|
|
|
cookie_cache_insert(&u->cookie_cache, out[RE_UDP_COOKIE], reply, len);
|
|
|
|
|
free(reply);
|
|
|
|
|
}
|
|
|
|
|
@ -147,7 +129,6 @@ next:
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
pcre_free(out);
|
|
|
|
|
goto next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct control_udp *control_udp_new(struct poller *p, struct in6_addr ip, u_int16_t port, struct callmaster *m) {
|
|
|
|
|
|