2007-10-16 01:27:29 -07:00
/*
* Copyright ( C ) 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
* Licensed under the GPL .
*/
2005-04-16 15:20:36 -07:00
# include <unistd.h>
# include <errno.h>
2007-10-16 01:27:29 -07:00
# include <string.h>
2005-04-16 15:20:36 -07:00
# include <sys/wait.h>
2012-10-08 03:27:32 +01:00
# include <net_user.h>
# include <os.h>
2007-10-16 01:27:29 -07:00
# include "slirp.h"
2005-04-16 15:20:36 -07:00
uml: network interface hotplug error handling
This fixes a number of problems associated with network interface hotplug.
The userspace initialization function can fail in some cases, but the
failure was never passed back to eth_configure, which proceeded with the
configuration. This results in a zombie device that is present, but can't
work. This is fixed by allowing the initialization routines to return an
error, which is checked, and the configuration aborted on failure.
eth_configure failed to check for many failures. Even when it did check,
it didn't undo whatever initializations has already happened, so a present,
but partially initialized and non-working device could result. It now
checks everything that can fail, and bails out, undoing whatever had been
done.
The return value of eth_configure was always ignored, so it is now just
void.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-06 14:51:04 -07:00
static int slirp_user_init ( void * data , void * dev )
2005-04-16 15:20:36 -07:00
{
struct slirp_data * pri = data ;
pri - > dev = dev ;
uml: network interface hotplug error handling
This fixes a number of problems associated with network interface hotplug.
The userspace initialization function can fail in some cases, but the
failure was never passed back to eth_configure, which proceeded with the
configuration. This results in a zombie device that is present, but can't
work. This is fixed by allowing the initialization routines to return an
error, which is checked, and the configuration aborted on failure.
eth_configure failed to check for many failures. Even when it did check,
it didn't undo whatever initializations has already happened, so a present,
but partially initialized and non-working device could result. It now
checks everything that can fail, and bails out, undoing whatever had been
done.
The return value of eth_configure was always ignored, so it is now just
void.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-06 14:51:04 -07:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
struct slirp_pre_exec_data {
int stdin ;
int stdout ;
} ;
static void slirp_pre_exec ( void * arg )
{
struct slirp_pre_exec_data * data = arg ;
2007-10-16 01:27:29 -07:00
if ( data - > stdin ! = - 1 )
dup2 ( data - > stdin , 0 ) ;
if ( data - > stdout ! = - 1 )
dup2 ( data - > stdout , 1 ) ;
2005-04-16 15:20:36 -07:00
}
static int slirp_tramp ( char * * argv , int fd )
{
struct slirp_pre_exec_data pe_data ;
int pid ;
pe_data . stdin = fd ;
pe_data . stdout = fd ;
2007-07-15 23:38:56 -07:00
pid = run_helper ( slirp_pre_exec , & pe_data , argv ) ;
2005-04-16 15:20:36 -07:00
2007-10-16 01:27:29 -07:00
return pid ;
2005-04-16 15:20:36 -07:00
}
static int slirp_open ( void * data )
{
struct slirp_data * pri = data ;
2005-06-13 15:52:18 -07:00
int fds [ 2 ] , pid , err ;
2005-04-16 15:20:36 -07:00
2005-06-13 15:52:18 -07:00
err = os_pipe ( fds , 1 , 1 ) ;
2007-10-16 01:27:29 -07:00
if ( err )
return err ;
2005-04-16 15:20:36 -07:00
2005-06-13 15:52:18 -07:00
err = slirp_tramp ( pri - > argw . argv , fds [ 1 ] ) ;
2007-10-16 01:27:29 -07:00
if ( err < 0 ) {
printk ( UM_KERN_ERR " slirp_tramp failed - errno = %d \n " , - err ) ;
2005-06-13 15:52:18 -07:00
goto out ;
2005-04-16 15:20:36 -07:00
}
2005-06-13 15:52:18 -07:00
pid = err ;
pri - > slave = fds [ 1 ] ;
pri - > slip . pos = 0 ;
pri - > slip . esc = 0 ;
pri - > pid = err ;
2007-10-16 01:27:29 -07:00
return fds [ 0 ] ;
2005-06-13 15:52:18 -07:00
out :
2007-10-16 01:27:29 -07:00
close ( fds [ 0 ] ) ;
close ( fds [ 1 ] ) ;
2005-06-13 15:52:18 -07:00
return err ;
2005-04-16 15:20:36 -07:00
}
static void slirp_close ( int fd , void * data )
{
struct slirp_data * pri = data ;
2007-12-17 16:19:46 -08:00
int err ;
2005-04-16 15:20:36 -07:00
2007-10-16 01:27:29 -07:00
close ( fd ) ;
close ( pri - > slave ) ;
2005-04-16 15:20:36 -07:00
pri - > slave = - 1 ;
2007-10-16 01:27:29 -07:00
if ( pri - > pid < 1 ) {
printk ( UM_KERN_ERR " slirp_close: no child process to shut "
" down \n " ) ;
2005-04-16 15:20:36 -07:00
return ;
}
#if 0
2007-10-16 01:27:29 -07:00
if ( kill ( pri - > pid , SIGHUP ) < 0 ) {
printk ( UM_KERN_ERR " slirp_close: sending hangup to %d failed "
" (%d) \n " , pri - > pid , errno ) ;
2005-04-16 15:20:36 -07:00
}
# endif
2008-02-04 22:31:10 -08:00
err = helper_wait ( pri - > pid ) ;
2007-12-17 16:19:46 -08:00
if ( err < 0 )
2005-04-16 15:20:36 -07:00
return ;
pri - > pid = - 1 ;
}
int slirp_user_read ( int fd , void * buf , int len , struct slirp_data * pri )
{
2005-06-13 15:52:18 -07:00
return slip_proto_read ( fd , buf , len , & pri - > slip ) ;
2005-04-16 15:20:36 -07:00
}
int slirp_user_write ( int fd , void * buf , int len , struct slirp_data * pri )
{
2005-06-13 15:52:18 -07:00
return slip_proto_write ( fd , buf , len , & pri - > slip ) ;
2005-04-16 15:20:36 -07:00
}
2006-09-27 01:50:33 -07:00
const struct net_user_info slirp_user_info = {
2005-04-16 15:20:36 -07:00
. init = slirp_user_init ,
. open = slirp_open ,
. close = slirp_close ,
. remove = NULL ,
. add_address = NULL ,
. delete_address = NULL ,
2007-10-16 01:27:31 -07:00
. mtu = BUF_SIZE ,
. max_packet = BUF_SIZE ,
2005-04-16 15:20:36 -07:00
} ;