/* $Id$ */
/** @file
* NAT - debug helpers.
*/
/*
* Copyright (C) 2006-2012 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.
*/
/*
* This code is based on:
*
* Copyright (c) 1995 Danny Gasparovski.
* Portions copyright (c) 2000 Kelly Price.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#include <slirp.h>
#include <iprt/critsect.h>
#include "zone.h"
#ifdef DEBUG
void dump_packet(void *, int);
#endif
#ifndef STRINGIFY
# define STRINGIFY(x) #x
#endif
{
};
typedef struct DEBUGSTRSOCKETSTATE
{
const char *pcszSocketStateName;
#define DEBUGSTRSOCKETSTATE_HELPER(x) {(x), #x}
{
};
{
};
/*
* Dump a packet in the same format as tcpdump -x
*/
#ifdef DEBUG
void
{
}
#endif
#ifdef LOG_ENABLED
static void
{
}
void
{
lprint("\n");
lprint("IP stats:\n");
lprint(" %6d total packets received (%d were unaligned)\n",
}
void
{
lprint("\n");
lprint("TCP stats:\n");
lprint(" %6d data packets (%d bytes)\n",
lprint(" %6d data packets retransmitted (%d bytes)\n",
lprint(" %6d ack-only packets (%d delayed)\n",
lprint(" %6d acks (for %d bytes)\n",
lprint(" %6d packets received in sequence (%d bytes)\n",
lprint(" %6d completely duplicate packets (%d bytes)\n",
lprint(" %6d packets with some duplicate data (%d bytes duped)\n",
lprint(" %6d out-of-order packets (%d bytes)\n",
lprint(" %6d packets of data after window (%d bytes)\n",
lprint(" %6d discarded for bad header offset fields\n",
lprint(" %6d connections closed (including %d drop)\n",
lprint(" %6d segments we tried to get rtt (%d succeeded)\n",
lprint(" %6d connections dropped by rxmt timeout\n",
/* lprint(" Packets received too short: %d\n", tcpstat.tcps_rcvshort); */
/* lprint(" Segments dropped due to PAWS: %d\n", tcpstat.tcps_pawsdrop); */
}
void
{
lprint("\n");
lprint("UDP stats:\n");
}
void
{
lprint("\n");
lprint("ICMP stats:\n");
}
void
{
/*
* (vvl) this static code can't work with mbuf zone anymore
* @todo: make statistic correct
*/
}
void
{
size_t n;
lprint("\n");
"Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\n");
/* { */
n = RTStrPrintf(buff, sizeof(buff), "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
while (n < 17)
buff[n++] = ' ';
buff[17] = 0;
lprint("%s %3d %15s %5d ",
lprint("%15s %5d %5d %5d\n",
}
/* { */
while (n < 17)
buff[n++] = ' ';
buff[17] = 0;
lprint("%s %3d %15s %5d ",
lprint("%15s %5d %5d %5d\n",
}
}
#endif
static DECLCALLBACK(size_t)
void *pvUser)
{
"socket is null");
if (so->s == -1)
"socket(%d)", so->s);
"socket %d:(proto:%u) exp. in %d "
" state=%R[natsockstate]"
" fUnderPolling:%RTbool"
" fShouldBeRemoved:%RTbool"
" f_(addr:port)=%RTnaipv4:%d"
" l_(addr:port)=%RTnaipv4:%d",
if (so->s != -1)
{
int status;
if (status != 0)
{
" (getsockname failed)");
}
{
" (unexpected address family %d)",
}
else
{
" name=%RTnaipv4:%d",
}
}
return cb;
}
static DECLCALLBACK(size_t)
void *pvUser)
{
int idxNATState = 0;
bool fFirst = true;
{
{
if (fFirst)
{
cbReturn += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, g_apszSocketStates[idxNATState].pcszSocketStateName);
fFirst = false;
}
else
cbReturn += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "|%s", g_apszSocketStates[idxNATState].pcszSocketStateName);
}
}
if (!cbReturn)
return cbReturn;
}
/**
* Print callback dumping TCP Control Block in terms of RFC 793.
*/
static DECLCALLBACK(size_t)
void *pvUser)
{
if (tp)
{
cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "TCB793[ state:%R[tcpstate] SND(UNA: %x, NXT: %x, UP: %x, WND: %x, WL1:%x, WL2:%x, ISS:%x), ",
cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "RCV(WND: %x, NXT: %x, UP: %x, IRS:%x)]", tp->rcv_wnd, tp->rcv_nxt, tp->rcv_up, tp->irs);
}
else
{
}
return cb;
}
/*
* Prints TCP segment in terms of RFC 793.
*/
static DECLCALLBACK(size_t)
void *pvUser)
{
cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SEG[ACK: %x, SEQ: %x, LEN: %x, WND: %x, UP: %x]",
return cb;
}
/*
* Prints TCP state
*/
static DECLCALLBACK(size_t)
void *pvUser)
{
char *pszTcpStateName = (idxTcpState >= 0 && idxTcpState < TCP_NSTATES) ? g_apszTcpStates[idxTcpState] : "TCPS_INVALIDE_STATE";
return cb;
}
/*
* Prints TCP flags
*/
static DECLCALLBACK(size_t)
void *pvUser)
{
bool fSingleValue = true;
int idxTcpFlags = 0;
NULL,
0,
{
{
NULL,
0,
fSingleValue = false;
}
}
NULL,
0,
"]");
return cbPrint;
}
/*
* Prints sbuf state
*/
static DECLCALLBACK(size_t)
void *pvUser)
{
cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "[sbuf:%p cc:%d, datalen:%d, wprt:%p, rptr:%p data:%p]",
return cb;
}
/*
* Prints zone state
*/
static DECLCALLBACK(size_t)
void *pvUser)
{
if (!zone)
else
return cb;
}
/*
* Prints zone's item state
*/
static DECLCALLBACK(size_t)
void *pvUser)
{
if (!it)
else
return cb;
}
static DECLCALLBACK(size_t)
void *pvUser)
{
#ifdef RT_OS_WINDOWS
bool fDelim = false;
#endif
#ifdef RT_OS_WINDOWS
{ \
fDelim = true; \
}
#else
#endif
return cb;
}
#if 0
/*
* Debugging
*/
{
int err = WSAGetLastError();
return err;
}
#endif
int
{
int rc = VINF_SUCCESS;
static int g_fFormatRegistered;
if (!g_fFormatRegistered)
{
g_fFormatRegistered = 1;
}
return rc;
}