VBoxNetAdpCtl.cpp revision fdd5745be4d1941123673bf7f8f3651d703822b6
/* $Id$ */
/** @file
* Apps - VBoxAdpCtl, Configuration tool for vboxnetX adapters.
*/
/*
* Copyright (C) 2009 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef RT_OS_LINUX
#endif
#ifdef RT_OS_SOLARIS
#endif
/** @todo Error codes must be moved to some header file */
#define ADPCTLERR_BAD_NAME 2
#define ADPCTLERR_NO_CTL_DEV 3
#define ADPCTLERR_IOCTL_FAILED 4
#define ADPCTLERR_SOCKET_FAILED 5
/** @todo These are duplicates from src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdpInternal.h */
#define VBOXNETADP_CTL_DEV_NAME "/dev/vboxnetctl"
#define VBOXNETADP_MAX_INSTANCES 128
#define VBOXNETADP_NAME "vboxnet"
#define VBOXNETADP_MAX_NAME_LEN 32
typedef struct VBoxNetAdpReq
{
char szName[VBOXNETADP_MAX_NAME_LEN];
typedef VBOXNETADPREQ *PVBOXNETADPREQ;
#define VBOXADPCTL_IFCONFIG_PATH "/sbin/ifconfig"
#if defined(RT_OS_LINUX)
# define VBOXADPCTL_DEL_CMD "del"
# define VBOXADPCTL_ADD_CMD "add"
#elif defined(RT_OS_SOLARIS)
# define VBOXADPCTL_DEL_CMD "removeif"
# define VBOXADPCTL_ADD_CMD "addif"
#else
# define VBOXADPCTL_DEL_CMD "delete"
# define VBOXADPCTL_ADD_CMD "add"
#endif
static void showUsage(void)
{
}
{
const char * const argv[] =
{
pcszArg1, /* [address family] */
pcszArg2, /* address */
pcszArg3, /* ['netmask'] */
pcszArg4, /* [network mask] */
pcszArg5, /* [network mask] */
NULL /* terminator */
};
int rc = EXIT_SUCCESS;
switch (childPid)
{
case -1: /* Something went wrong. */
perror("fork() failed");
rc = EXIT_FAILURE;
break;
case 0: /* Child process. */
rc = EXIT_FAILURE;
break;
default: /* Parent process. */
break;
}
return rc;
}
#define MAX_ADDRESSES 128
#define MAX_ADDRLEN 64
static bool removeAddresses(char *pszAdapterName)
{
char szBuf[1024];
int rc;
int fds[2];
if (rc < 0)
return false;
if (pid < 0)
return false;
if (pid == 0)
{
/* child */
if (rc >= 0)
return false;
}
/* parent */
if (!fp)
return false;
int cAddrs;
{
/* We are concerned with IPv6 address lines only. */
continue;
#ifdef RT_OS_LINUX
/* Skip "addr:". */
continue;
#endif
/* Skip link-local addresses. */
continue;
}
for (int i = 0; i < cAddrs; i++)
{
return false;
}
return true;
}
{
if (fd == -1)
{
return ADPCTLERR_NO_CTL_DEV;
}
if (rc == -1)
{
}
return rc;
}
{
int iAdapterIndex = -1;
{
return ADPCTLERR_BAD_NAME;
}
{
return ADPCTLERR_BAD_NAME;
}
return 0;
}
{
char *pszAdapterName = NULL;
const char *pszAddress = NULL;
const char *pszNetworkMask = NULL;
int rc = EXIT_SUCCESS;
bool fRemove = false;
switch (argc)
{
case 5:
{
/* Add a netmask to existing interface */
{
showUsage();
return 1;
}
pszOption = "netmask";
break;
}
case 4:
{
/* Remove a single address from existing interface */
{
showUsage();
return 1;
}
fRemove = true;
break;
}
case 3:
{
#ifdef RT_OS_LINUX
{
/*
* This ugly hack is needed for retrieving the link speed on
* pre-2.6.33 kernels (see @bugref{6345}).
*/
{
showUsage();
return -1;
}
struct ethtool_cmd EthToolReq;
if (fd < 0)
{
"speed for %s: ", pszAdapterName);
perror("VBoxNetAdpCtl: failed to open control socket");
return ADPCTLERR_SOCKET_FAILED;
}
if (rc == 0)
{
}
else
{
"speed for %s: ", pszAdapterName);
perror("VBoxNetAdpCtl: ioctl failed");
}
return rc;
}
#endif
if (rc)
return rc;
{
/* Remove an existing interface */
#ifdef RT_OS_SOLARIS
return 1;
#else
#endif
}
{
/* Create an interface with given name */
#ifdef RT_OS_SOLARIS
return 1;
#else
if (rc == 0)
#endif
return rc;
}
break;
}
case 2:
{
/* Create a new interface */
{
#ifdef RT_OS_SOLARIS
return 1;
#else
if (rc == 0)
#endif
return rc;
}
/* Fall through */
}
default:
/* Fall through */
case 1:
showUsage();
return 1;
}
if (rc)
return rc;
if (fRemove)
{
else
{
#if defined(RT_OS_LINUX)
#else
#endif
#ifdef RT_OS_SOLARIS
/* On Solaris we can unplumb the ipv4 interface */
#endif
}
}
else
{
{
#ifdef RT_OS_SOLARIS
/* On Solaris we need to plumb the interface first if it's not already plumbed. */
#endif
/*
* Before we set IPv6 address we'd like to remove
* all previously assigned addresses except the
* self-assigned one.
*/
if (!removeAddresses(pszAdapterName))
rc = EXIT_FAILURE;
else
rc = executeIfconfig(pszAdapterName, "inet6", VBOXADPCTL_ADD_CMD, pszAddress, pszOption, pszNetworkMask);
}
else
{
#ifdef RT_OS_SOLARIS
/* On Solaris we need to plumb the interface first if it's not already plumbed. */
#endif
}
}
return rc;
}