aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:21 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:21 -0800
commitc2db2b6accc7888df514261a7240e7759df95a4c (patch)
tree0d7ecd37a534c15348cbad01d0d1f84183b7b4d8
parentdf7881f07f53b041dc0568be8528e9dbb74994cc (diff)
downloadexternal_qemu-c2db2b6accc7888df514261a7240e7759df95a4c.zip
external_qemu-c2db2b6accc7888df514261a7240e7759df95a4c.tar.gz
external_qemu-c2db2b6accc7888df514261a7240e7759df95a4c.tar.bz2
auto import from //branches/cupcake/...@125939
-rw-r--r--CHANGES.TXT9
-rw-r--r--Makefile6
-rw-r--r--Makefile.android14
-rwxr-xr-xandroid-configure.sh11
-rw-r--r--android/build/definitions.make1
-rw-r--r--android/build/host_executable.make12
-rw-r--r--android/utils/ini.c2
-rw-r--r--android/utils/ini.h4
-rw-r--r--android/vm/info.c2
-rw-r--r--android_avm.c42
-rw-r--r--android_avm.h39
-rw-r--r--android_console.c125
-rw-r--r--android_help.c18
-rw-r--r--android_main.c94
-rw-r--r--android_options.h2
-rw-r--r--android_profile.c127
-rw-r--r--android_profile.h34
-rw-r--r--android_qemud.c3
-rw-r--r--android_utils.h5
-rw-r--r--gdbstub.c28
-rw-r--r--hw/goldfish_mmc.c4
-rw-r--r--loadpng.c2
-rw-r--r--proxy/proxy_common.c75
-rw-r--r--proxy/proxy_common.h7
-rw-r--r--proxy/proxy_http.c30
-rw-r--r--proxy/proxy_http_connector.c26
-rw-r--r--proxy/proxy_http_int.h10
-rw-r--r--proxy/proxy_http_rewriter.c21
-rw-r--r--proxy/proxy_int.h18
-rw-r--r--slirp/udp.c699
-rw-r--r--slirp2/COPYRIGHT (renamed from slirp/COPYRIGHT)0
-rw-r--r--slirp2/bootp.c (renamed from slirp/bootp.c)48
-rw-r--r--slirp2/bootp.h (renamed from slirp/bootp.h)8
-rw-r--r--slirp2/cksum.c (renamed from slirp/cksum.c)0
-rw-r--r--slirp2/ctl.h (renamed from slirp/ctl.h)0
-rw-r--r--slirp2/debug.c (renamed from slirp/debug.c)8
-rw-r--r--slirp2/debug.h (renamed from slirp/debug.h)0
-rw-r--r--slirp2/helper.h111
-rw-r--r--slirp2/icmp_var.h (renamed from slirp/icmp_var.h)0
-rw-r--r--slirp2/if.c (renamed from slirp/if.c)6
-rw-r--r--slirp2/if.h (renamed from slirp/if.h)0
-rw-r--r--slirp2/ip.h (renamed from slirp/ip.h)30
-rw-r--r--slirp2/ip_icmp.c (renamed from slirp/ip_icmp.c)59
-rw-r--r--slirp2/ip_icmp.h (renamed from slirp/ip_icmp.h)8
-rw-r--r--slirp2/ip_input.c (renamed from slirp/ip_input.c)6
-rw-r--r--slirp2/ip_output.c (renamed from slirp/ip_output.c)0
-rw-r--r--slirp2/libslirp.h (renamed from slirp/libslirp.h)15
-rw-r--r--slirp2/main.h (renamed from slirp/main.h)14
-rw-r--r--slirp2/mbuf.c (renamed from slirp/mbuf.c)0
-rw-r--r--slirp2/mbuf.h (renamed from slirp/mbuf.h)0
-rw-r--r--slirp2/misc.c (renamed from slirp/misc.c)61
-rw-r--r--slirp2/misc.h (renamed from slirp/misc.h)0
-rw-r--r--slirp2/sbuf.c (renamed from slirp/sbuf.c)8
-rw-r--r--slirp2/sbuf.h (renamed from slirp/sbuf.h)0
-rw-r--r--slirp2/slirp.c (renamed from slirp/slirp.c)84
-rw-r--r--slirp2/slirp.h (renamed from slirp/slirp.h)61
-rw-r--r--slirp2/slirp_config.h (renamed from slirp/slirp_config.h)6
-rw-r--r--slirp2/socket.c (renamed from slirp/socket.c)132
-rw-r--r--slirp2/socket.h (renamed from slirp/socket.h)12
-rw-r--r--slirp2/tcp.h (renamed from slirp/tcp.h)6
-rw-r--r--slirp2/tcp_input.c (renamed from slirp/tcp_input.c)34
-rw-r--r--slirp2/tcp_output.c (renamed from slirp/tcp_output.c)0
-rw-r--r--slirp2/tcp_subr.c (renamed from slirp/tcp_subr.c)145
-rw-r--r--slirp2/tcp_timer.c (renamed from slirp/tcp_timer.c)0
-rw-r--r--slirp2/tcp_timer.h (renamed from slirp/tcp_timer.h)0
-rw-r--r--slirp2/tcp_var.h (renamed from slirp/tcp_var.h)0
-rw-r--r--slirp2/tcpip.h (renamed from slirp/tcpip.h)0
-rw-r--r--slirp2/tftp.c (renamed from slirp/tftp.c)56
-rw-r--r--slirp2/tftp.h (renamed from slirp/tftp.h)0
-rw-r--r--slirp2/udp.c496
-rw-r--r--slirp2/udp.h (renamed from slirp/udp.h)17
-rw-r--r--sockets.c1126
-rw-r--r--sockets.h328
-rw-r--r--tcpdump.c147
-rw-r--r--tcpdump.h36
-rw-r--r--telephony/gsm.c9
-rw-r--r--telephony/remote_call.c8
-rw-r--r--telephony/sim_card.c15
-rw-r--r--telephony/sysdeps_qemu.c30
-rw-r--r--vl.c232
-rw-r--r--vnc.c24
81 files changed, 2815 insertions, 2041 deletions
diff --git a/CHANGES.TXT b/CHANGES.TXT
index 8f4b87a..05820d6 100644
--- a/CHANGES.TXT
+++ b/CHANGES.TXT
@@ -48,6 +48,15 @@ IMPORTANT CHANGES:
are enabled by default, so this only affects "normal" virtual machines
created with the 'android' tool.
+- The emulator now supports capturing network packets to a file.
+ You can either use the new -tcpdump <file> command-line option, or use
+ the new console 'network capture start <file>' command (then use
+ 'network capture stop' to stop it).
+
+ This captures all ethernet packets on the virtual LAN, so this includes
+ ARP, UDP, TCP, etc... The file is in libpcap format and can be opened with
+ external tools like WireShark for analysis.
+
OTHER:
- A new console command 'vm name' can be used to query the name of the
diff --git a/Makefile b/Makefile
index f911c2a..f39a14c 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,8 @@ CLEAR_VARS := $(BUILD_SYSTEM)/clear_vars.make
BUILD_HOST_EXECUTABLE := $(BUILD_SYSTEM)/host_executable.make
BUILD_HOST_STATIC_LIBRARY := $(BUILD_SYSTEM)/host_static_library.make
+DEPENDENCY_DIRS :=
+
all: libraries executables
EXECUTABLES :=
LIBRARIES :=
@@ -67,5 +69,5 @@ clean-config:
rm -f $(CONFIG_MAKE) $(CONFIG_H)
# include dependency information
-CLEAN_OBJS_DIRS := $(sort $(CLEAN_OBJS_DIRS))
--include $(wildcard $(CLEAN_OBJS_DIRS:%=%/*.d))
+DEPENDENCY_DIRS := $(sort $(DEPENDENCY_DIRS))
+-include $(wildcard $(DEPENDENCY_DIRS:%=%/*.d)) \ No newline at end of file
diff --git a/Makefile.android b/Makefile.android
index baf8344..a35a334 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -17,8 +17,8 @@ endif
ifeq ($(HOST_OS),windows)
MY_CFLAGS += -D_WIN32 -mno-cygwin
- # we need Win32 features that are available since Windows 2000 (NT 5.0)
- MY_CFLAGS += -DWINVER=0x500
+ # we need Win32 features that are available since Windows 2000 Professional/Server (NT 5.0)
+ MY_CFLAGS += -DWINVER=0x501
endif
MY_CC := $(HOST_CC)
@@ -199,7 +199,7 @@ LOCAL_STATIC_LIBRARIES := $(EMULATOR_OP_LIBRARIES) emulator-arm
LOCAL_LDFLAGS := $(my_32bit_ldflags)
# don't remove the -fno-strict-aliasing, or you'll break things
-# (e.g. slirp/network support)
+# (e.g. slirp2/network support)
#
LOCAL_CFLAGS := $(my_32bit_cflags) \
-fno-PIC -fomit-frame-pointer -Wno-sign-compare \
@@ -350,14 +350,14 @@ HW_SOURCES := android_arm.c arm_boot.c arm_pic.c cdrom.c \
LOCAL_SRC_FILES += $(HW_SOURCES:%=hw/%)
LOCAL_CFLAGS += -I$(LOCAL_PATH)/hw
-# include slirp code, i.e. the user-level networking stuff
+# include slirp2 code, i.e. the user-level networking stuff
#
SLIRP_SOURCES := bootp.c cksum.c debug.c if.c ip_icmp.c ip_input.c ip_output.c \
mbuf.c misc.c sbuf.c slirp.c socket.c tcp_input.c tcp_output.c \
tcp_subr.c tcp_timer.c tftp.c udp.c
-LOCAL_SRC_FILES += $(SLIRP_SOURCES:%=slirp/%)
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/slirp
+LOCAL_SRC_FILES += $(SLIRP_SOURCES:%=slirp2/%)
+LOCAL_CFLAGS += -I$(LOCAL_PATH)/slirp2
# socket proxy support
#
@@ -408,6 +408,7 @@ VL_SOURCES := vl.c osdep.c \
qemu_timers.c \
shaper.c charpipe.c loadpng.c \
framebuffer.c \
+ tcpdump.c \
android_debug.c \
android_help.c \
android_option.c \
@@ -415,7 +416,6 @@ VL_SOURCES := vl.c osdep.c \
android_charmap.c \
android_resource.c \
android_utils.c \
- android_profile.c \
android_console.c \
android_events.c \
android_timezone.c \
diff --git a/android-configure.sh b/android-configure.sh
index a73b89b..95409c5 100755
--- a/android-configure.sh
+++ b/android-configure.sh
@@ -105,11 +105,11 @@ if [ -n "$ANDROID_PRODUCT_OUT" ] ; then
log "TOP found at $TOP"
# $TOP/config/envsetup.make is for the old tree layout
# $TOP/build/envsetup.sh is for the new one
- ANDROID_ENVSETUP_MK=$TOP/config/envsetup.make
- if [ ! -f $ANDROID_ENVSETUP_MK ] ; then
- ANDROID_ENVSETUP_MK=$TOP/build/core/envsetup.mk
+ ANDROID_CONFIG_MK=$TOP/config/envsetup.make
+ if [ ! -f $ANDROID_CONFIG_MK ] ; then
+ ANDROID_CONFIG_MK=$TOP/build/core/config.mk
fi
- if [ ! -f $ANDROID_ENVSETUP_MK ] ; then
+ if [ ! -f $ANDROID_CONFIG_MK ] ; then
echo "Cannot find build system root (TOP)"
echo "defaulting to non-Android build"
unset TOP
@@ -219,8 +219,7 @@ if [ "$IN_ANDROID_BUILD" = "yes" ] ; then
# Get the value of a build variable as an absolute path.
function get_abs_build_var()
{
- (cd "$TOP" &&
- CALLED_FROM_SETUP=true make -f $ANDROID_ENVSETUP_MK dumpvar-abs-$1)
+ (cd $TOP && CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core make -f $ANDROID_CONFIG_MK dumpvar-abs-$1)
}
# locate prebuilt directory
diff --git a/android/build/definitions.make b/android/build/definitions.make
index c4183ea..fd1dd63 100644
--- a/android/build/definitions.make
+++ b/android/build/definitions.make
@@ -54,6 +54,7 @@ define compile-c-source
SRC:=$(1)
OBJ:=$$(LOCAL_OBJS_DIR)/$$(SRC:%.c=%.o)
LOCAL_OBJECTS += $$(OBJ)
+DEPENDENCY_DIRS += $$(dir $$(OBJ))
$$(OBJ): PRIVATE_CFLAGS := $$(CFLAGS) $$(LOCAL_CFLAGS) -I$$(LOCAL_PATH) -I$$(OBJS_DIR)
$$(OBJ): PRIVATE_CC := $$(LOCAL_CC)
$$(OBJ): PRIVATE_OBJ := $$(OBJ)
diff --git a/android/build/host_executable.make b/android/build/host_executable.make
index a9b51d8..62f4762 100644
--- a/android/build/host_executable.make
+++ b/android/build/host_executable.make
@@ -14,22 +14,20 @@
#
# first, call a library containing all object files
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-# now, link the executable with it
-LOCAL_BUILT_LIBRARY := $(LOCAL_BUILT_MODULE)
LOCAL_BUILT_MODULE := $(call executable-path,$(LOCAL_MODULE))
+LOCAL_CC ?= $(CC)
+include $(BUILD_SYSTEM)/binary.make
LOCAL_LDLIBS := $(foreach lib,$(LOCAL_STATIC_LIBRARIES),$(call library-path,$(lib))) $(LOCAL_LDLIBS)
$(LOCAL_BUILT_MODULE): PRIVATE_LDFLAGS := $(LDFLAGS) $(LOCAL_LDFLAGS)
$(LOCAL_BUILT_MODULE): PRIVATE_LDLIBS := $(LOCAL_LDLIBS)
-$(LOCAL_BUILT_MODULE): PRIVATE_LIBRARY := $(LOCAL_BUILT_LIBRARY)
+$(LOCAL_BUILT_MODULE): PRIVATE_OBJS := $(LOCAL_OBJECTS)
-$(LOCAL_BUILT_MODULE): $(LOCAL_BUILT_LIBRARY)
+$(LOCAL_BUILT_MODULE): $(LOCAL_OBJECTS)
@ mkdir -p $(dir $@)
@ echo "Executable: $@"
- $(hide) $(LD) $(PRIVATE_LDFLAGS) -o $@ $(PRIVATE_LIBRARY) $(PRIVATE_LDLIBS)
+ $(hide) $(LD) $(PRIVATE_LDFLAGS) -o $@ $(PRIVATE_LIBRARY) $(PRIVATE_OBJS) $(PRIVATE_LDLIBS)
EXECUTABLES += $(LOCAL_BUILT_MODULE)
$(LOCAL_BUILT_MODULE): $(foreach lib,$(LOCAL_STATIC_LIBRARIES),$(call library-path,$(lib)))
diff --git a/android/utils/ini.c b/android/utils/ini.c
index d99ecdd..096f44c 100644
--- a/android/utils/ini.c
+++ b/android/utils/ini.c
@@ -159,7 +159,7 @@ isKeyStartChar( int c )
static int
isKeyChar( int c )
{
- return isKeyStartChar(c) || ((unsigned)(c-'0') < 10) || (c == '.');
+ return isKeyStartChar(c) || ((unsigned)(c-'0') < 10) || (c == '.') || (c == '-');
}
IniFile*
diff --git a/android/utils/ini.h b/android/utils/ini.h
index 41b369b..ad6b36a 100644
--- a/android/utils/ini.h
+++ b/android/utils/ini.h
@@ -23,7 +23,7 @@
* assignment := <space>* <keyName> <space>* '=' <space>* <valueString> <space>* <LF>
* keyName := <keyNameStartChar> <keyNameChar>*
* keyNameStartChar := [A-Za-z_]
- * keyNameChar := [A-Za-z0-9_.]
+ * keyNameChar := [A-Za-z0-9_.-]
* valueString := <noLF>*
* space := ' ' | '\t'
* LF := '\r\n' | '\n' | '\r'
@@ -35,7 +35,7 @@
* - empty lines are ignored, as well as lines beginning with ';' or '#'
* - lines must be of the form: "<keyName> = <value>"
* - key names must start with a letter or an underscore
- * - other key name characters can be letters, digits, underscores or dots
+ * - other key name characters can be letters, digits, underscores, dots or dashes
*
* - leading and trailing space are allowed and ignored before/after the key name
* and before/after the value
diff --git a/android/vm/info.c b/android/vm/info.c
index e3f04ff..a82b60b 100644
--- a/android/vm/info.c
+++ b/android/vm/info.c
@@ -1094,7 +1094,7 @@ _checkSkinDir( char* temp, char* end, const char* skinDirRoot, const char* s
return -1;
/* first, is this a normal skin directory ? */
- q = bufprint(q, end, "/layout");
+ q = bufprint(p, end, "/layout");
if (q < end && path_exists(temp)) {
/* yes */
*p = 0;
diff --git a/android_avm.c b/android_avm.c
deleted file mode 100644
index 277233f..0000000
--- a/android_avm.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "android_avm.h"
-#include "android_utils.h"
-#include <string.h>
-
-int
-avm_check_name( const char* avm_name )
-{
- static const char* goodchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-0123456789.";
- int len = strlen(avm_name);
- int slen = strspn(avm_name, goodchars);
-
- return (len == slen);
-}
-
-
-char*
-avm_bufprint_default_root( char* p, char* end )
-{
- /* at the moment, store in $CONFIG_PATH/VMs */
- return bufprint_config_path(p, end, "VMs" );
-}
-
-char*
-avm_bufprint_avm_dir( char* p, char* end, const char* avm_name, const char* root_dir )
-{
- if (root_dir) {
- int len = strlen(root_dir);
- /* get rid of trailing path separators */
- while (len > 0 && root_dir[len-1] == PATH_SEP[0])
- len -= 1;
-
- p = bufprint( p, end, "%.*s", len, root_dir );
- } else {
- p = avm_bufprint_default_root( p, end );
-
- p = bufprint( p, end, PATH_SEP "%s", avm_name );
-
- return p;
-}
-
-
-
diff --git a/android_avm.h b/android_avm.h
deleted file mode 100644
index 24b7fa7..0000000
--- a/android_avm.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (C) 2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#ifndef ANDROID_VIRTUAL_MACHINE_H
-#define ANDROID_VIRTUAL_MACHINE_H
-
-/* An Android Virtual Machine (AVM for short) corresponds to
- * a directory containing all system + data disk images for a
- * given virtual device, plus some AVM-specific configuration
- * files.
- */
-
-/* checks that the name of an AVM doesn't contain fancy characters
- * returns 1 on success, 0 on failure
- */
-extern int avm_check_name( const char* avm_name );
-
-/* bufprint the path of the default root directory where all AVMs are stored
- * this is normally $HOME/.android/$SDK_VERSION/VMs on Unix
- */
-extern char* avm_bufprint_default_root( char* p, char* end );
-
-/* bufprint the path of a given AVM's directory
- * if 'root' is non NULL, this will be $root/$avm_name
- * otherwise, it will be the result of avm_bufprint_defalt_root followed by avm_name
- */
-extern char* avm_bufprint_avm_dir( char* p, char* end, const char* avm_name, const char* root_dir );
-
-
-
-#endif /* ANDROID_VIRTUAL_MACHINE_H */
diff --git a/android_console.c b/android_console.c
index a83bb85..defc0f9 100644
--- a/android_console.c
+++ b/android_console.c
@@ -31,6 +31,7 @@
#include "modem_driver.h"
#include "android_gps.h"
#include "android/globals.h"
+#include "tcpdump.h"
#include <stdlib.h>
#include <stdio.h>
@@ -75,7 +76,7 @@ typedef struct ControlClientRec_* ControlClient;
typedef struct {
int host_port;
int host_udp;
- unsigned int guest_addr;
+ unsigned int guest_ip;
int guest_port;
} RedirRec, *Redir;
@@ -119,7 +120,7 @@ static int
control_global_add_redir( ControlGlobal global,
int host_port,
int host_udp,
- unsigned int guest_addr,
+ unsigned int guest_ip,
int guest_port )
{
Redir redir;
@@ -141,7 +142,7 @@ control_global_add_redir( ControlGlobal global,
redir->host_port = host_port;
redir->host_udp = host_udp;
- redir->guest_addr = guest_addr;
+ redir->guest_ip = guest_ip;
redir->guest_port = guest_port;
return 0;
@@ -221,10 +222,10 @@ static void control_control_write( ControlClient client, const char* buff, in
#if USE_SYSDEPS
ret = sys_channel_write( client->sock, buff, len );
#else
- ret = send( client->sock, buff, len, 0);
+ ret = socket_send( client->sock, buff, len);
#endif
if (ret < 0) {
- if (socket_errno != EINTR && socket_errno != EWOULDBLOCK)
+ if (errno != EINTR && errno != EWOULDBLOCK)
return;
} else {
buff += ret;
@@ -485,11 +486,11 @@ control_client_read( void* _client )
#if USE_SYSDEPS
size = sys_channel_read( client->sock, buf, sizeof(buf) );
#else
- size = recv( client->sock, buf, sizeof(buf), 0 );
+ size = socket_recv( client->sock, buf, sizeof(buf) );
#endif
if (size < 0) {
- D(( "size < 0, exiting with %d: %s\n", socket_errno, socket_errstr() ));
- if (socket_errno != EWOULDBLOCK && socket_errno != EINTR)
+ D(( "size < 0, exiting with %d: %s\n", errno, errno_str ));
+ if (errno != EWOULDBLOCK && errno != EINTR)
control_client_destroy( client );
return;
}
@@ -503,18 +504,18 @@ control_client_read( void* _client )
int nn;
#ifdef _WIN32
# if DEBUG
- char temp[16];
- int count = size > sizeof(temp)-1 ? sizeof(temp)-1 : size;
- for (nn = 0; nn < count; nn++) {
- int c = buf[nn];
- if (c == '\n')
- temp[nn] = '!';
- else if (c < 32)
- temp[nn] = '.';
- else
- temp[nn] = (char)c;
- }
- temp[nn] = 0;
+ char temp[16];
+ int count = size > sizeof(temp)-1 ? sizeof(temp)-1 : size;
+ for (nn = 0; nn < count; nn++) {
+ int c = buf[nn];
+ if (c == '\n')
+ temp[nn] = '!';
+ else if (c < 32)
+ temp[nn] = '.';
+ else
+ temp[nn] = (char)c;
+ }
+ temp[nn] = 0;
D(( "received %d bytes: %s\n", size, temp ));
# endif
#else
@@ -549,12 +550,9 @@ control_global_accept( void* _global )
}
#else
for(;;) {
- struct sockaddr_in sockaddr;
- socklen_t len = sizeof(sockaddr);
-
- fd = accept( global->listen_fd, (struct sockaddr *)&sockaddr, &len);
- if (fd < 0 && socket_errno != EINTR) {
- D(( "problem in accept: %d: %s\n", socket_errno, socket_errstr() ));
+ fd = socket_accept( global->listen_fd, NULL );
+ if (fd < 0 && errno != EINTR) {
+ D(( "problem in accept: %d: %s\n", errno, errno_str ));
perror("accept");
return;
} else if (fd >= 0) {
@@ -583,7 +581,7 @@ control_global_init( ControlGlobal global,
Socket fd;
#if !USE_SYSDEPS
int ret;
- struct sockaddr_in sockaddr;
+ SockAddress sockaddr;
#endif
memset( global, 0, sizeof(*global) );
@@ -603,7 +601,7 @@ control_global_init( ControlGlobal global,
(SysChannelCallback) control_global_accept,
global );
#else
- fd = socket(PF_INET, SOCK_STREAM, 0);
+ fd = socket_create_inet( SOCKET_STREAM );
if (fd < 0) {
perror("socket");
return -1;
@@ -611,22 +609,19 @@ control_global_init( ControlGlobal global,
socket_set_xreuseaddr( fd );
- memset( &sockaddr, 0, sizeof(sockaddr) );
- sockaddr.sin_family = AF_INET;
- sockaddr.sin_port = htons(control_port);
- sockaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ sock_address_init_inet( &sockaddr, SOCK_ADDRESS_INET_LOOPBACK, control_port );
- ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
+ ret = socket_bind(fd, &sockaddr );
if (ret < 0) {
perror("bind");
- close( fd );
+ socket_close( fd );
return -1;
}
- ret = listen(fd, 0);
+ ret = socket_listen(fd, 0);
if (ret < 0) {
perror("listen");
- close( fd );
+ socket_close( fd );
return -1;
}
@@ -740,6 +735,46 @@ describe_network_delay( ControlClient client )
/* XXX: TODO */
}
+static int
+do_network_capture_start( ControlClient client, char* args )
+{
+ if ( !args ) {
+ control_write( client, "KO: missing <file> argument, see 'help network capture start'\r\n" );
+ return -1;
+ }
+ if ( qemu_tcpdump_start(args) < 0) {
+ control_write( client, "KO: could not start capture: %s", strerror(errno) );
+ return -1;
+ }
+ return 0;
+}
+
+static int
+do_network_capture_stop( ControlClient client, char* args )
+{
+ /* no need to return an error here */
+ qemu_tcpdump_stop();
+ return 0;
+}
+
+static const CommandDefRec network_capture_commands[] =
+{
+ { "start", "start network capture",
+ "'network capture start <file>' starts a new capture of network packets\r\n"
+ "into a specific <file>. This will stop any capture already in progress.\r\n"
+ "the capture file can later be analyzed by tools like WireShark. It uses\r\n"
+ "the libpcap file format.\r\n\r\n"
+ "you can stop the capture anytime with 'network capture stop'\r\n", NULL,
+ do_network_capture_start, NULL },
+
+ { "stop", "stop network capture",
+ "'network capture stop' stops a currently running packet capture, if any.\r\n"
+ "you can start one with 'network capture start <file>'\r\n", NULL,
+ do_network_capture_stop, NULL },
+
+ { NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
static const CommandDefRec network_commands[] =
{
{ "status", "dump network status", NULL, NULL,
@@ -751,6 +786,10 @@ static const CommandDefRec network_commands[] =
{ "delay", "change network latency", NULL, describe_network_delay,
do_network_delay, NULL },
+ { "capture", "dump network packets to file",
+ "allows to start/stop capture of network packets to a file for later analysis\r\n", NULL,
+ NULL, network_capture_commands },
+
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
@@ -841,9 +880,9 @@ redir_find( ControlGlobal global, int port, int isudp )
static int
do_redir_add( ControlClient client, char* args )
{
- int len, host_proto, host_port, guest_port;
- struct in_addr guest_addr;
- Redir redir;
+ int len, host_proto, host_port, guest_port;
+ uint32_t guest_ip;
+ Redir redir;
if ( !args )
goto BadFormat;
@@ -868,20 +907,20 @@ do_redir_add( ControlClient client, char* args )
return -1;
}
- if (!inet_aton("10.0.2.15", &guest_addr)) {
+ if (!inet_strtoip("10.0.2.15", &guest_ip)) {
control_write( client, "KO: unexpected internal failure when resolving 10.0.2.15\r\n" );
return -1;
}
D(("pattern hport=%d gport=%d proto=%d\n", host_port, guest_port, host_proto ));
if ( control_global_add_redir( client->global, host_port, host_proto,
- guest_addr.s_addr, guest_port ) < 0 )
+ guest_ip, guest_port ) < 0 )
{
control_write( client, "KO: not enough memory to allocate redirection\r\n" );
return -1;
}
- if (slirp_redir(host_proto, host_port, guest_addr, guest_port) < 0) {
+ if (slirp_redir(host_proto, host_port, guest_ip, guest_port) < 0) {
control_write( client, "KO: can't setup redirection, port probably used by another program on host\r\n" );
control_global_del_redir( client->global, host_port, host_proto );
return -1;
@@ -2109,7 +2148,7 @@ static const CommandDefRec main_commands[] =
NULL, network_commands },
{ "power", "power related commands",
- "allows change battery and AC power status\r\n", NULL,
+ "allows to change battery and AC power status\r\n", NULL,
NULL, power_commands },
{ "quit|exit", "quit control session", NULL, NULL,
diff --git a/android_help.c b/android_help.c
index b4c4f8e..555285b 100644
--- a/android_help.c
+++ b/android_help.c
@@ -1150,6 +1150,24 @@ help_bootchart(stralloc_t *out)
);
}
+static void
+help_tcpdump(stralloc_t *out)
+{
+ PRINTF(
+ " use the -tcpdump <file> option to start capturing all network packets\n"
+ " that are sent through the emulator's virtual Ethernet LAN. You can later\n"
+ " use tools like WireShark to analyze the traffic and understand what\n"
+ " really happens.\n\n"
+
+ " note that this captures all Ethernet packets, and is not limited to TCP\n"
+ " connections.\n\n"
+
+ " you can also start/stop the packet capture dynamically through the console;\n"
+ " see the 'network capture start' and 'network capture stop' commands for\n"
+ " details.\n\n"
+ );
+}
+
#define help_noskin NULL
#define help_netspeed help_shaper
#define help_netdelay help_shaper
diff --git a/android_main.c b/android_main.c
index 75d52c7..4fa3f28 100644
--- a/android_main.c
+++ b/android_main.c
@@ -14,12 +14,7 @@
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
-#ifndef _WIN32
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#else
-#include <winsock2.h>
+#ifdef _WIN32
#include <process.h>
#endif
#include "libslirp.h"
@@ -62,6 +57,7 @@
#include "hw/goldfish_nand.h"
#include "android/globals.h"
+#include "tcpdump.h"
#include "framebuffer.h"
AndroidRotation android_framebuffer_rotation;
@@ -611,7 +607,7 @@ qemulator_light_brightness( void* opaque, const char* light, int value )
{
QEmulator* emulator = opaque;
- D("%s: light='%s' value=%d window=%p", __FUNCTION__, light, value, emulator->window);
+ VERBOSE_PRINT(hw_control,"%s: light='%s' value=%d window=%p", __FUNCTION__, light, value, emulator->window);
if ( !strcmp(light, "lcd_backlight") ) {
emulator->lcd_brightness = value;
if (emulator->window)
@@ -1493,20 +1489,18 @@ void emulator_help( void )
static int
add_dns_server( const char* server_name )
{
- struct in_addr dns1;
- struct hostent* host = gethostbyname(server_name);
+ SockAddress addr;
- if (host == NULL) {
+ if (sock_address_init_resolve( &addr, server_name, 55, 0 ) < 0) {
fprintf(stderr,
"### WARNING: can't resolve DNS server name '%s'\n",
server_name );
return -1;
}
- dns1 = *(struct in_addr*)host->h_addr;
- D( "DNS server name '%s' resolved to %s", server_name, inet_ntoa(dns1) );
+ D( "DNS server name '%s' resolved to %s", server_name, sock_address_to_string(&addr) );
- if ( slirp_add_dns_server( dns1 ) < 0 ) {
+ if ( slirp_add_dns_server( &addr ) < 0 ) {
fprintf(stderr,
"### WARNING: could not add DNS server '%s' to the network stack\n", server_name);
return -1;
@@ -1559,7 +1553,7 @@ get_report_console_options( char* end, int *maxtries )
static void
report_console( const char* proto_port, int console_port )
{
- int s = -1, s2, ret;
+ int s = -1, s2;
int maxtries = 10;
int flags = 0;
signal_state_t sigstate;
@@ -1573,16 +1567,16 @@ report_console( const char* proto_port, int console_port )
flags = get_report_console_options( end, &maxtries );
if (flags & REPORT_CONSOLE_SERVER) {
- s = socket_loopback_server( port, SOCK_STREAM );
+ s = socket_loopback_server( port, SOCKET_STREAM );
if (s < 0) {
fprintf(stderr, "could not create server socket on TCP:%ld: %s\n",
- port, socket_errstr());
+ port, errno_str);
exit(3);
}
} else {
for ( ; maxtries > 0; maxtries-- ) {
D("trying to find console-report client on tcp:%d", port);
- s = socket_loopback_client( port, SOCK_STREAM );
+ s = socket_loopback_client( port, SOCKET_STREAM );
if (s >= 0)
break;
@@ -1590,7 +1584,7 @@ report_console( const char* proto_port, int console_port )
}
if (s < 0) {
fprintf(stderr, "could not connect to server on TCP:%ld: %s\n",
- port, socket_errstr());
+ port, errno_str);
exit(3);
}
}
@@ -1606,15 +1600,15 @@ report_console( const char* proto_port, int console_port )
*end = 0;
}
if (flags & REPORT_CONSOLE_SERVER) {
- s = socket_unix_server( path, SOCK_STREAM );
+ s = socket_unix_server( path, SOCKET_STREAM );
if (s < 0) {
fprintf(stderr, "could not bind unix socket on '%s': %s\n",
- proto_port+5, socket_errstr());
+ proto_port+5, errno_str);
exit(3);
}
} else {
for ( ; maxtries > 0; maxtries-- ) {
- s = socket_unix_client( path, SOCK_STREAM );
+ s = socket_unix_client( path, SOCKET_STREAM );
if (s >= 0)
break;
@@ -1622,7 +1616,7 @@ report_console( const char* proto_port, int console_port )
}
if (s < 0) {
fprintf(stderr, "could not connect to unix socket on '%s': %s\n",
- path, socket_errstr());
+ path, errno_str);
exit(3);
}
}
@@ -1637,12 +1631,12 @@ report_console( const char* proto_port, int console_port )
int tries = 3;
D( "waiting for console-reporting client" );
do {
- s2 = accept( s, NULL, NULL );
- } while (s2 < 0 && socket_errno == EINTR && --tries > 0);
+ s2 = socket_accept(s, NULL);
+ } while (s2 < 0 && --tries > 0);
if (s2 < 0) {
fprintf(stderr, "could not accept console-reporting client connection: %s\n",
- socket_errstr());
+ errno_str);
exit(3);
}
@@ -1654,13 +1648,10 @@ report_console( const char* proto_port, int console_port )
{
char temp[12];
snprintf( temp, sizeof(temp), "%d", console_port );
- do {
- ret = send( s, temp, strlen(temp), 0 );
- } while (ret < 0 && socket_errno == EINTR);
- if (ret < 0) {
+ if (socket_send(s, temp, strlen(temp)) < 0) {
fprintf(stderr, "could not send console number report: %d: %s\n",
- socket_errno, socket_errstr() );
+ errno, errno_str );
exit(3);
}
socket_close(s);
@@ -2215,6 +2206,12 @@ int main(int argc, char **argv)
opts->trace = tracePath;
}
+ if (opts->tcpdump) {
+ if (qemu_tcpdump_start(opts->tcpdump) < 0) {
+ dwarning( "could not start packet capture: %s", strerror(errno));
+ }
+ }
+
if (opts->nocache)
opts->cache = 0;
@@ -2571,10 +2568,11 @@ void android_emulation_setup( void )
int base_port = 5554;
int success = 0;
int s;
- struct in_addr guest_addr;
+ uint32_t guest_ip;
+
AndroidOptions* opts = qemulator->opts;
- inet_aton("10.0.2.15", &guest_addr);
+ inet_strtoip("10.0.2.15", &guest_ip);
#if 0
if (opts->adb_port) {
@@ -2610,7 +2608,7 @@ void android_emulation_setup( void )
exit(1);
}
- slirp_redir( 0, adb_port, guest_addr, 5555 );
+ slirp_redir( 0, adb_port, guest_ip, 5555 );
if ( control_console_start( console_port ) < 0 ) {
slirp_unredir( 0, adb_port );
}
@@ -2638,7 +2636,7 @@ void android_emulation_setup( void )
for ( ; tries > 0; tries--, base_port += 2 ) {
/* setup first redirection for ADB, the Android Debug Bridge */
- if ( slirp_redir( 0, base_port+1, guest_addr, 5555 ) < 0 )
+ if ( slirp_redir( 0, base_port+1, guest_ip, 5555 ) < 0 )
continue;
/* setup second redirection for the emulator console */
@@ -2670,39 +2668,29 @@ void android_emulation_setup( void )
*/
do
{
- struct sockaddr_in addr;
- char tmp[32];
- int ret;
+ SockAddress addr;
+ char tmp[32];
- s = socket(PF_INET, SOCK_STREAM, 0);
+ s = socket_create_inet( SOCKET_STREAM );
if (s < 0) {
D("can't create socket to talk to the ADB server");
break;
}
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(5037);
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- do {
- ret = connect(s, (struct sockaddr*)&addr, sizeof(addr));
- } while (ret < 0 && socket_errno == EINTR);
-
- if (ret < 0) {
- D("can't connect to ADB server: errno %d: %s", socket_errno, socket_errstr() );
+ sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, 5037 );
+ if (socket_connect( s, &addr ) < 0) {
+ D("can't connect to ADB server: %s", errno_str );
break;
}
sprintf(tmp,"0012host:emulator:%d",base_port+1);
-
- while ( send(s, tmp, 18+4, 0) < 0 && errno == EINTR ) {
- };
+ socket_send(s, tmp, 18+4);
D("sent '%s' to ADB server", tmp);
}
while (0);
+
if (s >= 0)
- close(s);
+ socket_close(s);
/* setup the http proxy, if any */
if (VERBOSE_CHECK(proxy))
diff --git a/android_options.h b/android_options.h
index 89a44db..0a7d79b 100644
--- a/android_options.h
+++ b/android_options.h
@@ -117,7 +117,7 @@ OPT_PARAM( gps, "<device>", "redirect NMEA GPS to character device" )
OPT_PARAM( keyset, "<name>", "specify keyset file name" )
OPT_PARAM( shell_serial, "<device>", "specific character device for root shell" )
OPT_FLAG ( old_system, "support old (pre 1.4) system images" )
-
+OPT_PARAM( tcpdump, "<file>", "capture network packets to file" )
#ifdef CONFIG_NAND_LIMITS
OPT_PARAM( nand_limits, "<nlimits>", "enforce NAND/Flash read/write thresholds" )
diff --git a/android_profile.c b/android_profile.c
deleted file mode 100644
index f8b430d..0000000
--- a/android_profile.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#include "android_profile.h"
-#include <string.h>
-#include <unistd.h>
-
-/* this environment variable can be set to change the root profiles directory */
-#define ENV_PROFILE_DIR "ANDROID_PROFILE_DIR"
-
-/* otherwise, we're going to use <config>/EMULATOR_PROFILE_DIR */
-#ifdef _WIN32
-# define EMULATOR_PROFILE_DIR "EmulatorProfiles"
-#else
-# define EMULATOR_PROFILE_DIR "profiles"
-#endif
-
-static char* profile_dir;
-
-static char*
-profile_dir_find( void )
-{
- const char* env = getenv( ENV_PROFILE_DIR );
- if (env != NULL) {
- int len = strlen(env);
-
- if ( access( env, R_OK ) < 0 ) {
- dprint( "%s variable does not point to a valid directory. ignored\n", ENV_PROFILE_DIR );
- }
- else {
- dprint( "using '%s' as profile root directory", env );
- if (len > 0 && env[len-1] == PATH_SEP[0]) {
- len -= 1;
- }
- profile_dir = malloc( len+1 );
- memcpy(profile_dir, env, len);
- profile_dir[len] = 0;
- return profile_dir;
- }
- }
-
- {
- char temp[512];
- char* p = temp;
- char* end = p + sizeof(temp);
- p = bufprint_config_file( p, end, EMULATOR_PROFILE_DIR );
- if (p >= end) {
- fprintf( stderr, "emulator configuration directory path too long. aborting" );
- exit(1);
- }
- if (p > temp && p[-1] == PATH_SEP[0])
- p[-1] = 0;
-
- dprint( "using '%s' as profile root directory", temp );
- profile_dir = strdup( temp );
- return profile_dir;
- }
-}
-
-int
-android_profile_check_name( const char* profile_name )
-{
- static const char* goodchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-0123456789.";
- int len = strlen(profile_name);
- int slen = strspn(profile_name, goodchars);
-
- return (len == slen);
-}
-
-char*
-android_profile_bufprint_path( char* p, char* end, const char* profile_name )
-{
- return android_profile_bufprint_file_path( p, end, profile_name, NULL );
-}
-
-char*
-android_profile_strdup_path( const char* profile_name )
-{
- return android_profile_strdup_file_path( profile_name, NULL );
-}
-
-char*
-android_profile_bufprint_file_path( char* p, char* end, const char* profile_name, const char* file_name )
-{
- if (profile_dir == NULL)
- profile_dir = profile_dir_find();
-
- p = bufprint( p, end, "%s", profile_dir );
- if (file_name != NULL) {
- p = bufprint( p, end, PATH_SEP "%s", file_name );
- }
- return p;
-}
-
-char*
-android_profile_strdup_file_path( const char* profile_name, const char* file_name )
-{
- int len1, len;
- char* result;
-
- if (profile_dir == NULL)
- profile_dir = profile_dir_find();
-
- len1 = strlen(profile_dir);
- len = len1;
- if (file_name) {
- len += 1 + strlen(file_name);
- }
-
- result = malloc( len+1 );
- memcpy( result, profile_dir, len1 );
- if (file_name) {
- result[len1] = PATH_SEP[0];
- strcpy( result+len1+1, file_name );
- }
- result[len] = 0;
- return result;
-}
-
diff --git a/android_profile.h b/android_profile.h
deleted file mode 100644
index cc8b1d5..0000000
--- a/android_profile.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#ifndef _ANDROID_PROFILE_H
-#define _ANDROID_PROFILE_H
-
-#include "android.h"
-#include "android_utils.h"
-
-/* verify that a profile name doesn't contain bad characters, returns 0 on success, or -1 in case of error */
-extern int android_profile_check_name( const char* profile_name );
-
-/* safely append the path of a given profile to a buffer */
-extern char* android_profile_bufprint_path( char* p, char* end, const char* profile_name );
-
-/* return a copy of a profile path */
-extern char* android_profile_strdup_path( const char* profile_name );
-
-/* safely append the path of a given profile file to a buffer */
-extern char* android_profile_bufprint_file_path( char* p, char* end, const char* profile_name, const char* file_name );
-
-/* return a copy of a profile file path */
-extern char* android_profile_strdup_file_path( const char* profile_name, const char* file_name );
-
-
-#endif /* ANDROID_PROFILE_H */
diff --git a/android_qemud.c b/android_qemud.c
index 02563a4..96d2eb4 100644
--- a/android_qemud.c
+++ b/android_qemud.c
@@ -428,7 +428,6 @@ android_qemud_set_channel( const char* name, CharDriverState* peer_cs )
{
Multiplexer* m = _multiplexer;
Channel* c;
- int ret;
if (m->cs == NULL)
android_qemud_init();
@@ -451,5 +450,5 @@ android_qemud_set_channel( const char* name, CharDriverState* peer_cs )
m->count += 1;
multiplexer_query_channel( m, c->name );
- return ret;
+ return 0;
}
diff --git a/android_utils.h b/android_utils.h
index 43546c0..42a0d61 100644
--- a/android_utils.h
+++ b/android_utils.h
@@ -42,13 +42,14 @@
# define PATH_SEP "/"
#endif
-/* get MAX_PATH, note that MAX_PATH is set to 260 on Windows for
+/* get MAX_PATH, note that PATH_MAX is set to 260 on Windows for
* stupid backwards-compatibility reason, though any 32-bit version
* of the OS handles much much longer paths
*/
#ifdef _WIN32
# undef MAX_PATH
# define MAX_PATH 1024
+# undef PATH_MAX
# define PATH_MAX MAX_PATH
#else
# include <limits.h>
@@ -258,7 +259,7 @@ extern void atexit_close_fd_remove(int fd);
extern int make_empty_file( const char* path );
extern int copy_file( const char* dest, const char* source );
-extern int unkink_file( const char* path );
+extern int unlink_file( const char* path );
extern void* load_text_file( const char* path );
/** HOST RESOLUTION SETTINGS
diff --git a/gdbstub.c b/gdbstub.c
index a91dcd9..564543a 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -79,7 +79,7 @@ static int get_char(GDBState *s)
int ret;
for(;;) {
- ret = recv(s->fd, &ch, 1, 0);
+ ret = socket_recv(s->fd, &ch, 1);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return -1;
@@ -97,7 +97,7 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
int ret;
while (len > 0) {
- ret = send(s->fd, buf, len, 0);
+ ret = socket_send(s->fd, buf, len);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return;
@@ -864,7 +864,7 @@ static void gdb_read(void *opaque)
int i, size;
uint8_t buf[4096];
- size = recv(s->fd, buf, sizeof(buf), 0);
+ size = socket_recv(s->fd, buf, sizeof(buf));
if (size < 0)
return;
if (size == 0) {
@@ -884,14 +884,11 @@ static void gdb_read(void *opaque)
static void gdb_accept(void *opaque)
{
GDBState *s;
- struct sockaddr_in sockaddr;
- socklen_t len;
- int fd;
+ int fd;
for(;;) {
- len = sizeof(sockaddr);
- fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len);
- if (fd < 0 && errno != EINTR) {
+ fd = socket_accept(gdbserver_fd, NULL);
+ if (fd < 0) {
perror("accept");
return;
} else if (fd >= 0) {
@@ -931,10 +928,10 @@ static void gdb_accept(void *opaque)
static int gdbserver_open(int port)
{
- struct sockaddr_in sockaddr;
+ SockAddress sockaddr;
int fd, ret;
- fd = socket(PF_INET, SOCK_STREAM, 0);
+ fd = socket_create_inet( SOCKET_STREAM );
if (fd < 0) {
perror("socket");
return -1;
@@ -943,17 +940,16 @@ static int gdbserver_open(int port)
/* allow fast reuse */
socket_set_xreuseaddr(fd);
- sockaddr.sin_family = AF_INET;
- sockaddr.sin_port = htons(port);
- sockaddr.sin_addr.s_addr = 0;
- ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
+ sock_address_init_inet( &sockaddr, port, SOCK_ADDRESS_INET_ANY );
+ ret = socket_bind(fd, &sockaddr);
if (ret < 0) {
perror("bind");
return -1;
}
- ret = listen(fd, 0);
+ ret = socket_listen(fd, 0);
if (ret < 0) {
perror("listen");
+ socket_close(fd);
return -1;
}
#ifndef CONFIG_USER_ONLY
diff --git a/hw/goldfish_mmc.c b/hw/goldfish_mmc.c
index a00340c..0daaebd 100644
--- a/hw/goldfish_mmc.c
+++ b/hw/goldfish_mmc.c
@@ -155,9 +155,10 @@ struct mmc_opcode {
{ "MMC_GEN_CMD", 56 },
{ "SD_APP_OP_COND", 41 },
{ "SD_APP_SEND_SCR", 51 },
- { "UNKNOWN" -1 }
+ { "UNKNOWN", -1 }
};
+#if 0
static const char* get_command_name(int command)
{
struct mmc_opcode* opcode = mmc_opcodes;
@@ -165,6 +166,7 @@ static const char* get_command_name(int command)
while (opcode->cmd != command && opcode->cmd != -1) opcode++;
return opcode->name;
}
+#endif
static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd, uint32_t arg)
{
diff --git a/loadpng.c b/loadpng.c
index b5c7a37..218ae20 100644
--- a/loadpng.c
+++ b/loadpng.c
@@ -175,7 +175,7 @@ void *readpng(const unsigned char *base, size_t size, unsigned *_width, unsign
reader.end = base + size;
reader.cursor = base;
- if(size < 8 || png_sig_cmp(base, 0, 8)) {
+ if(size < 8 || png_sig_cmp((unsigned char*)base, 0, 8)) {
LOG("%s: header is not a PNG header\n", fn);
goto oops;
}
diff --git a/proxy/proxy_common.c b/proxy/proxy_common.c
index 0e45481..ffe8e22 100644
--- a/proxy/proxy_common.c
+++ b/proxy/proxy_common.c
@@ -56,7 +56,7 @@ hex_dump( void* base, int size, const char* prefix )
void
proxy_connection_init( ProxyConnection* conn,
int socket,
- struct sockaddr_in* address,
+ SockAddress* address,
ProxyService* service,
ProxyConnectionFreeFunc conn_free,
ProxyConnectionSelectFunc conn_select,
@@ -74,16 +74,12 @@ proxy_connection_init( ProxyConnection* conn,
socket_set_nonblock(socket);
{
- uint32_t ip = ntohl(address->sin_addr.s_addr);
- uint16_t port = ntohs(address->sin_port);
- int type = socket_get_type(socket);
+ SocketType type = socket_get_type(socket);
snprintf( conn->name, sizeof(conn->name),
- "%s:%d.%d.%d.%d:%d(%d)",
- (type == SOCK_STREAM) ? "tcp" : "udp",
- (ip >> 24) & 255, (ip >> 16) & 255,
- (ip >> 8) & 255, ip & 255, port,
- socket );
+ "%s:%s(%d)",
+ (type == SOCKET_STREAM) ? "tcp" : "udp",
+ sock_address_to_string(address), socket );
/* just in case */
conn->name[sizeof(conn->name)-1] = 0;
@@ -133,20 +129,17 @@ proxy_connection_send( ProxyConnection* conn, int fd )
}
while (avail > 0) {
- int n = send(fd, str->s + conn->str_pos, avail, 0);
+ int n = socket_send(fd, str->s + conn->str_pos, avail);
if (n == 0) {
PROXY_LOG("%s: connection reset by peer (send)",
conn->name);
return DATA_ERROR;
}
if (n < 0) {
- if (socket_errno == EINTR)
- continue;
-
- if (socket_errno == EWOULDBLOCK || socket_errno == EAGAIN)
+ if (errno == EWOULDBLOCK || errno == EAGAIN)
return DATA_NEED_MORE;
- PROXY_LOG("%s: error: %s", conn->name, socket_errstr());
+ PROXY_LOG("%s: error: %s", conn->name, errno_str);
return DATA_ERROR;
}
conn->str_pos += n;
@@ -170,20 +163,17 @@ proxy_connection_receive( ProxyConnection* conn, int fd, int wanted )
int n;
stralloc_readyplus( str, wanted );
- n = recv(fd, str->s + str->n, wanted, 0);
+ n = socket_recv(fd, str->s + str->n, wanted);
if (n == 0) {
PROXY_LOG("%s: connection reset by peer (receive)",
conn->name);
return DATA_ERROR;
}
if (n < 0) {
- if (socket_errno == EINTR)
- continue;
-
- if (socket_errno == EWOULDBLOCK || socket_errno == EAGAIN)
+ if (errno == EWOULDBLOCK || errno == EAGAIN)
return DATA_NEED_MORE;
- PROXY_LOG("%s: error: %s", conn->name, socket_errstr());
+ PROXY_LOG("%s: error: %s", conn->name, errno_str);
return DATA_ERROR;
}
@@ -207,20 +197,17 @@ proxy_connection_receive_line( ProxyConnection* conn, int fd )
for (;;) {
char c;
- int n = recv(fd, &c, 1, 0);
+ int n = socket_recv(fd, &c, 1);
if (n == 0) {
PROXY_LOG("%s: disconnected from server", conn->name );
return DATA_ERROR;
}
if (n < 0) {
- if (socket_errno == EINTR)
- continue;
-
- if (socket_errno == EWOULDBLOCK || socket_errno == EAGAIN) {
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
PROXY_LOG("%s: blocked", conn->name);
return DATA_NEED_MORE;
}
- PROXY_LOG("%s: error: %s", conn->name, socket_errstr());
+ PROXY_LOG("%s: error: %s", conn->name, errno_str);
return DATA_ERROR;
}
@@ -336,10 +323,10 @@ proxy_connection_free( ProxyConnection* conn,
int
-proxy_manager_add( struct sockaddr_in* address,
- int sock_type,
- ProxyEventFunc ev_func,
- void* ev_opaque )
+proxy_manager_add( SockAddress* address,
+ SocketType sock_type,
+ ProxyEventFunc ev_func,
+ void* ev_opaque )
{
int n;
@@ -506,22 +493,17 @@ proxy_base64_encode( const char* src, int srclen,
}
int
-proxy_resolve_server( struct sockaddr_in* addr,
- const char* servername,
- int servernamelen,
- int serverport )
+proxy_resolve_server( SockAddress* addr,
+ const char* servername,
+ int servernamelen,
+ int serverport )
{
- char name0[64], *name = name0;
- int result = -1;
- struct hostent* host;
+ char name0[64], *name = name0;
+ int result = -1;
if (servernamelen < 0)
servernamelen = strlen(servername);
- memset(addr, 0, sizeof(*addr));
- addr->sin_family = AF_INET;
- addr->sin_port = htons(serverport);
-
if (servernamelen >= sizeof(name0)) {
name = qemu_malloc(servernamelen+1);
if (name == NULL)
@@ -531,18 +513,13 @@ proxy_resolve_server( struct sockaddr_in* addr,
memcpy(name, servername, servernamelen);
name[servernamelen] = 0;
- host = gethostbyname(name);
- if (host == NULL) {
+ if (sock_address_init_resolve( addr, name, serverport, 0 ) < 0) {
PROXY_LOG("%s: can't resolve proxy server name '%s'",
__FUNCTION__, name);
goto Exit;
}
- addr->sin_addr = *(struct in_addr*)host->h_addr;
- {
- uint32_t a = ntohl(addr->sin_addr.s_addr);
- PROXY_LOG("server name '%s' resolved to %d.%d.%d.%d", name, (a>>24)&255, (a>>16)&255,(a>>8)&255,a&255);
- }
+ PROXY_LOG("server name '%s' resolved to %s", name, sock_address_to_string(addr));
result = 0;
Exit:
diff --git a/proxy/proxy_common.h b/proxy/proxy_common.h
index 57f224d..78eddd8 100644
--- a/proxy/proxy_common.h
+++ b/proxy/proxy_common.h
@@ -12,11 +12,12 @@
#ifndef _PROXY_COMMON_H_
#define _PROXY_COMMON_H_
+#include "sockets.h"
+
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/select.h>
-#include <netinet/in.h>
#endif
/* types and definitions used by all proxy connections */
@@ -61,8 +62,8 @@ typedef struct {
*
* returns 0 on success, or -1 if there is no proxy service for this type of connection
*/
-extern int proxy_manager_add( struct sockaddr_in* address,
- int sock_type,
+extern int proxy_manager_add( SockAddress* address,
+ SocketType sock_type,
ProxyEventFunc ev_func,
void* ev_opaque );
diff --git a/proxy/proxy_http.c b/proxy/proxy_http.c
index c3d663c..5c185ca 100644
--- a/proxy/proxy_http.c
+++ b/proxy/proxy_http.c
@@ -29,34 +29,22 @@ http_service_free( HttpService* service )
static ProxyConnection*
-http_service_connect( HttpService* service,
- int sock_type,
- struct sockaddr_in* address )
+http_service_connect( HttpService* service,
+ SocketType sock_type,
+ SockAddress* address )
{
- uint32_t addr;
- int port;
-
/* the HTTP proxy can only handle TCP connections */
- if (sock_type != SOCK_STREAM)
+ if (sock_type != SOCKET_STREAM)
return NULL;
/* if the client tries to directly connect to the proxy, let it do so */
- if (address->sin_addr.s_addr == service->server_addr.sin_addr.s_addr &&
- address->sin_port == service->server_addr.sin_port)
+ if (sock_address_equal( address, &service->server_addr ))
return NULL;
- addr = ntohl(address->sin_addr.s_addr);
- port = ntohs(address->sin_port);
-
- PROXY_LOG("%s: trying to connect to %d.%d.%d.%d on port %d",
- __FUNCTION__,
- (addr >> 24) & 255,
- (addr >> 16) & 255,
- (addr >> 8) & 255,
- addr & 255,
- port );
+ PROXY_LOG("%s: trying to connect to %s",
+ __FUNCTION__, sock_address_to_string(address));
- if (port == 80) {
+ if (sock_address_get_port(address) == 80) {
/* use the rewriter for HTTP */
PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__);
return http_rewriter_connect(service, address);
@@ -75,7 +63,7 @@ proxy_http_setup( const char* servername,
const ProxyOption* options )
{
HttpService* service;
- struct sockaddr_in server_addr;
+ SockAddress server_addr;
const ProxyOption* opt_nocache = NULL;
const ProxyOption* opt_keepalive = NULL;
const ProxyOption* opt_auth_user = NULL;
diff --git a/proxy/proxy_http_connector.c b/proxy/proxy_http_connector.c
index 1b2ba3e..7bf2f53 100644
--- a/proxy/proxy_http_connector.c
+++ b/proxy/proxy_http_connector.c
@@ -52,35 +52,25 @@ connection_init( Connection* conn )
HttpService* service = (HttpService*) conn->root->service;
ProxyConnection* root = conn->root;
stralloc_t* str = root->str;
- int ret;
- uint32_t address = ntohl(root->address.sin_addr.s_addr);
- int port = ntohs(root->address.sin_port);
proxy_connection_rewind(root);
- stralloc_add_format(str, "CONNECT %d.%d.%d.%d:%d HTTP/" HTTP_VERSION "\r\n",
- (address >> 24) & 0xff, (address >> 16) & 0xff,
- (address >> 8) & 0xff, address & 0xff, port);
+ stralloc_add_format(str, "CONNECT %s HTTP/" HTTP_VERSION "\r\n",
+ sock_address_to_string(&root->address));
stralloc_add_bytes(str, service->footer, service->footer_len);
- do {
- ret = connect( root->socket,
- (struct sockaddr*) &service->server_addr,
- sizeof(service->server_addr) );
- } while (ret < 0 && socket_errno == EINTR);
-
- if (ret == 0) {
+ if (!socket_connect( root->socket, &service->server_addr )) {
/* immediate connection ?? */
conn->state = STATE_SEND_HEADER;
PROXY_LOG("%s: immediate connection", root->name);
}
else {
- if (socket_errno == EINPROGRESS || socket_errno == EWOULDBLOCK) {
+ if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
conn->state = STATE_CONNECTING;
PROXY_LOG("%s: connecting", root->name);
}
else {
- PROXY_LOG("%s: cannot connect to proxy: %s", root->name, socket_errstr());
+ PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str);
return -1;
}
}
@@ -183,13 +173,13 @@ connection_poll( ProxyConnection* root,
ProxyConnection*
-http_connector_connect( HttpService* service,
- struct sockaddr_in* address )
+http_connector_connect( HttpService* service,
+ SockAddress* address )
{
Connection* conn;
int s;
- s = socket(AF_INET, SOCK_STREAM, 0);
+ s = socket_create_inet( SOCKET_STREAM );
if (s < 0)
return NULL;
diff --git a/proxy/proxy_http_int.h b/proxy/proxy_http_int.h
index d0a6bc0..6daa9cb 100644
--- a/proxy/proxy_http_int.h
+++ b/proxy/proxy_http_int.h
@@ -18,7 +18,7 @@
/* the HttpService object */
typedef struct HttpService {
ProxyService root[1];
- struct sockaddr_in server_addr; /* server address and port */
+ SockAddress server_addr; /* server address and port */
char* footer; /* the footer contains the static parts of the */
int footer_len; /* connection header, we generate it only once */
char footer0[512];
@@ -26,13 +26,13 @@ typedef struct HttpService {
/* create a CONNECT connection (for port != 80) */
extern ProxyConnection* http_connector_connect(
- HttpService* service,
- struct sockaddr_in* address );
+ HttpService* service,
+ SockAddress* address );
/* create a HTTP rewriting connection (for port == 80) */
extern ProxyConnection* http_rewriter_connect(
- HttpService* service,
- struct sockaddr_in* address );
+ HttpService* service,
+ SockAddress* address );
#endif /* _PROXY_HTTP_INT_H */
diff --git a/proxy/proxy_http_rewriter.c b/proxy/proxy_http_rewriter.c
index 3e98557..f0bfbbc 100644
--- a/proxy/proxy_http_rewriter.c
+++ b/proxy/proxy_http_rewriter.c
@@ -364,23 +364,16 @@ rewrite_connection_init( RewriteConnection* conn )
{
HttpService* service = (HttpService*) conn->root->service;
ProxyConnection* root = conn->root;
- int ret;
conn->slirp_fd = -1;
conn->state = STATE_CONNECTING;
- do {
- ret = connect( root->socket,
- (struct sockaddr*) &service->server_addr,
- sizeof(service->server_addr) );
- } while (ret < 0 && socket_errno == EINTR);
-
- if (ret < 0) {
- if (socket_errno == EINPROGRESS || socket_errno == EWOULDBLOCK) {
+ if (socket_connect( root->socket, &service->server_addr ) < 0) {
+ if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
PROXY_LOG("%s: connecting", conn->root->name);
}
else {
- PROXY_LOG("%s: cannot connect to proxy: %s", root->name, socket_errstr());
+ PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str);
return -1;
}
}
@@ -401,7 +394,7 @@ rewrite_connection_create_sockets( RewriteConnection* conn )
if (socket_pair( &slirp_1, &conn->slirp_fd ) < 0) {
PROXY_LOG("%s: coult not create socket pair: %s",
- root->name, socket_errstr());
+ root->name, errno_str);
return -1;
}
@@ -1102,13 +1095,13 @@ rewrite_connection_poll( ProxyConnection* root,
ProxyConnection*
-http_rewriter_connect( HttpService* service,
- struct sockaddr_in* address )
+http_rewriter_connect( HttpService* service,
+ SockAddress* address )
{
RewriteConnection* conn;
int s;
- s = socket(AF_INET, SOCK_STREAM, 0);
+ s = socket_create_inet( SOCKET_STREAM );
if (s < 0)
return NULL;
diff --git a/proxy/proxy_int.h b/proxy/proxy_int.h
index e71d9d6..9bdac5c 100644
--- a/proxy/proxy_int.h
+++ b/proxy/proxy_int.h
@@ -67,7 +67,7 @@ typedef void (*ProxyConnectionPollFunc) ( ProxyConnection* conn,
/* root ProxyConnection object */
struct ProxyConnection {
int socket;
- struct sockaddr_in address; /* for debugging */
+ SockAddress address; /* for debugging */
ProxyConnection* next;
ProxyConnection* prev;
ProxyEventFunc ev_func;
@@ -95,7 +95,7 @@ struct ProxyConnection {
extern void
proxy_connection_init( ProxyConnection* conn,
int socket,
- struct sockaddr_in* address,
+ SockAddress* address,
ProxyService* service,
ProxyConnectionFreeFunc conn_free,
ProxyConnectionSelectFunc conn_select,
@@ -172,10 +172,10 @@ proxy_base64_encode( const char* src, int srclen,
char* dst, int dstlen );
extern int
-proxy_resolve_server( struct sockaddr_in* addr,
- const char* servername,
- int servernamelen,
- int serverport );
+proxy_resolve_server( SockAddress* addr,
+ const char* servername,
+ int servernamelen,
+ int serverport );
/* a ProxyService is really a proxy server and associated options */
@@ -184,9 +184,9 @@ typedef void (*ProxyServiceFreeFunc) ( void* opaque );
/* tries to create a new proxified connection, returns NULL if the service can't
* handle this address */
-typedef ProxyConnection* (*ProxyServiceConnectFunc)( void* opaque,
- int socket_type,
- struct sockaddr_in* address );
+typedef ProxyConnection* (*ProxyServiceConnectFunc)( void* opaque,
+ SocketType socket_type,
+ const SockAddress* address );
struct ProxyService {
void* opaque;
diff --git a/slirp/udp.c b/slirp/udp.c
deleted file mode 100644
index d96251d..0000000
--- a/slirp/udp.c
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * Copyright (c) 1982, 1986, 1988, 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
- * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
- */
-
-/*
- * Changes and additions relating to SLiRP
- * Copyright (c) 1995 Danny Gasparovski.
- *
- * Please read the file COPYRIGHT for the
- * terms and conditions of the copyright.
- */
-
-#include <slirp.h>
-#include "ip_icmp.h"
-
-struct udpstat udpstat;
-
-struct socket udb;
-
-/*
- * UDP protocol implementation.
- * Per RFC 768, August, 1980.
- */
-#ifndef COMPAT_42
-int udpcksum = 1;
-#else
-int udpcksum = 0; /* XXX */
-#endif
-
-struct socket *udp_last_so = &udb;
-
-void
-udp_init()
-{
- udb.so_next = udb.so_prev = &udb;
-}
-/* m->m_data points at ip packet header
- * m->m_len length ip packet
- * ip->ip_len length data (IPDU)
- */
-void
-udp_input(m, iphlen)
- register MBuf m;
- int iphlen;
-{
- register struct ip *ip;
- register struct udphdr *uh;
-/* MBuf opts = 0;*/
- int len;
- struct ip save_ip;
- struct socket *so;
-
- DEBUG_CALL("udp_input");
- DEBUG_ARG("m = %lx", (long)m);
- DEBUG_ARG("iphlen = %d", iphlen);
-
- udpstat.udps_ipackets++;
-
- /*
- * Strip IP options, if any; should skip this,
- * make available to user, and use on returned packets,
- * but we don't yet have a way to check the checksum
- * with options still present.
- */
- if(iphlen > sizeof(struct ip)) {
- ip_stripoptions(m, (MBuf )0);
- iphlen = sizeof(struct ip);
- }
-
- /*
- * Get IP and UDP header together in first mbuf.
- */
- ip = MBUF_TO(m, struct ip *);
- uh = (struct udphdr *)((caddr_t)ip + iphlen);
-
- /*
- * Make mbuf data length reflect UDP length.
- * If not enough data to reflect UDP length, drop.
- */
- len = ntohs((u_int16_t)uh->uh_ulen);
-
- if (ip->ip_len != len) {
- if (len > ip->ip_len) {
- udpstat.udps_badlen++;
- goto bad;
- }
- mbuf_trim(m, len - ip->ip_len);
- ip->ip_len = len;
- }
-
- /*
- * Save a copy of the IP header in case we want restore it
- * for sending an ICMP error message in response.
- */
- save_ip = *ip;
- save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
-
- /*
- * Checksum extended UDP header and data.
- */
- if (udpcksum && uh->uh_sum) {
- ((struct ipovly *)ip)->ih_next = 0;
- ((struct ipovly *)ip)->ih_prev = 0;
- ((struct ipovly *)ip)->ih_x1 = 0;
- ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
- /* keep uh_sum for ICMP reply
- * uh->uh_sum = cksum(m, len + sizeof (struct ip));
- * if (uh->uh_sum) {
- */
- if(cksum(m, len + sizeof(struct ip))) {
- udpstat.udps_badsum++;
- goto bad;
- }
- }
-
- /*
- * handle DHCP/BOOTP
- */
- if (ntohs(uh->uh_dport) == BOOTP_SERVER) {
- bootp_input(m);
- goto bad;
- }
-
- /*
- * handle TFTP
- */
- if (ntohs(uh->uh_dport) == TFTP_SERVER) {
- tftp_input(m);
- goto bad;
- }
-
- /*
- * Locate pcb for datagram.
- */
- so = udp_last_so;
- if (so->so_lport != uh->uh_sport ||
- so->so_laddr.s_addr != ip->ip_src.s_addr) {
- struct socket *tmp;
-
- for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
- if (tmp->so_lport == uh->uh_sport &&
- tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
- tmp->so_faddr.s_addr = ip->ip_dst.s_addr;
- tmp->so_fport = uh->uh_dport;
- so = tmp;
- break;
- }
- }
- if (tmp == &udb) {
- so = NULL;
- } else {
- udpstat.udpps_pcbcachemiss++;
- udp_last_so = so;
- }
- }
-
- if (so == NULL) {
- /*
- * If there's no socket for this packet,
- * create one
- */
- if ((so = socreate()) == NULL) goto bad;
- if(udp_attach(so) == -1) {
- DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
- errno,strerror(errno)));
- sofree(so);
- goto bad;
- }
-
- /*
- * Setup fields
- */
- /* udp_last_so = so; */
- so->so_laddr = ip->ip_src;
- so->so_lport = uh->uh_sport;
-
- if ((so->so_iptos = udp_tos(so)) == 0)
- so->so_iptos = ip->ip_tos;
-
- /*
- * XXXXX Here, check if it's in udpexec_list,
- * and if it is, do the fork_exec() etc.
- */
- }
-
- so->so_faddr = ip->ip_dst; /* XXX */
- so->so_fport = uh->uh_dport; /* XXX */
-
- iphlen += sizeof(struct udphdr);
- m->m_len -= iphlen;
- m->m_data += iphlen;
-
- /*
- * Now we sendto() the packet.
- */
- if (so->so_emu)
- udp_emu(so, m);
-
- if(sosendto(so,m) == -1) {
- m->m_len += iphlen;
- m->m_data -= iphlen;
- *ip=save_ip;
- DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
- icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
- }
-
- mbuf_free(so->so_m); /* used for ICMP if error on sorecvfrom */
-
- /* restore the orig mbuf packet */
- m->m_len += iphlen;
- m->m_data -= iphlen;
- *ip=save_ip;
- so->so_m=m; /* ICMP backup */
-
- return;
-bad:
- mbuf_free(m);
- /* if (opts) mbuf_free(opts); */
- return;
-}
-
-int udp_output2(struct socket *so, MBuf m,
- struct sockaddr_in *saddr, struct sockaddr_in *daddr,
- int iptos)
-{
- register struct udpiphdr *ui;
- int error = 0;
-
- DEBUG_CALL("udp_output");
- DEBUG_ARG("so = %lx", (long)so);
- DEBUG_ARG("m = %lx", (long)m);
- DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
- DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
-
- /*
- * Adjust for header
- */
- m->m_data -= sizeof(struct udpiphdr);
- m->m_len += sizeof(struct udpiphdr);
-
- /*
- * Fill in mbuf with extended UDP header
- * and addresses and length put into network format.
- */
- ui = MBUF_TO(m, struct udpiphdr *);
- ui->ui_next = ui->ui_prev = 0;
- ui->ui_x1 = 0;
- ui->ui_pr = IPPROTO_UDP;
- ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
- /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
- ui->ui_src = saddr->sin_addr;
- ui->ui_dst = daddr->sin_addr;
- ui->ui_sport = saddr->sin_port;
- ui->ui_dport = daddr->sin_port;
- ui->ui_ulen = ui->ui_len;
-
- /*
- * Stuff checksum and output datagram.
- */
- ui->ui_sum = 0;
- if (udpcksum) {
- if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
- ui->ui_sum = 0xffff;
- }
- ((struct ip *)ui)->ip_len = m->m_len;
-
- ((struct ip *)ui)->ip_ttl = ip_defttl;
- ((struct ip *)ui)->ip_tos = iptos;
-
- udpstat.udps_opackets++;
-
- error = ip_output(so, m);
-
- return (error);
-}
-
-int udp_output(struct socket *so, MBuf m,
- struct sockaddr_in *addr)
-
-{
- struct sockaddr_in saddr, daddr;
-
- saddr = *addr;
- if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
- saddr.sin_addr.s_addr = so->so_faddr.s_addr;
- if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))
- saddr.sin_addr.s_addr = alias_addr.s_addr;
- }
- daddr.sin_addr = so->so_laddr;
- daddr.sin_port = so->so_lport;
-
- return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
-}
-
-int
-udp_attach(so)
- struct socket *so;
-{
- struct sockaddr_in addr;
-
- if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
- /*
- * Here, we bind() the socket. Although not really needed
- * (sendto() on an unbound socket will bind it), it's done
- * here so that emulation of ytalk etc. don't have to do it
- */
- addr.sin_family = AF_INET;
- addr.sin_port = 0;
- addr.sin_addr.s_addr = INADDR_ANY;
- if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
- int lasterrno=errno;
- closesocket(so->s);
- so->s=-1;
-#ifdef _WIN32
- WSASetLastError(lasterrno);
-#else
- errno=lasterrno;
-#endif
- } else {
- /* success, insert in queue */
- so->so_expire = curtime + SO_EXPIRE;
- insque(so,&udb);
- }
- }
- return(so->s);
-}
-
-void
-udp_detach(so)
- struct socket *so;
-{
- closesocket(so->s);
- /* if (so->so_m) mbuf_free(so->so_m); done by sofree */
-
- sofree(so);
-}
-
-struct tos_t udptos[] = {
- {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
- {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */
- {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */
- {0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME}, /* Cu-Seeme */
- {0, 0, 0, 0}
-};
-
-u_int8_t
-udp_tos(so)
- struct socket *so;
-{
- int i = 0;
-
- while(udptos[i].tos) {
- if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
- (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
- so->so_emu = udptos[i].emu;
- return udptos[i].tos;
- }
- i++;
- }
-
- return 0;
-}
-
-#ifdef EMULATE_TALK
-#include "talkd.h"
-#endif
-
-/*
- * Here, talk/ytalk/ntalk requests must be emulated
- */
-void
-udp_emu(so, m)
- struct socket *so;
- MBuf m;
-{
- struct sockaddr_in addr;
- int addrlen = sizeof(addr);
-#ifdef EMULATE_TALK
- CTL_MSG_OLD *omsg;
- CTL_MSG *nmsg;
- char buff[sizeof(CTL_MSG)];
- u_char type;
-
-struct talk_request {
- struct talk_request *next;
- struct socket *udp_so;
- struct socket *tcp_so;
-} *req;
-
- static struct talk_request *req_tbl = 0;
-
-#endif
-
-struct cu_header {
- uint16_t d_family; // destination family
- uint16_t d_port; // destination port
- uint32_t d_addr; // destination address
- uint16_t s_family; // source family
- uint16_t s_port; // source port
- uint32_t so_addr; // source address
- uint32_t seqn; // sequence number
- uint16_t message; // message
- uint16_t data_type; // data type
- uint16_t pkt_len; // packet length
-} *cu_head;
-
- switch(so->so_emu) {
-
-#ifdef EMULATE_TALK
- case EMU_TALK:
- case EMU_NTALK:
- /*
- * Talk emulation. We always change the ctl_addr to get
- * some answers from the daemon. When an ANNOUNCE comes,
- * we send LEAVE_INVITE to the local daemons. Also when a
- * DELETE comes, we send copies to the local daemons.
- */
- if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
- return;
-
-#define IS_OLD (so->so_emu == EMU_TALK)
-
-#define COPY_MSG(dest, src) { dest->type = src->type; \
- dest->id_num = src->id_num; \
- dest->pid = src->pid; \
- dest->addr = src->addr; \
- dest->ctl_addr = src->ctl_addr; \
- memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \
- memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \
- memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE); }
-
-#define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field)
-/* old_sockaddr to sockaddr_in */
-
-
- if (IS_OLD) { /* old talk */
- omsg = MBUF_TO(m, CTL_MSG_OLD*);
- nmsg = (CTL_MSG *) buff;
- type = omsg->type;
- OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
- OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
- strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
- } else { /* new talk */
- omsg = (CTL_MSG_OLD *) buff;
- nmsg = MBUF_TO(m, CTL_MSG *);
- type = nmsg->type;
- OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port;
- OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
- strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
- }
-
- if (type == LOOK_UP)
- return; /* for LOOK_UP this is enough */
-
- if (IS_OLD) { /* make a copy of the message */
- COPY_MSG(nmsg, omsg);
- nmsg->vers = 1;
- nmsg->answer = 0;
- } else
- COPY_MSG(omsg, nmsg);
-
- /*
- * If if is an ANNOUNCE message, we go through the
- * request table to see if a tcp port has already
- * been redirected for this socket. If not, we solisten()
- * a new socket and add this entry to the table.
- * The port number of the tcp socket and our IP
- * are put to the addr field of the message structures.
- * Then a LEAVE_INVITE is sent to both local daemon
- * ports, 517 and 518. This is why we have two copies
- * of the message, one in old talk and one in new talk
- * format.
- */
-
- if (type == ANNOUNCE) {
- int s;
- u_short temp_port;
-
- for(req = req_tbl; req; req = req->next)
- if (so == req->udp_so)
- break; /* found it */
-
- if (!req) { /* no entry for so, create new */
- req = (struct talk_request *)
- malloc(sizeof(struct talk_request));
- req->udp_so = so;
- req->tcp_so = solisten(0,
- OTOSIN(omsg, addr)->sin_addr.s_addr,
- OTOSIN(omsg, addr)->sin_port,
- SS_FACCEPTONCE);
- req->next = req_tbl;
- req_tbl = req;
- }
-
- /* replace port number in addr field */
- addrlen = sizeof(addr);
- getsockname(req->tcp_so->s,
- (struct sockaddr *) &addr,
- &addrlen);
- OTOSIN(omsg, addr)->sin_port = addr.sin_port;
- OTOSIN(omsg, addr)->sin_addr = our_addr;
- OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
- OTOSIN(nmsg, addr)->sin_addr = our_addr;
-
- /* send LEAVE_INVITEs */
- temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
- OTOSIN(omsg, ctl_addr)->sin_port = 0;
- OTOSIN(nmsg, ctl_addr)->sin_port = 0;
- omsg->type = nmsg->type = LEAVE_INVITE;
-
- s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- addr.sin_addr = our_addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(517);
- sendto(s, (char *)omsg, sizeof(*omsg), 0,
- (struct sockaddr *)&addr, sizeof(addr));
- addr.sin_port = htons(518);
- sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
- (struct sockaddr *) &addr, sizeof(addr));
- closesocket(s) ;
-
- omsg->type = nmsg->type = ANNOUNCE;
- OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
- OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
- }
-
- /*
- * If it is a DELETE message, we send a copy to the
- * local daemons. Then we delete the entry corresponding
- * to our socket from the request table.
- */
-
- if (type == DELETE) {
- struct talk_request *temp_req, *req_next;
- int s;
- u_short temp_port;
-
- temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
- OTOSIN(omsg, ctl_addr)->sin_port = 0;
- OTOSIN(nmsg, ctl_addr)->sin_port = 0;
-
- s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- addr.sin_addr = our_addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(517);
- sendto(s, (char *)omsg, sizeof(*omsg), 0,
- (struct sockaddr *)&addr, sizeof(addr));
- addr.sin_port = htons(518);
- sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
- (struct sockaddr *)&addr, sizeof(addr));
- closesocket(s);
-
- OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
- OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
-
- /* delete table entry */
- if (so == req_tbl->udp_so) {
- temp_req = req_tbl;
- req_tbl = req_tbl->next;
- free(temp_req);
- } else {
- temp_req = req_tbl;
- for(req = req_tbl->next; req; req = req_next) {
- req_next = req->next;
- if (so == req->udp_so) {
- temp_req->next = req_next;
- free(req);
- break;
- } else {
- temp_req = req;
- }
- }
- }
- }
-
- return;
-#endif
-
- case EMU_CUSEEME:
-
- /*
- * Cu-SeeMe emulation.
- * Hopefully the packet is more that 16 bytes long. We don't
- * do any other tests, just replace the address and port
- * fields.
- */
- if (m->m_len >= sizeof (*cu_head)) {
- if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
- return;
- cu_head = MBUF_TO(m, struct cu_header *);
- cu_head->s_port = addr.sin_port;
- cu_head->so_addr = our_addr.s_addr;
- }
-
- return;
- }
-}
-
-struct socket *
-udp_listen(port, laddr, lport, flags)
- u_int port;
- u_int32_t laddr;
- u_int lport;
- int flags;
-{
- struct sockaddr_in addr;
- struct socket *so;
- int addrlen = sizeof(struct sockaddr_in);
-
- if ((so = socreate()) == NULL) {
- free(so);
- return NULL;
- }
- so->s = socket(AF_INET,SOCK_DGRAM,0);
- so->so_expire = curtime + SO_EXPIRE;
- so->so_hport = port;
- insque(so,&udb);
-
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = port;
-
- if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
- udp_detach(so);
- return NULL;
- }
- socket_set_xreuseaddr(so->s);
-
- getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
- so->so_fport = addr.sin_port;
- if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
- so->so_faddr = alias_addr;
- else
- so->so_faddr = addr.sin_addr;
-
- so->so_lport = lport;
- so->so_laddr.s_addr = laddr;
- if (flags != SS_FACCEPTONCE)
- so->so_expire = 0;
-
- so->so_state = SS_ISFCONNECTED;
-
- return so;
-}
-
-int udp_unlisten (u_int port)
-{
- struct socket *so;
-
- for (so = udb.so_next; so != &udb; so = so->so_next) {
- if (so->so_hport == htons(port)) {
- break;
- }
- }
-
- if (so == &udb)
- return -1;
-
- sofcantrcvmore( so );
- sofcantsendmore( so );
- close( so->s );
- so->s = -1;
- sofree( so );
- return 0;
-}
-
-
diff --git a/slirp/COPYRIGHT b/slirp2/COPYRIGHT
index 2e86862..2e86862 100644
--- a/slirp/COPYRIGHT
+++ b/slirp2/COPYRIGHT
diff --git a/slirp/bootp.c b/slirp2/bootp.c
index 79f5f9f..9ab4b15 100644
--- a/slirp/bootp.c
+++ b/slirp2/bootp.c
@@ -49,7 +49,7 @@ if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); }
#define dprintf(fmt, args...)
#endif
-static BOOTPClient *get_new_addr(struct in_addr *paddr)
+static BOOTPClient *get_new_addr(SockAddress* paddr)
{
BOOTPClient *bc;
int i;
@@ -62,11 +62,13 @@ static BOOTPClient *get_new_addr(struct in_addr *paddr)
found:
bc = &bootp_clients[i];
bc->allocated = 1;
- paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+ sock_address_init_inet( paddr,
+ special_addr_ip | (i+START_ADDR),
+ BOOTP_CLIENT );
return bc;
}
-static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
+static BOOTPClient *find_addr(SockAddress* paddr, const uint8_t *macaddr)
{
BOOTPClient *bc;
int i;
@@ -79,7 +81,9 @@ static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
found:
bc = &bootp_clients[i];
bc->allocated = 1;
- paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+ sock_address_init_inet( paddr,
+ special_addr_ip | (i + START_ADDR),
+ BOOTP_CLIENT );
return bc;
}
@@ -129,8 +133,8 @@ static void bootp_reply(struct bootp_t *bp)
BOOTPClient *bc;
MBuf m;
struct bootp_t *rbp;
- struct sockaddr_in saddr, daddr;
- struct in_addr dns_addr;
+ SockAddress saddr, daddr;
+ uint32_t dns_addr;
int dhcp_msg_type, val;
uint8_t *q;
@@ -156,14 +160,14 @@ static void bootp_reply(struct bootp_t *bp)
if (dhcp_msg_type == DHCPDISCOVER) {
new_addr:
- bc = get_new_addr(&daddr.sin_addr);
+ bc = get_new_addr(&daddr);
if (!bc) {
dprintf("no address left\n");
return;
}
memcpy(bc->macaddr, client_ethaddr, 6);
} else {
- bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
+ bc = find_addr(&daddr, bp->bp_hwaddr);
if (!bc) {
/* if never assigned, behaves as if it was already
assigned (windows fix because it remembers its address) */
@@ -173,12 +177,10 @@ static void bootp_reply(struct bootp_t *bp)
if (bootp_filename)
snprintf((char*)rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename);
- dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
+ dprintf("offered addr=%s\n", sock_address_to_string(&daddr));
- saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
- saddr.sin_port = htons(BOOTP_SERVER);
-
- daddr.sin_port = htons(BOOTP_CLIENT);
+ sock_address_init_inet( &saddr, special_addr_ip | CTL_ALIAS,
+ BOOTP_SERVER );
rbp->bp_op = BOOTP_REPLY;
rbp->bp_xid = bp->bp_xid;
@@ -186,8 +188,8 @@ static void bootp_reply(struct bootp_t *bp)
rbp->bp_hlen = 6;
memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);
- rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */
- rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
+ rbp->bp_yiaddr = htonl(sock_address_get_ip(&daddr)); /* Client IP address */
+ rbp->bp_siaddr = htonl(sock_address_get_ip(&saddr)); /* Server IP address */
q = rbp->bp_vend;
memcpy(q, rfc1533_cookie, 4);
@@ -202,12 +204,13 @@ static void bootp_reply(struct bootp_t *bp)
*q++ = 1;
*q++ = DHCPACK;
}
-
+
if (dhcp_msg_type == DHCPDISCOVER ||
dhcp_msg_type == DHCPREQUEST) {
+ uint32_t saddr_ip = htonl(sock_address_get_ip(&saddr));
*q++ = RFC2132_SRV_ID;
*q++ = 4;
- memcpy(q, &saddr.sin_addr, 4);
+ memcpy(q, &saddr_ip, 4);
q += 4;
*q++ = RFC1533_NETMASK;
@@ -216,15 +219,15 @@ static void bootp_reply(struct bootp_t *bp)
*q++ = 0xff;
*q++ = 0xff;
*q++ = 0x00;
-
+
*q++ = RFC1533_GATEWAY;
*q++ = 4;
- memcpy(q, &saddr.sin_addr, 4);
+ memcpy(q, &saddr_ip, 4);
q += 4;
-
+
*q++ = RFC1533_DNS;
*q++ = 4;
- dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
+ dns_addr = htonl(special_addr_ip | CTL_DNS);
memcpy(q, &dns_addr, 4);
q += 4;
@@ -246,7 +249,8 @@ static void bootp_reply(struct bootp_t *bp)
m->m_len = sizeof(struct bootp_t) -
sizeof(struct ip) - sizeof(struct udphdr);
- udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+
+ udp_output2_(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
}
void bootp_input(MBuf m)
diff --git a/slirp/bootp.h b/slirp2/bootp.h
index 1fb42fa..fbc96ac 100644
--- a/slirp/bootp.h
+++ b/slirp2/bootp.h
@@ -100,10 +100,10 @@ struct bootp_t {
uint32_t bp_xid;
uint16_t bp_secs;
uint16_t unused;
- struct in_addr bp_ciaddr;
- struct in_addr bp_yiaddr;
- struct in_addr bp_siaddr;
- struct in_addr bp_giaddr;
+ uint32_t bp_ciaddr;
+ uint32_t bp_yiaddr;
+ uint32_t bp_siaddr;
+ uint32_t bp_giaddr;
uint8_t bp_hwaddr[16];
uint8_t bp_sname[64];
uint8_t bp_file[128];
diff --git a/slirp/cksum.c b/slirp2/cksum.c
index 9474b9e..9474b9e 100644
--- a/slirp/cksum.c
+++ b/slirp2/cksum.c
diff --git a/slirp/ctl.h b/slirp2/ctl.h
index 854ae9a..854ae9a 100644
--- a/slirp/ctl.h
+++ b/slirp2/ctl.h
diff --git a/slirp/debug.c b/slirp2/debug.c
index a46626b..f3a424d 100644
--- a/slirp/debug.c
+++ b/slirp2/debug.c
@@ -287,9 +287,9 @@ sockstats()
buff[17] = 0;
lprint("%s %3d %15s %5d ",
buff, so->s,
- inet_ntoa(so->so_laddr), ntohs(so->so_lport));
+ inet_iptostr(so->so_laddr_ip), so->so_laddr_port);
lprint("%15s %5d %5d %5d\r\n",
- inet_ntoa(so->so_faddr), ntohs(so->so_fport),
+ inet_iptostr(so->so_faddr_ip), so->so_faddr_port,
so->so_rcv.sb_cc, so->so_snd.sb_cc);
}
@@ -301,9 +301,9 @@ sockstats()
buff[17] = 0;
lprint("%s %3d %15s %5d ",
buff, so->s,
- inet_ntoa(so->so_laddr), ntohs(so->so_lport));
+ inet_iptostr(so->so_laddr_ip), so->so_laddr_port);
lprint("%15s %5d %5d %5d\r\n",
- inet_ntoa(so->so_faddr), ntohs(so->so_fport),
+ inet_iptostr(so->so_faddr_ip), so->so_faddr_port,
so->so_rcv.sb_cc, so->so_snd.sb_cc);
}
}
diff --git a/slirp/debug.h b/slirp2/debug.h
index 6e8444d..6e8444d 100644
--- a/slirp/debug.h
+++ b/slirp2/debug.h
diff --git a/slirp2/helper.h b/slirp2/helper.h
new file mode 100644
index 0000000..e247f46
--- /dev/null
+++ b/slirp2/helper.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2009 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _SLIRP_HELPER_H
+#define _SLIRP_HELPER_H
+
+typedef union {
+ u_int32_t addr;
+ u_int8_t data[4];
+} ipaddr_t;
+
+/* return ip address in network order */
+static __inline__ uint32_t
+ip_getn( ipaddr_t ip )
+{
+ return ip.addr;
+}
+
+/* return ip address in host order */
+static __inline__ uint32_t
+ip_geth( ipaddr_t ip )
+{
+ return ntohl(ip.addr);
+}
+
+/* set ip address in network order */
+static __inline__ ipaddr_t
+ip_setn( uint32_t val )
+{
+ ipaddr_t ip;
+ ip.addr = val;
+ return ip;
+}
+
+/* set ip address in host order */
+static __inline__ ipaddr_t
+ip_seth( uint32_t val )
+{
+ ipaddr_t ip;
+ ip.addr = htonl(val);
+ return ip;
+}
+
+static __inline__ int
+ip_equal( ipaddr_t ip1, ipaddr_t ip2 )
+{
+ return ip1.addr == ip2.addr;
+}
+
+typedef union {
+ u_int16_t port;
+ u_int8_t data[2];
+} port_t;
+
+static __inline__ uint16_t
+port_getn( port_t p )
+{
+ return p.port;
+}
+
+static __inline__ uint16_t
+port_geth( port_t p )
+{
+ return ntohs(p.port);
+}
+
+static __inline__ port_t
+port_setn( uint16_t val )
+{
+ port_t p;
+ p.port = val;
+ return p;
+}
+
+static __inline__ port_t
+port_seth( uint16_t val )
+{
+ port_t p;
+ p.port = htons(val);
+ return p;
+}
+
+#endif /* _SLIRP_HELPER_H */
diff --git a/slirp/icmp_var.h b/slirp2/icmp_var.h
index 03fc8c3..03fc8c3 100644
--- a/slirp/icmp_var.h
+++ b/slirp2/icmp_var.h
diff --git a/slirp/if.c b/slirp2/if.c
index 9d814c2..cd96e65 100644
--- a/slirp/if.c
+++ b/slirp2/if.c
@@ -79,14 +79,14 @@ writen(fd, bptr, n)
int total;
/* This should succeed most of the time */
- ret = send(fd, bptr, n,0);
+ ret = socket_send(fd, bptr, n);
if (ret == n || ret <= 0)
return ret;
/* Didn't write everything, go into the loop */
total = ret;
while (n > total) {
- ret = send(fd, bptr+total, n-total,0);
+ ret = socket_send(fd, bptr+total, n-total);
if (ret <= 0)
return ret;
total += ret;
@@ -111,7 +111,7 @@ if_input(ttyp)
DEBUG_CALL("if_input");
DEBUG_ARG("ttyp = %lx", (long)ttyp);
- if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0);
+ if_n = socket_recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE);
DEBUG_MISC((dfd, " read %d bytes\n", if_n));
diff --git a/slirp/if.h b/slirp2/if.h
index f22f161..f22f161 100644
--- a/slirp/if.h
+++ b/slirp2/if.h
diff --git a/slirp/ip.h b/slirp2/ip.h
index 371537d..8b6ae30 100644
--- a/slirp/ip.h
+++ b/slirp2/ip.h
@@ -37,6 +37,8 @@
#ifndef _IP_H_
#define _IP_H_
+#include "helper.h"
+
#ifdef WORDS_BIGENDIAN
# ifndef NTOHL
# define NTOHL(d)
@@ -78,13 +80,13 @@ typedef u_int32_t n_long; /* long as received from the net */
*/
struct ip {
#ifdef WORDS_BIGENDIAN
- u_int ip_v:4, /* version */
- ip_hl:4; /* header length */
+ u_int ip_v:4; /* version */
+ u_int ip_hl:4; /* header length */
#else
- u_int ip_hl:4, /* header length */
- ip_v:4; /* version */
+ u_int ip_hl:4; /* header length */
+ u_int ip_v:4; /* version */
#endif
- u_int8_t ip_tos; /* type of service */
+ u_int8_t ip_tos; /* type of service */
u_int16_t ip_len; /* total length */
u_int16_t ip_id; /* identification */
u_int16_t ip_off; /* fragment offset field */
@@ -94,7 +96,7 @@ struct ip {
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_int16_t ip_sum; /* checksum */
- struct in_addr ip_src,ip_dst; /* source and dest address */
+ ipaddr_t ip_src, ip_dst; /* source and dest address */
};
#define IP_MAXPACKET 65535 /* maximum packet size */
@@ -153,8 +155,8 @@ struct ip_timestamp {
union ipt_timestamp {
n_long ipt_time[1];
struct ipt_ta {
- struct in_addr ipt_addr;
- n_long ipt_time;
+ ipaddr_t ipt_addr;
+ n_long ipt_time;
} ipt_ta[1];
} ipt_timestamp;
};
@@ -209,8 +211,8 @@ struct ipovly {
u_int8_t ih_x1; /* (unused) */
u_int8_t ih_pr; /* protocol */
u_int16_t ih_len; /* protocol length */
- struct in_addr ih_src; /* source internet address */
- struct in_addr ih_dst; /* destination internet address */
+ ipaddr_t ih_src; /* source internet address */
+ ipaddr_t ih_dst; /* destination internet address */
};
/*
@@ -225,9 +227,9 @@ struct ipq {
u_int8_t ipq_ttl; /* time for reass q to live */
u_int8_t ipq_p; /* protocol of this fragment */
u_int16_t ipq_id; /* sequence id for reassembly */
- ipasfragp_32 ipq_next,ipq_prev;
+ ipasfragp_32 ipq_next,ipq_prev;
/* to ip headers of fragments */
- struct in_addr ipq_src,ipq_dst;
+ ipaddr_t ipq_src,ipq_dst;
};
/*
@@ -268,8 +270,8 @@ struct ipasfrag {
#define MAX_IPOPTLEN 40
struct ipoption {
- struct in_addr ipopt_dst; /* first-hop dst if source routed */
- int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
+ u_int32_t ipopt_dst; /* first-hop dst if source routed */
+ int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
};
/*
diff --git a/slirp/ip_icmp.c b/slirp2/ip_icmp.c
index 2d50629..6594ec4 100644
--- a/slirp/ip_icmp.c
+++ b/slirp2/ip_icmp.c
@@ -36,6 +36,7 @@
#include "slirp.h"
#include "ip_icmp.h"
+#include "sockets.h"
struct icmpstat icmpstat;
@@ -114,48 +115,52 @@ icmp_input(m, hlen)
case ICMP_ECHO:
icp->icmp_type = ICMP_ECHOREPLY;
ip->ip_len += hlen; /* since ip_input subtracts this */
- if (ip->ip_dst.s_addr == alias_addr.s_addr) {
+ if (ip_geth(ip->ip_dst) == alias_addr_ip) {
icmp_reflect(m);
} else {
struct socket *so;
- struct sockaddr_in addr;
+ SockAddress addr;
+ uint32_t addr_ip;
+ uint16_t addr_port;
+
if ((so = socreate()) == NULL) goto freeit;
if(udp_attach(so) == -1) {
DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
- errno,strerror(errno)));
+ errno,errno_str));
sofree(so);
mbuf_free(m);
goto end_error;
}
so->so_m = m;
- so->so_faddr = ip->ip_dst;
- so->so_fport = htons(7);
- so->so_laddr = ip->ip_src;
- so->so_lport = htons(9);
+ so->so_faddr_ip = ip_geth(ip->ip_dst);
+ so->so_faddr_port = 7;
+ so->so_laddr_ip = ip_geth(ip->ip_src);
+ so->so_laddr_port = 9;
so->so_iptos = ip->ip_tos;
so->so_type = IPPROTO_ICMP;
so->so_state = SS_ISFCONNECTED;
/* Send the packet */
- addr.sin_family = AF_INET;
- if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
- /* It's an alias */
- int low = ntohl(so->so_faddr.s_addr) & 0xff;
+ if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) {
+ /* It's an alias */
+ int low = so->so_faddr_ip & 0xff;
if (low >= CTL_DNS && low < CTL_DNS + dns_addr_count)
- addr.sin_addr = dns_addr[low - CTL_DNS];
+ addr_ip = dns_addr[low - CTL_DNS];
else
- addr.sin_addr = loopback_addr;
+ addr_ip = loopback_addr_ip;
} else {
- addr.sin_addr = so->so_faddr;
+ addr_ip = so->so_faddr_ip;
}
- addr.sin_port = so->so_fport;
- if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
- (struct sockaddr *)&addr, sizeof(addr)) == -1) {
- DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
- errno,strerror(errno)));
- icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
- udp_detach(so);
+ addr_port = so->so_faddr_port;
+
+ sock_address_init_inet( &addr, addr_ip, addr_port );
+
+ if(socket_sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), &addr) < 0) {
+ DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
+ errno,errno_str));
+ icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,errno_str);
+ udp_detach(so);
}
} /* if ip->ip_dst.s_addr == alias_addr.s_addr */
break;
@@ -207,7 +212,7 @@ icmp_error(msrc, type, code, minsize, message)
u_char type;
u_char code;
int minsize;
- char *message;
+ const char *message;
{
unsigned hlen, shlen, s_ip_len;
register struct ip *ip;
@@ -225,8 +230,8 @@ icmp_error(msrc, type, code, minsize, message)
ip = MBUF_TO(msrc, struct ip *);
#if DEBUG
{ char bufa[20], bufb[20];
- strcpy(bufa, inet_ntoa(ip->ip_src));
- strcpy(bufb, inet_ntoa(ip->ip_dst));
+ strcpy(bufa, inet_iptostr(ip_geth(ip->ip_src)));
+ strcpy(bufb, inet_iptostr(ip_geth(ip->ip_dst)));
DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
}
#endif
@@ -307,7 +312,7 @@ icmp_error(msrc, type, code, minsize, message)
ip->ip_ttl = MAXTTL;
ip->ip_p = IPPROTO_ICMP;
ip->ip_dst = ip->ip_src; /* ip adresses */
- ip->ip_src = alias_addr;
+ ip->ip_src = ip_setn(alias_addr_ip);
(void ) ip_output((struct socket *)NULL, m);
@@ -360,8 +365,8 @@ icmp_reflect(m)
ip->ip_ttl = MAXTTL;
{ /* swap */
- struct in_addr icmp_dst;
- icmp_dst = ip->ip_dst;
+ ipaddr_t icmp_dst;
+ icmp_dst = ip->ip_dst;
ip->ip_dst = ip->ip_src;
ip->ip_src = icmp_dst;
}
diff --git a/slirp/ip_icmp.h b/slirp2/ip_icmp.h
index 42740db..bc0be51 100644
--- a/slirp/ip_icmp.h
+++ b/slirp2/ip_icmp.h
@@ -37,6 +37,8 @@
#ifndef _NETINET_IP_ICMP_H_
#define _NETINET_IP_ICMP_H_
+#include "helper.h"
+
/*
* Interface Control Message Protocol Definitions.
* Per RFC 792, September 1981.
@@ -52,8 +54,8 @@ struct icmp {
u_char icmp_code; /* type sub code */
u_short icmp_cksum; /* ones complement cksum of struct */
union {
- u_char ih_pptr; /* ICMP_PARAMPROB */
- struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
+ u_char ih_pptr; /* ICMP_PARAMPROB */
+ ipaddr_t ih_gwaddr; /* ICMP_REDIRECT */
struct ih_idseq {
u_short icd_id;
u_short icd_seq;
@@ -158,7 +160,7 @@ struct icmp {
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
void icmp_input _P((MBuf , int));
-void icmp_error _P((MBuf , u_char, u_char, int, char *));
+void icmp_error _P((MBuf , u_char, u_char, int, const char *));
void icmp_reflect _P((MBuf ));
#endif
diff --git a/slirp/ip_input.c b/slirp2/ip_input.c
index cc320de..a0013aa 100644
--- a/slirp/ip_input.c
+++ b/slirp2/ip_input.c
@@ -166,8 +166,8 @@ ip_input(m)
for (fp = (struct ipq *) ipq.next; fp != &ipq;
fp = (struct ipq *) fp->next)
if (ip->ip_id == fp->ipq_id &&
- ip->ip_src.s_addr == fp->ipq_src.s_addr &&
- ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
+ ip_equal(ip->ip_src, fp->ipq_src) &&
+ ip_equal(ip->ip_dst, fp->ipq_dst) &&
ip->ip_p == fp->ipq_p)
goto found;
fp = 0;
@@ -483,7 +483,7 @@ ip_dooptions(m)
register struct in_ifaddr *ia;
/* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */
int opt, optlen, cnt, off, code, type, forward = 0;
- struct in_addr *sin, dst;
+ ipaddr_t *sin, dst;
typedef u_int32_t n_time;
n_time ntime;
diff --git a/slirp/ip_output.c b/slirp2/ip_output.c
index 42d789c..42d789c 100644
--- a/slirp/ip_output.c
+++ b/slirp2/ip_output.c
diff --git a/slirp/libslirp.h b/slirp2/libslirp.h
index 3ce34b7..c9b19a0 100644
--- a/slirp/libslirp.h
+++ b/slirp2/libslirp.h
@@ -2,18 +2,21 @@
#define _LIBSLIRP_H
#include <stdint.h>
+#include "sockets.h"
#ifdef _WIN32
-#include <winsock2.h>
-int inet_aton(const char *cp, struct in_addr *ia);
+# define WIN32_LEAN_AND_MEAN
+# include <winsock2.h>
#else
-#include <sys/select.h>
-#include <arpa/inet.h>
+# include <sys/select.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
+int inet_strtoip(const char* str, uint32_t *ip);
+char* inet_iptostr(uint32_t ip);
+
void slirp_init(void);
void slirp_select_fill(int *pnfds,
@@ -28,11 +31,11 @@ int slirp_can_output(void);
void slirp_output(const uint8_t *pkt, int pkt_len);
int slirp_redir(int is_udp, int host_port,
- struct in_addr guest_addr, int guest_port);
+ uint32_t guest_addr, int guest_port);
int slirp_unredir(int is_udp, int host_port);
-int slirp_add_dns_server(struct in_addr dns_addr);
+int slirp_add_dns_server(const SockAddress* dns_addr);
int slirp_get_system_dns_servers(void);
extern const char *tftp_prefix;
diff --git a/slirp/main.h b/slirp2/main.h
index 49dad00..159e5f4 100644
--- a/slirp/main.h
+++ b/slirp2/main.h
@@ -34,13 +34,13 @@ extern char *slirp_tty;
extern char *exec_shell;
extern u_int curtime;
extern fd_set *global_readfds, *global_writefds, *global_xfds;
-extern struct in_addr ctl_addr;
-extern struct in_addr special_addr;
-extern struct in_addr alias_addr;
-extern struct in_addr our_addr;
-extern struct in_addr loopback_addr;
-extern struct in_addr dns_addr[DNS_ADDR_MAX];
-extern int dns_addr_count;
+extern uint32_t ctl_addr_ip;
+extern uint32_t special_addr_ip;
+extern uint32_t alias_addr_ip;
+extern uint32_t our_addr_ip;
+extern uint32_t loopback_addr_ip;
+extern uint32_t dns_addr[DNS_ADDR_MAX];
+extern int dns_addr_count;
extern char *username;
extern char *socket_path;
extern int towrite_max;
diff --git a/slirp/mbuf.c b/slirp2/mbuf.c
index efc8141..efc8141 100644
--- a/slirp/mbuf.c
+++ b/slirp2/mbuf.c
diff --git a/slirp/mbuf.h b/slirp2/mbuf.h
index ed83372..ed83372 100644
--- a/slirp/mbuf.h
+++ b/slirp2/mbuf.h
diff --git a/slirp/misc.c b/slirp2/misc.c
index beffeee..e34ca77 100644
--- a/slirp/misc.c
+++ b/slirp2/misc.c
@@ -7,24 +7,41 @@
#define WANT_SYS_IOCTL_H
#include <slirp.h>
-#define SLIRP_COMPILATION
-#include "sockets.h"
u_int curtime, time_fasttimo, last_slowtimo, detach_time;
u_int detach_wait = 600000; /* 10 minutes */
struct emu_t *tcpemu;
-#ifndef HAVE_INET_ATON
int
-inet_aton(const char* cp, struct in_addr* ia)
+inet_strtoip(const char* str, uint32_t *ip)
{
- u_int32_t addr = inet_addr(cp);
- if (addr == 0xffffffff)
- return 0;
- ia->s_addr = addr;
- return 1;
+ int comp[4];
+
+ if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4)
+ return -1;
+
+ if ((unsigned)comp[0] >= 256 ||
+ (unsigned)comp[1] >= 256 ||
+ (unsigned)comp[2] >= 256 ||
+ (unsigned)comp[3] >= 256)
+ return -1;
+
+ *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) |
+ (comp[2] << 8) | comp[3]);
+ return 0;
+}
+
+char* inet_iptostr(uint32_t ip)
+{
+ static char buff[32];
+
+ snprintf(buff, sizeof(buff), "%d.%d.%d.%d",
+ (ip >> 24) & 255,
+ (ip >> 16) & 255,
+ (ip >> 8) & 255,
+ ip & 255);
+ return buff;
}
-#endif
/*
* Get our IP address and put it in our_addr
@@ -32,15 +49,17 @@ inet_aton(const char* cp, struct in_addr* ia)
void
getouraddr()
{
- char buff[256];
- struct hostent *he = NULL;
-
- if (gethostname(buff,256) == 0)
- he = gethostbyname(buff);
- if (he)
- our_addr = *(struct in_addr *)he->h_addr;
- if (our_addr.s_addr == 0)
- our_addr.s_addr = loopback_addr.s_addr;
+ char* hostname = host_name();
+ SockAddress hostaddr;
+
+ our_addr_ip = loopback_addr_ip;
+
+ if (sock_address_init_resolve( &hostaddr, hostname, 0, 0 ) < 0)
+ return;
+
+ our_addr_ip = sock_address_get_ip(&hostaddr);
+ if (our_addr_ip == (uint32_t)-1)
+ our_addr_ip = loopback_addr_ip;
}
#if SIZEOF_CHAR_P == 8
@@ -247,8 +266,8 @@ add_emu(char* buff)
/* And finally, mark all current sessions, if any, as being emulated */
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
- if ((lport && lport == ntohs(so->so_lport)) ||
- (fport && fport == ntohs(so->so_fport))) {
+ if ((lport && lport == so->so_laddr_port) ||
+ (fport && fport == so->so_faddr_port)) {
if (emu)
so->so_emu = emu;
if (tos)
diff --git a/slirp/misc.h b/slirp2/misc.h
index aa4a0ce..aa4a0ce 100644
--- a/slirp/misc.h
+++ b/slirp2/misc.h
diff --git a/slirp/sbuf.c b/slirp2/sbuf.c
index 3d975f8..abececa 100644
--- a/slirp/sbuf.c
+++ b/slirp2/sbuf.c
@@ -6,8 +6,6 @@
*/
#include <slirp.h>
-#define SLIRP_COMPILATION
-#include "sockets.h"
void
sbuf_free(SBuf sb)
@@ -84,10 +82,8 @@ sbuf_append(struct socket *so, MBuf m)
* ottherwise it'll arrive out of order, and hence corrupt
*/
if (!so->so_rcv.sb_cc) {
- do {
- ret = send(so->s, m->m_data, m->m_len, 0);
- } while (ret == 0 && socket_errno == EINTR);
- }
+ ret = socket_send(so->s, m->m_data, m->m_len);
+ }
if (ret <= 0) {
/*
diff --git a/slirp/sbuf.h b/slirp2/sbuf.h
index 05fa01a..05fa01a 100644
--- a/slirp/sbuf.h
+++ b/slirp2/sbuf.h
diff --git a/slirp/slirp.c b/slirp2/slirp.c
index d6eaac4..d7bc545 100644
--- a/slirp/slirp.c
+++ b/slirp2/slirp.c
@@ -2,23 +2,25 @@
#include "proxy_common.h"
#include "android_utils.h" /* for dprint */
#include "android.h"
+#include "sockets.h"
#define D(...) VERBOSE_PRINT(slirp,__VA_ARGS__)
#define DN(...) do { if (VERBOSE_CHECK(slirp)) dprintn(__VA_ARGS__); } while (0)
/* host address */
-struct in_addr our_addr;
+uint32_t our_addr_ip;
/* host dns address */
-struct in_addr dns_addr[DNS_ADDR_MAX];
-int dns_addr_count;
+uint32_t dns_addr[DNS_ADDR_MAX];
+int dns_addr_count;
/* host loopback address */
-struct in_addr loopback_addr;
+uint32_t loopback_addr_ip;
/* address for slirp virtual addresses */
-struct in_addr special_addr;
+uint32_t special_addr_ip;
+
/* virtual address alias for host */
-struct in_addr alias_addr;
+uint32_t alias_addr_ip;
const uint8_t special_ethaddr[6] = {
0x52, 0x54, 0x00, 0x12, 0x35, 0x00
@@ -38,12 +40,18 @@ fd_set *global_readfds, *global_writefds, *global_xfds;
char slirp_hostname[33];
-int slirp_add_dns_server(struct in_addr new_dns_addr)
+int slirp_add_dns_server(const SockAddress* new_dns_addr)
{
+ int dns_ip;
+
if (dns_addr_count >= DNS_ADDR_MAX)
return -1;
- dns_addr[dns_addr_count++] = new_dns_addr;
+ dns_ip = sock_address_get_ip(new_dns_addr);
+ if (dns_ip < 0)
+ return -1;
+
+ dns_addr[dns_addr_count++] = dns_ip;
return 0;
}
@@ -56,7 +64,6 @@ int slirp_get_system_dns_servers()
ULONG BufLen;
DWORD ret;
IP_ADDR_STRING *pIPAddr;
- struct in_addr tmp_addr;
if (dns_addr_count > 0)
return dns_addr_count;
@@ -84,12 +91,14 @@ int slirp_get_system_dns_servers()
D( "DNS Servers:");
pIPAddr = &(FixedInfo->DnsServerList);
while (pIPAddr && dns_addr_count < DNS_ADDR_MAX) {
+ uint32_t ip;
D( " %s", pIPAddr->IpAddress.String );
- inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
- if (tmp_addr.s_addr == loopback_addr.s_addr)
- tmp_addr = our_addr;
- if (dns_addr_count < DNS_ADDR_MAX)
- dns_addr[dns_addr_count++] = tmp_addr;
+ if (inet_strtoip(pIPAddr->IpAddress.String, &ip) == 0) {
+ if (ip == loopback_addr_ip)
+ ip = our_addr_ip;
+ if (dns_addr_count < DNS_ADDR_MAX)
+ dns_addr[dns_addr_count++] = ip;
+ }
pIPAddr = pIPAddr->Next;
}
@@ -110,7 +119,6 @@ int slirp_get_system_dns_servers(void)
char buff[512];
char buff2[256];
FILE *f;
- struct in_addr tmp_addr;
if (dns_addr_count > 0)
return dns_addr_count;
@@ -133,15 +141,17 @@ int slirp_get_system_dns_servers(void)
DN("emulator: IP address of your DNS(s): ");
while (fgets(buff, 512, f) != NULL) {
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
- if (!inet_aton(buff2, &tmp_addr))
+ uint32_t tmp_ip;
+
+ if (inet_strtoip(buff2, &tmp_ip) < 0)
continue;
- if (tmp_addr.s_addr == loopback_addr.s_addr)
- tmp_addr = our_addr;
+ if (tmp_ip == loopback_addr_ip)
+ tmp_ip = our_addr_ip;
if (dns_addr_count < DNS_ADDR_MAX) {
- dns_addr[dns_addr_count++] = tmp_addr;
+ dns_addr[dns_addr_count++] = tmp_ip;
if (dns_addr_count > 1)
DN(", ");
- DN("%s", inet_ntoa(tmp_addr));
+ DN("%s", inet_iptostr(tmp_ip));
} else {
DN("(more)");
break;
@@ -164,9 +174,8 @@ extern void slirp_init_shapers();
void slirp_init(void)
{
#if DEBUG
- int slirp_logmask = 0;
- char slirp_logfile[512];
-
+ int slirp_logmask = 0;
+ char slirp_logfile[512];
{
const char* env = getenv( "ANDROID_SLIRP_LOGMASK" );
if (env != NULL)
@@ -200,18 +209,19 @@ void slirp_init(void)
mbuf_init();
/* set default addresses */
- inet_aton("127.0.0.1", &loopback_addr);
+ inet_strtoip("127.0.0.1", &loopback_addr_ip);
if (dns_addr_count == 0) {
if (slirp_get_system_dns_servers() < 0) {
- dns_addr[0] = loopback_addr;
+ dns_addr[0] = loopback_addr_ip;
dns_addr_count = 1;
fprintf (stderr, "Warning: No DNS servers found\n");
}
}
- inet_aton(CTL_SPECIAL, &special_addr);
- alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
+ inet_strtoip(CTL_SPECIAL, &special_addr_ip);
+
+ alias_addr_ip = special_addr_ip | CTL_ALIAS;
getouraddr();
slirp_init_shapers();
@@ -498,7 +508,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
/* Connected */
so->so_state &= ~SS_ISFCONNECTING;
- ret = send(so->s, (char*)&ret, 0, 0);
+ ret = socket_send(so->s, (char*)&ret, 0);
if (ret < 0) {
/* XXXXX Must fix, zero bytes is a NOP */
if (errno == EAGAIN || errno == EWOULDBLOCK ||
@@ -531,7 +541,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
*/
#ifdef PROBE_CONN
if (so->so_state & SS_ISFCONNECTING) {
- ret = recv(so->s, (char *)&ret, 0,0);
+ ret = socket_recv(so->s, (char *)&ret, 0);
if (ret < 0) {
/* XXX */
@@ -544,7 +554,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
/* tcp_input will take care of it */
} else {
- ret = send(so->s, &ret, 0,0);
+ ret = socket_send(so->s, &ret, 0,0);
if (ret < 0) {
/* XXX */
if (errno == EAGAIN || errno == EWOULDBLOCK ||
@@ -643,8 +653,10 @@ void arp_input(const uint8_t *pkt, int pkt_len)
ar_op = ntohs(ah->ar_op);
switch(ar_op) {
+ uint32_t ar_tip_ip;
case ARPOP_REQUEST:
- if (!memcmp(ah->ar_tip, &special_addr, 3)) {
+ ar_tip_ip = (ah->ar_tip[0] << 24) | (ah->ar_tip[1] << 16) | (ah->ar_tip[2] << 8);
+ if (ar_tip_ip == special_addr_ip) {
if ( CTL_IS_DNS(ah->ar_tip[3]) || ah->ar_tip[3] == CTL_ALIAS)
goto arp_ok;
return;
@@ -725,15 +737,15 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
}
int slirp_redir(int is_udp, int host_port,
- struct in_addr guest_addr, int guest_port)
+ uint32_t guest_ip, int guest_port)
{
if (is_udp) {
- if (!udp_listen(htons(host_port), guest_addr.s_addr,
- htons(guest_port), 0))
+ if (!udp_listen(host_port,
+ guest_ip,
+ guest_port, 0))
return -1;
} else {
- if (!solisten(htons(host_port), guest_addr.s_addr,
- htons(guest_port), 0))
+ if (!solisten(host_port, guest_ip, guest_port, 0))
return -1;
}
return 0;
diff --git a/slirp/slirp.h b/slirp2/slirp.h
index 50c0a77..bb21ff8 100644
--- a/slirp/slirp.h
+++ b/slirp2/slirp.h
@@ -11,6 +11,9 @@
#include "config.h"
#include "slirp_config.h"
+#include <stddef.h>
+#include "sockets.h"
+
#ifdef _WIN32
# include <inttypes.h>
@@ -21,19 +24,9 @@ typedef uint64_t u_int64_t;
typedef char *caddr_t;
# include <windows.h>
-# include <winsock2.h>
# include <sys/timeb.h>
# include <iphlpapi.h>
-
-# define EWOULDBLOCK WSAEWOULDBLOCK
-# define EINPROGRESS WSAEINPROGRESS
-# define ENOTCONN WSAENOTCONN
-# define EHOSTUNREACH WSAEHOSTUNREACH
-# define ENETUNREACH WSAENETUNREACH
-# define ECONNREFUSED WSAECONNREFUSED
#else
-# define ioctlsocket ioctl
-# define closesocket(s) close(s)
# define O_BINARY 0
#endif
@@ -118,7 +111,6 @@ typedef unsigned char u_int8_t;
#endif
#ifndef _WIN32
-#include <netinet/in.h>
#include <arpa/inet.h>
#endif
@@ -137,50 +129,12 @@ void *malloc _P((size_t arg));
void free _P((void *ptr));
#endif
-#ifndef HAVE_INET_ATON
-int inet_aton _P((const char *cp, struct in_addr *ia));
-#endif
-
-#include <fcntl.h>
-#ifndef NO_UNIX_SOCKETS
-#include <sys/un.h>
-#endif
-#include <signal.h>
-#ifdef HAVE_SYS_SIGNAL_H
-# include <sys/signal.h>
-#endif
-#ifndef _WIN32
-#include <sys/socket.h>
-#endif
-
-#if defined(HAVE_SYS_IOCTL_H)
-# include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
-#endif
-
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-
-#ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-#endif
-
-#ifdef USE_PPP
-#include <ppp/slirppp.h>
-#endif
-
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
-#include <sys/stat.h>
-
/* Avoid conflicting with the libc insque() and remque(), which
have different prototypes. */
#define insque slirp_insque
@@ -265,10 +219,6 @@ extern int do_echo;
inline void remque_32 _P((void *));
#endif
-#ifndef _WIN32
-#include <netdb.h>
-#endif
-
#define DEFAULT_BAUD 115200
/* cksum.c */
@@ -331,9 +281,4 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
-#ifdef _WIN32
-#undef errno
-#define errno (WSAGetLastError())
-#endif
-
#endif
diff --git a/slirp/slirp_config.h b/slirp2/slirp_config.h
index e7e95dd..030d2ff 100644
--- a/slirp/slirp_config.h
+++ b/slirp2/slirp_config.h
@@ -160,12 +160,6 @@
/* Define if you have srandom() */
#undef HAVE_SRANDOM
-/* Define if you have inet_aton */
-#undef HAVE_INET_ATON
-#ifndef _WIN32
-#define HAVE_INET_ATON
-#endif
-
/* Define if you have setenv */
#undef HAVE_SETENV
diff --git a/slirp/socket.c b/slirp2/socket.c
index bdae392..05fb4b7 100644
--- a/slirp/socket.c
+++ b/slirp2/socket.c
@@ -12,7 +12,7 @@
#ifdef __sun__
#include <sys/filio.h>
#endif
-#define SLIRP_COMPILATION
+#define SLIRP_COMPILATION 1
#include "sockets.h"
#include "proxy_common.h"
@@ -26,18 +26,18 @@ so_init()
struct socket *
solookup(head, laddr, lport, faddr, fport)
struct socket *head;
- struct in_addr laddr;
+ uint32_t laddr;
u_int lport;
- struct in_addr faddr;
+ uint32_t faddr;
u_int fport;
{
struct socket *so;
for (so = head->so_next; so != head; so = so->so_next) {
- if (so->so_lport == lport &&
- so->so_laddr.s_addr == laddr.s_addr &&
- so->so_faddr.s_addr == faddr.s_addr &&
- so->so_fport == fport)
+ if (so->so_laddr_port == lport &&
+ so->so_laddr_ip == laddr &&
+ so->so_faddr_ip == faddr &&
+ so->so_faddr_port == fport)
break;
}
@@ -161,13 +161,13 @@ soread(so)
nn = readv(so->s, (struct iovec *)iov, n);
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#else
- nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
+ nn = socket_recv(so->s, iov[0].iov_base, iov[0].iov_len);
#endif
if (nn <= 0) {
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
return 0;
else {
- DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
+ DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,errno_str));
sofcantrcvmore(so);
tcp_sockclosed(sototcpcb(so));
return -1;
@@ -186,7 +186,7 @@ soread(so)
*/
if (n == 2 && nn == iov[0].iov_len) {
int ret;
- ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
+ ret = socket_recv(so->s, iov[1].iov_base, iov[1].iov_len);
if (ret > 0)
nn += ret;
}
@@ -254,7 +254,7 @@ sosendoob(so)
if (sb->sb_rptr < sb->sb_wptr) {
/* We can send it directly */
- n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
+ n = socket_send_oob(so->s, sb->sb_rptr, so->so_urgc); /* |MSG_DONTWAIT)); */
so->so_urgc -= n;
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
@@ -275,7 +275,7 @@ sosendoob(so)
so->so_urgc -= n;
len += n;
}
- n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
+ n = socket_send_oob(so->s, buff, len); /* |MSG_DONTWAIT)); */
#ifdef DEBUG
if (n != len)
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
@@ -345,7 +345,7 @@ sowrite(so)
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#else
- nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
+ nn = socket_send(so->s, iov[0].iov_base, iov[0].iov_len);
#endif
/* This should never happen, but people tell me it does *shrug* */
if (nn < 0 && (errno == EAGAIN || errno == EINTR))
@@ -362,7 +362,7 @@ sowrite(so)
#ifndef HAVE_READV
if (n == 2 && nn == iov[0].iov_len) {
int ret;
- ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0);
+ ret = socket_send(so->s, iov[1].iov_base, iov[1].iov_len);
if (ret > 0)
nn += ret;
}
@@ -392,8 +392,7 @@ void
sorecvfrom(so)
struct socket *so;
{
- struct sockaddr_in addr;
- int addrlen = sizeof(struct sockaddr_in);
+ SockAddress addr;
DEBUG_CALL("sorecvfrom");
DEBUG_ARG("so = %lx", (long)so);
@@ -402,8 +401,7 @@ sorecvfrom(so)
char buff[256];
int len;
- len = recvfrom(so->s, buff, 256, 0,
- (struct sockaddr *)&addr, &addrlen);
+ len = socket_recvfrom(so->s, buff, 256, &addr);
/* XXX Check if reply is "correct"? */
if(len == -1 || len == 0) {
@@ -413,8 +411,8 @@ sorecvfrom(so)
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
- errno,strerror(errno)));
- icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
+ errno,errno_str));
+ icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str);
} else {
icmp_reflect(so->so_m);
so->so_m = 0; /* Don't mbuf_free() it again! */
@@ -434,7 +432,7 @@ sorecvfrom(so)
*/
len = mbuf_freeroom(m);
/* if (so->so_fport != htons(53)) { */
- ioctlsocket(so->s, FIONREAD, &n);
+ n = socket_can_read(so->s);
if (n > len) {
n = (m->m_data - m->m_dat) + m->m_len + n + 1;
@@ -443,10 +441,9 @@ sorecvfrom(so)
}
/* } */
- m->m_len = recvfrom(so->s, m->m_data, len, 0,
- (struct sockaddr *)&addr, &addrlen);
+ m->m_len = socket_recvfrom(so->s, m->m_data, len, &addr);
DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
- m->m_len, errno,strerror(errno)));
+ m->m_len, errno,errno_str));
if(m->m_len<0) {
u_char code=ICMP_UNREACH_PORT;
@@ -454,7 +451,7 @@ sorecvfrom(so)
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
- icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
+ icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str);
mbuf_free(m);
} else {
/*
@@ -464,7 +461,7 @@ sorecvfrom(so)
* out much quicker (10 seconds for now...)
*/
if (so->so_expire) {
- if (so->so_fport == htons(53))
+ if (so->so_faddr_port == 53)
so->so_expire = curtime + SO_EXPIREFAST;
else
so->so_expire = curtime + SO_EXPIRE;
@@ -480,7 +477,7 @@ sorecvfrom(so)
* If this packet was destined for CTL_ADDR,
* make it look like that's where it came from, done by udp_output
*/
- udp_output(so, m, &addr);
+ udp_output_(so, m, &addr);
} /* rx error */
} /* if ping packet */
}
@@ -493,31 +490,34 @@ sosendto(so, m)
struct socket *so;
MBuf m;
{
- int ret;
- struct sockaddr_in addr;
+ SockAddress addr;
+ uint32_t addr_ip;
+ uint16_t addr_port;
+ int ret;
DEBUG_CALL("sosendto");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m);
- addr.sin_family = AF_INET;
- if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
+ if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) {
/* It's an alias */
- int low = ntohl(so->so_faddr.s_addr) & 0xff;
+ int low = so->so_faddr_ip & 0xff;
if ( CTL_IS_DNS(low) )
- addr.sin_addr = dns_addr[low - CTL_DNS];
+ addr_ip = dns_addr[low - CTL_DNS];
else
- addr.sin_addr = loopback_addr;
+ addr_ip = loopback_addr_ip;
} else
- addr.sin_addr = so->so_faddr;
- addr.sin_port = so->so_fport;
+ addr_ip = so->so_faddr_ip;
- DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
+ addr_port = so->so_faddr_port;
+
+ sock_address_init_inet(&addr, addr_ip, addr_port);
+
+ DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%08x\n", addr_port, addr_ip));
/* Don't care what port we get */
- ret = sendto(so->s, m->m_data, m->m_len, 0,
- (struct sockaddr *)&addr, sizeof (struct sockaddr));
+ ret = socket_sendto(so->s, m->m_data, m->m_len,&addr);
if (ret < 0)
return -1;
@@ -541,9 +541,10 @@ solisten(port, laddr, lport, flags)
u_int lport;
int flags;
{
- struct sockaddr_in addr;
+ SockAddress addr;
+ uint32_t addr_ip;
struct socket *so;
- int s, addrlen = sizeof(addr);
+ int s;
DEBUG_CALL("solisten");
DEBUG_ARG("port = %d", port);
@@ -569,46 +570,25 @@ solisten(port, laddr, lport, flags)
if (flags & SS_FACCEPTONCE)
so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
- so->so_state = (SS_FACCEPTCONN|flags);
- so->so_lport = lport; /* Kept in network format */
- so->so_hport = port;
- so->so_laddr.s_addr = laddr; /* Ditto */
-
- memset( &addr, 0, sizeof(addr) );
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr.sin_port = port;
+ so->so_state = (SS_FACCEPTCONN|flags);
+ so->so_laddr_port = lport; /* Kept in host format */
+ so->so_laddr_ip = laddr; /* Ditto */
+ so->so_haddr_port = port;
- if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) {
- sofree(so);
+ s = socket_loopback_server( port, SOCKET_STREAM );
+ if (s < 0)
return NULL;
- }
- socket_set_xreuseaddr(s);
+ socket_get_address(s, &addr);
- if ((socket_set_xreuseaddr(s) < 0) ||
- (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
- (listen(s,1) < 0)) {
- int tmperrno = errno; /* Don't clobber the real reason we failed */
+ so->so_faddr_port = sock_address_get_port(&addr);
- close(s);
- sofree(so);
- /* Restore the real errno */
-#ifdef _WIN32
- WSASetLastError(tmperrno);
-#else
- errno = tmperrno;
-#endif
- return NULL;
- }
- socket_set_oobinline(s);
+ addr_ip = (uint32_t) sock_address_get_ip(&addr);
- getsockname(s,(struct sockaddr *)&addr,&addrlen);
- so->so_fport = addr.sin_port;
- if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
- so->so_faddr = alias_addr;
- else
- so->so_faddr = addr.sin_addr;
+ if (addr_ip == 0 || addr_ip == loopback_addr_ip)
+ so->so_faddr_ip = alias_addr_ip;
+ else
+ so->so_faddr_ip = addr_ip;
so->s = s;
return so;
@@ -621,7 +601,7 @@ sounlisten(u_int port)
struct socket *so;
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
- if (so->so_hport == htons(port)) {
+ if (so->so_haddr_port == port) {
break;
}
}
diff --git a/slirp/socket.h b/slirp2/socket.h
index 54cb21c..5b71d45 100644
--- a/slirp/socket.h
+++ b/slirp2/socket.h
@@ -29,11 +29,11 @@ struct socket {
struct tcpiphdr *so_ti; /* Pointer to the original ti within
* so_mconn, for non-blocking connections */
int so_urgc;
- struct in_addr so_faddr; /* foreign host table entry */
- struct in_addr so_laddr; /* local host table entry */
- u_int16_t so_fport; /* foreign port */
- u_int16_t so_lport; /* local port */
- u_int16_t so_hport;
+ uint32_t so_faddr_ip;
+ uint32_t so_laddr_ip;
+ uint16_t so_faddr_port;
+ uint16_t so_laddr_port;
+ uint16_t so_haddr_port;
u_int8_t so_iptos; /* Type of service */
u_int8_t so_emu; /* Is the socket emulated? */
@@ -84,7 +84,7 @@ struct iovec {
#endif
void so_init _P((void));
-struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
+struct socket * solookup _P((struct socket *, uint32_t, u_int, uint32_t, u_int));
struct socket * socreate _P((void));
void sofree _P((struct socket *));
int soread _P((struct socket *));
diff --git a/slirp/tcp.h b/slirp2/tcp.h
index 769f364..3cddb77 100644
--- a/slirp/tcp.h
+++ b/slirp2/tcp.h
@@ -37,6 +37,8 @@
#ifndef _TCP_H_
#define _TCP_H_
+#include "helper.h"
+
typedef u_int32_t tcp_seq;
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
@@ -54,8 +56,8 @@ extern struct socket *tcp_last_so;
* Per RFC 793, September, 1981.
*/
struct tcphdr {
- u_int16_t th_sport; /* source port */
- u_int16_t th_dport; /* destination port */
+ port_t th_sport; /* source port */
+ port_t th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
#ifdef WORDS_BIGENDIAN
diff --git a/slirp/tcp_input.c b/slirp2/tcp_input.c
index 4621ca2..1c5a709 100644
--- a/slirp/tcp_input.c
+++ b/slirp2/tcp_input.c
@@ -367,16 +367,22 @@ tcp_input(m, iphlen, inso)
*/
findso:
so = tcp_last_so;
- if (so->so_fport != ti->ti_dport ||
- so->so_lport != ti->ti_sport ||
- so->so_laddr.s_addr != ti->ti_src.s_addr ||
- so->so_faddr.s_addr != ti->ti_dst.s_addr) {
- so = solookup(&tcb, ti->ti_src, ti->ti_sport,
- ti->ti_dst, ti->ti_dport);
+ {
+ uint32_t srcip = ip_geth(ti->ti_src);
+ uint32_t dstip = ip_geth(ti->ti_dst);
+ uint16_t dstport = port_geth(ti->ti_dport);
+ uint16_t srcport = port_geth(ti->ti_sport);
+
+ if (so->so_faddr_port != dstport ||
+ so->so_laddr_port != srcport ||
+ so->so_laddr_ip != srcip ||
+ so->so_faddr_ip != dstip) {
+ so = solookup(&tcb, srcip, srcport, dstip, dstport);
if (so)
tcp_last_so = so;
++tcpstat.tcps_socachemiss;
}
+ }
/*
* If the state is CLOSED (i.e., TCB does not exist) then
@@ -408,10 +414,10 @@ findso:
/* tcp_last_so = so; */ /* XXX ? */
/* tp = sototcpcb(so); */
- so->so_laddr = ti->ti_src;
- so->so_lport = ti->ti_sport;
- so->so_faddr = ti->ti_dst;
- so->so_fport = ti->ti_dport;
+ so->so_laddr_ip = ip_geth(ti->ti_src);
+ so->so_laddr_port = port_geth(ti->ti_sport);
+ so->so_faddr_ip = ip_geth(ti->ti_dst);
+ so->so_faddr_port = port_geth(ti->ti_dport);
if ((so->so_iptos = tcp_tos(so)) == 0)
so->so_iptos = ((struct ip *)ti)->ip_tos;
@@ -634,8 +640,8 @@ findso:
* If this is destined for the control address, then flag to
* tcp_ctl once connected, otherwise connect
*/
- if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) {
- int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff;
+ if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) {
+ //int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff;
/* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */
}
@@ -647,7 +653,7 @@ findso:
if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
u_char code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n",
- errno,strerror(errno)));
+ errno,errno_str));
if(errno == ECONNREFUSED) {
/* ACK the SYN, send RST to refuse the connection */
tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
@@ -661,7 +667,7 @@ findso:
m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
*ip=save_ip;
- icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno));
+ icmp_error(m, ICMP_UNREACH,code, 0,errno_str);
}
tp = tcp_close(tp);
mbuf_free(m);
diff --git a/slirp/tcp_output.c b/slirp2/tcp_output.c
index 95246aa..95246aa 100644
--- a/slirp/tcp_output.c
+++ b/slirp2/tcp_output.c
diff --git a/slirp/tcp_subr.c b/slirp2/tcp_subr.c
index 59aae0a..fb55513 100644
--- a/slirp/tcp_subr.c
+++ b/slirp2/tcp_subr.c
@@ -44,8 +44,6 @@
#define WANT_SYS_IOCTL_H
#include <slirp.h>
-#define SLIRP_COMPILATION
-#include "sockets.h"
#include "proxy_common.h"
/* patchable/settable parameters for tcp */
@@ -91,10 +89,10 @@ tcp_template(tp)
n->ti_x1 = 0;
n->ti_pr = IPPROTO_TCP;
n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
- n->ti_src = so->so_faddr;
- n->ti_dst = so->so_laddr;
- n->ti_sport = so->so_fport;
- n->ti_dport = so->so_lport;
+ n->ti_src = ip_seth(so->so_faddr_ip);
+ n->ti_dst = ip_seth(so->so_laddr_ip);
+ n->ti_sport = port_seth(so->so_faddr_port);
+ n->ti_dport = port_seth(so->so_laddr_port);
n->ti_seq = 0;
n->ti_ack = 0;
@@ -162,8 +160,8 @@ tcp_respond(tp, ti, m, ack, seq, flags)
m->m_len = sizeof (struct tcpiphdr);
tlen = 0;
#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
- xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t);
- xchg(ti->ti_dport, ti->ti_sport, u_int16_t);
+ xchg(ti->ti_dst, ti->ti_src, ipaddr_t);
+ xchg(ti->ti_dport, ti->ti_sport, port_t);
#undef xchg
}
ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
@@ -304,7 +302,7 @@ tcp_close(tp)
/* clobber input socket cache if we're closing the cached connection */
if (so == tcp_last_so)
tcp_last_so = &tcb;
- closesocket(so->s);
+ socket_close(so->s);
sbuf_free(&so->so_rcv);
sbuf_free(&so->so_snd);
sofree(so);
@@ -419,33 +417,34 @@ int tcp_fconnect(so)
{
int ret=0;
int try_proxy = 1;
- struct sockaddr_in addr;
+ SockAddress sockaddr;
+ uint32_t sock_ip;
+ uint16_t sock_port;
DEBUG_CALL("tcp_fconnect");
DEBUG_ARG("so = %lx", (long )so);
- addr.sin_family = AF_INET;
- addr.sin_addr = so->so_faddr;
- addr.sin_port = so->so_fport;
+ sock_ip = so->so_faddr_ip;
+ sock_port = so->so_faddr_port;
- if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
+ if ((sock_ip & 0xffffff00) == special_addr_ip) {
/* It's an alias */
- int last_byte = ntohl(so->so_faddr.s_addr) & 0xff;
+ int last_byte = sock_ip & 0xff;
if (CTL_IS_DNS(last_byte))
- addr.sin_addr = dns_addr[last_byte - CTL_DNS];
+ sock_ip = dns_addr[last_byte - CTL_DNS];
else
- addr.sin_addr = loopback_addr;
+ sock_ip = loopback_addr_ip;
try_proxy = 0;
}
- DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
- "addr.sin_addr.s_addr=%.16s proxy=%d\n",
- ntohs(addr.sin_port), inet_ntoa(addr.sin_addr),
- try_proxy));
+ sock_address_init_inet( &sockaddr, sock_ip, sock_port );
+
+ DEBUG_MISC((dfd, " connect()ing, addr=%s, proxy=%d\n",
+ sock_address_to_string(&sockaddr), try_proxy));
if (try_proxy) {
- if (!proxy_manager_add(&addr, SOCK_STREAM, (ProxyEventFunc) tcp_proxy_event, so)) {
+ if (!proxy_manager_add(&sockaddr, SOCKET_STREAM, (ProxyEventFunc) tcp_proxy_event, so)) {
soisfconnecting(so);
so->s = -1;
so->so_state |= SS_PROXIFIED;
@@ -453,7 +452,7 @@ int tcp_fconnect(so)
}
}
- if ((ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0)
+ if ((ret=so->s=socket_create_inet(SOCKET_STREAM)) >= 0)
{
int s = so->s;
@@ -462,7 +461,7 @@ int tcp_fconnect(so)
socket_set_oobinline(s);
/* We don't care what port we get */
- ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
+ socket_connect(s, &sockaddr);
/*
* If it's not in progress, it failed, so we just return 0,
@@ -491,8 +490,8 @@ tcp_connect(inso)
struct socket *inso;
{
struct socket *so;
- struct sockaddr_in addr;
- int addrlen = sizeof(struct sockaddr_in);
+ SockAddress addr;
+ uint32_t addr_ip;
struct tcpcb *tp;
int s;
@@ -509,20 +508,20 @@ tcp_connect(inso)
} else {
if ((so = socreate()) == NULL) {
/* If it failed, get rid of the pending connection */
- closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
+ socket_close(socket_accept(inso->s, NULL));
return;
}
if (tcp_attach(so) < 0) {
free(so); /* NOT sofree */
return;
}
- so->so_laddr = inso->so_laddr;
- so->so_lport = inso->so_lport;
+ so->so_laddr_ip = inso->so_laddr_ip;
+ so->so_laddr_port = inso->so_laddr_port;
}
(void) tcp_mss(sototcpcb(so), 0);
- if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
+ if ((s = socket_accept(inso->s, &addr)) < 0) {
tcp_close(sototcpcb(so)); /* This will sofree() as well */
return;
}
@@ -531,11 +530,14 @@ tcp_connect(inso)
socket_set_oobinline(s);
socket_set_lowlatency(s);
- so->so_fport = addr.sin_port;
- so->so_faddr = addr.sin_addr;
+ so->so_faddr_port = sock_address_get_port(&addr);
+
+ addr_ip = sock_address_get_ip(&addr);
+
+ so->so_faddr_ip = addr_ip;
/* Translate connections from localhost to the real hostname */
- if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
- so->so_faddr = alias_addr;
+ if (addr_ip == 0 || addr_ip == loopback_addr_ip)
+ so->so_faddr_ip = alias_addr_ip;
/* Close the accept() socket, set right state */
if (inso->so_state & SS_FACCEPTONCE) {
@@ -610,11 +612,10 @@ tcp_tos(so)
struct socket *so;
{
int i = 0;
- struct emu_t *emup;
while(tcptos[i].tos) {
- if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
- (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
+ if ((tcptos[i].fport && so->so_faddr_port == tcptos[i].fport) ||
+ (tcptos[i].lport && so->so_laddr_port == tcptos[i].lport)) {
so->so_emu = tcptos[i].emu;
return tcptos[i].tos;
}
@@ -675,8 +676,7 @@ tcp_emu(so, m)
{
struct socket *tmpso;
- struct sockaddr_in addr;
- int addrlen = sizeof(struct sockaddr_in);
+ SockAddress addr;
SBuf so_rcv = &so->so_rcv;
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
@@ -685,17 +685,14 @@ tcp_emu(so, m)
m->m_data[m->m_len] = 0; /* NULL terminate */
if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) {
- HTONS(n1);
- HTONS(n2);
/* n2 is the one on our host */
for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
- if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
- tmpso->so_lport == n2 &&
- tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
- tmpso->so_fport == n1) {
- if (getsockname(tmpso->s,
- (struct sockaddr *)&addr, &addrlen) == 0)
- n2 = ntohs(addr.sin_port);
+ if (tmpso->so_laddr_ip == so->so_laddr_ip &&
+ tmpso->so_laddr_port == n2 &&
+ tmpso->so_faddr_ip == so->so_faddr_ip &&
+ tmpso->so_faddr_port == n1) {
+ if (socket_get_address(tmpso->s, &addr) == 0)
+ n2 = sock_address_get_port(&addr);
break;
}
}
@@ -719,18 +716,18 @@ tcp_emu(so, m)
if (x < 6)
return 1;
- laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
- lport = htons((n5 << 8) | (n6));
+ laddr = (n1 << 24) | (n2 << 16) | (n3 << 8) | (n4);
+ lport = (n5 << 8) | (n6);
if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
- n6 = ntohs(so->so_fport);
+ n6 = so->so_faddr_port;
n5 = (n6 >> 8) & 0xff;
n6 &= 0xff;
- laddr = ntohl(so->so_faddr.s_addr);
+ laddr = so->so_faddr_ip;
n1 = ((laddr >> 24) & 0xff);
n2 = ((laddr >> 16) & 0xff);
@@ -750,18 +747,18 @@ tcp_emu(so, m)
if (x < 6)
return 1;
- laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
- lport = htons((n5 << 8) | (n6));
+ laddr = (n1 << 24) | (n2 << 16) | (n3 << 8) | (n4);
+ lport = (n5 << 8) | (n6);
if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
- n6 = ntohs(so->so_fport);
+ n6 = so->so_faddr_port;
n5 = (n6 >> 8) & 0xff;
n6 &= 0xff;
- laddr = ntohl(so->so_faddr.s_addr);
+ laddr = so->so_faddr_ip;
n1 = ((laddr >> 24) & 0xff);
n2 = ((laddr >> 16) & 0xff);
@@ -792,8 +789,8 @@ tcp_emu(so, m)
lport += m->m_data[i] - '0';
}
if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
- (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
- m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1;
+ (so = solisten(0, so->so_laddr_ip, lport, SS_FACCEPTONCE)) != NULL)
+ m->m_len = sprintf(m->m_data, "%d", so->so_faddr_port)+1;
return 1;
case EMU_IRC:
@@ -806,29 +803,29 @@ tcp_emu(so, m)
/* The %256s is for the broken mIRC */
if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
- if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+ if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n",
- (unsigned long)ntohl(so->so_faddr.s_addr),
- ntohs(so->so_fport), 1);
+ (unsigned long) so->so_faddr_ip,
+ so->so_faddr_port, 1);
} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
- if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+ if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n",
- buff, (unsigned long)ntohl(so->so_faddr.s_addr),
- ntohs(so->so_fport), n1, 1);
+ buff, (unsigned long)so->so_faddr_ip,
+ so->so_faddr_port, n1, 1);
} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
- if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+ if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n",
- buff, (unsigned long)ntohl(so->so_faddr.s_addr),
- ntohs(so->so_fport), n1, 1);
+ buff, (unsigned long)so->so_faddr_ip,
+ so->so_faddr_port, n1, 1);
}
return 1;
@@ -936,10 +933,10 @@ tcp_emu(so, m)
/* try to get udp port between 6970 - 7170 */
for (p = 6970; p < 7071; p++) {
- if (udp_listen( htons(p),
- so->so_laddr.s_addr,
- htons(lport),
- SS_FACCEPTONCE)) {
+ if (udp_listen( p,
+ so->so_laddr_ip,
+ lport,
+ SS_FACCEPTONCE)) {
break;
}
}
@@ -976,8 +973,10 @@ tcp_ctl(so)
{
SBuf sb = &so->so_snd;
int command;
+#if 0
struct ex_list *ex_ptr;
int do_pty;
+#endif
// struct socket *tmpso;
DEBUG_CALL("tcp_ctl");
@@ -987,13 +986,13 @@ tcp_ctl(so)
/*
* Check if they're authorised
*/
- if (ctl_addr.s_addr && (ctl_addr.s_addr == -1 || (so->so_laddr.s_addr != ctl_addr.s_addr))) {
+ if (ctl_addr_ip && (ctl_addr_ip == -1 || (so->so_laddr_ip != ctl_addr_ip))) {
sb->sb_cc = sprintf(sb->sb_wptr,"Error: Permission denied.\r\n");
sb->sb_wptr += sb->sb_cc;
return 0;
}
#endif
- command = (ntohl(so->so_faddr.s_addr) & 0xff);
+ command = (so->so_faddr_ip & 0xff);
switch(command) {
default:
diff --git a/slirp/tcp_timer.c b/slirp2/tcp_timer.c
index ad03098..ad03098 100644
--- a/slirp/tcp_timer.c
+++ b/slirp2/tcp_timer.c
diff --git a/slirp/tcp_timer.h b/slirp2/tcp_timer.h
index 59933bc..59933bc 100644
--- a/slirp/tcp_timer.h
+++ b/slirp2/tcp_timer.h
diff --git a/slirp/tcp_var.h b/slirp2/tcp_var.h
index b30a15d..b30a15d 100644
--- a/slirp/tcp_var.h
+++ b/slirp2/tcp_var.h
diff --git a/slirp/tcpip.h b/slirp2/tcpip.h
index 82708b0..82708b0 100644
--- a/slirp/tcpip.h
+++ b/slirp2/tcpip.h
diff --git a/slirp/tftp.c b/slirp2/tftp.c
index 8af404a..37933d9 100644
--- a/slirp/tftp.c
+++ b/slirp2/tftp.c
@@ -23,13 +23,15 @@
*/
#include <slirp.h>
+#include <fcntl.h>
+#include <sys/stat.h>
struct tftp_session {
int in_use;
unsigned char filename[TFTP_FILENAME_MAX];
- struct in_addr client_ip;
- u_int16_t client_port;
+ uint32_t client_ip;
+ uint16_t client_port;
int timestamp;
};
@@ -69,8 +71,8 @@ static int tftp_session_allocate(struct tftp_t *tp)
found:
memset(spt, 0, sizeof(*spt));
- memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip));
- spt->client_port = tp->udp.uh_sport;
+ spt->client_ip = ip_geth(tp->ip.ip_src);
+ spt->client_port = port_geth(tp->udp.uh_sport);
tftp_session_update(spt);
@@ -86,8 +88,8 @@ static int tftp_session_find(struct tftp_t *tp)
spt = &tftp_sessions[k];
if (spt->in_use) {
- if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
- if (spt->client_port == tp->udp.uh_sport) {
+ if (spt->client_ip == ip_geth(tp->ip.ip_src)) {
+ if (spt->client_port == port_geth(tp->udp.uh_sport)) {
return k;
}
}
@@ -131,7 +133,7 @@ static int tftp_send_oack(struct tftp_session *spt,
const char *key, uint32_t value,
struct tftp_t *recv_tp)
{
- struct sockaddr_in saddr, daddr;
+ SockAddress saddr, daddr;
MBuf m;
struct tftp_t *tp;
int n = 0;
@@ -151,15 +153,17 @@ static int tftp_send_oack(struct tftp_session *spt,
n += sprintf((char*)tp->x.tp_buf + n, "%s", key) + 1;
n += sprintf((char*)tp->x.tp_buf + n, "%u", value) + 1;
- saddr.sin_addr = recv_tp->ip.ip_dst;
- saddr.sin_port = recv_tp->udp.uh_dport;
+ sock_address_init_inet( &saddr,
+ ip_geth(recv_tp->ip.ip_dst),
+ port_geth(recv_tp->udp.uh_dport) );
- daddr.sin_addr = spt->client_ip;
- daddr.sin_port = spt->client_port;
+ sock_address_init_inet( &daddr,
+ spt->client_ip,
+ spt->client_port );
m->m_len = sizeof(struct tftp_t) - 514 + n -
sizeof(struct ip) - sizeof(struct udphdr);
- udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+ udp_output2_(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
return 0;
}
@@ -170,7 +174,7 @@ static int tftp_send_error(struct tftp_session *spt,
u_int16_t errorcode, const char *msg,
struct tftp_t *recv_tp)
{
- struct sockaddr_in saddr, daddr;
+ SockAddress saddr, daddr;
MBuf m;
struct tftp_t *tp;
int nobytes;
@@ -191,18 +195,20 @@ static int tftp_send_error(struct tftp_session *spt,
tp->x.tp_error.tp_error_code = htons(errorcode);
strcpy((char*)tp->x.tp_error.tp_msg, msg);
- saddr.sin_addr = recv_tp->ip.ip_dst;
- saddr.sin_port = recv_tp->udp.uh_dport;
+ sock_address_init_inet( &saddr,
+ ip_geth(recv_tp->ip.ip_dst),
+ port_geth(recv_tp->udp.uh_dport) );
- daddr.sin_addr = spt->client_ip;
- daddr.sin_port = spt->client_port;
+ sock_address_init_inet( &daddr,
+ spt->client_ip,
+ spt->client_port );
nobytes = 2;
m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
sizeof(struct ip) - sizeof(struct udphdr);
- udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+ udp_output2_(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
tftp_session_terminate(spt);
@@ -213,7 +219,7 @@ static int tftp_send_data(struct tftp_session *spt,
u_int16_t block_nr,
struct tftp_t *recv_tp)
{
- struct sockaddr_in saddr, daddr;
+ SockAddress saddr, daddr;
MBuf m;
struct tftp_t *tp;
int nobytes;
@@ -237,11 +243,13 @@ static int tftp_send_data(struct tftp_session *spt,
tp->tp_op = htons(TFTP_DATA);
tp->x.tp_data.tp_block_nr = htons(block_nr);
- saddr.sin_addr = recv_tp->ip.ip_dst;
- saddr.sin_port = recv_tp->udp.uh_dport;
+ sock_address_init_inet( &saddr,
+ ip_geth(recv_tp->ip.ip_dst),
+ port_geth(recv_tp->udp.uh_dport) );
- daddr.sin_addr = spt->client_ip;
- daddr.sin_port = spt->client_port;
+ sock_address_init_inet( &daddr,
+ spt->client_ip,
+ spt->client_port );
nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512);
@@ -258,7 +266,7 @@ static int tftp_send_data(struct tftp_session *spt,
m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
sizeof(struct ip) - sizeof(struct udphdr);
- udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+ udp_output2_(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
if (nobytes == 512) {
tftp_session_update(spt);
diff --git a/slirp/tftp.h b/slirp2/tftp.h
index 06018a7..06018a7 100644
--- a/slirp/tftp.h
+++ b/slirp2/tftp.h
diff --git a/slirp2/udp.c b/slirp2/udp.c
new file mode 100644
index 0000000..d4296d7
--- /dev/null
+++ b/slirp2/udp.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
+ * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
+ */
+
+/*
+ * Changes and additions relating to SLiRP
+ * Copyright (c) 1995 Danny Gasparovski.
+ *
+ * Please read the file COPYRIGHT for the
+ * terms and conditions of the copyright.
+ */
+
+#include <slirp.h>
+#include "ip_icmp.h"
+#define SLIRP_COMPILATION 1
+#include "sockets.h"
+
+struct udpstat udpstat;
+
+struct socket udb;
+
+/*
+ * UDP protocol implementation.
+ * Per RFC 768, August, 1980.
+ */
+#ifndef COMPAT_42
+int udpcksum = 1;
+#else
+int udpcksum = 0; /* XXX */
+#endif
+
+struct socket *udp_last_so = &udb;
+
+void
+udp_init()
+{
+ udb.so_next = udb.so_prev = &udb;
+}
+/* m->m_data points at ip packet header
+ * m->m_len length ip packet
+ * ip->ip_len length data (IPDU)
+ */
+void
+udp_input(m, iphlen)
+ register MBuf m;
+ int iphlen;
+{
+ register struct ip *ip;
+ register struct udphdr *uh;
+/* MBuf opts = 0;*/
+ int len;
+ struct ip save_ip;
+ struct socket *so;
+
+ DEBUG_CALL("udp_input");
+ DEBUG_ARG("m = %lx", (long)m);
+ DEBUG_ARG("iphlen = %d", iphlen);
+
+ udpstat.udps_ipackets++;
+
+ /*
+ * Strip IP options, if any; should skip this,
+ * make available to user, and use on returned packets,
+ * but we don't yet have a way to check the checksum
+ * with options still present.
+ */
+ if(iphlen > sizeof(struct ip)) {
+ ip_stripoptions(m, (MBuf )0);
+ iphlen = sizeof(struct ip);
+ }
+
+ /*
+ * Get IP and UDP header together in first mbuf.
+ */
+ ip = MBUF_TO(m, struct ip *);
+ uh = (struct udphdr *)((caddr_t)ip + iphlen);
+
+ /*
+ * Make mbuf data length reflect UDP length.
+ * If not enough data to reflect UDP length, drop.
+ */
+ len = ntohs((u_int16_t)uh->uh_ulen);
+
+ if (ip->ip_len != len) {
+ if (len > ip->ip_len) {
+ udpstat.udps_badlen++;
+ goto bad;
+ }
+ mbuf_trim(m, len - ip->ip_len);
+ ip->ip_len = len;
+ }
+
+ /*
+ * Save a copy of the IP header in case we want restore it
+ * for sending an ICMP error message in response.
+ */
+ save_ip = *ip;
+ save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
+
+ /*
+ * Checksum extended UDP header and data.
+ */
+ if (udpcksum && uh->uh_sum) {
+ ((struct ipovly *)ip)->ih_next = 0;
+ ((struct ipovly *)ip)->ih_prev = 0;
+ ((struct ipovly *)ip)->ih_x1 = 0;
+ ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
+ /* keep uh_sum for ICMP reply
+ * uh->uh_sum = cksum(m, len + sizeof (struct ip));
+ * if (uh->uh_sum) {
+ */
+ if(cksum(m, len + sizeof(struct ip))) {
+ udpstat.udps_badsum++;
+ goto bad;
+ }
+ }
+
+ /*
+ * handle DHCP/BOOTP
+ */
+ if (port_geth(uh->uh_dport) == BOOTP_SERVER) {
+ bootp_input(m);
+ goto bad;
+ }
+
+ /*
+ * handle TFTP
+ */
+ if (port_geth(uh->uh_dport) == TFTP_SERVER) {
+ tftp_input(m);
+ goto bad;
+ }
+
+ /*
+ * Locate pcb for datagram.
+ */
+ so = udp_last_so;
+ if (so->so_laddr_port != port_geth(uh->uh_sport) ||
+ so->so_laddr_ip != ip_geth(ip->ip_src)) {
+ struct socket *tmp;
+
+ for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
+ if (tmp->so_laddr_port == port_geth(uh->uh_sport) &&
+ tmp->so_laddr_ip == ip_geth(ip->ip_src)) {
+ tmp->so_faddr_ip = ip_geth(ip->ip_dst);
+ tmp->so_faddr_port = port_geth(uh->uh_dport);
+ so = tmp;
+ break;
+ }
+ }
+ if (tmp == &udb) {
+ so = NULL;
+ } else {
+ udpstat.udpps_pcbcachemiss++;
+ udp_last_so = so;
+ }
+ }
+
+ if (so == NULL) {
+ /*
+ * If there's no socket for this packet,
+ * create one
+ */
+ if ((so = socreate()) == NULL) goto bad;
+ if(udp_attach(so) == -1) {
+ DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
+ errno,errno_str));
+ sofree(so);
+ goto bad;
+ }
+
+ /*
+ * Setup fields
+ */
+ /* udp_last_so = so; */
+ so->so_laddr_ip = ip_geth(ip->ip_src);
+ so->so_laddr_port = port_geth(uh->uh_sport);
+
+ if ((so->so_iptos = udp_tos(so)) == 0)
+ so->so_iptos = ip->ip_tos;
+
+ /*
+ * XXXXX Here, check if it's in udpexec_list,
+ * and if it is, do the fork_exec() etc.
+ */
+ }
+
+ so->so_faddr_ip = ip_geth(ip->ip_dst); /* XXX */
+ so->so_faddr_port = port_geth(uh->uh_dport); /* XXX */
+
+ iphlen += sizeof(struct udphdr);
+ m->m_len -= iphlen;
+ m->m_data += iphlen;
+
+ /*
+ * Now we sendto() the packet.
+ */
+ if (so->so_emu)
+ udp_emu(so, m);
+
+ if(sosendto(so,m) == -1) {
+ m->m_len += iphlen;
+ m->m_data -= iphlen;
+ *ip=save_ip;
+ DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno, errno_str));
+ icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,errno_str);
+ }
+
+ mbuf_free(so->so_m); /* used for ICMP if error on sorecvfrom */
+
+ /* restore the orig mbuf packet */
+ m->m_len += iphlen;
+ m->m_data -= iphlen;
+ *ip=save_ip;
+ so->so_m=m; /* ICMP backup */
+
+ return;
+bad:
+ mbuf_free(m);
+ /* if (opts) mbuf_free(opts); */
+ return;
+}
+
+int udp_output2_(struct socket* so, MBuf m,
+ const SockAddress* saddr,
+ const SockAddress* daddr,
+ int iptos)
+{
+ register struct udpiphdr *ui;
+ uint32_t saddr_ip = sock_address_get_ip(saddr);
+ uint32_t daddr_ip = sock_address_get_ip(daddr);
+ int saddr_port = sock_address_get_port(saddr);
+ int daddr_port = sock_address_get_port(daddr);
+ int error = 0;
+
+ DEBUG_CALL("udp_output");
+ DEBUG_ARG("so = %lx", (long)so);
+ DEBUG_ARG("m = %lx", (long)m);
+ DEBUG_ARG("saddr = %lx", (long) saddr_ip);
+ DEBUG_ARG("daddr = %lx", (long) daddr_ip);
+
+ /*
+ * Adjust for header
+ */
+ m->m_data -= sizeof(struct udpiphdr);
+ m->m_len += sizeof(struct udpiphdr);
+
+ /*
+ * Fill in mbuf with extended UDP header
+ * and addresses and length put into network format.
+ */
+ ui = MBUF_TO(m, struct udpiphdr *);
+ ui->ui_next = ui->ui_prev = 0;
+ ui->ui_x1 = 0;
+ ui->ui_pr = IPPROTO_UDP;
+ ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
+ /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
+ ui->ui_src = ip_seth(saddr_ip);
+ ui->ui_dst = ip_seth(daddr_ip);
+ ui->ui_sport = port_seth(saddr_port);
+ ui->ui_dport = port_seth(daddr_port);
+ ui->ui_ulen = ui->ui_len;
+
+ /*
+ * Stuff checksum and output datagram.
+ */
+ ui->ui_sum = 0;
+ if (udpcksum) {
+ if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
+ ui->ui_sum = 0xffff;
+ }
+ ((struct ip *)ui)->ip_len = m->m_len;
+
+ ((struct ip *)ui)->ip_ttl = ip_defttl;
+ ((struct ip *)ui)->ip_tos = iptos;
+
+ udpstat.udps_opackets++;
+
+ error = ip_output(so, m);
+
+ return (error);
+}
+
+int udp_output_(struct socket *so, MBuf m, SockAddress* from)
+{
+ SockAddress saddr, daddr;
+ uint32_t saddr_ip;
+ uint16_t saddr_port;
+
+ saddr_ip = sock_address_get_ip(from);
+ saddr_port = sock_address_get_port(from);
+
+ if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) {
+ saddr_ip = so->so_faddr_ip;
+ if ((so->so_faddr_ip & 0x000000ff) == 0xff)
+ saddr_ip = alias_addr_ip;
+ }
+
+ sock_address_init_inet( &saddr, saddr_ip, saddr_port );
+ sock_address_init_inet( &daddr, so->so_laddr_ip, so->so_laddr_port );
+
+ return udp_output2_(so, m, &saddr, &daddr, so->so_iptos);
+}
+
+int
+udp_attach(so)
+ struct socket *so;
+{
+ so->s = socket_anyaddr_server( 0, SOCKET_DGRAM );
+ if (so->s != -1) {
+ /* success, insert in queue */
+ so->so_expire = curtime + SO_EXPIRE;
+ insque(so,&udb);
+ }
+ return(so->s);
+}
+
+void
+udp_detach(so)
+ struct socket *so;
+{
+ socket_close(so->s);
+ /* if (so->so_m) mbuf_free(so->so_m); done by sofree */
+
+ sofree(so);
+}
+
+struct tos_t udptos[] = {
+ {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
+ {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */
+ {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */
+ {0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME}, /* Cu-Seeme */
+ {0, 0, 0, 0}
+};
+
+u_int8_t
+udp_tos(so)
+ struct socket *so;
+{
+ int i = 0;
+
+ while(udptos[i].tos) {
+ if ((udptos[i].fport && so->so_faddr_port == udptos[i].fport) ||
+ (udptos[i].lport && so->so_laddr_port == udptos[i].lport)) {
+ so->so_emu = udptos[i].emu;
+ return udptos[i].tos;
+ }
+ i++;
+ }
+
+ return 0;
+}
+
+/*
+ * Here, talk/ytalk/ntalk requests must be emulated
+ */
+void
+udp_emu(so, m)
+ struct socket *so;
+ MBuf m;
+{
+ SockAddress sockaddr;
+
+struct cu_header {
+ uint16_t d_family; // destination family
+ uint16_t d_port; // destination port
+ uint32_t d_addr; // destination address
+ uint16_t s_family; // source family
+ uint16_t s_port; // source port
+ uint32_t so_addr; // source address
+ uint32_t seqn; // sequence number
+ uint16_t message; // message
+ uint16_t data_type; // data type
+ uint16_t pkt_len; // packet length
+} *cu_head;
+
+ switch(so->so_emu) {
+
+ case EMU_CUSEEME:
+
+ /*
+ * Cu-SeeMe emulation.
+ * Hopefully the packet is more that 16 bytes long. We don't
+ * do any other tests, just replace the address and port
+ * fields.
+ */
+ if (m->m_len >= sizeof (*cu_head)) {
+ if (socket_get_address(so->s, &sockaddr) < 0)
+ return;
+
+ cu_head = MBUF_TO(m, struct cu_header *);
+ cu_head->s_port = htons( sock_address_get_port(&sockaddr));
+ cu_head->so_addr = htonl( sock_address_get_ip(&sockaddr));
+ }
+
+ return;
+ }
+}
+
+struct socket *
+udp_listen(port, laddr, lport, flags)
+ u_int port;
+ u_int32_t laddr;
+ u_int lport;
+ int flags;
+{
+ struct socket *so;
+ SockAddress addr;
+ uint32_t addr_ip;
+
+ if ((so = socreate()) == NULL) {
+ free(so);
+ return NULL;
+ }
+ so->s = socket_anyaddr_server( port, SOCKET_DGRAM );
+ so->so_expire = curtime + SO_EXPIRE;
+ so->so_haddr_port = port;
+ insque(so,&udb);
+
+ if (so->s < 0) {
+ udp_detach(so);
+ return NULL;
+ }
+
+ socket_get_address(so->s, &addr);
+
+ so->so_faddr_port = sock_address_get_port(&addr);
+ addr_ip = sock_address_get_ip(&addr);
+
+ if (addr_ip == 0 || addr_ip == loopback_addr_ip)
+ so->so_faddr_ip = alias_addr_ip;
+ else
+ so->so_faddr_ip = addr_ip;
+
+ so->so_laddr_port = lport;
+ so->so_laddr_ip = laddr;
+ if (flags != SS_FACCEPTONCE)
+ so->so_expire = 0;
+
+ so->so_state = SS_ISFCONNECTED;
+
+ return so;
+}
+
+int udp_unlisten (u_int port)
+{
+ struct socket *so;
+
+ for (so = udb.so_next; so != &udb; so = so->so_next) {
+ if (so->so_haddr_port == port) {
+ break;
+ }
+ }
+
+ if (so == &udb)
+ return -1;
+
+ sofcantrcvmore( so );
+ sofcantsendmore( so );
+ socket_close( so->s );
+ so->s = -1;
+ sofree( so );
+ return 0;
+}
diff --git a/slirp/udp.h b/slirp2/udp.h
index f59925d..f1bb8c9 100644
--- a/slirp/udp.h
+++ b/slirp2/udp.h
@@ -37,6 +37,8 @@
#ifndef _UDP_H_
#define _UDP_H_
+#include "helper.h"
+
#define UDP_TTL 0x60
#define UDP_UDPDATALEN 16192
@@ -47,8 +49,8 @@ extern struct socket *udp_last_so;
* Per RFC 768, September, 1981.
*/
struct udphdr {
- u_int16_t uh_sport; /* source port */
- u_int16_t uh_dport; /* destination port */
+ port_t uh_sport; /* source port */
+ port_t uh_dport; /* destination port */
int16_t uh_ulen; /* udp length */
u_int16_t uh_sum; /* udp checksum */
};
@@ -98,14 +100,17 @@ struct mbuf;
void udp_init _P((void));
void udp_input _P((register MBuf , int));
-int udp_output _P((struct socket *, MBuf , struct sockaddr_in *));
int udp_attach _P((struct socket *));
void udp_detach _P((struct socket *));
u_int8_t udp_tos _P((struct socket *));
void udp_emu _P((struct socket *, MBuf ));
struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
int udp_unlisten _P((u_int));
-int udp_output2(struct socket *so, MBuf m,
- struct sockaddr_in *saddr, struct sockaddr_in *daddr,
- int iptos);
+
+int udp_output_(struct socket *, MBuf, SockAddress*);
+
+int udp_output2_(struct socket* so, MBuf m,
+ const SockAddress* saddr, const SockAddress* daddr,
+ int iptos);
+
#endif
diff --git a/sockets.c b/sockets.c
index 1a0d356..5c841ba 100644
--- a/sockets.c
+++ b/sockets.c
@@ -13,6 +13,30 @@
#include "vl.h"
#include <fcntl.h>
#include "android_debug.h"
+#include <stdlib.h>
+#include <string.h>
+#include "android_utils.h"
+
+#ifdef _WIN32
+# define xxWIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#else /* !_WIN32 */
+# include <sys/ioctl.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <netdb.h>
+# if HAVE_UNIX_SOCKETS
+# include <sys/un.h>
+# ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX (sizeof(((struct sockaddr_un*)0)->sun_path)-1)
+# endif
+# endif
+#endif /* !_WIN32 */
+
+
/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
* easily in QEMU since we use SIGALRM to implement periodic timers
@@ -26,88 +50,757 @@
#endif
#ifdef _WIN32
-const char* socket_strerr(void)
-{
- int err = WSAGetLastError();
- switch (err) {
- case WSA_INVALID_HANDLE:
- return "invalid handle";
- case WSA_NOT_ENOUGH_MEMORY:
- return "not enough memory";
- case WSA_INVALID_PARAMETER:
- return "invalid parameter";
- case WSA_OPERATION_ABORTED:
- return "operation aborted";
- case WSA_IO_INCOMPLETE:
- return "incomplete i/o";
- case WSA_IO_PENDING:
- return "pending i/o";
- case WSAEINTR:
- return "interrupted";
- case WSAEBADF:
- return "bad file descriptor";
- case WSAEACCES:
- return "permission denied";
- case WSAEFAULT:
- return "bad address";
- case WSAEINVAL:
- return "invalid argument";
- case WSAEMFILE:
- return "too many opened files";
- case WSAEWOULDBLOCK:
- return "resource temporarily unavailable";
- case WSAEINPROGRESS:
- return "operation in progress";
- case WSAEALREADY:
- return "operation already in progress";
- case WSAENOTSOCK:
- return "socket operation not on socket";
- case WSAEDESTADDRREQ:
- return "destination address required";
- case WSAEMSGSIZE:
- return "message too long";
- case WSAEPROTOTYPE:
- return "wrong protocol for socket type";
- case WSAENOPROTOOPT:
- return "bad option for protocol";
- case WSAEPROTONOSUPPORT:
- return "protocol not supported";
- case WSAEADDRINUSE:
- return "address already in use";
- case WSAEADDRNOTAVAIL:
- return "address not available";
- case WSAENETDOWN:
- return "network is down";
- case WSAENETUNREACH:
- return "network unreachable";
- case WSAENETRESET:
- return "network dropped connection on reset";
- case WSAECONNABORTED:
- return "connection aborted";
- case WSAECONNRESET:
- return "connection reset by peer";
- case WSAENOBUFS:
- return "no buffer space available";
- case WSAETIMEDOUT:
- return "connection timed out";
- case WSAECONNREFUSED:
- return "connection refused";
- case WSAEHOSTDOWN:
- return "host is down";
- case WSAEHOSTUNREACH:
- return "no route to host";
- default:
- return "unknown/TODO";
+
+#include <errno.h>
+
+static int winsock_error;
+
+#define WINSOCK_ERRORS_LIST \
+ EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
+ EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
+ EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
+ EE(WSAEINTR,EINTR,"interrupted function call") \
+ EE(WSAEBADF,EBADF,"bad file descriptor") \
+ EE(WSAEACCES,EACCES,"permission denied") \
+ EE(WSAEFAULT,EFAULT,"bad address") \
+ EE(WSAEINVAL,EINVAL,"invalid argument") \
+ EE(WSAEMFILE,EMFILE,"too many opened files") \
+ EE(WSAEWOULDBLOCK,EAGAIN,"resource temporarily unavailable") \
+ EE(WSAEINPROGRESS,EAGAIN,"operation now in progress") \
+ EE(WSAEALREADY,EAGAIN,"operation already in progress") \
+ EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
+ EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
+ EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
+ EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
+ EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
+ EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
+ EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
+ EE(WSAENETDOWN,ENETDOWN,"network is down") \
+ EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
+ EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
+ EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
+ EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
+ EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
+ EE(WSAEISCONN,EISCONN,"socket is already connected") \
+ EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
+ EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
+ EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
+ EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
+ EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
+ EE(WSAELOOP,ELOOP,"cannot translate name") \
+ EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
+ EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
+ EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
+
+typedef struct {
+ int winsock;
+ int unix;
+ const char* string;
+} WinsockError;
+
+static const WinsockError _winsock_errors[] = {
+#define EE(w,u,s) { w, u, s },
+ WINSOCK_ERRORS_LIST
+#undef EE
+ { -1, -1, NULL }
+};
+
+/* this function reads the latest winsock error code and updates
+ * errno to a matching value. It also returns the new value of
+ * errno.
+ */
+static int
+_fix_errno( void )
+{
+ const WinsockError* werr = _winsock_errors;
+ int unix = EINVAL; /* generic error code */
+
+ for ( ; werr->string != NULL; werr++ ) {
+ if (werr->winsock == winsock_error) {
+ unix = werr->unix;
+ break;
+ }
}
+ errno = unix;
+ return -1;
+}
+
+static int
+_set_errno( int code )
+{
+ winsock_error = -1;
+ errno = code;
+ return -1;
+}
+
+/* this function returns a string describing the latest Winsock error */
+const char*
+_errno_str(void)
+{
+ const WinsockError* werr = _winsock_errors;
+ const char* result = "<unknown error>";
+
+ for ( ; werr->string; werr++ ) {
+ if (werr->winsock == winsock_error) {
+ result = werr->string;
+ break;
+ }
+ }
+
+ if (result == NULL)
+ result = strerror(errno);
+
+ return result;
+}
+#else
+static int
+_fix_errno( void )
+{
+ return -1;
+}
+
+static int
+_set_errno( int code )
+{
+ errno = code;
+ return -1;
}
#endif
-int socket_get_type(int fd)
+/* socket types */
+
+static int
+socket_family_to_bsd( SocketFamily family )
+{
+ switch (family) {
+ case SOCKET_INET: return AF_INET;
+ case SOCKET_IN6: return AF_INET6;
+#if HAVE_UNIX_SOCKETS
+ case SOCKET_UNIX: return AF_LOCAL;
+#endif
+ default: return -1;
+ }
+}
+
+static int
+socket_type_to_bsd( SocketType type )
+{
+ switch (type) {
+ case SOCKET_DGRAM: return SOCK_DGRAM;
+ case SOCKET_STREAM: return SOCK_STREAM;
+ default: return -1;
+ }
+}
+
+static SocketType
+socket_type_from_bsd( int type )
+{
+ switch (type) {
+ case SOCK_DGRAM: return SOCKET_DGRAM;
+ case SOCK_STREAM: return SOCKET_STREAM;
+ default: return (SocketType) -1;
+ }
+}
+
+#if 0
+static int
+socket_type_check( SocketType type )
+{
+ return (type == SOCKET_DGRAM || type == SOCKET_STREAM);
+}
+#endif
+
+/* socket addresses */
+
+void
+sock_address_init_inet( SockAddress* a, uint32_t ip, uint16_t port )
+{
+ a->family = SOCKET_INET;
+ a->u.inet.port = port;
+ a->u.inet.address = ip;
+}
+
+void
+sock_address_init_in6 ( SockAddress* a, const uint8_t* ip6[16], uint16_t port )
+{
+ a->family = SOCKET_IN6;
+ a->u.in6.port = port;
+ memcpy( a->u.in6.address, ip6, sizeof(a->u.in6.address) );
+}
+
+void
+sock_address_init_unix( SockAddress* a, const char* path )
+{
+ a->family = SOCKET_UNIX;
+ a->u._unix.path = strdup(path ? path : "");
+ a->u._unix.owner = 1;
+}
+
+void sock_address_done( SockAddress* a )
+{
+ if (a->family == SOCKET_UNIX && a->u._unix.owner) {
+ a->u._unix.owner = 0;
+ free((char*)a->u._unix.path);
+ }
+}
+
+static char*
+format_char( char* buf, char* end, int c )
+{
+ if (buf >= end)
+ return buf;
+ if (buf+1 == end)
+ c = 0;
+ *buf++ = (char) c;
+ return buf;
+}
+
+static char*
+format_str( char* buf, char* end, const char* str )
+{
+ int len = strlen(str);
+ int avail = end - buf;
+
+ if (len > avail)
+ len = avail;
+
+ memcpy( buf, str, len );
+ buf += len;
+
+ if (buf == end)
+ buf[-1] = 0;
+ else
+ buf[0] = 0;
+
+ return buf;
+}
+
+static char*
+format_unsigned( char* buf, char* end, unsigned val )
+{
+ char temp[16];
+ int nn;
+
+ for ( nn = 0; val != 0; nn++ ) {
+ int rem = val % 10;
+ temp[nn] = '0'+rem;
+ val /= 10;
+ }
+
+ if (nn == 0)
+ temp[nn++] = '0';
+
+ while (nn > 0)
+ buf = format_char(buf, end, temp[--nn]);
+
+ return buf;
+}
+
+static char*
+format_hex( char* buf, char* end, unsigned val, int ndigits )
+{
+ int shift = 4*ndigits;
+ static const char hex[16] = "0123456789abcdef";
+
+ while (shift >= 0) {
+ buf = format_char(buf, end, hex[(val >> shift) & 15]);
+ shift -= 4;
+ }
+ return buf;
+}
+
+static char*
+format_ip4( char* buf, char* end, uint32_t ip )
+{
+ buf = format_unsigned( buf, end, (unsigned)(ip >> 24) );
+ buf = format_char( buf, end, '.');
+ buf = format_unsigned( buf, end, (unsigned)((ip >> 16) & 255));
+ buf = format_char( buf, end, '.');
+ buf = format_unsigned( buf, end, (unsigned)((ip >> 8) & 255));
+ buf = format_char( buf, end, '.');
+ buf = format_unsigned( buf, end, (unsigned)(ip & 255));
+ return buf;
+}
+
+static char*
+format_ip6( char* buf, char* end, const uint8_t* ip6 )
+{
+ int nn;
+ for (nn = 0; nn < 8; nn++) {
+ int val = (ip6[0] << 16) | ip6[1];
+ ip6 += 2;
+ if (nn > 0)
+ buf = format_char(buf, end, ':');
+ if (val == 0)
+ continue;
+ buf = format_hex(buf, end, val, 4);
+ }
+ return buf;
+}
+
+const char*
+sock_address_to_string( const SockAddress* a )
+{
+ static char buf0[MAX_PATH];
+ char *buf = buf0, *end = buf + sizeof(buf0);
+
+ switch (a->family) {
+ case SOCKET_INET:
+ buf = format_ip4( buf, end, a->u.inet.address );
+ buf = format_char( buf, end, ':' );
+ buf = format_unsigned( buf, end, (unsigned) a->u.inet.port );
+ break;
+
+ case SOCKET_IN6:
+ buf = format_ip6( buf, end, a->u.in6.address );
+ buf = format_char( buf, end, ':' );
+ buf = format_unsigned( buf, end, (unsigned) a->u.in6.port );
+ break;
+
+ case SOCKET_UNIX:
+ buf = format_str( buf, end, a->u._unix.path );
+ break;
+
+ default:
+ return NULL;
+ }
+
+ return buf0;
+}
+
+int
+sock_address_equal( const SockAddress* a, const SockAddress* b )
+{
+ if (a->family != b->family)
+ return 0;
+
+ switch (a->family) {
+ case SOCKET_INET:
+ return (a->u.inet.address == b->u.inet.address &&
+ a->u.inet.port == b->u.inet.port);
+
+ case SOCKET_IN6:
+ return (!memcmp(a->u.in6.address, b->u.in6.address, 16) &&
+ a->u.in6.port == b->u.in6.port);
+
+ case SOCKET_UNIX:
+ return (!strcmp(a->u._unix.path, b->u._unix.path));
+
+ default:
+ return 0;
+ }
+}
+
+int
+sock_address_get_port( const SockAddress* a )
+{
+ switch (a->family) {
+ case SOCKET_INET:
+ return a->u.inet.port;
+ case SOCKET_IN6:
+ return a->u.in6.port;
+ default:
+ return -1;
+ }
+}
+
+int
+sock_address_get_ip( const SockAddress* a )
+{
+ if (a->family == SOCKET_INET)
+ return a->u.inet.address;
+
+ return -1;
+}
+
+#if 0
+char*
+bufprint_sock_address( char* p, char* end, const SockAddress* a )
+{
+ switch (a->family) {
+ case SOCKET_INET:
+ {
+ uint32_t ip = a->u.inet.address;
+
+ return bufprint( p, end, "%d.%d.%d.%d:%d",
+ (ip >> 24) & 255, (ip >> 16) & 255,
+ (ip >> 8) & 255, ip & 255,
+ a->u.inet.port );
+ }
+ case SOCKET_IN6:
+ {
+ int nn = 0;
+ const char* column = "";
+ const uint8_t* tab = a->u.in6.address;
+ for (nn = 0; nn < 16; nn += 2) {
+ p = bufprint(p, end, "%s%04x", column, (tab[n] << 8) | tab[n+1]);
+ column = ":";
+ }
+ return bufprint(p, end, ":%d", a->u.in6.port);
+ }
+ case SOCKET_UNIX:
+ {
+ return bufprint(p, end, "%s", a->u._unix.path);
+ }
+ default:
+ return p;
+ }
+}
+#endif
+
+int
+sock_address_to_bsd( const SockAddress* a, void* paddress, size_t *psize )
+{
+ switch (a->family) {
+ case SOCKET_INET:
+ {
+ struct sockaddr_in* dst = (struct sockaddr_in*) paddress;
+
+ *psize = sizeof(*dst);
+
+ memset( paddress, 0, *psize );
+
+ dst->sin_family = AF_INET;
+ dst->sin_port = htons(a->u.inet.port);
+ dst->sin_addr.s_addr = htonl(a->u.inet.address);
+ }
+ break;
+
+#if HAVE_IN6_SOCKETS
+ case SOCKET_IN6:
+ {
+ struct sockaddr_in6* dst = (struct sockaddr_in6*) paddress;
+
+ *psize = sizeof(*dst);
+
+ memset( paddress, 0, *psize );
+
+ dst->sin6_family = AF_INET6;
+ dst->sin6_port = htons(a->u.in6.port);
+ memcpy( dst->sin6_addr.s6_addr, a->u.in6.address, 16 );
+ }
+ break;
+#endif /* HAVE_IN6_SOCKETS */
+
+#if HAVE_UNIX_SOCKETS
+ case SOCKET_UNIX:
+ {
+ int slen = strlen(a->u._unix.path);
+ struct sockaddr_un* dst = (struct sockaddr_un*) paddress;
+
+ if (slen >= UNIX_PATH_MAX)
+ return -1;
+
+ memset( paddress, 0, sizeof(*dst) );
+
+ dst->sun_family = AF_LOCAL;
+ memcpy( dst->sun_path, a->u._unix.path, slen );
+ dst->sun_path[slen] = 0;
+
+ *psize = (char*)&dst->sun_path[slen+1] - (char*)dst;
+ }
+ break;
+#endif /* HAVE_UNIX_SOCKETS */
+
+ default:
+ return _set_errno(EINVAL);
+ }
+
+ return 0;
+}
+
+int
+sock_address_to_inet( SockAddress* a, int *paddr_ip, int *paddr_port )
+{
+ struct sockaddr addr;
+ socklen_t addrlen;
+
+ if (a->family != SOCKET_INET) {
+ return _set_errno(EINVAL);
+ }
+
+ if (sock_address_to_bsd(a, &addr, &addrlen) < 0)
+ return -1;
+
+ *paddr_ip = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
+ *paddr_port = ntohs(((struct sockaddr_in*)&addr)->sin_port);
+
+ return 0;
+}
+
+int
+sock_address_from_bsd( SockAddress* a, const void* from, size_t fromlen )
+{
+ switch (((struct sockaddr*)from)->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in* src = (struct sockaddr_in*) from;
+
+ if (fromlen < sizeof(*src))
+ return _set_errno(EINVAL);
+
+ a->family = SOCKET_INET;
+ a->u.inet.port = ntohs(src->sin_port);
+ a->u.inet.address = ntohl(src->sin_addr.s_addr);
+ }
+ break;
+
+#ifdef HAVE_IN6_SOCKETS
+ case AF_INET6:
+ {
+ struct sockaddr_in6* src = (struct sockaddr_in6*) from;
+
+ if (fromlen < sizeof(*src))
+ return _set_errno(EINVAL);
+
+ a->family = SOCKET_IN6;
+ a->u.in6.port = ntohs(src->sin6_port);
+ memcpy(a->u.in6.address, src->sin6_addr.s6_addr, 16);
+ }
+ break;
+#endif
+
+#ifdef HAVE_UNIX_SOCKETS
+ case AF_LOCAL:
+ {
+ struct sockaddr_un* src = (struct sockaddr_un*) from;
+ char* end;
+
+ if (fromlen < sizeof(*src))
+ return _set_errno(EINVAL);
+
+ /* check that the path is zero-terminated */
+ end = memchr(src->sun_path, 0, UNIX_PATH_MAX);
+ if (end == NULL)
+ return _set_errno(EINVAL);
+
+ a->family = SOCKET_UNIX;
+ a->u._unix.owner = 1;
+ a->u._unix.path = strdup(src->sun_path);
+ }
+ break;
+#endif
+
+ default:
+ return _set_errno(EINVAL);
+ }
+ return 0;
+}
+
+
+int
+sock_address_init_resolve( SockAddress* a, const char* hostname, uint16_t port, int preferIn6 )
+{
+ struct addrinfo hints[1];
+ struct addrinfo* res;
+ int ret;
+
+ memset(hints, 0, sizeof(hints));
+ hints->ai_family = preferIn6 ? AF_INET6 : AF_UNSPEC;
+
+ if (getaddrinfo(hostname, NULL, hints, &res) < 0) {
+ return _fix_errno();
+ }
+
+ ret = sock_address_from_bsd( a, res->ai_addr, res->ai_addrlen );
+ freeaddrinfo(res);
+
+ /* need to set the port */
+ switch (a->family) {
+ case SOCKET_INET: a->u.inet.port = port; break;
+ case SOCKET_IN6: a->u.in6.port = port; break;
+ default: ;
+ }
+
+ return ret;
+}
+
+
+int
+socket_create( SocketFamily family, SocketType type )
+{
+ int ret;
+ int sfamily = socket_family_to_bsd(family);
+ int stype = socket_type_to_bsd(type);
+
+ if (sfamily < 0 || stype < 0) {
+ return _set_errno(EINVAL);
+ }
+
+ QSOCKET_CALL(ret, socket(sfamily, stype, 0));
+ if (ret < 0)
+ return _fix_errno();
+
+ return ret;
+}
+
+
+int
+socket_create_inet( SocketType type )
+{
+ return socket_create( SOCKET_INET, type );
+}
+
+#if HAVE_IN6_SOCKETS
+int
+socket_create_in6 ( SocketType type )
+{
+ return socket_create( SOCKET_IN6, type );
+}
+#endif
+
+#if HAVE_UNIX_SOCKETS
+int
+socket_create_unix( SocketType type )
+{
+ return socket_create( SOCKET_UNIX, type );
+}
+#endif
+
+int socket_can_read(int fd)
+{
+#ifdef _WIN32
+ unsigned long opt;
+
+ if (ioctlsocket(fd, FIONREAD, &opt) < 0)
+ return 0;
+
+ return opt;
+#else
+ int opt;
+
+ if (ioctl(fd, FIONREAD, &opt) < 0)
+ return 0;
+
+ return opt;
+#endif
+}
+
+#define SOCKET_CALL(cmd) \
+ int ret; \
+ QSOCKET_CALL(ret, (cmd)); \
+ if (ret < 0) \
+ return _fix_errno(); \
+ return ret; \
+
+int
+socket_send(int fd, const void* buf, int buflen)
+{
+ SOCKET_CALL(send(fd, buf, buflen, 0))
+}
+
+int
+socket_send_oob( int fd, const void* buf, int buflen )
+{
+ SOCKET_CALL(send(fd, buf, buflen, MSG_OOB));
+}
+
+int
+socket_sendto(int fd, const void* buf, int buflen, const SockAddress* to)
+{
+ struct sockaddr sa;
+ socklen_t salen;
+
+ if (sock_address_to_bsd(to, &sa, &salen) < 0)
+ return -1;
+
+ SOCKET_CALL(sendto(fd, buf, buflen, 0, &sa, salen));
+}
+
+int
+socket_recv(int fd, void* buf, int len)
+{
+ SOCKET_CALL(recv(fd, buf, len, 0));
+}
+
+int
+socket_recvfrom(int fd, void* buf, int len, SockAddress* from)
+{
+ struct sockaddr sa;
+ socklen_t salen = sizeof(sa);
+ int ret;
+
+ QSOCKET_CALL(ret,recvfrom(fd,buf,len,0,&sa,&salen));
+ if (ret < 0)
+ return _fix_errno();
+
+ if (sock_address_from_bsd(from, &sa, salen) < 0)
+ return -1;
+
+ return ret;
+}
+
+int
+socket_connect( int fd, const SockAddress* address )
+{
+ struct sockaddr addr;
+ socklen_t addrlen;
+
+ if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
+ return -1;
+
+ SOCKET_CALL(connect(fd,&addr,addrlen));
+}
+
+int
+socket_bind( int fd, const SockAddress* address )
+{
+ struct sockaddr addr;
+ socklen_t addrlen;
+
+ if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
+ return -1;
+
+ SOCKET_CALL(bind(fd, &addr, addrlen));
+}
+
+int
+socket_get_address( int fd, SockAddress* address )
+{
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+ int ret;
+
+ QSOCKET_CALL(ret, getsockname(fd, &addr, &addrlen));
+ if (ret < 0)
+ return _fix_errno();
+
+ return sock_address_from_bsd(address, &addr, addrlen);
+}
+
+int
+socket_listen( int fd, int backlog )
+{
+ SOCKET_CALL(listen(fd, backlog));
+}
+
+int
+socket_accept( int fd, SockAddress* address )
+{
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+ int ret;
+
+ QSOCKET_CALL(ret, accept(fd, &addr, &addrlen));
+ if (ret < 0)
+ return _fix_errno();
+
+ if (address) {
+ if (sock_address_from_bsd(address, &addr, addrlen) < 0) {
+ socket_close(ret);
+ return -1;
+ }
+ }
+ return ret;
+}
+
+SocketType socket_get_type(int fd)
{
int opt = -1;
int optlen = sizeof(opt);
getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&opt, (void*)&optlen );
- return opt;
+
+ return socket_type_from_bsd(opt);
}
int socket_set_nonblock(int fd)
@@ -116,7 +809,8 @@ int socket_set_nonblock(int fd)
unsigned long opt = 1;
return ioctlsocket(fd, FIONBIO, &opt);
#else
- return fcntl(fd, F_SETFL, O_NONBLOCK);
+ int flags = fcntl(fd, F_GETFL);
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#endif
}
@@ -126,10 +820,22 @@ int socket_set_blocking(int fd)
unsigned long opt = 0;
return ioctlsocket(fd, FIONBIO, &opt);
#else
- return fcntl(fd, F_SETFL, O_NONBLOCK);
+ int flags = fcntl(fd, F_GETFL);
+ return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
#endif
}
+static int
+socket_setoption(int fd, int domain, int option, int _flag)
+{
+#ifdef _WIN32
+ DWORD flag = (DWORD) _flag;
+#else
+ int flag = _flag;
+#endif
+ return setsockopt( fd, domain, option, (const char*)&flag, sizeof(flag) );
+}
+
int socket_set_xreuseaddr(int fd)
{
@@ -139,36 +845,22 @@ int socket_set_xreuseaddr(int fd)
* semantics. instead of SO_EXCLUSIVEADDR to ensure that explicitely prevent
* this.
*/
- BOOL flag = 1;
- return setsockopt( fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&flag, sizeof(flag) );
+ return socket_setoption(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1);
#else
- int flag = 1;
- return setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, sizeof(flag) );
+ return socket_setoption(fd, SOL_SOCKET, SO_REUSEADDR, 1);
#endif
}
int socket_set_oobinline(int fd)
{
-#ifdef _WIN32
- BOOL flag = 1;
-#else
- int flag = 1;
-#endif
- /* enable low-latency */
- return setsockopt( fd, SOL_SOCKET, SO_OOBINLINE, (const char*)&flag, sizeof(flag) );
+ return socket_setoption(fd, SOL_SOCKET, SO_OOBINLINE, 1);
}
int socket_set_lowlatency(int fd)
{
-#ifdef _WIN32
- BOOL flag = 1;
-#else
- int flag = 1;
-#endif
- /* enable low-latency */
- return setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(flag) );
+ return socket_setoption(fd, IPPROTO_TCP, TCP_NODELAY, 1);
}
@@ -215,9 +907,9 @@ socket_close_handler( void* _fd )
/* we want to drain the read side of the socket before closing it */
do {
ret = recv( fd, buff, sizeof(buff), 0 );
- } while (ret < 0 && socket_errno == EINTR);
+ } while (ret < 0 && WSAGetLastError() == WSAEINTR);
- if (ret < 0 && socket_errno == EWOULDBLOCK)
+ if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
return;
qemu_set_fd_handler( fd, NULL, NULL, NULL );
@@ -227,9 +919,13 @@ socket_close_handler( void* _fd )
void
socket_close( int fd )
{
+ int old_errno = errno;
+
shutdown( fd, SD_BOTH );
/* we want to drain the socket before closing it */
qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
+
+ errno = old_errno;
}
#else /* !_WIN32 */
@@ -239,47 +935,49 @@ socket_close( int fd )
void
socket_close( int fd )
{
+ int old_errno = errno;
+
shutdown( fd, SHUT_RDWR );
close( fd );
+
+ errno = old_errno;
}
#endif /* !_WIN32 */
static int
-socket_bind_server( int s, const struct sockaddr* addr, socklen_t addrlen, int type )
+socket_bind_server( int s, const SockAddress* to, SocketType type )
{
- int ret;
-
socket_set_xreuseaddr(s);
- QSOCKET_CALL(ret, bind(s, addr, addrlen));
- if ( ret < 0 ) {
- dprint("could not bind server socket: %s", socket_errstr());
- socket_close(s);
- return -1;
+ if (socket_bind(s, to) < 0) {
+ dprint("could not bind server socket address %s: %s",
+ sock_address_to_string(to), errno_str);
+ goto FAIL;
}
- if (type == SOCK_STREAM) {
- QSOCKET_CALL( ret, listen(s, 4) );
- if ( ret < 0 ) {
- dprint("could not listen server socket: %s", socket_errstr());
- socket_close(s);
- return -1;
+ if (type == SOCKET_STREAM) {
+ if (socket_listen(s, 4) < 0) {
+ dprint("could not listen server socket %s: %s",
+ sock_address_to_string(to), errno_str);
+ goto FAIL;
}
}
return s;
+
+FAIL:
+ socket_close(s);
+ return -1;
}
static int
-socket_connect_client( int s, const struct sockaddr* addr, socklen_t addrlen )
+socket_connect_client( int s, const SockAddress* to )
{
- int ret;
-
- QSOCKET_CALL(ret, connect(s, addr, addrlen));
- if ( ret < 0 ) {
- dprint( "could not connect client socket: %s\n", socket_errstr() );
+ if (socket_connect(s, to) < 0) {
+ dprint( "could not connect client socket to %s: %s\n",
+ sock_address_to_string(to), errno_str );
socket_close(s);
return -1;
}
@@ -290,76 +988,64 @@ socket_connect_client( int s, const struct sockaddr* addr, socklen_t addrlen
static int
-socket_in_server( int address, int port, int type )
+socket_in_server( int address, int port, SocketType type )
{
- struct sockaddr_in addr;
- int s;
+ SockAddress addr;
+ int s;
- memset( &addr, 0, sizeof(addr) );
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(address);
-
- s = socket(PF_INET, type, 0);
- if (s < 0) return -1;
+ sock_address_init_inet( &addr, address, port );
+ s = socket_create_inet( type );
+ if (s < 0)
+ return -1;
- return socket_bind_server( s, (struct sockaddr*) &addr, sizeof(addr), type );
+ return socket_bind_server( s, &addr, type );
}
static int
-socket_in_client( struct sockaddr_in* addr, int type )
+socket_in_client( SockAddress* to, SocketType type )
{
int s;
- s = socket(addr->sin_family, type, 0);
+ s = socket_create_inet( type );
if (s < 0) return -1;
- return socket_connect_client( s, (struct sockaddr*) addr, sizeof(*addr) );
+ return socket_connect_client( s, to );
}
int
-socket_loopback_server( int port, int type )
+socket_loopback_server( int port, SocketType type )
{
- return socket_in_server( INADDR_LOOPBACK, port, type );
+ return socket_in_server( SOCK_ADDRESS_INET_LOOPBACK, port, type );
}
int
-socket_loopback_client( int port, int type )
+socket_loopback_client( int port, SocketType type )
{
- struct sockaddr_in addr;
- memset( &addr, 0, sizeof(addr) );
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ SockAddress addr;
+ sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, port );
return socket_in_client( &addr, type );
}
int
-socket_network_client( const char* host, int port, int type )
+socket_network_client( const char* host, int port, SocketType type )
{
- struct hostent* hp;
- struct sockaddr_in addr;
+ SockAddress addr;
- hp = gethostbyname(host);
- if (hp == 0) return -1;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = hp->h_addrtype;
- addr.sin_port = htons(port);
- memcpy( &addr.sin_addr, hp->h_addr, hp->h_length );
+ if (sock_address_init_resolve( &addr, host, port, 0) < 0)
+ return -1;
return socket_in_client( &addr, type );
}
int
-socket_anyaddr_server( int port, int type )
+socket_anyaddr_server( int port, SocketType type )
{
- return socket_in_server( INADDR_ANY, port, type );
+ return socket_in_server( SOCK_ADDRESS_INET_ANY, port, type );
}
int
@@ -370,7 +1056,7 @@ socket_accept_any( int server_fd )
QSOCKET_CALL(fd, accept( server_fd, NULL, 0 ));
if (fd < 0) {
dprint( "could not accept client connection from fd %d: %s",
- server_fd, socket_errstr() );
+ server_fd, errno_str );
return -1;
}
@@ -380,72 +1066,49 @@ socket_accept_any( int server_fd )
}
-#ifndef _WIN32
-
-#include <sys/un.h>
-
-static int
-socket_unix_prepare_address( struct sockaddr_un* addr, const char* name )
-{
- size_t namelen = strlen(name);
- size_t offset = offsetof(struct sockaddr_un, sun_path);
-
- if (offset + namelen + 1 > sizeof(*addr)) {
- fprintf(stderr, "unix socket path too long\n");
- return -1;
- }
- memset( addr, 0, sizeof(*addr) );
- addr->sun_family = AF_LOCAL;
- memcpy( addr->sun_path, name, namelen+1 );
- return offset + namelen + 1;
-}
+#if HAVE_UNIX_SOCKETS
int
-socket_unix_server( const char* name, int type )
+socket_unix_server( const char* name, SocketType type )
{
- struct sockaddr_un addr;
- int addrlen;
- int s, ret;
-
- do {
- s = socket(AF_LOCAL, type, 0);
- } while (s < 0 && socket_errno == EINTR);
- if (s < 0) return -1;
+ SockAddress addr;
+ int s, ret;
- addrlen = socket_unix_prepare_address( &addr, name );
- if (addrlen < 0) {
- socket_close(s);
+ s = socket_create_unix( type );
+ if (s < 0)
return -1;
- }
+
+ sock_address_init_unix( &addr, name );
do {
- ret = unlink( addr.sun_path );
+ ret = unlink( name );
} while (ret < 0 && errno == EINTR);
- return socket_bind_server( s, (struct sockaddr*) &addr, (socklen_t)addrlen, type );
+ ret = socket_bind_server( s, &addr, type );
+
+ sock_address_done( &addr );
+ return ret;
}
int
-socket_unix_client( const char* name, int type )
+socket_unix_client( const char* name, SocketType type )
{
- struct sockaddr_un addr;
- int addrlen;
- int s;
+ SockAddress addr;
+ int s, ret;
- do {
- s = socket(AF_LOCAL, type, 0);
- } while (s < 0 && socket_errno == EINTR);
- if (s < 0) return -1;
-
- addrlen = socket_unix_prepare_address( &addr, name );
- if (addrlen < 0) {
- socket_close(s);
+ s = socket_create_unix(type);
+ if (s < 0)
return -1;
- }
- return socket_connect_client( s, (struct sockaddr*) &addr, (socklen_t)addrlen );
+ sock_address_init_unix( &addr, name );
+
+ ret = socket_connect_client( s, &addr );
+
+ sock_address_done( &addr );
+ return ret;
}
-#endif
+
+#endif /* HAVE_UNIX_SOCKETS */
@@ -515,3 +1178,66 @@ socket_pair(int *fd1, int *fd2)
return 0;
#endif /* _WIN32 */
}
+
+
+
+int
+socket_mcast_inet_add_membership( int s, uint32_t ip )
+{
+ struct ip_mreq imr;
+
+ imr.imr_multiaddr.s_addr = htonl(ip);
+ imr.imr_interface.s_addr = htonl(INADDR_ANY);
+
+ if ( setsockopt( s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (const char *)&imr,
+ sizeof(struct ip_mreq)) < 0 )
+ {
+ return _fix_errno();
+ }
+ return 0;
+}
+
+int
+socket_mcast_inet_drop_membership( int s, uint32_t ip )
+{
+ struct ip_mreq imr;
+
+ imr.imr_multiaddr.s_addr = htonl(ip);
+ imr.imr_interface.s_addr = htonl(INADDR_ANY);
+
+ if ( setsockopt( s, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (const char *)&imr,
+ sizeof(struct ip_mreq)) < 0 )
+ {
+ return _fix_errno();
+ }
+ return 0;
+}
+
+int
+socket_mcast_inet_set_loop( int s, int enabled )
+{
+ return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_LOOP, !!enabled );
+}
+
+int
+socket_mcast_inet_set_ttl( int s, int ttl )
+{
+ return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_TTL, ttl );
+}
+
+
+char*
+host_name( void )
+{
+ static char buf[256]; /* 255 is the max host name length supported by DNS */
+ int ret;
+
+ QSOCKET_CALL(ret, gethostname(buf, sizeof(buf)));
+
+ if (ret < 0)
+ return "localhost";
+ else
+ return buf;
+}
diff --git a/sockets.h b/sockets.h
index f336ada..7cdc693 100644
--- a/sockets.h
+++ b/sockets.h
@@ -13,44 +13,278 @@
#ifndef QEMU_SOCKET_H
#define QEMU_SOCKET_H
+#include <stddef.h>
+#include <stdint.h>
+#include <errno.h>
+
+/* we're going to hide the implementation details of sockets behind
+ * a simple wrapper interface declared here.
+ *
+ * all socket operations set the global 'errno' variable on error.
+ * this is unlike Winsock which instead modifies another internal
+ * variable accessed through WSAGetLastError() and WSASetLastError()
+ */
+
+/* the wrapper will convert any Winsock error message into an errno
+ * code for you. There are however a few standard Unix error codes
+ * that are not defined by the MS C library headers, so we add them
+ * here. We use the official Winsock error codes, which are documented
+ * even though we don't want to include the Winsock headers
+ */
#ifdef _WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
+# ifndef EINTR
+# define EINTR 10004
+# endif
+# ifndef EWOULDBLOCK
+# define EWOULDBLOCK 10035
+# endif
+# ifndef EINPROGRESS
+# define EINPROGRESS 10036
+# endif
+# ifndef EDESTADDRREQ
+# define EDESTADDRREQ 10039
+# endif
+# ifndef EMSGSIZE
+# define EMSGSIZE 10040
+# endif
+# ifndef EPROTOTYPE
+# define EPROTOTYPE 10041
+# endif
+# ifndef ENOPROTOOPT
+# define ENOPROTOOPT 10042
+# endif
+# ifndef EADDRINUSE
+# define EADDRINUSE 10048
+# endif
+# ifndef EADDRNOTAVAIL
+# define EADDRNOTAVAIL 10049
+# endif
+# ifndef ENETDOWN
+# define ENETDOWN 10050
+# endif
+# ifndef ENETUNREACH
+# define ENETUNREACH 10051
+# endif
+# ifndef ENETRESET
+# define ENETRESET 10052
+# endif
+# ifndef ECONNABORTED
+# define ECONNABORTED 10053
+# endif
+# ifndef ECONNRESET
+# define ECONNRESET 10054
+# endif
+# ifndef ENOBUFS
+# define ENOBUFS 10055
+# endif
+# ifndef EISCONN
+# define EISCONN 10056
+# endif
+# ifndef ENOTCONN
+# define ENOTCONN 10057
+# endif
+# ifndef ESHUTDOWN
+# define ESHUTDOWN 10058
+# endif
+# ifndef ETOOMANYREFS
+# define ETOOMANYREFS 10059
+# endif
+# ifndef ETIMEDOUT
+# define ETIMEDOUT 10060
+# endif
+# ifndef ECONNREFUSED
+# define ECONNREFUSED 10061
+# endif
+# ifndef ELOOP
+# define ELOOP 10062
+# endif
+# ifndef EHOSTDOWN
+# define EHOSTDOWN 10064
+# endif
+# ifndef EHOSTUNREACH
+# define EHOSTUNREACH 10065
+# endif
+#endif /* _WIN32 */
-#define socket_errno WSAGetLastError()
-#define socket_errstr() socket_strerr()
+/* Define 'errno_str' as a handy macro to return the string
+ * corresponding to a given errno code. On Unix, this is
+ * equivalent to strerror(errno), but on Windows, this will
+ * take care of Winsock-originated errors as well.
+ */
+#ifdef _WIN32
+ extern const char* _errno_str(void);
+# define errno_str _errno_str()
+#else
+# define errno_str strerror(errno)
+#endif
-#undef EINTR
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define EINTR WSAEINTR
-#define EINPROGRESS WSAEINPROGRESS
+/* always enable IPv6 sockets for now.
+ * the QEMU internal router is not capable of
+ * supporting them, but we plan to replace it
+ * with something better in the future.
+ */
+#define HAVE_IN6_SOCKETS 1
-extern const char* socket_strerr(void);
+/* Unix sockets are not available on Win32 */
+#ifndef _WIN32
+# define HAVE_UNIX_SOCKETS 1
+#endif
-#else
+/* initialize the socket sub-system. this must be called before
+ * using any of the declarations below.
+ */
+int socket_init( void );
+
+/* return the name of the current host */
+char* host_name( void );
+
+/* supported socket types */
+typedef enum {
+ SOCKET_DGRAM = 0,
+ SOCKET_STREAM
+} SocketType;
+
+/* supported socket families */
+typedef enum {
+ SOCKET_UNSPEC,
+ SOCKET_INET,
+ SOCKET_IN6,
+ SOCKET_UNIX
+} SocketFamily;
-/* if this code is included from slirp/ sources, don't include the
- * system header files because this might conflict with some of the
- * slirp definitions
+/* Generic socket address structure. Note that for Unix
+ * sockets, the path is stored in a heap-allocated block,
+ * unless the 'owner' field is cleared. If this is the case,
*/
-#include <errno.h>
-#ifndef SLIRP_COMPILATION
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netdb.h>
+typedef struct {
+ SocketFamily family;
+ union {
+ struct {
+ uint16_t port;
+ uint32_t address;
+ } inet;
+ struct {
+ uint16_t port;
+ uint8_t address[16];
+ } in6;
+ struct {
+ int owner;
+ const char* path;
+ } _unix;
+ } u;
+} SockAddress;
+
+#define SOCK_ADDRESS_INET_ANY 0x00000000
+#define SOCK_ADDRESS_INET_LOOPBACK 0x7f000001
+
+/* initialize a new IPv4 socket address, the IP address and port are
+ * in host endianess.
+ */
+void sock_address_init_inet( SockAddress* a, uint32_t ip, uint16_t port );
+
+/* Initialize an IPv6 socket address, the address is in network order
+ * and the port in host endianess.
+ */
+#if HAVE_IN6_SOCKETS
+void sock_address_init_in6 ( SockAddress* a, const uint8_t* ip6[16], uint16_t port );
#endif
-#define socket_errno errno
-#define socket_errstr() strerror(errno)
+/* Intialize a Unix socket address, this will copy the 'path' string into the
+ * heap. You need to call sock_address_done() to release the copy
+ */
+#if HAVE_UNIX_SOCKETS
+void sock_address_init_unix( SockAddress* a, const char* path );
+#endif
-#endif /* !_WIN32 */
+/* Finalize a socket address, only needed for now for Unix addresses */
+void sock_address_done( SockAddress* a );
-int socket_init( void );
+int sock_address_equal( const SockAddress* a, const SockAddress* b );
+
+/* THIS SHOULD DISAPPEAR SOON - TRANSITIONAL HELPER */
+int sock_address_to_bsd( const SockAddress* a, void* sa, size_t* salen );
+int sock_address_from_bsd( SockAddress* a, const void* sa, size_t salen );
+int sock_address_to_inet( SockAddress* a, int *paddr_ip, int *paddr_port );
+
+/* return a static string describing the address */
+const char* sock_address_to_string( const SockAddress* a );
+
+/* return the port number of a given socket address, or -1 if it's a Unix one */
+int sock_address_get_port( const SockAddress* a );
+
+/* return the inet address, or -1 if it's not SOCKET_INET */
+int sock_address_get_ip( const SockAddress* a );
+
+/* bufprint a socket address into a human-readable string */
+char* bufprint_sock_address( char* p, char* end, const SockAddress* a );
+
+/* resolve a hostname or decimal IPv4/IPv6 address into a socket address.
+ * returns 0 on success, or -1 on failure */
+int sock_address_init_resolve( SockAddress* a, const char* hostname, uint16_t port, int preferIn6 );
+
+/* create a new socket, return the socket number of -1 on failure */
+int socket_create( SocketFamily family, SocketType type );
+
+/* create a new socket intended for IPv4 communication. returns the socket number,
+ * or -1 on failure.
+ */
+int socket_create_inet( SocketType type );
+
+/* create a new socket intended for IPv6 communication. returns the socket number,
+ * or -1 on failure.
+ */
+#if HAVE_IN6_SOCKETS
+int socket_create_in6 ( SocketType type );
+#endif
+
+/* create a unix/local domain socket. returns the socket number,
+ * or -1 on failure.
+ */
+#if HAVE_UNIX_SOCKETS
+int socket_create_unix( SocketType type );
+#endif
+
+/* return the type of a given socket */
+SocketType socket_get_type(int fd);
+
+/* set SO_REUSEADDR on Unix, SO_EXCLUSIVEADDR on Windows */
+int socket_set_xreuseaddr(int fd);
+
+/* set socket in non-blocking mode */
+int socket_set_nonblock(int fd);
+
+/* set socket in blocking mode */
+int socket_set_blocking(int fd);
+
+/* disable the TCP Nagle algorithm for lower latency */
+int socket_set_lowlatency(int fd);
+
+/* send OOB data inline for this socket */
+int socket_set_oobinline(int fd);
+
+/* close an opened socket. Note that this is unlike the Unix 'close' because:
+ * - it will properly shutdown the socket in the background
+ * - it does not modify errno
+ */
+void socket_close( int fd );
-int socket_get_type(int fd);
+/* the following functions are equivalent to the BSD sockets ones
+ */
+int socket_recv ( int fd, void* buf, int buflen );
+int socket_recvfrom( int fd, void* buf, int buflen, SockAddress* from );
+
+int socket_send ( int fd, const void* buf, int buflen );
+int socket_send_oob( int fd, const void* buf, int buflen );
+int socket_sendto( int fd, const void* buf, int buflen, const SockAddress* to );
+
+int socket_connect( int fd, const SockAddress* address );
+int socket_bind( int fd, const SockAddress* address );
+int socket_get_address( int fd, SockAddress* address );
+int socket_listen( int fd, int backlog );
+int socket_accept( int fd, SockAddress* address );
+
+/* returns the number of bytes that can be read from a socket */
+int socket_can_read( int fd );
/* this call creates a pair of non-blocking sockets connected
* to each other. this is equivalent to calling the Unix function:
@@ -61,22 +295,36 @@ int socket_get_type(int fd);
*/
int socket_pair(int *fd1, int *fd2);
-/* set SO_REUSEADDR on Unix, SO_EXCLUSIVEADDR on Windows */
-int socket_set_xreuseaddr(int fd);
-int socket_set_nonblock(int fd);
-int socket_set_blocking(int fd);
-int socket_set_lowlatency(int fd);
-int socket_set_oobinline(int fd);
-void socket_close(int fd);
+/* create a server socket listening on the host's loopback interface */
+int socket_loopback_server( int port, SocketType type );
-int socket_loopback_server( int port, int type );
-int socket_loopback_client( int port, int type );
-#ifndef _WIN32
-int socket_unix_server( const char* name, int type );
-int socket_unix_client( const char* name, int type );
+/* connect to a port on the host's loopback interface */
+int socket_loopback_client( int port, SocketType type );
+
+/* create a server socket listening to a Unix domain path */
+#if HAVE_UNIX_SOCKETS
+int socket_unix_server( const char* name, SocketType type );
#endif
-int socket_network_client( const char* host, int port, int type );
-int socket_anyaddr_server( int port, int type );
+
+/* create a Unix sockets and connects it to a Unix server */
+#if HAVE_UNIX_SOCKETS
+int socket_unix_client( const char* name, SocketType type );
+#endif
+
+/* create an IPv4 client socket and connect it to a given host */
+int socket_network_client( const char* host, int port, SocketType type );
+
+/* create an IPv4 socket and binds it to a given port of the host's interface */
+int socket_anyaddr_server( int port, SocketType type );
+
+/* accept a connection from the host's any interface, return the new socket
+ * descriptor or -1 */
int socket_accept_any( int server_fd );
+
+int socket_mcast_inet_add_membership( int s, uint32_t ip );
+int socket_mcast_inet_drop_membership( int s, uint32_t ip );
+int socket_mcast_inet_set_loop( int s, int enabled );
+int socket_mcast_inet_set_ttl( int s, int ttl );
+
#endif /* QEMU_SOCKET_H */
diff --git a/tcpdump.c b/tcpdump.c
new file mode 100644
index 0000000..e562253
--- /dev/null
+++ b/tcpdump.c
@@ -0,0 +1,147 @@
+/* Copyright (C) 2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#include "tcpdump.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+int qemu_tcpdump_active;
+
+static FILE* capture_file;
+static uint64_t capture_count;
+static uint64_t capture_size;
+static int capture_init;
+
+static void
+capture_atexit(void)
+{
+ if (qemu_tcpdump_active) {
+ fclose(capture_file);
+ qemu_tcpdump_active = 0;
+ }
+}
+
+/* See http://wiki.wireshark.org/Development/LibpcapFileFormat for
+ * the complete description of the packet capture file format
+ */
+
+#define PCAP_MAGIC 0xa1b2c3d4
+#define PCAP_MAJOR 2
+#define PCAP_MINOR 4
+#define PCAP_SNAPLEN 65535
+#define PCAP_ETHERNET 1
+
+static int
+pcap_write_header( FILE* out )
+{
+ typedef struct {
+ uint32_t magic;
+ uint16_t version_major;
+ uint16_t version_minor;
+ int32_t this_zone;
+ uint32_t sigfigs;
+ uint32_t snaplen;
+ uint32_t network;
+ } PcapHeader;
+
+ PcapHeader h;
+
+ h.magic = PCAP_MAGIC;
+ h.version_major = PCAP_MAJOR;
+ h.version_minor = PCAP_MINOR;
+ h.this_zone = 0;
+ h.sigfigs = 0; /* all tools set it to 0 in practice */
+ h.snaplen = PCAP_SNAPLEN;
+ h.network = PCAP_ETHERNET;
+
+ if (fwrite(&h, sizeof(h), 1, out) != 1) {
+ return -1;
+ }
+ return 0;
+}
+
+int
+qemu_tcpdump_start( const char* filepath )
+{
+ if (!capture_init) {
+ capture_init = 1;
+ atexit(capture_atexit);
+ }
+
+ qemu_tcpdump_stop();
+
+ if (filepath == NULL)
+ return -1;
+
+ capture_file = fopen(filepath, "wb");
+ if (capture_file == NULL)
+ return -1;
+
+ if (pcap_write_header(capture_file) < 0)
+ return -1;
+
+ qemu_tcpdump_active = 1;
+ return 0;
+}
+
+void
+qemu_tcpdump_stop( void )
+{
+ if (!qemu_tcpdump_active)
+ return;
+
+ qemu_tcpdump_active = 0;
+
+ capture_count = 0;
+ capture_size = 0;
+
+ fclose(capture_file);
+ capture_file = NULL;
+}
+
+void
+qemu_tcpdump_packet( const void* base, int len )
+{
+ typedef struct {
+ uint32_t ts_sec;
+ uint32_t ts_usec;
+ uint32_t incl_len;
+ uint32_t orig_len;
+ } PacketHeader;
+
+ PacketHeader h;
+ struct timeval now;
+ int len2 = len;
+
+ if (len2 > PCAP_SNAPLEN)
+ len2 = PCAP_SNAPLEN;
+
+ gettimeofday(&now, NULL);
+ h.ts_sec = (uint32_t) now.tv_sec;
+ h.ts_usec = (uint32_t) now.tv_usec;
+ h.incl_len = (uint32_t) len2;
+ h.orig_len = (uint32_t) len;
+
+ fwrite( &h, sizeof(h), 1, capture_file );
+ fwrite( base, 1, len2, capture_file );
+
+ capture_count += 1;
+ capture_size += len2;
+}
+
+void
+qemu_tcpdump_stats( uint64_t *pcount, uint64_t* psize )
+{
+ *pcount = capture_count;
+ *psize = capture_size;
+}
+
diff --git a/tcpdump.h b/tcpdump.h
new file mode 100644
index 0000000..fc23d3f
--- /dev/null
+++ b/tcpdump.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2008 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+#ifndef _QEMU_TCPDUMP_H
+#define _QEMU_TCPDUMP_H
+
+#include <stdint.h>
+
+/* global flag, set to 1 when packet captupe is active */
+extern int qemu_tcpdump_active;
+
+/* start a new packet capture, close the current one if any.
+ * returns 0 on success, and -1 on failure (see errno then) */
+extern int qemu_tcpdump_start( const char* filepath );
+
+/* stop the current packet capture, if any */
+extern void qemu_tcpdump_stop( void );
+
+/* send an ethernet packet to the packet capture file, if any */
+extern void qemu_tcpdump_packet( const void* base, int len );
+
+/* returns interesting stats, like the number of packets captures,
+ * and the total size of these packets. Note: the file will be larger
+ * due to global and packet headers.
+ */
+extern void qemu_tcpdump_stats( uint64_t *pcount, uint64_t* psize );
+
+#endif /* _QEMU_TCPDUMP_H */
diff --git a/telephony/gsm.c b/telephony/gsm.c
index 89ff79e..b55578d 100644
--- a/telephony/gsm.c
+++ b/telephony/gsm.c
@@ -35,7 +35,7 @@ gsm_int_from_bcdi( byte_t val )
return ret;
}
-
+#if 0
static int
gsm_bcdi_to_ascii( cbytes_t bcd, int bcdlen, bytes_t dst )
{
@@ -63,8 +63,9 @@ gsm_bcdi_to_ascii( cbytes_t bcd, int bcdlen, bytes_t dst )
}
return result;
}
+#endif
-
+#if 0
static int
gsm_bcdi_from_ascii( cbytes_t ascii, int asciilen, bytes_t dst )
{
@@ -101,7 +102,7 @@ gsm_bcdi_from_ascii( cbytes_t ascii, int asciilen, bytes_t dst )
}
return result;
}
-
+#endif
int
gsm_hexchar_to_int( char c )
@@ -1129,6 +1130,7 @@ sim_adn_alpha_to_utf8( cbytes_t alpha, cbytes_t end, bytes_t dst )
return result;
}
+#if 0
static int
sim_adn_alpha_from_utf8( cbytes_t utf8, int utf8len, bytes_t dst )
{
@@ -1146,6 +1148,7 @@ sim_adn_alpha_from_utf8( cbytes_t utf8, int utf8len, bytes_t dst )
}
return result;
}
+#endif
int
sim_adn_record_from_bytes( SimAdnRecord rec, cbytes_t data, int len )
diff --git a/telephony/remote_call.c b/telephony/remote_call.c
index d5b58eb..2bd5fa8 100644
--- a/telephony/remote_call.c
+++ b/telephony/remote_call.c
@@ -269,7 +269,7 @@ remote_call_event( void* opaque, int events )
int n = sys_channel_read( call->channel, temp, sizeof(temp) );
if (n <= 0) {
/* remote emulator probably quitted */
- //S("%s: emulator %d quitted with %d: %s\n", __FUNCTION__, call->to_port, socket_errno, socket_errstr());
+ //S("%s: emulator %d quitted with %d: %s\n", __FUNCTION__, call->to_port, errno, errno_str);
remote_call_free( call );
return;
}
@@ -305,7 +305,7 @@ remote_call_event( void* opaque, int events )
if (n <= 0) {
/* remote emulator probably quitted */
S("%s: emulator %d quitted unexpectedly with error %d: %s\n",
- __FUNCTION__, call->to_port, socket_errno, socket_errstr());
+ __FUNCTION__, call->to_port, errno, errno_str);
if (call->result_func)
call->result_func( call->result_opaque, 0 );
remote_call_free( call );
@@ -334,7 +334,7 @@ remote_call_event( void* opaque, int events )
static RemoteCall _the_remote_calls;
-
+#if 0
static int
remote_from_number( const char* from )
{
@@ -349,7 +349,7 @@ remote_from_number( const char* from )
return (int) num;
}
-
+#endif
static RemoteCall
remote_call_generic( RemoteCallType type, const char* to_number, int from_port )
diff --git a/telephony/sim_card.c b/telephony/sim_card.c
index 9e48200..a5a3249 100644
--- a/telephony/sim_card.c
+++ b/telephony/sim_card.c
@@ -13,6 +13,11 @@
#include <string.h>
#include <assert.h>
+/* set ENABLE_DYNAMIC_RECORDS to 1 to enable dynamic records
+ * for now, this is an experimental feature that needs more testing
+ */
+#define ENABLE_DYNAMIC_RECORDS 0
+
#define A_SIM_PIN_SIZE 4
#define A_SIM_PUK_SIZE 8
@@ -180,6 +185,7 @@ typedef union {
} SimFileRec, *SimFile;
+#if ENABLE_DYNAMIC_RECORDS
/* convert a SIM File descriptor into an ASCII string,
assumes 'dst' is NULL or properly sized.
return the number of chars, or -1 on error */
@@ -196,7 +202,7 @@ sim_file_to_hex( SimFile file, bytes_t dst )
case SIM_FILE_EF_CYCLIC:
{
if (dst) {
- int file_size, file_type, perm;
+ int file_size, perm;
memcpy(dst, "0000", 4); /* bytes 1-2 are RFU */
dst += 4;
@@ -311,14 +317,15 @@ static SimFileEFDedicatedRec _const_files_dedicated[] =
{ 0, 0, 0, NULL, 0 } /* end of list */
};
-
+#endif /* ENABLE_DYNAMIC_RECORDS */
const char*
asimcard_io( ASimCard sim, const char* cmd )
{
int nn;
+#if ENABLE_DYNAMIC_RECORDS
int command, id, p1, p2, p3;
-
+#endif
static const struct { const char* cmd; const char* answer; } answers[] =
{
{ "+CRSM=192,28436,0,0,15", "+CRSM: 144,0,000000146f1404001aa0aa01020000" },
@@ -365,7 +372,7 @@ asimcard_io( ASimCard sim, const char* cmd )
assert( memcmp( cmd, "+CRSM=", 6 ) == 0 );
-#if 0 /* this code officially disabled in the depot until properly tested and debugged */
+#if ENABLE_DYNAMIC_RECORDS
if ( sscanf(cmd, "+CRSM=%d,%d,%d,%d,%d", &command, &id, &p1, &p2, &p3) == 5 ) {
switch (command) {
case A_SIM_CMD_GET_RESPONSE:
diff --git a/telephony/sysdeps_qemu.c b/telephony/sysdeps_qemu.c
index 469e0fe..39d966e 100644
--- a/telephony/sysdeps_qemu.c
+++ b/telephony/sysdeps_qemu.c
@@ -12,16 +12,6 @@
#include "sockets.h"
#include "sysdeps.h"
#include "vl.h"
-#ifdef _WIN32
-#include <winsock2.h>
-#else
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netdb.h>
-#endif
#define DEBUG 1
@@ -243,14 +233,14 @@ sys_channel_read( SysChannel channel, void* buffer, int size )
char* buf = (char*) buffer;
while (len > 0) {
- int ret = recv(channel->fd, buf, len, 0);
+ int ret = socket_recv(channel->fd, buf, len);
if (ret < 0) {
- if (socket_errno == EINTR)
+ if (errno == EINTR)
continue;
- if (socket_errno == EWOULDBLOCK)
+ if (errno == EWOULDBLOCK)
break;
D( "%s: after reading %d bytes, recv() returned error %d: %s\n",
- __FUNCTION__, size - len, socket_errno, socket_errstr());
+ __FUNCTION__, size - len, errno, errno_str);
return -1;
} else if (ret == 0) {
break;
@@ -270,14 +260,14 @@ sys_channel_write( SysChannel channel, const void* buffer, int size )
const char* buf = (const char*) buffer;
while (len > 0) {
- int ret = send(channel->fd, buf, len, 0);
+ int ret = socket_send(channel->fd, buf, len);
if (ret < 0) {
- if (socket_errno == EINTR)
+ if (errno == EINTR)
continue;
- if (socket_errno == EWOULDBLOCK)
+ if (errno == EWOULDBLOCK)
break;
D( "%s: send() returned error %d: %s\n",
- __FUNCTION__, socket_errno, socket_errstr());
+ __FUNCTION__, errno, errno_str);
return -1;
} else if (ret == 0) {
break;
@@ -316,7 +306,7 @@ sys_channel_create_tcp_server( int port )
{
SysChannel channel = sys_channel_alloc();
- channel->fd = socket_anyaddr_server( port, SOCK_STREAM );
+ channel->fd = socket_anyaddr_server( port, SOCKET_STREAM );
if (channel->fd < 0) {
D( "%s: failed to created network socket on TCP:%d\n",
__FUNCTION__, port );
@@ -361,7 +351,7 @@ sys_channel_create_tcp_client( const char* hostname, int port )
{
SysChannel channel = sys_channel_alloc();
- channel->fd = socket_network_client( hostname, port, SOCK_STREAM );
+ channel->fd = socket_network_client( hostname, port, SOCKET_STREAM );
if (channel->fd < 0) {
sys_channel_free(channel);
return NULL;
diff --git a/vl.c b/vl.c
index 98d2fa3..ee2362a 100644
--- a/vl.c
+++ b/vl.c
@@ -30,6 +30,7 @@
#include "android_gps.h"
#include "android_qemud.h"
#include "android_kmsg.h"
+#include "tcpdump.h"
#include <unistd.h>
#include <fcntl.h>
@@ -756,11 +757,9 @@ static int send_all(int fd, const uint8_t *buf, int len1)
len = len1;
while (len > 0) {
- ret = send(fd, buf, len, 0);
+ ret = socket_send(fd, buf, len);
if (ret < 0) {
- int errno;
- errno = WSAGetLastError();
- if (errno != WSAEWOULDBLOCK) {
+ if (errno != EWOULDBLOCK) {
return -1;
}
} else if (ret == 0) {
@@ -1827,7 +1826,7 @@ typedef struct {
IOReadHandler *fd_read;
void *fd_opaque;
int fd;
- struct sockaddr_in daddr;
+ SockAddress daddr;
char buf[1024];
int bufcnt;
int bufptr;
@@ -1838,8 +1837,7 @@ static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
NetCharDriver *s = chr->opaque;
- return sendto(s->fd, buf, len, 0,
- (struct sockaddr *)&s->daddr, sizeof(struct sockaddr_in));
+ return socket_sendto(s->fd, buf, len, &s->daddr);
}
static int udp_chr_read_poll(void *opaque)
@@ -1895,9 +1893,9 @@ static void udp_chr_add_read_handler(CharDriverState *chr,
}
}
-int parse_host_port(struct sockaddr_in *saddr, const char *str);
-int parse_host_src_port(struct sockaddr_in *haddr,
- struct sockaddr_in *saddr,
+int parse_host_port(SockAddress *saddr, const char *str);
+int parse_host_src_port(SockAddress *haddr,
+ SockAddress *saddr,
const char *str);
CharDriverState *qemu_chr_open_udp(const char *def)
@@ -1905,7 +1903,7 @@ CharDriverState *qemu_chr_open_udp(const char *def)
CharDriverState *chr = NULL;
NetCharDriver *s = NULL;
int fd = -1;
- struct sockaddr_in saddr;
+ SockAddress saddr;
chr = qemu_mallocz(sizeof(CharDriverState));
if (!chr)
@@ -1925,7 +1923,7 @@ CharDriverState *qemu_chr_open_udp(const char *def)
goto return_err;
}
- if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
+ if (socket_bind(fd, &saddr) < 0)
{
perror("bind");
goto return_err;
@@ -2047,7 +2045,7 @@ static void tcp_chr_read(void *opaque)
len = sizeof(buf);
if (len > s->max_size)
len = s->max_size;
- size = recv(s->fd, buf, len, 0);
+ size = socket_recv(s->fd, buf, len);
if (size == 0) {
/* connection closed */
s->connected = 0;
@@ -2092,26 +2090,23 @@ static void tcp_chr_telnet_init(int fd)
char buf[3];
/* Send the telnet negotion to put telnet in binary, no echo, single char mode */
IACSET(buf, 0xff, 0xfb, 0x01); /* IAC WILL ECHO */
- send(fd, (char *)buf, 3, 0);
+ socket_send(fd, (char *)buf, 3);
IACSET(buf, 0xff, 0xfb, 0x03); /* IAC WILL Suppress go ahead */
- send(fd, (char *)buf, 3, 0);
+ socket_send(fd, (char *)buf, 3);
IACSET(buf, 0xff, 0xfb, 0x00); /* IAC WILL Binary */
- send(fd, (char *)buf, 3, 0);
+ socket_send(fd, (char *)buf, 3);
IACSET(buf, 0xff, 0xfd, 0x00); /* IAC DO Binary */
- send(fd, (char *)buf, 3, 0);
+ socket_send(fd, (char *)buf, 3);
}
static void tcp_chr_accept(void *opaque)
{
CharDriverState *chr = opaque;
TCPCharDriver *s = chr->opaque;
- struct sockaddr_in saddr;
- socklen_t len;
int fd;
for(;;) {
- len = sizeof(saddr);
- fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len);
+ fd = socket_accept(s->listen_fd, NULL);
if (fd < 0 && errno != EINTR) {
return;
} else if (fd >= 0) {
@@ -2145,7 +2140,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
int is_listen = 0;
int is_waitconnect = 1;
const char *ptr;
- struct sockaddr_in saddr;
+ SockAddress saddr;
if (parse_host_port(&saddr, host_str) < 0)
goto fail;
@@ -2172,7 +2167,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
if (!s)
goto fail;
- fd = socket(PF_INET, SOCK_STREAM, 0);
+ fd = socket_create_inet( SOCKET_STREAM );
if (fd < 0)
goto fail;
@@ -2186,21 +2181,19 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
/* allow fast reuse */
socket_set_xreuseaddr(fd);
- ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
- if (ret < 0)
- goto fail;
- ret = listen(fd, 0);
- if (ret < 0)
+ if (socket_bind(fd, &saddr) < 0 ||
+ socket_listen(fd, 0) < 0)
goto fail;
+
s->listen_fd = fd;
qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr);
if (is_telnet)
s->do_telnetopt = 1;
} else {
for(;;) {
- ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
+ ret = socket_connect(fd, &saddr);
if (ret < 0) {
- err = socket_errno;
+ err = errno;
if (err == EINTR || err == EWOULDBLOCK) {
} else if (err == EINPROGRESS) {
break;
@@ -2383,8 +2376,8 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
return 0;
}
-int parse_host_src_port(struct sockaddr_in *haddr,
- struct sockaddr_in *saddr,
+int parse_host_src_port(SockAddress *haddr,
+ SockAddress *saddr,
const char *input_str)
{
char *str = strdup(input_str);
@@ -2422,33 +2415,26 @@ fail:
return -1;
}
-int parse_host_port(struct sockaddr_in *saddr, const char *str)
+int parse_host_port(SockAddress *saddr, const char *str)
{
char buf[512];
- struct hostent *he;
const char *p, *r;
- int port;
+ uint16_t port;
p = str;
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
return -1;
- saddr->sin_family = AF_INET;
- if (buf[0] == '\0') {
- saddr->sin_addr.s_addr = 0;
- } else {
- if (isdigit(buf[0])) {
- if (!inet_aton(buf, &saddr->sin_addr))
- return -1;
- } else {
- if ((he = gethostbyname(buf)) == NULL)
- return - 1;
- saddr->sin_addr = *(struct in_addr *)he->h_addr;
- }
- }
+
port = strtol(p, (char **)&r, 0);
if (r == p)
return -1;
- saddr->sin_port = htons(port);
+
+ if (buf[0] == '\0') {
+ sock_address_init_inet( saddr, SOCK_ADDRESS_INET_ANY, port );
+ } else {
+ if (sock_address_init_resolve( saddr, buf, port, 0 ) < 0)
+ return -1;
+ }
return 0;
}
@@ -2850,6 +2836,9 @@ void slirp_output(const uint8_t *pkt, int pkt_len)
if (!slirp_vc)
return;
+ if (qemu_tcpdump_active)
+ qemu_tcpdump_packet(pkt, pkt_len);
+
/* always send internal packets */
if ( ip_packet_is_internal( pkt, pkt_len ) ) {
qemu_send_packet( slirp_vc, pkt, pkt_len );
@@ -2872,6 +2861,9 @@ static void slirp_receive(void *opaque, const uint8_t *buf, int size)
printf("slirp input:\n");
hex_dump(stdout, buf, size);
#endif
+ if (qemu_tcpdump_active)
+ qemu_tcpdump_packet(buf, size);
+
if ( ip_packet_is_internal( buf, size ) ) {
slirp_input(buf, size);
return;
@@ -2904,7 +2896,7 @@ static int net_slirp_redir(const char *redir_str)
int is_udp;
char buf[256], *r;
const char *p;
- struct in_addr guest_addr;
+ uint32_t guest_ip;
int host_port, guest_port;
if (!slirp_inited) {
@@ -2934,14 +2926,14 @@ static int net_slirp_redir(const char *redir_str)
if (buf[0] == '\0') {
pstrcpy(buf, sizeof(buf), "10.0.2.15");
}
- if (!inet_aton(buf, &guest_addr))
+ if (inet_strtoip(buf, &guest_ip) < 0)
goto fail;
guest_port = strtol(p, &r, 0);
if (r == p)
goto fail;
- if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
+ if (slirp_redir(is_udp, host_port, guest_ip, guest_port) < 0) {
return -1;
}
@@ -3199,7 +3191,7 @@ typedef struct NetSocketState {
int index;
int packet_len;
uint8_t buf[4096];
- struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
+ SockAddress dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
} NetSocketState;
typedef struct NetSocketListenState {
@@ -3221,8 +3213,7 @@ static void net_socket_receive(void *opaque, const uint8_t *buf, int size)
static void net_socket_receive_dgram(void *opaque, const uint8_t *buf, int size)
{
NetSocketState *s = opaque;
- sendto(s->fd, buf, size, 0,
- (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst));
+ socket_sendto(s->fd, buf, size, &s->dgram_dst);
}
static void net_socket_send(void *opaque)
@@ -3232,9 +3223,9 @@ static void net_socket_send(void *opaque)
uint8_t buf1[4096];
const uint8_t *buf;
- size = recv(s->fd, buf1, sizeof(buf1), 0);
+ size = socket_recv(s->fd, buf1, sizeof(buf1));
if (size < 0) {
- err = socket_errno;
+ err = errno;
if (err != EWOULDBLOCK)
goto eoc;
} else if (size == 0) {
@@ -3286,7 +3277,7 @@ static void net_socket_send_dgram(void *opaque)
NetSocketState *s = opaque;
int size;
- size = recv(s->fd, s->buf, sizeof(s->buf), 0);
+ size = socket_recv(s->fd, s->buf, sizeof(s->buf));
if (size < 0)
return;
if (size == 0) {
@@ -3297,54 +3288,44 @@ static void net_socket_send_dgram(void *opaque)
qemu_send_packet(s->vc, s->buf, size);
}
-static int net_socket_mcast_create(struct sockaddr_in *mcastaddr)
+static int net_socket_mcast_create(SockAddress* mcastaddr)
{
- struct ip_mreq imr;
+ uint32_t mcast_ip = (uint32_t) sock_address_get_ip(mcastaddr);
+
int fd;
- int val, ret;
- if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) {
- fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n",
- inet_ntoa(mcastaddr->sin_addr),
- (int)ntohl(mcastaddr->sin_addr.s_addr));
- return -1;
+
+ if (!IN_MULTICAST(mcast_ip)) {
+ fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" does not contain a multicast address\n",
+ sock_address_to_string(mcastaddr));
+ return -1;
}
- fd = socket(PF_INET, SOCK_DGRAM, 0);
+ fd = socket_create_inet( SOCKET_DGRAM );
if (fd < 0) {
perror("socket(PF_INET, SOCK_DGRAM)");
return -1;
}
- ret=socket_set_xreuseaddr(fd);
- if (ret < 0) {
- perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
- goto fail;
+ if (socket_set_xreuseaddr(fd) < 0) {
+ perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
+ goto fail;
}
- ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr));
- if (ret < 0) {
+ if (socket_bind(fd, mcastaddr) < 0) {
perror("bind");
goto fail;
}
/* Add host to multicast group */
- imr.imr_multiaddr = mcastaddr->sin_addr;
- imr.imr_interface.s_addr = htonl(INADDR_ANY);
-
- ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (const char *)&imr, sizeof(struct ip_mreq));
- if (ret < 0) {
- perror("setsockopt(IP_ADD_MEMBERSHIP)");
- goto fail;
+ if (socket_mcast_inet_add_membership(fd, mcast_ip) < 0) {
+ perror("setsockopt(IP_ADD_MEMBERSHIP)");
+ goto fail;
}
/* Force mcast msgs to loopback (eg. several QEMUs in same host */
- val = 1;
- ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
- (const char *)&val, sizeof(val));
- if (ret < 0) {
- perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
- goto fail;
+ if (socket_mcast_inet_set_loop(fd, 1) < 0) {
+ perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)");
+ goto fail;
}
socket_set_nonblock(fd);
@@ -3358,9 +3339,8 @@ fail:
static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd,
int is_connected)
{
- struct sockaddr_in saddr;
+ SockAddress saddr;
int newfd;
- socklen_t saddr_len;
NetSocketState *s;
/* fd passed: multicast: "learn" dgram_dst address from bound address and save it
@@ -3369,9 +3349,9 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd,
*/
if (is_connected) {
- if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) {
+ if (socket_get_address(fd, &saddr) == 0) {
/* must be bound */
- if (saddr.sin_addr.s_addr==0) {
+ if (sock_address_get_ip(&saddr) == 0) {
fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, cannot setup multicast dst addr\n",
fd);
return NULL;
@@ -3389,7 +3369,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd,
} else {
fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n",
- fd, strerror(errno));
+ fd, errno_str);
return NULL;
}
}
@@ -3406,9 +3386,9 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd,
if (is_connected) s->dgram_dst=saddr;
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
- "socket: fd=%d (%s mcast=%s:%d)",
+ "socket: fd=%d (%s mcast=%s)",
fd, is_connected? "cloned" : "",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ sock_address_to_string(&saddr));
return s;
}
@@ -3441,16 +3421,13 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd,
static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd,
int is_connected)
{
- int so_type=-1, optlen=sizeof(so_type);
+ SocketType so_type;
- if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, (unsigned*)&optlen)< 0) {
- fprintf(stderr, "qemu: error: setsockopt(SO_TYPE) for fd=%d failed\n", fd);
- return NULL;
- }
+ so_type = socket_get_type(fd);
switch(so_type) {
- case SOCK_DGRAM:
+ case SOCKET_DGRAM:
return net_socket_fd_init_dgram(vlan, fd, is_connected);
- case SOCK_STREAM:
+ case SOCKET_STREAM:
return net_socket_fd_init_stream(vlan, fd, is_connected);
default:
/* who knows ... this could be a eg. a pty, do warn and continue as stream */
@@ -3464,34 +3441,29 @@ static void net_socket_accept(void *opaque)
{
NetSocketListenState *s = opaque;
NetSocketState *s1;
- struct sockaddr_in saddr;
- socklen_t len;
+ SockAddress saddr;
int fd;
- for(;;) {
- len = sizeof(saddr);
- fd = accept(s->fd, (struct sockaddr *)&saddr, &len);
- if (fd < 0 && errno != EINTR) {
- return;
- } else if (fd >= 0) {
- break;
- }
- }
+ fd = socket_accept(s->fd, &saddr);
+ if (fd < 0)
+ return;
+
s1 = net_socket_fd_init(s->vlan, fd, 1);
if (!s1) {
socket_close(fd);
} else {
snprintf(s1->vc->info_str, sizeof(s1->vc->info_str),
- "socket: connection from %s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ "socket: connection from %s",
+ sock_address_to_string(&saddr));
}
+ sock_address_done(&saddr);
}
static int net_socket_listen_init(VLANState *vlan, const char *host_str)
{
NetSocketListenState *s;
int fd, ret;
- struct sockaddr_in saddr;
+ SockAddress saddr;
if (parse_host_port(&saddr, host_str) < 0)
return -1;
@@ -3500,27 +3472,28 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str)
if (!s)
return -1;
- fd = socket(PF_INET, SOCK_STREAM, 0);
+ fd = socket_create_inet( SOCKET_STREAM );
if (fd < 0) {
perror("socket");
return -1;
}
socket_set_nonblock(fd);
-
socket_set_xreuseaddr(fd);
- ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
+ ret = socket_bind(fd, &saddr);
if (ret < 0) {
perror("bind");
+ socket_close(fd);
return -1;
}
- ret = listen(fd, 0);
+ ret = socket_listen(fd, 0);
if (ret < 0) {
perror("listen");
+ socket_close(fd);
return -1;
}
s->vlan = vlan;
- s->fd = fd;
+ s->fd = fd;
qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
return 0;
}
@@ -3529,12 +3502,12 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str)
{
NetSocketState *s;
int fd, connected, ret, err;
- struct sockaddr_in saddr;
+ SockAddress saddr;
if (parse_host_port(&saddr, host_str) < 0)
return -1;
- fd = socket(PF_INET, SOCK_STREAM, 0);
+ fd = socket_create_inet( SOCKET_STREAM );
if (fd < 0) {
perror("socket");
return -1;
@@ -3543,9 +3516,9 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str)
connected = 0;
for(;;) {
- ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
+ ret = socket_connect(fd, &saddr);
if (ret < 0) {
- err = socket_errno;
+ err = errno;
if (err == EINTR || err == EWOULDBLOCK) {
} else if (err == EINPROGRESS) {
break;
@@ -3562,9 +3535,9 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str)
s = net_socket_fd_init(vlan, fd, connected);
if (!s)
return -1;
+
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
- "socket: connect to %s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ "socket: connect to %s", sock_address_to_string(&saddr));
return 0;
}
@@ -3572,7 +3545,7 @@ static int net_socket_mcast_init(VLANState *vlan, const char *host_str)
{
NetSocketState *s;
int fd;
- struct sockaddr_in saddr;
+ SockAddress saddr;
if (parse_host_port(&saddr, host_str) < 0)
return -1;
@@ -3589,8 +3562,7 @@ static int net_socket_mcast_init(VLANState *vlan, const char *host_str)
s->dgram_dst = saddr;
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
- "socket: mcast=%s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ "socket: mcast=%s", sock_address_to_string(&saddr));
return 0;
}
@@ -5849,7 +5821,7 @@ const QEMUOption qemu_options[] = {
{ "nand", HAS_ARG, QEMU_OPTION_nand },
#endif
{ "clock", HAS_ARG, QEMU_OPTION_clock },
- { NULL },
+ { NULL, 0, 0 },
};
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
diff --git a/vnc.c b/vnc.c
index b4485b4..f832283 100644
--- a/vnc.c
+++ b/vnc.c
@@ -542,8 +542,8 @@ static void vnc_client_write(void *opaque)
long ret;
VncState *vs = opaque;
- ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
- ret = vnc_client_io_error(vs, ret, socket_errno);
+ ret = socket_send(vs->csock, vs->output.buffer, vs->output.offset);
+ ret = vnc_client_io_error(vs, ret, errno);
if (!ret)
return;
@@ -568,8 +568,8 @@ static void vnc_client_read(void *opaque)
buffer_reserve(&vs->input, 4096);
- ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
- ret = vnc_client_io_error(vs, ret, socket_errno);
+ ret = socket_recv(vs->csock, buffer_end(&vs->input), 4096);
+ ret = vnc_client_io_error(vs, ret, errno);
if (!ret)
return;
@@ -998,10 +998,8 @@ static int protocol_version(VncState *vs, char *version, size_t len)
static void vnc_listen_read(void *opaque)
{
VncState *vs = opaque;
- struct sockaddr_in addr;
- socklen_t addrlen = sizeof(addr);
- vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
+ vs->csock = socket_accept(vs->lsock, NULL);
if (vs->csock != -1) {
socket_set_nonblock(vs->csock);
qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
@@ -1018,7 +1016,7 @@ static void vnc_listen_read(void *opaque)
void vnc_display_init(DisplayState *ds, int display)
{
- struct sockaddr_in addr;
+ SockAddress addr;
int ret;
VncState *vs;
@@ -1041,15 +1039,13 @@ void vnc_display_init(DisplayState *ds, int display)
if (!vs->kbd_layout)
exit(1);
- vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
+ vs->lsock = socket_create_inet( SOCKET_STREAM );
if (vs->lsock == -1) {
fprintf(stderr, "Could not create socket\n");
exit(1);
}
- addr.sin_family = AF_INET;
- addr.sin_port = htons(5900 + display);
- memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
+ sock_address_init_inet( &addr, SOCK_ADDRESS_INET_ANY, 5900+display );
ret = socket_set_xreuseaddr(vs->lsock);
if (ret == -1) {
@@ -1057,12 +1053,12 @@ void vnc_display_init(DisplayState *ds, int display)
exit(1);
}
- if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ if (socket_bind(vs->lsock, &addr) < 0) {
fprintf(stderr, "bind() failed\n");
exit(1);
}
- if (listen(vs->lsock, 1) == -1) {
+ if (socket_listen(vs->lsock, 1) == -1) {
fprintf(stderr, "listen() failed\n");
exit(1);
}