DevINIP.cpp revision e74eef731a813e4e06680c587a6759b9974b29c9
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/* $Id$ */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/** @file
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * DevINIP - Internal Network IP stack device/service.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Copyright (C) 2007-2009 Sun Microsystems, Inc.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * available from http://www.virtualbox.org. This file is free software;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * General Public License (GPL) as published by the Free Software
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * additional information or have any questions.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*******************************************************************************
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync* Header Files *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync*******************************************************************************/
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define LOG_GROUP LOG_GROUP_DEV_INIP
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/cdefs.h> /* include early to allow RT_C_DECLS_BEGIN hack */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/mem.h> /* include anything of ours that the lwip headers use. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/semaphore.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/thread.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/alloca.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/* All lwip header files are not C++ safe. So hack around this. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncRT_C_DECLS_BEGIN
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/sys.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/stats.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/mem.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/memp.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/pbuf.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/netif.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "ipv4/lwip/ip.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/udp.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/tcp.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/tcpip.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "lwip/sockets.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "netif/etharp.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncRT_C_DECLS_END
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <VBox/pdmdev.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <VBox/tm.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/assert.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/string.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include <iprt/uuid.h>
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#include "../Builtins.h"
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*******************************************************************************
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync* Macros and Defines *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync*******************************************************************************/
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/** Maximum frame size this device can handle. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define DEVINIP_MAX_FRAME 1514
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*******************************************************************************
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync* Structures and Typedefs *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync*******************************************************************************/
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Internal Network IP stack device instance data.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @implements PDMIBASE
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @implements PDMINETWORKPORT
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsynctypedef struct DEVINTNETIP
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** The base interface for LUN\#0. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMIBASE IBase;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** The network port this device provides (LUN\#0). */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMINETWORKPORT INetworkPort;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** The base interface of the network driver below us. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PPDMIBASE pDrvBase;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** The connector of the network driver below us. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PPDMINETWORKCONNECTOR pDrv;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Pointer to the device instance. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PPDMDEVINSR3 pDevIns;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** MAC adress. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTMAC MAC;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Static IP address of the interface. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync char *pszIP;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Netmask of the interface. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync char *pszNetmask;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Gateway for the interface. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync char *pszGateway;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** lwIP network interface description. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct netif IntNetIF;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** lwIP ARP timer. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PTMTIMERR3 ARPTimer;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** lwIP TCP fast timer. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PTMTIMERR3 TCPFastTimer;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** lwIP TCP slow timer. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PTMTIMERR3 TCPSlowTimer;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** lwIP semaphore to coordinate TCPIP init/terminate. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync sys_sem_t LWIPTcpInitSem;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** hack: get linking right. remove this eventually, once the device
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * provides a proper interface to all IP stack functions. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync const void *pLinkHack;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync} DEVINTNETIP, *PDEVINTNETIP;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*******************************************************************************
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync* Global Variables *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync*******************************************************************************/
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Pointer to the (only) instance data in this device.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic PDEVINTNETIP g_pDevINIPData = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * really ugly hack to avoid linking problems on unix style platforms
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * using .a libraries for now.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic const PFNRT g_pDevINILinkHack[] =
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync (PFNRT)lwip_socket,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync (PFNRT)lwip_close,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync (PFNRT)lwip_setsockopt,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync (PFNRT)lwip_recv,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync (PFNRT)lwip_send,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync (PFNRT)lwip_select
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync};
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*******************************************************************************
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync* Internal Functions *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync*******************************************************************************/
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void) devINIPARPTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void) devINIPTCPFastTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void) devINIPTCPSlowTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(err_t) devINIPOutput(struct netif *netif, struct pbuf *p,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct ip_addr *ipaddr);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(err_t) devINIPOutputRaw(struct netif *netif,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct pbuf *p);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(err_t) devINIPInterface(struct netif *netif);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * ARP cache timeout handling for lwIP.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pDevIns Device instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pTimer Pointer to timer.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void) devINIPARPTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_etharp_tmr();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTimerSetMillies(pThis->ARPTimer, ARP_TMR_INTERVAL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: return\n", __FUNCTION__));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * TCP fast timer handling for lwIP.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pDevIns Device instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pTimer Pointer to timer.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void) devINIPTCPFastTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_tcp_fasttmr();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTimerSetMillies(pThis->TCPFastTimer, TCP_FAST_INTERVAL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: return\n", __FUNCTION__));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync/**
9f22c692723a5d3cb78b91896c48cf681c4fb608vboxsync * TCP slow timer handling for lwIP.
83d61602c6968041692aa7203ee51c4085c7e460vboxsync *
83d61602c6968041692aa7203ee51c4085c7e460vboxsync * @param pDevIns Device instance.
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync * @param pTimer Pointer to timer.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
4f9276b4c85a4617d08094484cc1d983791bbb16vboxsyncstatic DECLCALLBACK(void) devINIPTCPSlowTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
83d61602c6968041692aa7203ee51c4085c7e460vboxsync PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_tcp_slowtmr();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTimerSetMillies(pThis->TCPSlowTimer, TCP_SLOW_INTERVAL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: return\n", __FUNCTION__));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Output a TCP/IP packet on the interface. Uses the generic lwIP ARP
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * code to resolve the address and call the link-level packet function.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns lwIP error code
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync * @param netif Interface on which to send IP packet.
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync * @param p Packet data.
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsync * @param ipaddr Destination IP address.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(err_t) devINIPOutput(struct netif *netif, struct pbuf *p,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct ip_addr *ipaddr)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync err_t lrc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: netif=%p p=%p ipaddr=%#04x\n", __FUNCTION__, netif, p,
9f22c692723a5d3cb78b91896c48cf681c4fb608vboxsync ipaddr->addr));
9f22c692723a5d3cb78b91896c48cf681c4fb608vboxsync lrc = lwip_etharp_output(netif, ipaddr, p);
9f22c692723a5d3cb78b91896c48cf681c4fb608vboxsync LogFlow(("%s: return %d\n", __FUNCTION__, lrc));
83d61602c6968041692aa7203ee51c4085c7e460vboxsync return lrc;
83d61602c6968041692aa7203ee51c4085c7e460vboxsync}
83d61602c6968041692aa7203ee51c4085c7e460vboxsync
83d61602c6968041692aa7203ee51c4085c7e460vboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Output a raw packet on the interface.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns lwIP error code
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param netif Interface on which to send frame.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param p Frame data.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(err_t) devINIPOutputRaw(struct netif *netif,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct pbuf *p)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
83d61602c6968041692aa7203ee51c4085c7e460vboxsync uint8_t aFrame[DEVINIP_MAX_FRAME], *pbBuf;
83d61602c6968041692aa7203ee51c4085c7e460vboxsync size_t cbBuf;
83d61602c6968041692aa7203ee51c4085c7e460vboxsync struct pbuf *q;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = VINF_SUCCESS;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: netif=%p p=%p\n", __FUNCTION__, netif, p));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(g_pDevINIPData);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(g_pDevINIPData->pDrv);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Silently ignore packets being sent while lwIP isn't set up. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!g_pDevINIPData)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#if ETH_PAD_SIZE
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pbBuf = &aFrame[0];
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync cbBuf = 0;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync for (q = p; q != NULL; q = q->next)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (cbBuf + q->len <= DEVINIP_MAX_FRAME)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync memcpy(pbBuf, q->payload, q->len);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pbBuf += q->len;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync cbBuf += q->len;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogRel(("INIP: exceeded frame size\n"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync break;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (cbBuf)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = g_pDevINIPData->pDrv->pfnSend(g_pDevINIPData->pDrv,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync &aFrame[0], cbBuf);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#if ETH_PAD_SIZE
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncout:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync err_t lrc = ERR_OK;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lrc = ERR_IF;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: return %d (vbox: %Rrc)\n", __FUNCTION__, rc, lrc));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return lrc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Implements the ethernet interface backend initialization for lwIP.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns lwIP error code
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param netif Interface to configure.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(err_t) devINIPInterface(struct netif *netif)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: netif=%p\n", __FUNCTION__, netif));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(g_pDevINIPData != NULL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync netif->state = g_pDevINIPData;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync netif->hwaddr_len = sizeof(g_pDevINIPData->MAC);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync memcpy(netif->hwaddr, &g_pDevINIPData->MAC, sizeof(g_pDevINIPData->MAC));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync netif->mtu = DEVINIP_MAX_FRAME;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync netif->flags = NETIF_FLAG_BROADCAST;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync netif->output = devINIPOutput;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync netif->linkoutput = devINIPOutputRaw;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_etharp_init();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTimerSetMillies(g_pDevINIPData->ARPTimer, ARP_TMR_INTERVAL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: success\n", __FUNCTION__));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return ERR_OK;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Wait until data can be received.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code. VINF_SUCCESS means there is at least one receive descriptor available.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pInterface PDM network port interface pointer.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param cMillies Number of milliseconds to wait. 0 means return immediately.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) devINIPWaitInputAvail(PPDMINETWORKPORT pInterface, RTMSINTERVAL cMillies)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: pInterface=%p\n", __FUNCTION__, pInterface));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: return VINF_SUCCESS\n", __FUNCTION__));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return VINF_SUCCESS;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Receive data and pass it to lwIP for processing.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pInterface PDM network port interface pointer.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pvBuf Pointer to frame data.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param cb Frame size.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) devINIPInput(PPDMINETWORKPORT pInterface,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync const void *pvBuf, size_t cb)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync const uint8_t *pbBuf = (const uint8_t *)pvBuf;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync size_t len = cb;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync const struct eth_hdr *ethhdr;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct pbuf *p, *q;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = VINF_SUCCESS;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: pInterface=%p pvBuf=%p cb=%lu\n", __FUNCTION__, pInterface,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pvBuf, cb));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(g_pDevINIPData);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Assert(g_pDevINIPData->pDrv);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Silently ignore packets being received while lwIP isn't set up. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!g_pDevINIPData)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#if ETH_PAD_SIZE
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* We allocate a pbuf chain of pbufs from the pool. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync p = lwip_pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (p != NULL)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#if ETH_PAD_SIZE
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync for (q = p; q != NULL; q = q->next)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Fill the buffers, and clean out unused buffer space. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync memcpy(q->payload, pbBuf, RT_MIN(cb, q->len));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pbBuf += RT_MIN(cb, q->len);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (q->len > cb)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync memset(((uint8_t *)q->payload) + cb, '\0', q->len - cb);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync cb -= RT_MIN(cb, q->len);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ethhdr = (const struct eth_hdr *)p->payload;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct netif *iface = &g_pDevINIPData->IntNetIF;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync err_t lrc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync switch (htons(ethhdr->type))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync case ETHTYPE_IP: /* IP packet */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_pbuf_header(p, -(ssize_t)sizeof(struct eth_hdr));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lrc = iface->input(p, iface);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (lrc)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VERR_NET_IO_ERROR;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync break;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync case ETHTYPE_ARP: /* ARP packet */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_etharp_arp_input(iface, (struct eth_addr *)iface->hwaddr, p);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync break;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync default:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_pbuf_free(p);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncout:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: return %Rrc\n", __FUNCTION__, rc));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Signals the end of lwIP TCPIP initialization.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param arg opaque argument, here the pointer to the semaphore.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void) devINIPTcpipInitDone(void *arg)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync sys_sem_t *sem = (sys_sem_t *)arg;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_sys_sem_signal(*sem);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/* -=-=-=-=- PDMIBASE -=-=-=-=- */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void *) devINIPQueryInterface(PPDMIBASE pInterface,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync const char *pszIID)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDEVINTNETIP pThis = RT_FROM_MEMBER(pInterface, DEVINTNETIP, IBase);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKPORT, &pThis->INetworkPort);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/* -=-=-=-=- PDMDEVREG -=-=-=-=- */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Destruct a device instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Most VM resources are freed by the VM. This callback is provided so that any non-VM
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * resources can be freed correctly.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pDevIns The device instance data.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) devINIPDestruct(PPDMDEVINS pDevIns)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDEVINTNETIP pThis = PDMINS_2_DATA(pDevIns, PDEVINTNETIP);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: pDevIns=%p\n", __FUNCTION__, pDevIns));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (g_pDevINIPData != NULL)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync netif_set_down(&pThis->IntNetIF);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync netif_remove(&pThis->IntNetIF);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync tcpip_terminate();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_sys_sem_wait(pThis->LWIPTcpInitSem);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_sys_sem_free(pThis->LWIPTcpInitSem);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pThis->pszIP)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync MMR3HeapFree(pThis->pszIP);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pThis->pszNetmask)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync MMR3HeapFree(pThis->pszNetmask);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pThis->pszGateway)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync MMR3HeapFree(pThis->pszGateway);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: success\n", __FUNCTION__));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return VINF_SUCCESS;
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync}
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync/**
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * Construct an internal networking IP stack device instance.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync *
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @returns VBox status.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @param pDevIns The device instance data.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * If the registration structure is needed, pDevIns->pDevReg points to it.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @param iInstance Instance number. Use this to figure out which registers
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * and such to use.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * he device number is also found in pDevIns->iInstance, but since it's
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * likely to be freqently used PDM passes it as parameter.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * of the device instance. It's also found in pDevIns->pCfgHandle, but like
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * iInstance it's expected to be used a bit in this function.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync */
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsyncstatic DECLCALLBACK(int) devINIPConstruct(PPDMDEVINS pDevIns, int iInstance,
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync PCFGMNODE pCfgHandle)
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync{
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync PDEVINTNETIP pThis = PDMINS_2_DATA(pDevIns, PDEVINTNETIP);
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync int rc = VINF_SUCCESS;
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync LogFlow(("%s: pDevIns=%p iInstance=%d pCfgHandle=%p\n", __FUNCTION__,
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync pDevIns, iInstance, pCfgHandle));
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync Assert(iInstance == 0);
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync /*
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * Validate the config.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync */
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync if (!CFGMR3AreValuesValid(pCfgHandle, "MAC\0IP\0Netmask\0Gateway\0"))
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync {
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync rc = PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync N_("Unknown Internal Networking IP configuration option"));
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync goto out;
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync }
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync /*
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * Init the static parts.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync */
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync pThis->pszIP = NULL;
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync pThis->pszNetmask = NULL;
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync pThis->pszGateway = NULL;
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync /* Pointer to device instance */
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync pThis->pDevIns = pDevIns;
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync /* IBase */
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync pThis->IBase.pfnQueryInterface = devINIPQueryInterface;
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync /* INetworkPort */
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync pThis->INetworkPort.pfnWaitReceiveAvail = devINIPWaitInputAvail;
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync pThis->INetworkPort.pfnReceive = devINIPInput;
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync /*
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * Get the configuration settings.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync */
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync rc = CFGMR3QueryBytes(pCfgHandle, "MAC", &pThis->MAC, sizeof(pThis->MAC));
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync if (rc == VERR_CFGM_NOT_BYTES)
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync {
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync char szMAC[64];
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync rc = CFGMR3QueryString(pCfgHandle, "MAC", &szMAC[0], sizeof(szMAC));
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync if (RT_SUCCESS(rc))
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync {
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync char *macStr = &szMAC[0];
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync char *pMac = (char *)&pThis->MAC;
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync for (uint32_t i = 0; i < 6; i++)
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync {
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync if ( !*macStr || !*(macStr + 1)
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync || *macStr == ':' || *(macStr + 1) == ':')
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync {
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync rc = PDMDEV_SET_ERROR(pDevIns,
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync N_("Configuration error: Invalid \"MAC\" value"));
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync goto out;
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync }
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync char c1 = *macStr++ - '0';
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync if (c1 > 9)
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync c1 -= 7;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync char c2 = *macStr++ - '0';
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (c2 > 9)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync c2 -= 7;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *pMac++ = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (i != 5 && *macStr == ':')
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync macStr++;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMDEV_SET_ERROR(pDevIns, rc,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Failed to get the \"MAC\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = CFGMR3QueryStringAlloc(pCfgHandle, "IP", &pThis->pszIP);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMDEV_SET_ERROR(pDevIns, rc,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Failed to get the \"IP\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = CFGMR3QueryStringAlloc(pCfgHandle, "Netmask", &pThis->pszNetmask);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMDEV_SET_ERROR(pDevIns, rc,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Failed to get the \"Netmask\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = CFGMR3QueryStringAlloc(pCfgHandle, "Gateway", &pThis->pszGateway);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VINF_SUCCESS;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMDEV_SET_ERROR(pDevIns, rc,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Failed to get the \"Gateway\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Attach driver and query the network connector interface.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync "Network Port");
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->pDrvBase = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->pDrv = NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKCONNECTOR);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!pThis->pDrv)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertMsgFailed(("Failed to obtain the PDMINETWORKCONNECTOR interface!\n"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VERR_PDM_MISSING_INTERFACE_BELOW;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct ip_addr ipaddr, netmask, gw;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct in_addr ip;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!inet_aton(pThis->pszIP, &ip))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Invalid \"IP\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync memcpy(&ipaddr, &ip, sizeof(ipaddr));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!inet_aton(pThis->pszNetmask, &ip))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Invalid \"Netmask\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync memcpy(&netmask, &ip, sizeof(netmask));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (pThis->pszGateway)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!inet_aton(pThis->pszGateway, &ip))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDEV_SET_ERROR(pDevIns,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Invalid \"Gateway\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync memcpy(&gw, &ip, sizeof(gw));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync else
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync inet_aton(pThis->pszIP, &ip);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync memcpy(&gw, &ip, sizeof(gw));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Initialize lwIP.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_stats_init();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_sys_init();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#if MEM_LIBC_MALLOC == 0
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_mem_init();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_memp_init();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_pbuf_init();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_netif_init();
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPARPTimer, pThis,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP ARP", &pThis->ARPTimer);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPTCPFastTimer, pThis,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP fast TCP", &pThis->TCPFastTimer);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTimerSetMillies(pThis->TCPFastTimer, TCP_FAST_INTERVAL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPTCPSlowTimer, pThis,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP slow TCP", &pThis->TCPSlowTimer);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (RT_FAILURE(rc))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync TMTimerSetMillies(pThis->TCPFastTimer, TCP_SLOW_INTERVAL);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->LWIPTcpInitSem = lwip_sys_sem_new(0);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_tcpip_init(devINIPTcpipInitDone, &pThis->LWIPTcpInitSem);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_sys_sem_wait(pThis->LWIPTcpInitSem);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /*
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Set up global pointer to interface data.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync g_pDevINIPData = pThis;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync struct netif *ret;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->IntNetIF.name[0] = 'I';
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->IntNetIF.name[1] = 'N';
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync ret = netif_add(&pThis->IntNetIF, &ipaddr, &netmask, &gw, NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync devINIPInterface, lwip_tcpip_input);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!ret)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = VERR_NET_NO_NETWORK;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync goto out;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync }
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_netif_set_default(&pThis->IntNetIF);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync lwip_netif_set_up(&pThis->IntNetIF);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* link hack */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pThis->pLinkHack = g_pDevINILinkHack;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncout:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("%s: return %Rrc\n", __FUNCTION__, rc));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return rc;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Query whether lwIP is initialized or not. Since there is only a single
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * instance of this device ever for a VM, it can be a global function.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns True if lwIP is initialized.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncbool DevINIPConfigured(void)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return g_pDevINIPData != NULL;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync}
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/**
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Internal network IP stack device registration record.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncconst PDMDEVREG g_DeviceINIP =
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync{
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* u32Version */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDM_DEVREG_VERSION,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* szDeviceName */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync "IntNetIP",
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* szRCMod/szR0Mod */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync "",
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync "",
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pszDescription */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync "Internal Network IP stack device",
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* fFlags */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDM_DEVREG_FLAGS_DEFAULT_BITS,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* fClass. As this is used by the storage devices, it must come earlier. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDM_DEVREG_CLASS_VMM_DEV,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* cMaxInstances */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync 1,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* cbInstance */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync sizeof(DEVINTNETIP),
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync /* pfnConstruct */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync devINIPConstruct,
728b52f802ac19865bd4aa8e9ade8f506a9e6c10vboxsync /* pfnDestruct */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync devINIPDestruct,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnRelocate */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnIOCtl */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnPowerOn */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnReset */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnSuspend */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnResume */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnAttach */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnDetach */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnQueryInterface */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnInitComplete */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnPowerOff */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* pfnSoftReset */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync NULL,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* u32VersionEnd */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDM_DEVREG_VERSION
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync};
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync