From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:44315) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q9ozC-0002Fy-Bi for qemu-devel@nongnu.org; Tue, 12 Apr 2011 21:35:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q9oOp-0008Lu-3r for qemu-devel@nongnu.org; Tue, 12 Apr 2011 20:57:40 -0400 Received: from smtp-out.google.com ([216.239.44.51]:24080) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q9oOo-0008LD-UV for qemu-devel@nongnu.org; Tue, 12 Apr 2011 20:57:39 -0400 Received: from wpaz33.hot.corp.google.com (wpaz33.hot.corp.google.com [172.24.198.97]) by smtp-out.google.com with ESMTP id p3D0vcka002084 for ; Tue, 12 Apr 2011 17:57:38 -0700 Received: from pxi7 (pxi7.prod.google.com [10.243.27.7]) by wpaz33.hot.corp.google.com with ESMTP id p3D0vImW009207 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Tue, 12 Apr 2011 17:57:37 -0700 Received: by pxi7 with SMTP id 7so62593pxi.2 for ; Tue, 12 Apr 2011 17:57:37 -0700 (PDT) MIME-Version: 1.0 Date: Tue, 12 Apr 2011 17:55:38 -0700 Message-ID: From: Daisuke Nojiri Content-Type: multipart/alternative; boundary=000e0cd29c926bf96b04a0c24476 Subject: [Qemu-devel] [PATCH 2/3] Slirp Reverse UDP Firewal List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --000e0cd29c926bf96b04a0c24476 Content-Type: text/plain; charset=ISO-8859-1 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 diff --git a/net.c b/net.c index 95256ce..38ca29a 100644 --- a/net.c +++ b/net.c @@ -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 */ } }, diff --git a/net/slirp.c b/net/slirp.c index c3a296a..38995ec 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -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, diff --git a/qemu-options.hx b/qemu-options.hx index d0a14a7..e59bf93 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -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 diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 3e88f37..a389cc5 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -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); diff --git a/slirp/slirp.c b/slirp/slirp.c index c570ef5..29dd0ca 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -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; +} diff --git a/slirp/udp.c b/slirp/udp.c index 7e583b4..f92731c 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -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 { /* PASS */ --000e0cd29c926bf96b04a0c24476 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
This patch series adds a reverse UDP firewall functionality = to Slirp.
The series consists of three patches. Each adds one -ne= t user option:

=A0 =A0 1. dropudp=3Dy|n - enables = the firewall
=A0 =A0 2. droplog=3DFILE - sets the drop log filename
=A0 = =A0 3. allow=3Dudp:ADDR:PORT - adds an allow rule

= =A0 e.g.) $ qemu -net user,dropudp=3Dy,droplog=3Dqemu.drop,allow=3Dudp: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 packet= s 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 s= upport will follow (in another patch series).

Sign= ed-off-by: Daisuke Nojiri <dnojiri= @google.com>

