diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:21 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:21 -0800 |
commit | c2db2b6accc7888df514261a7240e7759df95a4c (patch) | |
tree | 0d7ecd37a534c15348cbad01d0d1f84183b7b4d8 | |
parent | df7881f07f53b041dc0568be8528e9dbb74994cc (diff) | |
download | external_qemu-c2db2b6accc7888df514261a7240e7759df95a4c.zip external_qemu-c2db2b6accc7888df514261a7240e7759df95a4c.tar.gz external_qemu-c2db2b6accc7888df514261a7240e7759df95a4c.tar.bz2 |
auto import from //branches/cupcake/...@125939
-rw-r--r-- | CHANGES.TXT | 9 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | Makefile.android | 14 | ||||
-rwxr-xr-x | android-configure.sh | 11 | ||||
-rw-r--r-- | android/build/definitions.make | 1 | ||||
-rw-r--r-- | android/build/host_executable.make | 12 | ||||
-rw-r--r-- | android/utils/ini.c | 2 | ||||
-rw-r--r-- | android/utils/ini.h | 4 | ||||
-rw-r--r-- | android/vm/info.c | 2 | ||||
-rw-r--r-- | android_avm.c | 42 | ||||
-rw-r--r-- | android_avm.h | 39 | ||||
-rw-r--r-- | android_console.c | 125 | ||||
-rw-r--r-- | android_help.c | 18 | ||||
-rw-r--r-- | android_main.c | 94 | ||||
-rw-r--r-- | android_options.h | 2 | ||||
-rw-r--r-- | android_profile.c | 127 | ||||
-rw-r--r-- | android_profile.h | 34 | ||||
-rw-r--r-- | android_qemud.c | 3 | ||||
-rw-r--r-- | android_utils.h | 5 | ||||
-rw-r--r-- | gdbstub.c | 28 | ||||
-rw-r--r-- | hw/goldfish_mmc.c | 4 | ||||
-rw-r--r-- | loadpng.c | 2 | ||||
-rw-r--r-- | proxy/proxy_common.c | 75 | ||||
-rw-r--r-- | proxy/proxy_common.h | 7 | ||||
-rw-r--r-- | proxy/proxy_http.c | 30 | ||||
-rw-r--r-- | proxy/proxy_http_connector.c | 26 | ||||
-rw-r--r-- | proxy/proxy_http_int.h | 10 | ||||
-rw-r--r-- | proxy/proxy_http_rewriter.c | 21 | ||||
-rw-r--r-- | proxy/proxy_int.h | 18 | ||||
-rw-r--r-- | slirp/udp.c | 699 | ||||
-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.h | 111 | ||||
-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.c | 496 | ||||
-rw-r--r-- | slirp2/udp.h (renamed from slirp/udp.h) | 17 | ||||
-rw-r--r-- | sockets.c | 1126 | ||||
-rw-r--r-- | sockets.h | 328 | ||||
-rw-r--r-- | tcpdump.c | 147 | ||||
-rw-r--r-- | tcpdump.h | 36 | ||||
-rw-r--r-- | telephony/gsm.c | 9 | ||||
-rw-r--r-- | telephony/remote_call.c | 8 | ||||
-rw-r--r-- | telephony/sim_card.c | 15 | ||||
-rw-r--r-- | telephony/sysdeps_qemu.c | 30 | ||||
-rw-r--r-- | vl.c | 232 | ||||
-rw-r--r-- | vnc.c | 24 |
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 @@ -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 @@ -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) { @@ -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 @@ -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)); @@ -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 @@ -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; +} @@ -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; @@ -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) @@ -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); } |