mirror of
https://github.com/troglobit/finit.git
synced 2026-10-08 16:34:45 +07:00
Initial support for figuring out inbound interface for inetd connections
This patch adds initial support (only SOCK_STREAM verified!) for figuring out the inbound interface for inetd service connections. The intention is to use this later on for a very simple tcpwrappers replacement, e.g: `deny telnet eth0 eth3` Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
@@ -21,8 +21,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//#include <unistd.h>
|
||||
//#include <sys/types.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@@ -76,11 +76,18 @@ static void spawn_socket(uev_ctx_t *ctx, svc_t *svc)
|
||||
return;
|
||||
}
|
||||
|
||||
if (svc->port && svc->sock_type != SOCK_DGRAM) {
|
||||
if (-1 == listen(sd, 20)) {
|
||||
FLOG_PERROR("Failed listening to inetd service %s", svc->service);
|
||||
close(sd);
|
||||
return;
|
||||
if (svc->port) {
|
||||
if (svc->sock_type == SOCK_STREAM) {
|
||||
if (-1 == listen(sd, 20)) {
|
||||
FLOG_PERROR("Failed listening to inetd service %s", svc->service);
|
||||
close(sd);
|
||||
return;
|
||||
}
|
||||
} else { /* SOCK_DGRAM */
|
||||
int opt = 1;
|
||||
|
||||
/* Set extra sockopt to get ifindex from inbound packets */
|
||||
setsockopt(sd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +96,64 @@ static void spawn_socket(uev_ctx_t *ctx, svc_t *svc)
|
||||
uev_io_init(ctx, &svc->watcher, socket_cb, svc, sd, UEV_READ);
|
||||
}
|
||||
|
||||
/* Peek into SOCK_DGRAM socket to figure out where an inbound packet comes from. */
|
||||
int inetd_dgram_peek(int sd, char *ifname)
|
||||
{
|
||||
struct msghdr msgh;
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
if (recvmsg(sd, &msgh, MSG_PEEK) < 0)
|
||||
return -1;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg; cmsg = CMSG_NXTHDR(&msgh,cmsg)) {
|
||||
struct in_pktinfo *ipi = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
||||
|
||||
if (cmsg->cmsg_level != SOL_IP || cmsg->cmsg_type != IP_PKTINFO)
|
||||
continue;
|
||||
|
||||
if_indextoname(ipi->ipi_ifindex, ifname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Peek into SOCK_STREAM on accepted client socket to figure out inbound interface */
|
||||
int inetd_stream_peek(int sd, char *ifname)
|
||||
{
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
|
||||
if (-1 == getsockname(sd, (struct sockaddr *)&sin, &len))
|
||||
return -1;
|
||||
|
||||
if (-1 == getifaddrs(&ifaddr))
|
||||
return -1;
|
||||
|
||||
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
|
||||
size_t len = sizeof(struct in_addr);
|
||||
struct sockaddr_in *iin;
|
||||
|
||||
if (!ifa->ifa_addr)
|
||||
continue;
|
||||
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
|
||||
iin = (struct sockaddr_in *)ifa->ifa_addr;
|
||||
if (!memcmp(&sin.sin_addr, &iin->sin_addr, len)) {
|
||||
strncpy(ifname, ifa->ifa_name, IF_NAMESIZE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Inetd monitor, called by svc_monitor() */
|
||||
int inetd_respawn(pid_t pid)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
|
||||
#include "libuev/uev.h"
|
||||
|
||||
int inetd_dgram_peek (int sd, char *ifname);
|
||||
int inetd_stream_peek (int sd, char *ifname);
|
||||
|
||||
int inetd_respawn (pid_t pid);
|
||||
void inetd_runlevel(uev_ctx_t *ctx, int runlevel);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <sys/wait.h>
|
||||
#include <utmp.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "finit.h"
|
||||
#include "helpers.h"
|
||||
@@ -517,6 +518,7 @@ void svc_monitor(pid_t lost)
|
||||
int svc_start(svc_t *svc)
|
||||
{
|
||||
int respawn, sd = 0;
|
||||
char ifname[IF_NAMESIZE] = "UNKNOWN";
|
||||
pid_t pid;
|
||||
sigset_t nmask, omask;
|
||||
|
||||
@@ -551,9 +553,17 @@ int svc_start(svc_t *svc)
|
||||
}
|
||||
|
||||
_d("New client socket %d accepted for inetd service %d/tcp", sd, svc->port);
|
||||
|
||||
/* Find ifname by means of getsockname() and getifaddrs() */
|
||||
inetd_stream_peek(sd, ifname);
|
||||
} else { /* SOCK_DGRAM */
|
||||
/* Find ifname by means of IP_PKTINFO sockopt --> ifindex + if_indextoname() */
|
||||
inetd_dgram_peek(sd, ifname);
|
||||
}
|
||||
|
||||
FLOG_INFO("Starting inetd service %s ...", svc->service);
|
||||
/* XXX: Add poor man's tcpwrappers here, we now know inbound ifname ... */
|
||||
|
||||
FLOG_INFO("Starting inetd service %s for requst from iface %s ...", svc->service, ifname);
|
||||
}
|
||||
else if (SVC_CMD_SERVICE != svc->type)
|
||||
print_desc("", svc->desc);
|
||||
|
||||
Reference in New Issue
Block a user