@@ -929,6 +929,10 @@ static const struct {
.name = "dropudp",
.type = QEMU_OPT_STRING,
.help = "Enable UDP reverse firewall",
+ }, {
+ .name = "droplog",
+ .type = QEMU_OPT_STRING,
+ .help = "Set log filename for the reverse firewall",
},
{ /* end of list */ }
},
@@ -690,6 +690,7 @@ int net_init_slirp(QemuOpts *opts,
const char *bootfile;
const char *smb_export;
const char *vsmbsrv;
+ const char *droplog;
char *vnet = NULL;
int restricted = 0;
int ret;
@@ -731,6 +732,16 @@ int net_init_slirp(QemuOpts *opts,
slirp_enable_drop_udp();
}
+ droplog = qemu_opt_get(opts, "droplog");
+ if (droplog) {
+ FILE *drop_log_fd = fopen(droplog, "w");
+ if (!drop_log_fd) {
+ error_report("Unable to open reverse firewall log");
+ return -1;
+ }
+ slirp_set_drop_log_fd(drop_log_fd);
+ }
+
qemu_opt_foreach(opts, net_init_slirp_configs, NULL, 0);
ret = net_slirp_init(vlan, "user", name, restricted, vnet, vhost,
@@ -1067,7 +1067,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
#ifdef CONFIG_SLIRP
"-net
user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n"
"
[,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n"
- " [,hostfwd=rule][,guestfwd=rule][,dropudp=y|n]"
+ " [,hostfwd=rule][,guestfwd=rule][,dropudp=y|n][,droplog=file]"
#ifndef _WIN32
"[,smb=dir[,smbserver=addr]]\n"
#endif
@@ -46,6 +46,8 @@ size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr
guest_addr,
/* Usermode firewall functions */
void slirp_enable_drop_udp(void);
+void slirp_set_drop_log_fd(FILE *fd);
+int slirp_drop_log(const char *format, ...);
int slirp_should_drop(unsigned long dst_addr,
unsigned short dst_port,
u_int8_t proto);
@@ -1112,17 +1112,22 @@ static int slirp_state_load(QEMUFile *f, void
*opaque, int version_id)
return 0;
}
-
/*
* Global variables for the usermode firewall
*/
static int drop_udp = 0;
+static FILE *drop_log_fd = NULL;
void slirp_enable_drop_udp(void)
{
drop_udp = 1;
}
+void slirp_set_drop_log_fd(FILE *fd)
+{
+ drop_log_fd = fd;
+}
+
int slirp_should_drop(unsigned long dst_addr,
unsigned short dst_port,
u_int8_t proto) {
@@ -1139,3 +1144,23 @@ int slirp_should_drop(unsigned long dst_addr,
return 1;
}
+
+/*
+ * Write to drop-log
+ */
+int slirp_drop_log(const char *format, ...)
+{
+ va_list args;
+
+ if (!drop_log_fd) {
+ return 0;
+ }
+
+ va_start(args, format);
+ vfprintf(drop_log_fd, format, args);
+ va_end(args);
+
+ fflush(drop_log_fd);
+
+ return 1;
+}
@@ -67,6 +67,8 @@ udp_input(register struct mbuf *m, int iphlen)
DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("iphlen = %d", iphlen);
+ time_t timestamp = time(NULL);
+
/*
* Strip IP options, if any; should skip this,
* make available to user, and use on returned packets,
@@ -103,6 +105,13 @@ udp_input(register struct mbuf *m, int iphlen)
*/
if (slirp_should_drop(ip->ip_dst.s_addr, uh->uh_dport,
IPPROTO_UDP)) {
/* DROP */
+ slirp_drop_log(
+ "Dropped UDP: src:0x%08x:0x%04hx dst:0x%08x:0x%04hx %ld\n",
+ ntohl(ip->ip_src.s_addr),
+ ntohs(uh->uh_sport),
+ ntohl(ip->ip_dst.s_addr),
+ ntohs(uh->uh_dport),
+ timestamp);
goto bad;
} else {
This patch series adds a reverse UDP firewall functionality to Slirp. The series consists of three patches. Each adds one -net user option: 1. dropudp=y|n - enables the firewall 2. droplog=FILE - sets the drop log filename 3. allow=udp:ADDR:PORT - adds an allow rule e.g.) $ qemu -net user,dropudp=y,droplog=qemu.drop,allow=udp:10.0.2.3:53 All UDP packets except ones allowed by allow rules will be dropped. The source and the destination of the dropped packets are logged in the file specified by FILE. PORT can be a single number (e.g. 53) or a range (e.g. [80-81]). If ADDR is ommitted, all addresses match the rule. TCP support will follow (in another patch series). Signed-off-by: Daisuke Nojiri <dnojiri@google.com> /* PASS */