6d73c66200a04223ae56a22ff221ec32193717a5vboxsync/* $Id$ */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync/** @file
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * VBoxNetPortForwardString - Routines for managing port-forward strings.
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync/*
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * Copyright (C) 2006-2013 Oracle Corporation
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync *
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * available from http://www.virtualbox.org. This file is free software;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * General Public License (GPL) as published by the Free Software
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync/*******************************************************************************
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync* Header Files *
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync*******************************************************************************/
a613d86b5c042651bc429cdaaa207503fdd31788vboxsync#ifndef RT_OS_WINDOWS
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <netinet/in.h>
a613d86b5c042651bc429cdaaa207503fdd31788vboxsync#else
a613d86b5c042651bc429cdaaa207503fdd31788vboxsync# include <Winsock2.h>
2050786855059bc194ff2314a212acb91f36a516vboxsync# include <Ws2ipdef.h>
a613d86b5c042651bc429cdaaa207503fdd31788vboxsync#endif
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/cdefs.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/cidr.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/param.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/path.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/stream.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/string.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/net.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/getopt.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <iprt/ctype.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include <VBox/log.h>
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#include "VBoxPortForwardString.h"
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#define PF_FIELD_SEPARATOR ':'
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#define PF_ADDRESS_FIELD_STARTS '['
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#define PF_ADDRESS_FIELD_ENDS ']'
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#define PF_STR_FIELD_SEPARATOR ":"
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#define PF_STR_ADDRESS_FIELD_STARTS "["
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync#define PF_STR_ADDRESS_FIELD_ENDS "]"
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsyncstatic int netPfStrAddressParse(char *pszRaw, int cbRaw,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync char *pszAddress, int cbAddress,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync bool fEmptyAcceptable)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync{
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int idxRaw = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int cbField = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pszRaw, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pszAddress, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(pszRaw[0] == PF_ADDRESS_FIELD_STARTS, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (pszRaw[0] == PF_ADDRESS_FIELD_STARTS)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync {
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* shift pszRaw to next symbol */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw++;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbRaw--;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* we shouldn't face with ending here */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(cbRaw > 0, VERR_INVALID_PARAMETER);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync char *pszEndOfAddress = RTStrStr(pszRaw, PF_STR_ADDRESS_FIELD_ENDS);
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* no pair closing sign */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pszEndOfAddress, VERR_INVALID_PARAMETER);
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbField = pszEndOfAddress - pszRaw;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* field should be less then the rest of the string */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(cbField < cbRaw, VERR_INVALID_PARAMETER);
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (cbField != 0)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync RTStrCopy(pszAddress, RT_MIN(cbField + 1, cbAddress), pszRaw);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync else if (!fEmptyAcceptable)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return -1;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync }
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(pszRaw[cbField] == PF_ADDRESS_FIELD_ENDS, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync return cbField + 2; /* length of the field and closing braces */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync}
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsyncstatic int netPfStrPortParse(char *pszRaw, int cbRaw, uint16_t *pu16Port)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync{
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync char *pszEndOfPort = NULL;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync uint16_t u16Port = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int idxRaw = 1; /* we increment pszRaw after checks. */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int cbRest = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync size_t cbPort = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pszRaw, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pu16Port, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(pszRaw[0] == PF_FIELD_SEPARATOR, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw++; /* skip line separator */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbRaw --;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszEndOfPort = RTStrStr(pszRaw, ":");
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (!pszEndOfPort)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync {
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbRest = strlen(pszRaw);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync Assert(cbRaw == cbRest);
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* XXX: Assumption that if string is too big, it will be reported by
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * RTStrToUint16.
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (cbRest > 0)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync {
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszEndOfPort = pszRaw + cbRest;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbPort = cbRest;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync }
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync else
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return -1;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync }
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync else
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbPort = pszEndOfPort - pszRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw += cbPort;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync Assert(cbRest || pszRaw[idxRaw - 1] == PF_FIELD_SEPARATOR); /* we are 1 char ahead */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
b47ede7e57e074b8986a68e28d984d17639b6cd2vboxsync char szPort[10];
b47ede7e57e074b8986a68e28d984d17639b6cd2vboxsync RT_ZERO(szPort);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync Assert(idxRaw > 0);
b47ede7e57e074b8986a68e28d984d17639b6cd2vboxsync RTStrCopy(szPort, RT_MIN(sizeof(szPort), (size_t)(cbPort) + 1), pszRaw);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
b47ede7e57e074b8986a68e28d984d17639b6cd2vboxsync if (!(u16Port = RTStrToUInt16(szPort)))
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return -1;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync *pu16Port = u16Port;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync}
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsyncstatic int netPfStrAddressPortPairParse(char *pszRaw, int cbRaw,
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync char *pszAddress, int cbAddress,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync bool fEmptyAddressAcceptable,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync uint16_t *pu16Port)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync{
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int idxRaw = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int idxRawTotal = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pszRaw, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pszAddress, -1);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pu16Port, -2);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* XXX: Here we should check 0 - ':' and 1 - '[' */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync Assert( pszRaw[0] == PF_FIELD_SEPARATOR
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync && pszRaw[1] == PF_ADDRESS_FIELD_STARTS);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw++; /* field separator skip */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbRaw--;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(cbRaw > 0, VERR_INVALID_PARAMETER);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (pszRaw[0] == PF_ADDRESS_FIELD_STARTS)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync {
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync idxRaw += netPfStrAddressParse(pszRaw,
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync cbRaw - idxRaw,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszAddress,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbAddress,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync fEmptyAddressAcceptable);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (idxRaw == -1)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return -1;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync Assert(pszRaw[idxRaw] == PF_FIELD_SEPARATOR);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync }
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync else return -1;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw += idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRawTotal += idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbRaw -= idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(cbRaw > 0, VERR_INVALID_PARAMETER);
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync Assert(pszRaw[0] == PF_FIELD_SEPARATOR);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (pszRaw[0] == PF_FIELD_SEPARATOR)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync {
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw = netPfStrPortParse(pszRaw, strlen(pszRaw), pu16Port);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync Assert(strlen(&pszRaw[idxRaw]) == 0 || pszRaw[idxRaw] == PF_FIELD_SEPARATOR);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (idxRaw == -1)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return -2;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRawTotal += idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return idxRawTotal + 1;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync }
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync else return -1; /* trailing garbage in the address */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync}
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync/* XXX: Having fIPv6 we might emprove adress verification comparing address length
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync * with INET[6]_ADDRLEN
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsyncint netPfStrToPf(const char *pcszStrPortForward, int fIPv6, PPORTFORWARDRULE pPfr)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync{
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync char *pszName;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int proto;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync char *pszHostAddr;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync char *pszGuestAddr;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync uint16_t u16HostPort;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync uint16_t u16GuestPort;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync bool fTcpProto = false;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync char *pszRawBegin = NULL;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync char *pszRaw = NULL;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int idxRaw = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int cbToken = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int cbRaw = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync int rc = VINF_SUCCESS;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pcszStrPortForward, VERR_INVALID_PARAMETER);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertPtrReturn(pPfr, VERR_INVALID_PARAMETER);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync memset(pPfr, 0, sizeof(PORTFORWARDRULE));
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
b47ede7e57e074b8986a68e28d984d17639b6cd2vboxsync pszHostAddr = &pPfr->szPfrHostAddr[0];
b47ede7e57e074b8986a68e28d984d17639b6cd2vboxsync pszGuestAddr = &pPfr->szPfrGuestAddr[0];
b47ede7e57e074b8986a68e28d984d17639b6cd2vboxsync pszName = &pPfr->szPfrName[0];
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync cbRaw = strlen(pcszStrPortForward);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* Minimal rule ":tcp:[]:0:[]:0" has got lenght 14 */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(cbRaw > 14, VERR_INVALID_PARAMETER);
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw = RTStrDup(pcszStrPortForward);
710471d588cfb61fa17fdbbd6a42ffd68e950f02vboxsync AssertReturn(pszRaw, VERR_NO_MEMORY);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRawBegin = pszRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* name */
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync if (pszRaw[idxRaw] == PF_FIELD_SEPARATOR)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw = 1; /* begin of the next segment */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync else
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync {
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync char *pszEndOfName = RTStrStr(pszRaw + 1, PF_STR_FIELD_SEPARATOR);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (!pszEndOfName)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync goto invalid_parameter;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbToken = (pszEndOfName) - pszRaw; /* don't take : into account */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* XXX it's unacceptable to have only name entry in PF */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(cbToken < cbRaw, VERR_INVALID_PARAMETER);
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if ( cbToken < 0
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync || (size_t)cbToken >= PF_NAMELEN)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync goto invalid_parameter;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync RTStrCopy(pszName,
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync RT_MIN((size_t)cbToken + 1, PF_NAMELEN),
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw += cbToken; /* move to separator */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync }
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync AssertReturn(pszRaw[0] == PF_FIELD_SEPARATOR, VERR_INVALID_PARAMETER);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* protocol */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw++; /* skip separator */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw = 0;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbRaw--;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
2fba578404ebd7269ef2eebc3209910b2dbceb3bvboxsync if ( ( (fTcpProto = (RTStrNICmp(pszRaw, "tcp", 3) == 0))
2fba578404ebd7269ef2eebc3209910b2dbceb3bvboxsync || RTStrNICmp(pszRaw, "udp", 3) == 0)
2fba578404ebd7269ef2eebc3209910b2dbceb3bvboxsync && pszRaw[3] == PF_FIELD_SEPARATOR)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync {
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync proto = (fTcpProto ? IPPROTO_TCP : IPPROTO_UDP);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw = 3;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync }
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync else
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync goto invalid_parameter;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw += idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbRaw -= idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw = 0;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszHostAddr, INET6_ADDRSTRLEN,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync true, &u16HostPort);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (idxRaw < 0)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return VERR_INVALID_PARAMETER;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszRaw += idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync cbRaw -= idxRaw;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync Assert(pszRaw[0] == PF_FIELD_SEPARATOR);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync idxRaw = 0;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync idxRaw = netPfStrAddressPortPairParse(pszRaw, cbRaw,
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync pszGuestAddr,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync INET6_ADDRSTRLEN,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync false,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync &u16GuestPort);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (idxRaw < 0)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync goto invalid_parameter;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync /* XXX: fill the rule */
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pPfr->fPfrIPv6 = fIPv6;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pPfr->iPfrProto = proto;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pPfr->u16PfrHostPort = u16HostPort;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
426e44b9204d6ba32d950854c588e624c750a7favboxsync if (*pszGuestAddr == '\0')
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync goto invalid_parameter; /* guest address should be defined */
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pPfr->u16PfrGuestPort = u16GuestPort;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync Log(("name: %s\n"
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync "proto: %d\n"
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync "host address: %s\n"
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync "host port: %d\n"
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync "guest address: %s\n"
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync "guest port:%d\n",
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszName, proto,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszHostAddr, u16HostPort,
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync pszGuestAddr, u16GuestPort));
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync RTStrFree(pszRawBegin);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return VINF_SUCCESS;
d5b5f09d8841828e647de9da5003fda55ca4cd5evboxsync
6d73c66200a04223ae56a22ff221ec32193717a5vboxsyncinvalid_parameter:
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync RTStrFree(pszRawBegin);
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync if (pPfr)
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync memset(pPfr, 0, sizeof(PORTFORWARDRULE));
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync return VERR_INVALID_PARAMETER;
6d73c66200a04223ae56a22ff221ec32193717a5vboxsync}