diff --git a/net.c b/net.c
index 95256c= e..38ca29a 100644
--- a/net.c
+++ b/net.c
@@ = -929,6 +929,10 @@ static const struct {
=A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0.name =3D "dropudp",
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_STRING,
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0.help =3D "Enable UDP reverse fir= ewall",
+ =A0 =A0 =A0 =A0 =A0 =A0}, {
+ =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0.name =3D "droplog",
+ =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_STRING,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0.help =3D "Set log filename for = the reverse firewall",
=A0 =A0 =A0 =A0 =A0 =A0 =A0},
=A0 =A0 =A0 =A0 =A0 =A0 =A0{ /* end of list */ }
=A0 =A0 =A0 = =A0 =A0},
diff --git a/net/slirp.c b/net/slirp.c
index c3a296a..38995ec 100644
--- a/net/slirp.c
++= + b/net/slirp.c
@@ -690,6 +690,7 @@ int net_init_slirp(QemuOpts *= opts,
=A0 =A0 =A0const char *bootfile;
=A0 =A0 =A0const= char *smb_export;
=A0 =A0 =A0const char *vsmbsrv;
+ =A0 =A0const char *droplog= ;
=A0 =A0 =A0char *vnet =3D NULL;
=A0 =A0 =A0int restri= cted =3D 0;
=A0 =A0 =A0int ret;
@@ -731,6 +732,16 @@ in= t net_init_slirp(QemuOpts *opts,
=A0 =A0 =A0 =A0 =A0slirp_enable_drop_udp();
=A0 =A0 =A0}
=A0
+ =A0 =A0droplog =3D qemu_opt_get(opts, "droplog&= quot;);
+ =A0 =A0if (droplog) {
+ =A0 =A0 =A0 =A0FILE *= drop_log_fd =3D fopen(droplog, "w");
+ =A0 =A0 =A0 =A0if (!drop_log_fd) {
+ =A0 =A0 =A0 =A0 =A0 = =A0error_report("Unable to open reverse firewall log");
+ =A0 =A0 =A0 =A0 =A0 =A0return -1;
+ =A0 =A0 =A0 =A0}
+ =A0 =A0 =A0 =A0slirp_set_drop_log_fd(drop_log_fd);
+ =A0 =A0}
+
=A0 =A0 =A0qemu_opt_foreach(opts, net= _init_slirp_configs, NULL, 0);
=A0
=A0 =A0 =A0ret =3D n= et_slirp_init(vlan, "user", name, restricted, vnet, vhost,
<= div>diff --git a/qemu-options.hx b/qemu-options.hx
index d0a14a7..e59bf93 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1067,7 +1067,7 @@ DEF("net"= , HAS_ARG, QEMU_OPTION_net,
=A0#ifdef CONFIG_SLIRP
=A0 = =A0 =A0"-net user[,vlan=3Dn][,name=3Dstr][,net=3Daddr[/mask]][,host=3D= addr][,restrict=3Dy|n]\n"
=A0 =A0 =A0" =A0 =A0 =A0 =A0 [,hostname=3Dhost][,dhcpstart=3Daddr= ][,dns=3Daddr][,tftp=3Ddir][,bootfile=3Df]\n"
- =A0 =A0"= ; =A0 =A0 =A0 =A0 [,hostfwd=3Drule][,guestfwd=3Drule][,dropudp=3Dy|n]"=
+ =A0 =A0" =A0 =A0 =A0 =A0 [,hostfwd=3Drule][,guestfwd=3Dru= le][,dropudp=3Dy|n][,droplog=3Dfile]"
=A0#ifndef _WIN32
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "[,smb=3Ddir[,smbs= erver=3Daddr]]\n"
=A0#endif
diff --git a/slirp/lib= slirp.h b/slirp/libslirp.h
index 3e88f37..a389cc5 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -= 46,6 +46,8 @@ size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr gue= st_addr,
=A0
=A0/* Usermode firewall functions */
=A0void slirp_enable_drop_udp(void);
+void slirp_set_drop_lo= g_fd(FILE *fd);
+int slirp_drop_log(const char *format, ...);
=A0int slirp_should_drop(unsigned long dst_addr,
=A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned short dst_port,
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u_int8_t proto);
<= div>diff --git a/slirp/slirp.c b/slirp/slirp.c
index c570ef5..29d= d0ca 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -1112,17 +1112,22 @@ static int slirp_state_load(QEMUFile *f, voi= d *opaque, int version_id)
=A0 =A0 =A0return 0;
=A0}
=A0
-
=A0/*
=A0 * Global variables for the usermode firewall
=A0 */
=A0static int drop_udp =3D 0;
+static FILE *dr= op_log_fd =3D NULL;
=A0
=A0void slirp_enable_drop_udp(void)
=A0{
=
=A0 =A0 =A0drop_udp =3D 1;
=A0}
=A0
+voi= d slirp_set_drop_log_fd(FILE *fd)
+{
+ =A0 =A0drop_log_= fd =3D fd;
+}
+
=A0int slirp_should_drop(unsigned long dst_addr,
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned short dst_= port,
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u_int8_t pro= to) {
@@ -1139,3 +1144,23 @@ int slirp_should_drop(unsigned long = dst_addr,
=A0
=A0 =A0 =A0return 1;
=A0}
+
+/*
+ * Write to drop-log
+ */
+int slirp_d= rop_log(const char *format, ...)
+{
+ =A0 =A0va_list ar= gs;
+
+ =A0 =A0if (!drop_log_fd) {
+ =A0 =A0 =A0 =A0return = 0;
+ =A0 =A0}
+
+ =A0 =A0va_start(args, forma= t);
+ =A0 =A0vfprintf(drop_log_fd, format, args);
+ =A0= =A0va_end(args);
+
+ =A0 =A0fflush(drop_log_fd);
+
+ =A0 =A0re= turn 1;
+}
diff --git a/slirp/udp.c b/slirp/udp.c
=
index 7e583b4..f92731c 100644
--- a/slirp/udp.c
++= + b/slirp/udp.c
@@ -67,6 +67,8 @@ udp_input(register struct mbuf *m, int iphlen)
=
=A0 DE= BUG_ARG("m =3D %lx", (long)m);
=A0 DEBUG_ARG("iphlen =3D %d&q= uot;, iphlen);
=A0
+ =A0 =A0 =A0 =A0time_t timestamp =3D time(NULL);
<= div>+
=A0 /*
=A0 * Strip IP options, if any; should skip this,
=A0 *= make available to user, and use on returned packets,
@@ -103,6 += 105,13 @@ udp_input(register struct mbuf *m, int iphlen)
=A0 =A0 = =A0 =A0 =A0 */
=A0 =A0 =A0 =A0 =A0if (slirp_should_drop(ip->ip_dst.s_addr, uh->= uh_dport, IPPROTO_UDP)) {
=A0 =A0 =A0 =A0 =A0 =A0 =A0/* DROP */
+ =A0 =A0 =A0 =A0 =A0 =A0slirp_drop_log(
+ =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0"Dropped UDP: src:0x%08x:0x%04hx dst:0x%08x:0x%04hx= %ld\n",
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ntohl(ip->ip_src.s_addr),
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ntohs(uh->uh_sport),
+ =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0ntohl(ip->ip_dst.s_addr),
+ =A0 =A0= =A0 =A0 =A0 =A0 =A0 =A0ntohs(uh->uh_dport),
+ =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0timestamp);
=A0 =A0 =A0 =A0 =A0 =A0 =A0goto bad;
=A0 =A0 =A0 =A0 =A0} el= se {
=A0 =A0 =A0 =A0 =A0 =A0 =A0/* PASS */

--000e0cd29c926bf96b04a0c24476--