Initial upload of modified SLiRP

This commit is contained in:
waltje
2018-11-04 17:37:57 -05:00
commit b3dee48c9c
78 changed files with 20488 additions and 0 deletions

37
.gitattributes vendored Normal file
View File

@@ -0,0 +1,37 @@
#
# Set up for native EOL's with automatic conversion for text files.
#
# Autodetect text files
* text=auto
# Definitively text files.
*.txt text
*.md text
# Standard C source files.
*.c text
*.cc text
*.cpp text
*.h text
# UNIX makefiles.
makefile* text
Makefile* text
# MS Visual Studio diles.
*.mpp text
*.rc text
*.props text
*.vcxproj text
*.vcxproj.user text
*.vcxproj.filters text
*.sln text
# Binary files; ensure those won't be messed with.
*.ico binary
*.jpg binary
*.png binary
*.xpm binary
# End of file.

82
.travis-build.sh Normal file
View File

@@ -0,0 +1,82 @@
#!/bin/bash
#
# VARCem Virtual ARchaeological Computer EMulator.
# An emulator of (mostly) x86-based PC systems and devices,
# using the ISA,EISA,VLB,MCA and PCI system buses, roughly
# spanning the era between 1981 and 1995.
#
# This file is part of the VARCem Project.
#
# Build script for the Travis CI remote builder service.
#
# Version: @(#).travis-build.sh 1.0.4 2018/04/26
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
# Copyright 2018 Fred N. van Kempen.
#
# Redistribution and use in source and binary forms, with
# or without modification, are permitted provided that the
# following conditions are met:
#
# 1. Redistributions of source code must retain the entire
# above notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names
# of its contributors may be used to endorse or promote
# products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[ "x${DEBUG}" = "xy" ] && TARGET=debug
if [ "x${DEV_BUILD}" = "xy" ]; then
TARGET="win-${TRAVIS_BUILD_NUMBER}_dev-x86"
elif [ "x${DEBUG}" = "xy" ]; then
TARGET="win-${TRAVIS_BUILD_NUMBER}_debug-x86"
else
TARGET="win-${TRAVIS_BUILD_NUMBER}-x86"
fi
echo "Building VARCem, build #${TRAVIS_BUILD_NUMBER} target ${TARGET}"
cd src
# We only need the first few characters of the commit ID.
export COMMIT=${TRAVIS_COMMIT::7}
# Build the project.
make -f win/mingw/Makefile.MinGW BUILD=${TRAVIS_BUILD_NUMBER}
if [ $? != 0 ]; then
echo "Build failed, not uploading."
exit 1
fi
echo "Build #${TRAVIS_BUILD_NUMBER} OK, packing up."
zip -9 ../${TARGET}.zip *.exe
if [ $? != 0 ]; then
echo "ZIP failed, not uploading."
exit 1
fi
exit 0
# End of file.

86
.travis-deploy.sh Normal file
View File

@@ -0,0 +1,86 @@
#!/bin/bash
#
# VARCem Virtual ARchaeological Computer EMulator.
# An emulator of (mostly) x86-based PC systems and devices,
# using the ISA,EISA,VLB,MCA and PCI system buses, roughly
# spanning the era between 1981 and 1995.
#
# This file is part of the VARCem Project.
#
# Deployment script for the Travis CI remote builder service.
#
# Version: @(#).travis-deploy.sh 1.0.1 2018/11/04
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
# Copyright 2018 Fred N. van Kempen.
#
# Redistribution and use in source and binary forms, with
# or without modification, are permitted provided that the
# following conditions are met:
#
# 1. Redistributions of source code must retain the entire
# above notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names
# of its contributors may be used to endorse or promote
# products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Ignore the cron builds.
[ "x${TRAVIS_EVENT_TYPE}" = "xcron" ] && exit 0
[ "x${DEBUG}" = "xy" ] && TARGET=debug
if [ "x${DEBUG}" = "xy" ]; then
TARGET="slirp-win-${TRAVIS_BUILD_NUMBER}_debug-x86"
BTYPE=debug
else
TARGET="slirp-win-${TRAVIS_BUILD_NUMBER}-x86"
BTYPE=regular
fi
if [ ! -f ${TARGET}.zip ]; then
echo "Target file ${TARGET}.zip not found, giving up."
exit 1
fi
# We only need the first few characters of the commit ID.
export COMMIT=${TRAVIS_COMMIT::7}
echo "Uploading SLiRP build #${TRAVIS_BUILD_NUMBER} target ${TARGET}"
curl -# -X POST \
-F "type=${BTYPE}" \
-F "build=${TRAVIS_BUILD_NUMBER}" \
-F "id=${COMMIT}" \
-F "notes=not available" \
-F "file_name=@${TARGET}.zip" \
${SITE_URL}
if [ $? != 0 ]; then
echo Upload failed.
exit 1
fi
exit 0
# End of file.

91
.travis.yml Normal file
View File

@@ -0,0 +1,91 @@
#
# VARCem Virtual ARchaeological Computer EMulator.
# An emulator of (mostly) x86-based PC systems and devices,
# using the ISA,EISA,VLB,MCA and PCI system buses, roughly
# spanning the era between 1981 and 1995.
#
# This file is part of the VARCem Project.
#
# Project file for the Travis CI remote builder service.
#
# Version: @(#).travis.yml 1.0.1 2018/11/04
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
# Copyright 2018 Fred N. van Kempen.
#
# Redistribution and use in source and binary forms, with
# or without modification, are permitted provided that the
# following conditions are met:
#
# 1. Redistributions of source code must retain the entire
# above notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names
# of its contributors may be used to endorse or promote
# products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sudo: required
dist: trusty
language: c
env:
global:
- MAKEFLAGS="-j 4"
matrix:
- PROG=libslirp CROSS=y DEBUG=n
- PROG=libslirp CROSS=y DEBUG=y
before_install:
script:
- chmod +x .travis-build.sh .travis-deploy.sh
- ./.travis-build.sh
addons:
apt:
packages:
- binutils-mingw-w64-i686
- gcc-mingw-w64-i686
- binutils-mingw-w64-x86-64
- gcc-mingw-w64-x86-64
- gcc-mingw-w64
- mingw-w64
notifications:
irc:
channels:
- "chat.freenode.net#varcem-dev"
- "chat.freenode.net#varcem"
template:
- "Build #%{build_number} for #%{commit} by %{author} in %{branch} %{result}."
- "Commit changes: %{commit_subject}"
- "Build details on %{build_url}"
# - "Details on %{build_url}, changes on %{compare_url}"
after_success:
- ./.travis-deploy.sh
# End of file.

61
COPYRIGHT.txt Normal file
View File

@@ -0,0 +1,61 @@
Slirp was written by Danny Gasparovski.
Copyright (c), 1995,1996 All Rights Reserved.
Slirp is maintained by Kelly Price <tygris+slirp@erols.com>
Slirp is free software; "free" as in you don't have to pay for it, and you
are free to do whatever you want with it. I do not accept any donations,
monetary or otherwise, for Slirp. Instead, I would ask you to pass this
potential donation to your favorite charity. In fact, I encourage
*everyone* who finds Slirp useful to make a small donation to their
favorite charity (for example, GreenPeace). This is not a requirement, but
a suggestion from someone who highly values the service they provide.
The copyright terms and conditions:
---BEGIN---
Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
DANNY GASPAROVSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---END---
This basically means you can do anything you want with the software, except
1) call it your own, and 2) claim warranty on it. There is no warranty for
this software. None. Nada. If you lose a million dollars while using
Slirp, that's your loss not mine. So, ***USE AT YOUR OWN RISK!***.
If these conditions cannot be met due to legal restrictions (E.g. where it
is against the law to give out Software without warranty), you must cease
using the software and delete all copies you have.
Slirp uses code that is copyrighted by the following people/organizations:
Juha Pirkola.
Gregory M. Christy.
The Regents of the University of California.
Carnegie Mellon University.
The Australian National University.
RSA Data Security, Inc.
Please read the top of each source file for the details on the various
copyrights.

44
README.md Normal file
View File

@@ -0,0 +1,44 @@
Welcome to **VARCem**, the Virtual Archaeological Computer EMulator.
This is the SLiRP Host Gateway module for VARCem. It is based on a much-
hacked variant of SLiRP, initially modified for use with the PCem emulator
by neozeed.
As an external module, it can be used as needed. Configuration is handled
by the calling application (VARCem), and multiple instances can be run at
the same time.
The SLiRP module can be considered a simple, virtual in-application IP
router with PAT (Port Address Translation) capabilities. Its "internal" leg
talks to the emulated network cards within the emulator, and the "external"
side use the host system's network stack to connect to the outside world,
using the host's IP address and translating back to the internal side.
Community and Support
---------------------
Information, downloads, additional modules and such can be found on our
[Website](http://www.varcem.com/). Live support and general help can
also be found on our [IRC channel](https://kiwiirc.com/client/irc.freenode.net/?nick=VARCem_Guest|?#VARCem)
LEGAL
-----
"This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
It's free, it comes with all the sources, but it does not come with
any warranty whatsoever. You probably should not use this software to run
a business-critical piece of (old) software at work, for example.
If there is a problem with the software, please open up a GIT issue so we
can work on it, and/or talk to us on the IRC channel. We cannot promise a
fix, but will try the best we can !
BUILD STATUS
------------
The auto-builds handled by Travis-CI are [![Build Status](https://travis-ci.org/VARCem/SLiRP.svg?branch=master)](https://travis-ci.org/VARCem/SLiRP)
Last Updated: 11/04/2018

0
git Normal file
View File

75
src/arp.c Normal file
View File

@@ -0,0 +1,75 @@
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "mbuf.h"
#include "if.h"
#include "arp.h"
void
arp_input(const uint8_t *pkt, int pkt_len)
{
uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
struct ethhdr *eh = (struct ethhdr *)pkt;
struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
struct ethhdr *reh = (struct ethhdr *)arp_reply;
struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
#ifdef USE_REDIR
struct ex_list *ex_ptr;
#endif
int ar_op;
ar_op = ntohs(ah->ar_op);
switch (ar_op) {
case ARPOP_REQUEST:
if (! memcmp(ah->ar_tip, &special_addr, 3)) {
if (ah->ar_tip[3] == CTL_ROUTER ||
ah->ar_tip[3] == CTL_SERVER)
goto arp_ok;
#ifdef USE_REDIR
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if (ex_ptr->ex_addr == ah->ar_tip[3])
goto arp_ok;
}
#endif
return;
arp_ok:
/* XXX: make an ARP request for the client address */
memcpy(client_macaddr, eh->h_source, ETH_ALEN);
/* ARP request for alias/dns mac address */
memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
memcpy(reh->h_source, special_macaddr, ETH_ALEN - 1);
reh->h_source[5] = ah->ar_tip[3];
reh->h_proto = htons(ETH_P_ARP);
rah->ar_hrd = htons(1);
rah->ar_pro = htons(ETH_P_IP);
rah->ar_hln = ETH_ALEN;
rah->ar_pln = 4;
rah->ar_op = htons(ARPOP_REPLY);
memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
memcpy(rah->ar_sip, ah->ar_tip, 4);
memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
memcpy(rah->ar_tip, ah->ar_sip, 4);
slirp_output(arp_reply, sizeof(arp_reply));
}
break;
default:
break;
}
}

42
src/arp.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef SLIRP_ARP_H
# define SLIRP_ARP_H
#define ETH_ALEN 6
#define ETH_HLEN 14
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
#define ETH_P_ARP 0x0806 /* Address Resolution packet */
#define ARPOP_REQUEST 1 /* ARP request */
#define ARPOP_REPLY 2 /* ARP reply */
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned short h_proto; /* packet type ID field */
};
struct arphdr {
unsigned short ar_hrd; /* format of hardware address */
unsigned short ar_pro; /* format of protocol address */
unsigned char ar_hln; /* length of hardware address */
unsigned char ar_pln; /* length of protocol address */
unsigned short ar_op; /* ARP opcode (command) */
/*
* Ethernet looks like this : This bit is variable sized however...
*/
unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
unsigned char ar_sip[4]; /* sender IP address */
unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
unsigned char ar_tip[4]; /* target IP address */
};
extern void arp_input(const uint8_t *pkt, int pkt_len);
#endif /*SLIRP_ARP_H*/

359
src/bootp.c Normal file
View File

@@ -0,0 +1,359 @@
/*
* QEMU BOOTP/DHCP server
*
* Copyright (c) 2004 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "mbuf.h"
#include "if.h"
#include "arp.h"
#include "ip.h"
#include "udp.h"
#include "bootp.h"
#define NB_ADDR 16
#define START_ADDR 100
#define LEASE_TIME (24 * 3600)
typedef struct {
uint8_t allocated;
uint8_t macaddr[ETH_ALEN];
} BOOTPClient;
static BOOTPClient clients[NB_ADDR];
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
static char *
pr_mac(const uint8_t *mac)
{
static char buff[20];
sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return(buff);
}
static BOOTPClient *
get_new_addr(const struct in_addr *ciaddr, struct in_addr *paddr)
{
BOOTPClient *bc;
int i;
for (i = 0; i < NB_ADDR; i++) {
bc = &clients[i];
if (! bc->allocated) {
bc->allocated = 1;
paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
return bc;
}
}
return NULL;
}
static BOOTPClient *
find_addr(struct in_addr *paddr, const uint8_t *macaddr)
{
BOOTPClient *bc;
int i;
for (i = 0; i < NB_ADDR; i++) {
bc = &clients[i];
if (! memcmp(macaddr, bc->macaddr, 6)) {
bc = &clients[i];
bc->allocated = 1;
paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
return bc;
}
}
return NULL;
}
static int
dhcp_decode(const uint8_t *buf, int size)
{
const uint8_t *p, *p_end;
int msg_type, len, tag;
msg_type = 0;
p = buf;
p_end = buf + size;
if (size < 5)
return(msg_type);
if (memcmp(p, rfc1533_cookie, 4) != 0)
return(msg_type);
p += 4;
while (p < p_end) {
tag = p[0];
if (tag == RFC1533_PAD) {
p++;
} else if (tag == RFC1533_END) {
break;
} else {
p++;
if (p >= p_end)
break;
len = *p++;
switch(tag) {
case RFC2132_MSG_TYPE:
if (len >= 1)
msg_type = p[0];
break;
default:
break;
}
p += len;
}
}
return msg_type;
}
static void
bootp_reply(struct bootp_t *bp)
{
BOOTPClient *bc;
struct SLIRPmbuf *m;
struct bootp_t *rbp;
struct sockaddr_in addr, saddr, daddr;
struct in_addr xaddr;
int msg_type, val;
uint8_t *q;
/* Decode the Vendor area to guesstimate the protocol and message type. */
msg_type = dhcp_decode(bp->bp_vend, DHCP_OPT_LEN);
if (msg_type == 0) {
/* Force reply for old BOOTP clients */
msg_type = BOOTPREQUEST;
lprint("BOOTP: BOOTP REQUEST from %s\n", pr_mac(bp->bp_hwaddr));
} else if (msg_type == DHCPDISCOVER) {
lprint("BOOTP: DHCP DISCOVER from %s\n", pr_mac(bp->bp_hwaddr));
} else if (msg_type == DHCPREQUEST) {
lprint("BOOTP: DHCP REQUEST from %s\n", pr_mac(bp->bp_hwaddr));
} else {
lprint("BOOTP: invalid message %d from %s\n", pr_mac(bp->bp_hwaddr));
return;
}
/* Make sure we support this topology. */
if (bp->bp_htype != 1 || bp->bp_hlen != ETH_ALEN) {
lprint("BOOTP: unsupported topology %d or hlen %d from %s\n",
bp->bp_htype, bp->bp_hlen, pr_mac(bp->bp_hwaddr));
return;
}
/* Save the client MAC address. */
memcpy(client_macaddr, bp->bp_hwaddr, bp->bp_hlen);
/* Reset client IP address. */
memset(&addr, 0x00, sizeof(addr));
addr.sin_port = htons(BOOTP_CLIENT);
/* Create return packet. */
if ((m = m_get()) == NULL) {
lprint("BOOTP: out of memory for reply to %s\n",
pr_mac(bp->bp_hwaddr));
return;
}
m->m_data += if_maxlinkhdr;
rbp = (struct bootp_t *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
memset(rbp, 0x00, sizeof(struct bootp_t));
switch(msg_type) {
case BOOTPREQUEST:
/*
* If client already has an address, see if we can
* re-assign that to it. Otherwise, allocate a new
* address for the client.
*/
bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
if (! bc)
bc = get_new_addr(&bp->bp_ciaddr, &daddr.sin_addr);
if (! bc) {
lprint("BOOTP: out of slots for %s\n",
pr_mac(bp->bp_hwaddr));
return;
}
memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen);
addr.sin_addr.s_addr = 0xffffffff;
break;
case DHCPDISCOVER:
new_addr:
bc = get_new_addr(&bp->bp_ciaddr, &daddr.sin_addr);
if (! bc) {
lprint("DHCP: out of slots for %s\n",
pr_mac(bp->bp_hwaddr));
return;
}
memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen);
break;
default:
/* Find the client's MAC address. */
bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
if (! bc) {
/*
* If client not found, could be a Windows
* machine trying to keep its current (but
* expired) address. FIXME: wrong!! --FvK
*/
goto new_addr;
}
break;
}
/* Set up my IP address. */
saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_SERVER);
saddr.sin_port = htons(BOOTP_SERVER);
/* Target address is either broadcast, or the client IP address. */
if (addr.sin_addr.s_addr == 0)
addr.sin_addr.s_addr = daddr.sin_addr.s_addr;
/* Set up the reply packet. */
rbp->bp_op = BOOTP_REPLY;
rbp->bp_xid = bp->bp_xid;
rbp->bp_htype = bp->bp_htype;
rbp->bp_hlen = bp->bp_hlen;
memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, bp->bp_hlen);
rbp->bp_ciaddr = bp->bp_ciaddr; /* client current IP address */
rbp->bp_yiaddr = daddr.sin_addr; /* client new IP address */
rbp->bp_siaddr = saddr.sin_addr; /* server IP address */
/* Set up the RFC1533 cookie to indicate standard Vendor Extensions. */
q = rbp->bp_vend;
memcpy(q, rfc1533_cookie, 4);
q += 4;
if (msg_type == DHCPDISCOVER) {
*q++ = RFC2132_MSG_TYPE;
*q++ = 1;
*q++ = DHCPOFFER;
}
if (msg_type == DHCPREQUEST) {
*q++ = RFC2132_MSG_TYPE;
*q++ = 1;
*q++ = DHCPACK;
}
if (msg_type == DHCPDISCOVER || msg_type == DHCPREQUEST) {
*q++ = RFC2132_SRV_ID;
*q++ = 4;
memcpy(q, &saddr.sin_addr, 4);
q += 4;
*q++ = RFC2132_LEASE_TIME;
*q++ = 4;
val = htonl(LEASE_TIME);
memcpy(q, &val, 4);
q += 4;
}
if (msg_type == BOOTPREQUEST || msg_type == DHCPDISCOVER || msg_type == DHCPREQUEST) {
*q++ = RFC1533_NETMASK;
*q++ = 4;
*q++ = 0xff; /* FIXME: wrong, but works for now --FvK */
*q++ = 0xff;
*q++ = 0xff;
*q++ = 0x00;
*q++ = RFC1533_GATEWAY;
*q++ = 4;
xaddr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ROUTER);
memcpy(q, &xaddr, 4);
q += 4;
*q++ = RFC1533_DNS;
*q++ = 4;
xaddr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_SERVER);
memcpy(q, &xaddr, 4);
q += 4;
if (slirp_hostname[0]) {
val = strlen(slirp_hostname);
*q++ = RFC1533_HOSTNAME;
*q++ = val;
memcpy(q, slirp_hostname, val);
q += val;
}
/* End of option list. */
*q++ = RFC1533_END;
}
m->m_len = sizeof(struct bootp_t) -
sizeof(struct ip) - sizeof(struct udphdr);
lprint("BOOTP: sending reply=%d to %s\n", m->m_len, inet_ntoa(addr.sin_addr));
udp_output2(NULL, m, &saddr, &addr, IPTOS_LOWDELAY);
}
void
bootp_input(struct SLIRPmbuf *m)
{
struct bootp_t *bp = mtod(m, struct bootp_t *);
switch(bp->bp_op) {
case BOOTP_REQUEST:
bootp_reply(bp);
break;
default:
lprint("BOOTP: invalid opcode %d (ignored)\n", bp->bp_op);
break;
}
}

122
src/bootp.h Normal file
View File

@@ -0,0 +1,122 @@
/* bootp/dhcp defines */
#define BOOTP_SERVER 67
#define BOOTP_CLIENT 68
#define BOOTP_REQUEST 1
#define BOOTP_REPLY 2
#define RFC1533_COOKIE 99, 130, 83, 99
#define RFC1533_PAD 0
#define RFC1533_NETMASK 1
#define RFC1533_TIMEOFFSET 2
#define RFC1533_GATEWAY 3
#define RFC1533_TIMESERVER 4
#define RFC1533_IEN116NS 5
#define RFC1533_DNS 6
#define RFC1533_LOGSERVER 7
#define RFC1533_COOKIESERVER 8
#define RFC1533_LPRSERVER 9
#define RFC1533_IMPRESSSERVER 10
#define RFC1533_RESOURCESERVER 11
#define RFC1533_HOSTNAME 12
#define RFC1533_BOOTFILESIZE 13
#define RFC1533_MERITDUMPFILE 14
#define RFC1533_DOMAINNAME 15
#define RFC1533_SWAPSERVER 16
#define RFC1533_ROOTPATH 17
#define RFC1533_EXTENSIONPATH 18
#define RFC1533_IPFORWARDING 19
#define RFC1533_IPSOURCEROUTING 20
#define RFC1533_IPPOLICYFILTER 21
#define RFC1533_IPMAXREASSEMBLY 22
#define RFC1533_IPTTL 23
#define RFC1533_IPMTU 24
#define RFC1533_IPMTUPLATEAU 25
#define RFC1533_INTMTU 26
#define RFC1533_INTLOCALSUBNETS 27
#define RFC1533_INTBROADCAST 28
#define RFC1533_INTICMPDISCOVER 29
#define RFC1533_INTICMPRESPOND 30
#define RFC1533_INTROUTEDISCOVER 31
#define RFC1533_INTROUTESOLICIT 32
#define RFC1533_INTSTATICROUTES 33
#define RFC1533_LLTRAILERENCAP 34
#define RFC1533_LLARPCACHETMO 35
#define RFC1533_LLETHERNETENCAP 36
#define RFC1533_TCPTTL 37
#define RFC1533_TCPKEEPALIVETMO 38
#define RFC1533_TCPKEEPALIVEGB 39
#define RFC1533_NISDOMAIN 40
#define RFC1533_NISSERVER 41
#define RFC1533_NTPSERVER 42
#define RFC1533_VENDOR 43
#define RFC1533_NBNS 44
#define RFC1533_NBDD 45
#define RFC1533_NBNT 46
#define RFC1533_NBSCOPE 47
#define RFC1533_XFS 48
#define RFC1533_XDM 49
#define RFC2132_REQ_ADDR 50
#define RFC2132_LEASE_TIME 51
#define RFC2132_MSG_TYPE 53
#define RFC2132_SRV_ID 54
#define RFC2132_PARAM_LIST 55
#define RFC2132_MAX_SIZE 57
#define RFC2132_RENEWAL_TIME 58
#define RFC2132_REBIND_TIME 59
#define BOOTPREQUEST 0
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPACK 5
#define RFC1533_VENDOR_MAJOR 0
#define RFC1533_VENDOR_MINOR 0
#define RFC1533_VENDOR_MAGIC 128
#define RFC1533_VENDOR_ADDPARM 129
#define RFC1533_VENDOR_ETHDEV 130
#define RFC1533_VENDOR_HOWTO 132
#define RFC1533_VENDOR_MNUOPTS 160
#define RFC1533_VENDOR_SELECTION 176
#define RFC1533_VENDOR_MOTD 184
#define RFC1533_VENDOR_NUMOFMOTD 8
#define RFC1533_VENDOR_IMG 192
#define RFC1533_VENDOR_NUMOFIMG 16
#define RFC1533_END 255
#define BOOTP_VENDOR_LEN 64
#define DHCP_OPT_LEN 312
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct bootp_t {
struct ip ip;
struct udphdr udp;
uint8_t bp_op;
uint8_t bp_htype;
uint8_t bp_hlen;
uint8_t bp_hops;
uint32_t bp_xid;
uint16_t bp_secs;
uint16_t unused;
struct in_addr bp_ciaddr;
struct in_addr bp_yiaddr;
struct in_addr bp_siaddr;
struct in_addr bp_giaddr;
uint8_t bp_hwaddr[16];
uint8_t bp_sname[64];
uint8_t bp_file[128];
uint8_t bp_vend[DHCP_OPT_LEN];
} PACKED__;
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_END)
#endif
void bootp_input(struct SLIRPmbuf *m);

145
src/cksum.c Normal file
View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 1988, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
* in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "mbuf.h"
/*
* Checksum routine for Internet Protocol family headers (Portable Version).
*
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
*
* XXX Since we will never span more than 1 SLIRPmbuf, we can optimise this
*/
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
int cksum(struct SLIRPmbuf *m, int len)
{
register uint16_t *w;
register int sum = 0;
register int mlen = 0;
int byte_swapped = 0;
union {
uint8_t c[2];
uint16_t s;
} s_util;
union {
uint16_t s[2];
uint32_t l;
} l_util;
if (m->m_len == 0)
goto cont;
w = mtod(m, uint16_t *);
mlen = m->m_len;
if (len < mlen)
mlen = len;
len -= mlen;
/*
* Force to even boundary.
*/
if ((1 & (intptr_t) w) && (mlen > 0)) {
REDUCE;
sum <<= 8;
s_util.c[0] = *(uint8_t *)w;
w = (uint16_t *)((int8_t *)w + 1);
mlen--;
byte_swapped = 1;
}
/*
* Unroll the loop to make overhead from
* branches &c small.
*/
while ((mlen -= 32) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
w += 16;
}
mlen += 32;
while ((mlen -= 8) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
w += 4;
}
mlen += 8;
if (mlen == 0 && byte_swapped == 0)
goto cont;
REDUCE;
while ((mlen -= 2) >= 0) {
sum += *w++;
}
if (byte_swapped) {
REDUCE;
sum <<= 8;
byte_swapped = 0;
if (mlen == -1) {
s_util.c[1] = *(uint8_t *)w;
sum += s_util.s;
mlen = 0;
} else
mlen = -1;
} else if (mlen == -1)
s_util.c[0] = *(uint8_t *)w;
cont:
#ifdef _DEBUG
if (len) {
DEBUG_ERROR((dfd, "cksum: out of data\n"));
DEBUG_ERROR((dfd, " len = %d\n", len));
}
#endif
if (mlen == -1) {
/* The last SLIRPmbuf has odd # of bytes. Follow the
standard (the odd byte may be shifted left by 8 bits
or not as determined by endian-ness of the machine) */
s_util.c[1] = 0;
sum += s_util.s;
}
REDUCE;
return (~sum & 0xffff);
}

71
src/config.h Normal file
View File

@@ -0,0 +1,71 @@
/* Define to sizeof(char *) */
#ifdef SIZEOF_VOID_P
# define SIZEOF_CHAR_P SIZEOF_VOID_P
#else
# define SIZEOF_CHAR_P 8 /*FIXME: sizeof() does not work in cpp!*/
#endif
#define HAVE_MEMMOVE /* Define if you have memmove() */
#define HAVE_STRERROR /* Define if you have strerror() */
#ifdef _WIN32
# define DECLARE_IOVEC
typedef unsigned int u_int;
typedef char *SLIRPcaddr_t;
typedef int socklen_t;
typedef unsigned long ioctlsockopt_t;
# define USE_FIONBIO 1
# ifndef EWOULDBLOCK
# define EWOULDBLOCK WSAEWOULDBLOCK
# endif
# ifndef EINPROGRESS
# define EINPROGRESS WSAEINPROGRESS
# endif
# ifndef ENOTCONN
# define ENOTCONN WSAENOTCONN
# endif
# ifndef EHOSTUNREACH
# define EHOSTUNREACH WSAEHOSTUNREACH
# endif
# ifndef ENETUNREACH
# define ENETUNREACH WSAENETUNREACH
# endif
# ifndef ECONNREFUSED
# define ECONNREFUSED WSAECONNREFUSED
# endif
# define udp_read_completion slirp_udp_read_completion
# define write_udp slirp_write_udp
# define init_udp slirp_init_udp
# define final_udp slirp_final_udp
#else
# define HAVE_INET_ATON
typedef char *SLIRPcaddr_t;
typedef int ioctlsockopt_t;
# define ioctlsocket ioctl
# define closesocket(s) close(s)
# define O_BINARY 0
#endif
#ifndef HAVE_MEMMOVE
# define memmove(x, y, z) bcopy(y, x, z)
#endif
#ifdef GETTIMEOFDAY_ONE_ARG
# define gettimeofday(x, y) gettimeofday(x)
#endif
#if defined(__GNUC__)
#define PACKED__ __attribute__ ((packed))
#elif defined(__sgi)
#define PRAGMA_PACK_SUPPORTED 1
#define PACK_END 0
#define PACKED__
#elif defined(_MSC_VER)
#define PACKED__
#else
#error "Packed attribute or pragma shall be supported"
#endif

90
src/debug.c Normal file
View File

@@ -0,0 +1,90 @@
/*
* 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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "slirp.h"
#include "debug.h" // merge with slirp.h
static log_func_t log_func = NULL;
FILE *dfd = NULL;
#ifdef _DEBUG
int dostats = 1;
#else
int dostats = 0;
#endif
int dbglvl = 0;
void
debug_init(char *file, int dbg)
{
/* Close the old debugging file */
if (dfd)
fclose(dfd);
/* Reset logger function. */
log_func = NULL;
dfd = fopen(file, "w");
if (dfd != NULL) {
dbglvl = dbg;
fprintf(dfd, "Debugging Started level %i.\n", dbglvl);
fflush(dfd);
}
}
void
lprint(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (log_func != NULL)
(*log_func)(NULL, fmt, args);
va_end(args);
}
/* Dump a packet in the same format as tcpdump -x */
#ifdef _DEBUG
void
dump_packet(void *dat, int n)
{
u_char *pptr = (u_char *)dat;
int j, k;
n /= 16;
n++;
DEBUG_MISC((dfd, "PACKET DUMPED:\n"));
for (j = 0; j < n; j++) {
for(k = 0; k < 6; k++)
DEBUG_MISC((dfd, "%02x ", *pptr++));
DEBUG_MISC((dfd, "\n"));
fflush(dfd);
}
}
#endif
/* API: set logging output function to caller. */
void
slirp_debug(log_func_t func)
{
log_func = func;
/* Feedback to indicate logging is set up. */
lprint("SLiRP: debug level %i\n", dbglvl);
}

70
src/debug.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifndef DEBUG_H
# define DEBUG_H
#define DBG_CALL 0x01
#define DBG_MISC 0x02
#define DBG_ERROR 0x04
#define DEBUG_DEFAULT DBG_CALL|DBG_MISC|DBG_ERROR
#ifdef _DEBUG
# define DEBUG_CALL(x) \
if (dbglvl & DBG_CALL) { \
fprintf(dfd, "%s...\n", x); \
fflush(dfd); \
}
# define DEBUG_ARG(x, y) \
if (dbglvl & DBG_CALL) { \
fputc(' ', dfd); \
fprintf(dfd, x, y); \
fputc('\n', dfd); \
fflush(dfd); \
}
# define DEBUG_ARGS(x) \
if (dbglvl & DBG_CALL) { \
fprintf x ; \
fflush(dfd); \
}
# define DEBUG_MISC(x) \
if (dbglvl & DBG_MISC) { \
fprintf x ; \
fflush(dfd); \
}
# define DEBUG_ERROR(x) \
if (dbglvl & DBG_ERROR) { \
fprintf x ; \
fflush(dfd); \
}
#else
# define DEBUG_CALL(x)
# define DEBUG_ARG(x, y)
# define DEBUG_ARGS(x)
# define DEBUG_MISC(x)
# define DEBUG_ERROR(x)
#endif
extern FILE *dfd;
extern int dostats;
extern int dbglvl;
extern void debug_init(char *, int);
extern void lprint(const char *fmt, ...);
#ifdef _DEBUG
extern void dump_packet(void *dat, int n);
#endif
#ifndef _MSC_VER
extern char *strerror(int);
#endif
#endif /*DEBUG_H*/

14
src/host.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef SLIRP_HOST_H
# define SLIRP_HOST_H
extern int host_get_info(struct in_addr *, char *, char *);
extern int host_init(void);
extern void host_close(void);
#ifdef _WIN32
extern int inet_aton(const char *, struct in_addr *);
#endif
#endif /*SLIRP_HOST_H*/

65
src/icmp_var.h Normal file
View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)icmp_var.h 8.1 (Berkeley) 6/10/93
* icmp_var.h,v 1.4 1995/02/16 00:27:40 wollman Exp
*/
#ifndef _NETINET_ICMP_VAR_H_
#define _NETINET_ICMP_VAR_H_
/*
* Variables related to this implementation
* of the internet control message protocol.
*/
struct icmpstat {
/* statistics related to input messages processed */
u_long icps_received; /* #ICMP packets received */
u_long icps_tooshort; /* packet < ICMP_MINLEN */
u_long icps_checksum; /* bad checksum */
u_long icps_notsupp; /* #ICMP packets not supported */
u_long icps_badtype; /* #with bad type feild */
u_long icps_reflect; /* number of responses */
};
/*
* Names for ICMP sysctl objects
*/
#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */
#define ICMPCTL_STATS 2 /* statistics (read-only) */
#define ICMPCTL_MAXID 3
#define ICMPCTL_NAMES { \
{ 0, 0 }, \
{ "maskrepl", CTLTYPE_INT }, \
{ "stats", CTLTYPE_STRUCT }, \
}
extern struct icmpstat icmpstat;
#endif

250
src/if.c Normal file
View File

@@ -0,0 +1,250 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <unistd.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "misc.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
#include "if.h"
#include "ip.h"
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
int if_mtu, if_mru;
int if_maxlinkhdr;
int if_queued = 0; /* Number of packets queued so far */
static struct SLIRPmbuf if_fastq; /* fast queue (for interactive data) */
static struct SLIRPmbuf if_batchq; /* queue for non-interactive data */
static struct SLIRPmbuf *next_m; /* Pointer to next SLIRPmbuf to output */
static void
ifs_insque(struct SLIRPmbuf *ifm, struct SLIRPmbuf *ifmhead)
{
ifm->ifs_next = ifmhead->ifs_next;
ifmhead->ifs_next = ifm;
ifm->ifs_prev = ifmhead;
ifm->ifs_next->ifs_prev = ifm;
}
static void
ifs_remque(struct SLIRPmbuf *ifm)
{
ifm->ifs_prev->ifs_next = ifm->ifs_next;
ifm->ifs_next->ifs_prev = ifm->ifs_prev;
}
void
if_init(slirp_t *slirp)
{
if_mtu = 1500;
if_mru = 1500;
if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
next_m = &if_batchq;
}
/*
* if_output: Queue packet into an output queue.
*
* There are 2 output queues, if_fastq and if_batchq.
* Each output queue is a doubly linked list of double linked lists
* of SLIRPmbufs, each list belonging to one "session" (socket). This
* way, we can output packets fairly by sending one packet from each
* session, instead of all the packets from one session, then all packets
* from the next session, etc. Packets on the if_fastq get absolute
* priority, but if one session hogs the link, it gets "downgraded"
* to the batchq until it runs out of packets, then it'll return
* to the fastq (eg. if the user does an ls -alR in a telnet session,
* it'll temporarily get downgraded to the batchq)
*/
void
if_output(struct SLIRPsocket *so, struct SLIRPmbuf *ifm)
{
struct SLIRPmbuf *ifq;
int on_fastq = 1;
DEBUG_CALL("if_output");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("ifm = %lx", (long)ifm);
/*
* First remove the SLIRPmbuf from m_usedlist,
* since we're gonna use m_next and m_prev ourselves
* XXX Shouldn't need this, gotta change dtom() etc.
*/
if (ifm->m_flags & M_USEDLIST) {
remque(ifm);
ifm->m_flags &= ~M_USEDLIST;
}
/*
* See if there's already a batchq list for this session.
* This can include an interactive session, which should go on fastq,
* but gets too greedy... hence it'll be downgraded from fastq to batchq.
* We mustn't put this packet back on the fastq (or we'll send it out of order)
* XXX add cache here?
*/
for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) {
if (so == ifq->ifq_so) {
/* A match! */
ifm->ifq_so = so;
ifs_insque(ifm, ifq->ifs_prev);
goto diddit;
}
}
/* No match, check which queue to put it on */
if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
ifq = if_fastq.ifq_prev;
on_fastq = 1;
/*
* Check if this packet is a part of the last
* packet's session
*/
if (ifq->ifq_so == so) {
ifm->ifq_so = so;
ifs_insque(ifm, ifq->ifs_prev);
goto diddit;
}
} else
ifq = if_batchq.ifq_prev;
/* Create a new doubly linked list for this session */
ifm->ifq_so = so;
ifs_init(ifm);
insque(ifm, ifq);
diddit:
if_queued++;
if (so) {
/* Update *_queued */
so->so_queued++;
so->so_nqueued++;
/*
* Check if the interactive session should be downgraded to
* the batchq. A session is downgraded if it has queued 6
* packets without pausing, and at least 3 of those packets
* have been sent over the link
* (XXX These are arbitrary numbers, probably not optimal..)
*/
if (on_fastq && ((so->so_nqueued >= 6) &&
(so->so_nqueued - so->so_queued) >= 3)) {
/* Remove from current queue... */
remque(ifm->ifs_next);
/* ...And insert in the new. That'll teach ya! */
insque(ifm->ifs_next, &if_batchq);
}
}
#ifndef FULL_BOLT
/* This prevents us from malloc()ing too many SLIRPmbufs. */
if (link_up) {
/* if_start will check towrite */
if_start();
}
#endif
}
/*
* Send a packet
*
* We choose a packet based on it's position in the output queues;
* If there are packets on the fastq, they are sent FIFO, before
* everything else. Otherwise we choose the first packet from the
* batchq and send it. the next packet chosen will be from the session
* after this one, then the session after that one, and so on.. So,
* for example, if there are 3 ftp session's fighting for bandwidth,
* one packet will be sent from the first session, then one packet
* from the second session, then one packet from the third, then back
* to the first, etc. etc.
*/
void
if_start(void)
{
struct SLIRPmbuf *ifm, *ifqt;
DEBUG_CALL("if_start");
if (if_queued == 0)
return; /* Nothing to do */
again:
/* check if we can really output */
if (! slirp_can_output())
return;
/*
* See which queue to get next packet from
* If there's something in the fastq, select it immediately
*/
if (if_fastq.ifq_next != &if_fastq) {
ifm = if_fastq.ifq_next;
} else {
/* Nothing on fastq, see if next_m is valid */
if (next_m != &if_batchq)
ifm = next_m;
else
ifm = if_batchq.ifq_next;
/* Set which packet to send on next iteration */
next_m = ifm->ifq_next;
}
/* Remove it from the queue */
ifqt = ifm->ifq_prev;
remque(ifm);
if_queued--;
/* If there are more packets for this session, re-queue them */
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
insque(ifm->ifs_next, ifqt);
ifs_remque(ifm);
}
/* Update so_queued */
if (ifm->ifq_so) {
if (--ifm->ifq_so->so_queued == 0) {
/* If there's no more queued, reset nqueued */
ifm->ifq_so->so_nqueued = 0;
}
}
/* Encapsulate the packet for sending */
if_encap((uint8_t*)ifm->m_data, ifm->m_len);
m_free(ifm);
if (if_queued)
goto again;
}

44
src/if.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifndef SLIRP_IF_H
# define SLIRP_IF_H
/* Needed for FreeBSD */
#undef if_mtu
extern int if_mtu;
extern int if_mru; /* MTU and MRU */
extern int if_maxlinkhdr;
extern int if_queued; /* Number of packets queued so far */
/* Interface statistics */
struct slirp_ifstats {
u_int out_pkts; /* Output packets */
u_int out_bytes; /* Output bytes */
u_int out_errpkts; /* Output Error Packets */
u_int out_errbytes; /* Output Error Bytes */
u_int in_pkts; /* Input packets */
u_int in_bytes; /* Input bytes */
u_int in_errpkts; /* Input Error Packets */
u_int in_errbytes; /* Input Error Bytes */
u_int bytes_saved; /* Number of bytes that compression "saved" */
/* ie: #bytes not sent over the link
* because of compression */
u_int in_mbad; /* Bad incoming packets */
};
extern void if_init(slirp_t *);
extern void if_start(void);
extern void if_output(struct SLIRPsocket *, struct SLIRPmbuf *);
extern void if_encap(const uint8_t *ip_data, int ip_data_len);
#endif /*SLIRP_IF_H*/

365
src/ip.h Normal file
View File

@@ -0,0 +1,365 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip.h 8.1 (Berkeley) 6/10/93
* ip.h,v 1.3 1994/08/21 05:27:30 paul Exp
*/
#ifndef SLIRP_IP_H
# define SLIRP_IP_H
#ifdef WORDS_BIGENDIAN
# ifndef NTOHL
# define NTOHL(d)
# endif
# ifndef NTOHS
# define NTOHS(d)
# endif
# ifndef HTONL
# define HTONL(d)
# endif
# ifndef HTONS
# define HTONS(d)
# endif
#else
# ifndef NTOHL
# define NTOHL(d) ((d) = ntohl((d)))
# endif
# ifndef NTOHS
# define NTOHS(d) ((d) = ntohs((uint16_t)(d)))
# endif
# ifndef HTONL
# define HTONL(d) ((d) = htonl((d)))
# endif
# ifndef HTONS
# define HTONS(d) ((d) = htons((uint16_t)(d)))
# endif
#endif
typedef uint32_t n_long; /* long as received from the net */
/*
* Definitions for internet protocol version 4.
* Per RFC 791, September 1981.
*/
#define IPVERSION 4
#if defined(_MSC_VER)
#pragma pack(push, 1)
#endif
/*
* Structure of an internet header, naked of options.
*/
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct ip {
#ifdef WORDS_BIGENDIAN
uint8_t ip_v:4, /* version */
ip_hl:4; /* header length */
#else
uint8_t ip_hl:4, /* header length */
ip_v:4; /* version */
#endif
uint8_t ip_tos; /* type of service */
uint16_t ip_len; /* total length */
uint16_t ip_id; /* identification */
uint16_t ip_off; /* fragment offset field */
#define IP_DF 0x4000 /* don't fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
uint8_t ip_ttl; /* time to live */
uint8_t ip_p; /* protocol */
uint16_t ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
} PACKED__;
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_END) //WAS 0
#endif
#define IP_MAXPACKET 65535 /* maximum packet size */
/*
* Definitions for IP type of service (ip_tos)
*/
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
/*
* Definitions for options.
*/
#define IPOPT_COPIED(o) ((o)&0x80)
#define IPOPT_CLASS(o) ((o)&0x60)
#define IPOPT_NUMBER(o) ((o)&0x1f)
#define IPOPT_CONTROL 0x00
#define IPOPT_RESERVED1 0x20
#define IPOPT_DEBMEAS 0x40
#define IPOPT_RESERVED2 0x60
#define IPOPT_EOL 0 /* end of option list */
#define IPOPT_NOP 1 /* no operation */
#define IPOPT_RR 7 /* record packet route */
#define IPOPT_TS 68 /* timestamp */
#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
#define IPOPT_LSRR 131 /* loose source route */
#define IPOPT_SATID 136 /* satnet id */
#define IPOPT_SSRR 137 /* strict source route */
/*
* Offsets to fields in options other than EOL and NOP.
*/
#define IPOPT_OPTVAL 0 /* option ID */
#define IPOPT_OLEN 1 /* option length */
#define IPOPT_OFFSET 2 /* offset within option */
#define IPOPT_MINOFF 4 /* min value of above */
/*
* Time stamp option structure.
*/
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct ip_timestamp {
uint8_t ipt_code; /* IPOPT_TS */
uint8_t ipt_len; /* size of structure (variable) */
uint8_t ipt_ptr; /* index of current entry */
#ifdef WORDS_BIGENDIAN
uint8_t ipt_oflw:4, /* overflow counter */
ipt_flg:4; /* flags, see below */
#else
uint8_t ipt_flg:4, /* flags, see below */
ipt_oflw:4; /* overflow counter */
#endif
union ipt_timestamp {
n_long ipt_time[1];
struct ipt_ta {
struct in_addr ipt_addr;
n_long ipt_time;
} ipt_ta[1];
} ipt_timestamp;
} PACKED__;
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_END)
#endif
/* flag bits for ipt_flg */
#define IPOPT_TS_TSONLY 0 /* timestamps only */
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
/* bits for security (not byte swapped) */
#define IPOPT_SECUR_UNCLASS 0x0000
#define IPOPT_SECUR_CONFID 0xf135
#define IPOPT_SECUR_EFTO 0x789a
#define IPOPT_SECUR_MMMM 0xbc4d
#define IPOPT_SECUR_RESTR 0xaf13
#define IPOPT_SECUR_SECRET 0xd788
#define IPOPT_SECUR_TOPSECRET 0x6bc5
/*
* Internet implementation parameters.
*/
#define MAXTTL 255 /* maximum time to live (seconds) */
#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
#define IPFRAGTTL 60 /* time to live for frags, slowhz */
#define IPTTLDEC 1 /* subtracted when forwarding */
#define IP_MSS 576 /* default maximum segment size */
#ifdef HAVE_SYS_TYPES32_H /* Overcome some Solaris 2.x junk */
#include <sys/types32.h>
#else
#if SIZEOF_CHAR_P == 4
typedef SLIRPcaddr_t caddr32_t;
#else
typedef uint32_t caddr32_t;
#endif
#endif
#ifdef __amd64__
typedef uintptr_t ipqp_32;
typedef uintptr_t ipasfragp_32;
#else
#if SIZEOF_CHAR_P == 4
typedef struct ipq *ipqp_32;
typedef struct ipasfrag *ipasfragp_32;
#else
typedef caddr32_t ipqp_32;
typedef caddr32_t ipasfragp_32;
#endif
#endif
/*
* Overlay for ip header used by other protocols (tcp, udp).
*/
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct ipovly {
#ifdef __amd64__
uintptr_t ih_next, ih_prev; /* for protocol sequence q's */
#else
caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
#endif
uint8_t ih_x1; /* (unused) */
uint8_t ih_pr; /* protocol */
uint16_t ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */
} PACKED__;
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_END)
#endif
#if defined(_MSC_VER)
#pragma pack(pop)
#endif
/*
* Ip reassembly queue structure. Each fragment
* being reassembled is attached to one of these structures.
* They are timed out after ipq_ttl drops to 0, and may also
* be reclaimed if memory becomes tight.
* size 28 bytes
*/
struct ipq {
#ifdef __amd64__
uintptr_t next,prev; /* to other reass headers */
#else
ipqp_32 next,prev; /* to other reass headers */
#endif
uint8_t ipq_ttl; /* time for reass q to live */
uint8_t ipq_p; /* protocol of this fragment */
uint16_t ipq_id; /* sequence id for reassembly */
ipasfragp_32 ipq_next,ipq_prev;
/* to ip headers of fragments */
struct in_addr ipq_src,ipq_dst;
};
/*
* Ip header, when holding a fragment.
*
* Note: ipf_next must be at same offset as ipq_next above
*/
struct ipasfrag {
#ifdef WORDS_BIGENDIAN
uint8_t ip_v:4,
ip_hl:4;
#else
uint8_t ip_hl:4,
ip_v:4;
#endif
/* BUG : u_int changed to u_int8_t.
* sizeof(u_int)==4 on linux 2.0
*/
uint8_t ipf_mff; /* XXX overlays ip_tos: use low bit
* to avoid destroying tos (PPPDTRuu);
* copied from (ip_off&IP_MF) */
uint16_t ip_len;
uint16_t ip_id;
uint16_t ip_off;
uint8_t ip_ttl;
uint8_t ip_p;
uint16_t ip_sum;
ipasfragp_32 ipf_next; /* next fragment */
ipasfragp_32 ipf_prev; /* previous fragment */
};
/*
* Structure stored in mbuf in inpcb.ip_options
* and passed to ip_output when ip options are in use.
* The actual length of the options (including ipopt_dst)
* is in m_len.
*/
#define MAX_IPOPTLEN 40
struct ipoption {
struct in_addr ipopt_dst; /* first-hop dst if source routed */
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
};
/*
* Structure attached to inpcb.ip_moptions and
* passed to ip_output when IP multicast options are in use.
*/
struct ipstat {
uint32_t ips_total; /* total packets received */
uint32_t ips_badsum; /* checksum bad */
uint32_t ips_tooshort; /* packet too short */
uint32_t ips_toosmall; /* not enough data */
uint32_t ips_badhlen; /* ip header length < data size */
uint32_t ips_badlen; /* ip length < ip header length */
uint32_t ips_fragments; /* fragments received */
uint32_t ips_fragdropped; /* frags dropped (dups, out of space) */
uint32_t ips_fragtimeout; /* fragments timed out */
uint32_t ips_forward; /* packets forwarded */
uint32_t ips_cantforward; /* packets rcvd for unreachable dest */
uint32_t ips_redirectsent; /* packets forwarded on same net */
uint32_t ips_noproto; /* unknown or unsupported protocol */
uint32_t ips_delivered; /* datagrams delivered to upper level*/
uint32_t ips_localout; /* total ip packets generated here */
uint32_t ips_odropped; /* lost packets due to nobufs, etc. */
uint32_t ips_reassembled; /* total packets reassembled ok */
uint32_t ips_fragmented; /* datagrams successfully fragmented */
uint32_t ips_ofragments; /* output fragments created */
uint32_t ips_cantfrag; /* don't fragment flag was set, etc. */
uint32_t ips_badoptions; /* error in option processing */
uint32_t ips_noroute; /* packets discarded due to no route */
uint32_t ips_badvers; /* ip version != 4 */
uint32_t ips_rawout; /* total raw ip packets generated */
uint32_t ips_unaligned; /* times the ip packet was not aligned */
};
extern struct ipstat ipstat;
extern struct ipq ipq; /* ip reass. queue */
extern uint16_t ip_id; /* ip packet ctr, for ids */
extern int ip_defttl; /* default IP ttl */
extern void ip_init(void);
extern void ip_input(struct SLIRPmbuf *);
extern struct ip *ip_reass(register struct ipasfrag *, register struct ipq *);
extern void ip_freef(struct ipq *);
extern void ip_enq(register struct ipasfrag *, register struct ipasfrag *);
extern void ip_deq(register struct ipasfrag *);
extern void ip_slowtimo(void);
extern void ip_stripoptions(register struct SLIRPmbuf *, struct SLIRPmbuf *);
extern int ip_output(struct SLIRPsocket *, struct SLIRPmbuf *);
extern int cksum(struct SLIRPmbuf *m, int len);
#endif /*SLIRP_IP_H*/

378
src/ip_icmp.c Normal file
View File

@@ -0,0 +1,378 @@
/*
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
* ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp
*/
#ifdef _WIN32
# include <windows.h>
# undef errno
# define errno (WSAGetLastError())
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
# include <errno.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
#include "ip.h"
#include "ip_icmp.h"
#include "icmp_var.h"
#include "udp.h"
struct icmpstat icmpstat;
/* The message sent when emulating PING */
/* Be nice and tell them it's just a psuedo-ping packet */
char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
/* list of actions for icmp_error() on RX of an icmp message */
static int icmp_flush[19] = {
/* ECHO REPLY (0) */ 0,
1,
1,
/* DEST UNREACH (3) */ 1,
/* SOURCE QUENCH (4)*/ 1,
/* REDIRECT (5) */ 1,
1,
1,
/* ECHO (8) */ 0,
/* ROUTERADVERT (9) */ 1,
/* ROUTERSOLICIT (10) */ 1,
/* TIME EXCEEDED (11) */ 1,
/* PARAMETER PROBLEM (12) */ 1,
/* TIMESTAMP (13) */ 0,
/* TIMESTAMP REPLY (14) */ 0,
/* INFO (15) */ 0,
/* INFO REPLY (16) */ 0,
/* ADDR MASK (17) */ 0,
/* ADDR MASK REPLY (18) */ 0
};
/* Reflect the ip packet back to the source. */
void
icmp_reflect(struct SLIRPmbuf *m)
{
register struct ip *ip = mtod(m, struct ip *);
int hlen = ip->ip_hl << 2;
int optlen = hlen - sizeof(struct ip);
register struct icmp *icp;
struct in_addr icmp_dst;
/*
* Send an icmp packet back to the ip level,
* after supplying a checksum.
*/
m->m_data += hlen;
m->m_len -= hlen;
icp = mtod(m, struct icmp *);
icp->icmp_cksum = 0;
icp->icmp_cksum = cksum(m, ip->ip_len - hlen);
m->m_data -= hlen;
m->m_len += hlen;
/* fill in ip */
if (optlen > 0) {
/*
* Strip out original options by copying rest of first
* SLIRPmbuf's data back, and adjust the IP length.
*/
memmove((SLIRPcaddr_t)(ip + 1), (SLIRPcaddr_t)ip + hlen,
(unsigned )(m->m_len - hlen));
hlen -= optlen;
ip->ip_hl = hlen >> 2;
ip->ip_len -= optlen;
m->m_len -= optlen;
}
ip->ip_ttl = MAXTTL;
/* swap */
icmp_dst = ip->ip_dst;
ip->ip_dst = ip->ip_src;
ip->ip_src = icmp_dst;
(void)ip_output((struct SLIRPsocket *)NULL, m);
icmpstat.icps_reflect++;
}
/* Process a received ICMP message. */
void
icmp_input(struct SLIRPmbuf *m, int hlen)
{
register struct icmp *icp;
register struct ip *ip = mtod(m, struct ip *);
int icmplen = ip->ip_len;
#if 0
int code;
#endif
DEBUG_CALL("icmp_input");
DEBUG_ARG("m = %lx", (long )m);
DEBUG_ARG("m_len = %d", m->m_len);
icmpstat.icps_received++;
/*
* Locate icmp structure in SLIRPmbuf, and check
* that its not corrupted and of at least minimum length.
*/
if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
icmpstat.icps_tooshort++;
freeit:
m_freem(m);
goto end_error;
}
m->m_len -= hlen;
m->m_data += hlen;
icp = mtod(m, struct icmp *);
if (cksum(m, icmplen)) {
icmpstat.icps_checksum++;
goto freeit;
}
m->m_len += hlen;
m->m_data -= hlen;
#if 0
icmpstat.icps_inhist[icp->icmp_type]++;
code = icp->icmp_code;
#endif
DEBUG_ARG("icmp_type = %d", icp->icmp_type);
switch (icp->icmp_type) {
case ICMP_ECHO:
icp->icmp_type = ICMP_ECHOREPLY;
ip->ip_len += hlen; /* since ip_input subtracts this */
if (ip->ip_dst.s_addr == router_addr.s_addr) {
icmp_reflect(m);
} else {
struct SLIRPsocket *so;
struct sockaddr_in addr;
if ((so = socreate()) == NULL) goto freeit;
if (udp_attach(so) == -1) {
DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
errno,strerror(errno)));
sofree(so);
m_free(m);
goto end_error;
}
so->so_m = m;
so->so_faddr = ip->ip_dst;
so->so_fport = htons(7);
so->so_laddr = ip->ip_src;
so->so_lport = htons(9);
so->so_iptos = ip->ip_tos;
so->so_type = IPPROTO_ICMP;
so->so_state = SS_ISFCONNECTED;
/* Send the packet */
addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
/* It's an alias */
switch (ntohl(so->so_faddr.s_addr) & 0xff) {
case CTL_SERVER:
addr.sin_addr = dns_addr;
break;
case CTL_ROUTER:
default:
addr.sin_addr = loopback_addr;
break;
}
} else {
addr.sin_addr = so->so_faddr;
}
addr.sin_port = so->so_fport;
if (sendto(so->s, icmp_ping_msg,
strlen(icmp_ping_msg), 0,
(struct sockaddr *)&addr,
sizeof(addr)) == -1) {
DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
errno,strerror(errno)));
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
udp_detach(so);
}
}
break;
case ICMP_UNREACH:
/* XXX? report error? close socket? */
case ICMP_TIMXCEED:
case ICMP_PARAMPROB:
case ICMP_SOURCEQUENCH:
case ICMP_TSTAMP:
case ICMP_MASKREQ:
case ICMP_REDIRECT:
icmpstat.icps_notsupp++;
m_freem(m);
break;
default:
icmpstat.icps_badtype++;
m_freem(m);
}
end_error:
/* m is m_free()'d xor put in a socket xor or given to ip_send */
return;
}
/*
* Send an ICMP message in response to a situation
*
* RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we do).
* MUST NOT change this header information.
* MUST NOT reply to a multicast/broadcast IP address.
* MUST NOT reply to a multicast/broadcast MAC address.
* MUST reply to only the first fragment.
*/
/*
* Send ICMP_UNREACH back to the source regarding msrc.
* SLIRPmbuf *msrc is used as a template, but is NOT m_free()'d.
* It is reported as the bad ip packet. The header should
* be fully correct and in host byte order.
* ICMP fragmentation is illegal. All machines must accept 576 bytes in one
* packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
*/
#define ICMP_MAXDATALEN (IP_MSS-28)
void
icmp_error(struct SLIRPmbuf *msrc, u_char type, u_char code, int minsize, char *message)
{
unsigned hlen, shlen, s_ip_len;
register struct ip *ip;
register struct icmp *icp;
register struct SLIRPmbuf *m;
u_int new_m_size;
DEBUG_CALL("icmp_error");
DEBUG_ARG("msrc = %lx", (long )msrc);
DEBUG_ARG("msrc_len = %d", msrc->m_len);
if (type != ICMP_UNREACH && type != ICMP_TIMXCEED)
goto end_error;
/* check msrc */
if (! msrc)
goto end_error;
/* Only reply to fragment 0. */
ip = mtod(msrc, struct ip *);
if (ip->ip_off & IP_OFFMASK)
goto end_error;
shlen = ip->ip_hl << 2;
s_ip_len = ip->ip_len;
if (ip->ip_p == IPPROTO_ICMP) {
icp = (struct icmp *)((char *)ip + shlen);
/*
* Assume any unknown ICMP type is an error. This isn't
* specified by the RFC, but think about it..
*/
if (icp->icmp_type>18 || icmp_flush[icp->icmp_type])
goto end_error;
}
/* Copy msrc into m. */
if (! (m=m_get()))
goto end_error;
new_m_size = sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
if (new_m_size > m->m_size)
m_inc(m, new_m_size);
memcpy(m->m_data, msrc->m_data, msrc->m_len);
m->m_len = msrc->m_len;
/* make the header of the reply packet */
ip = mtod(m, struct ip *);
hlen = sizeof(struct ip); /* no options in reply */
/* fill in icmp */
m->m_data += hlen;
m->m_len -= hlen;
icp = mtod(m, struct icmp *);
if (minsize)
s_ip_len = shlen + ICMP_MINLEN; /* return header+8b only */
else if (s_ip_len > ICMP_MAXDATALEN) /* maximum size */
s_ip_len = ICMP_MAXDATALEN;
m->m_len = ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */
/* min. size = 8+sizeof(struct ip)+8 */
icp->icmp_type = type;
icp->icmp_code = code;
icp->icmp_id = 0;
icp->icmp_seq = 0;
memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len); /* report the ip packet */
HTONS(icp->icmp_ip.ip_len);
HTONS(icp->icmp_ip.ip_id);
HTONS(icp->icmp_ip.ip_off);
icp->icmp_cksum = 0;
icp->icmp_cksum = cksum(m, m->m_len);
m->m_data -= hlen;
m->m_len += hlen;
/* fill in ip */
ip->ip_hl = hlen >> 2;
ip->ip_len = (uint16_t)m->m_len;
ip->ip_tos = ((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
ip->ip_ttl = MAXTTL;
ip->ip_p = IPPROTO_ICMP;
ip->ip_dst = ip->ip_src; /* ip adresses */
ip->ip_src = router_addr;
(void)ip_output((struct SLIRPsocket *)NULL, m);
icmpstat.icps_reflect++;
end_error:
return;
}

170
src/ip_icmp.h Normal file
View File

@@ -0,0 +1,170 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
* ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp
*/
#ifndef SLIRP_IP_ICMP_H
# define SLIRP_IP_ICMP_H
/*
* Interface Control Message Protocol Definitions.
* Per RFC 792, September 1981.
*/
typedef uint32_t n_time;
/*
* Structure of an icmp header.
*/
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct icmp {
uint8_t icmp_type; /* type of message, see below */
uint8_t icmp_code; /* type sub code */
uint16_t icmp_cksum; /* ones complement cksum of struct */
union {
uint8_t ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
struct ih_idseq {
uint16_t icd_id;
uint16_t icd_seq;
} ih_idseq;
int ih_void;
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
struct ih_pmtu {
uint16_t ipm_void;
uint16_t ipm_nextmtu;
} ih_pmtu;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id icmp_hun.ih_idseq.icd_id
#define icmp_seq icmp_hun.ih_idseq.icd_seq
#define icmp_void icmp_hun.ih_void
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
union {
struct id_ts {
n_time its_otime;
n_time its_rtime;
n_time its_ttime;
} id_ts;
struct id_ip {
struct ip idi_ip;
/* options and then 64 bits of data */
} id_ip;
uint32_t id_mask;
char id_data[1];
} icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
} PACKED__;
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(0)
#endif
/*
* Lower bounds on packet lengths for various types.
* For the error advice packets must first insure that the
* packet is large enought to contain the returned ip header.
* Only then can we do the check to see if 64 bits of packet
* data have been returned, since we need to check the returned
* ip header length.
*/
#define ICMP_MINLEN 8 /* abs minimum */
#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
#define ICMP_MASKLEN 12 /* address mask */
#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
/* N.B.: must separately check that ip_hl >= 5 */
/*
* Definition of type and code field values.
*/
#define ICMP_ECHOREPLY 0 /* echo reply */
#define ICMP_UNREACH 3 /* dest unreachable, codes: */
#define ICMP_UNREACH_NET 0 /* bad net */
#define ICMP_UNREACH_HOST 1 /* bad host */
#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
#define ICMP_UNREACH_PORT 3 /* bad port */
#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */
#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
#define ICMP_REDIRECT 5 /* shorter route, codes: */
#define ICMP_REDIRECT_NET 0 /* for network */
#define ICMP_REDIRECT_HOST 1 /* for host */
#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
#define ICMP_ECHO 8 /* echo service */
#define ICMP_ROUTERADVERT 9 /* router advertisement */
#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
#define ICMP_TIMXCEED 11 /* time exceeded, code: */
#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
#define ICMP_PARAMPROB 12 /* ip header bad */
#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
#define ICMP_TSTAMP 13 /* timestamp request */
#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
#define ICMP_IREQ 15 /* information request */
#define ICMP_IREQREPLY 16 /* information reply */
#define ICMP_MASKREQ 17 /* address mask request */
#define ICMP_MASKREPLY 18 /* address mask reply */
#define ICMP_MAXTYPE 18
#define ICMP_INFOTYPE(type) \
((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
(type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
extern void icmp_reflect(struct SLIRPmbuf *m);
extern void icmp_input(struct SLIRPmbuf *, int);
extern void icmp_error(struct SLIRPmbuf *, uint8_t, uint8_t, int, char *);
#endif /*SLIRP_IP_ICMP_H*/

704
src/ip_input.c Normal file
View File

@@ -0,0 +1,704 @@
/*
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
* ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
#include "ip.h"
#include "ip_icmp.h"
#include "tcp.h"
#include "udp.h"
/*
* Changes and additions relating to SLiRP are
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
int ip_defttl;
struct ipstat ipstat;
struct ipq ipq;
/*
* IP initialization: fill in IP protocol switch table.
* All protocols not implemented in kernel go to raw IP protocol handler.
*/
void
ip_init()
{
ipq.next = ipq.prev = (ipqp_32)&ipq;
ip_id = 0x1234; /* was: tt.tv_sec & 0xffff */
udp_init();
tcp_init();
ip_defttl = IPDEFTTL;
}
/*
* Ip input routine. Checksum and byte swap header. If fragmented
* try to reassemble. Process options. Pass to next level.
*/
void
ip_input(struct SLIRPmbuf *m)
{
register struct ip *ip;
u_int hlen;
DEBUG_CALL("ip_input");
DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("m_len = %d", m->m_len);
ipstat.ips_total++;
if (m->m_len < sizeof (struct ip)) {
ipstat.ips_toosmall++;
return;
}
ip = mtod(m, struct ip *);
if (ip->ip_v != IPVERSION) {
ipstat.ips_badvers++;
goto bad;
}
hlen = ip->ip_hl << 2;
if (hlen<(u_int)sizeof(struct ip ) || hlen>(u_int)m->m_len) {/* min header length */
ipstat.ips_badhlen++; /* or packet too short */
goto bad;
}
/* keep ip header intact for ICMP reply
* ip->ip_sum = cksum(m, hlen);
* if (ip->ip_sum) {
*/
if(cksum(m,hlen)) {
ipstat.ips_badsum++;
goto bad;
}
/*
* Convert fields to host representation.
*/
NTOHS(ip->ip_len);
if (ip->ip_len < hlen) {
ipstat.ips_badlen++;
goto bad;
}
NTOHS(ip->ip_id);
NTOHS(ip->ip_off);
/*
* Check that the amount of data in the buffers
* is as at least much as the IP header would have us expect.
* Trim SLIRPmbufs if longer than we expect.
* Drop packet if shorter than we expect.
*/
if (m->m_len < ip->ip_len) {
ipstat.ips_tooshort++;
goto bad;
}
/* Should drop packet if SLIRPmbuf too long? hmmm... */
if (m->m_len > ip->ip_len)
m_adj(m, ip->ip_len - m->m_len);
/* check ip_ttl for a correct ICMP reply */
if(ip->ip_ttl==0 || ip->ip_ttl==1) {
icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
goto bad;
}
/*
* Process options and, if not destined for us,
* ship it on. ip_dooptions returns 1 when an
* error was detected (causing an icmp message
* to be sent and the original packet to be freed).
*/
/* We do no IP options */
/* if (hlen > sizeof (struct ip) && ip_dooptions(m))
* goto next;
*/
/*
* If offset or IP_MF are set, must reassemble.
* Otherwise, nothing need be done.
* (We could look in the reassembly queue to see
* if the packet was previously fragmented,
* but it's not worth the time; just let them time out.)
*
* XXX This should fail, don't fragment yet
*/
if (ip->ip_off &~ IP_DF) {
register struct ipq *fp;
/*
* Look for queue of fragments
* of this datagram.
*/
for (fp = (struct ipq *) ipq.next; fp != &ipq;
fp = (struct ipq *) fp->next)
if (ip->ip_id == fp->ipq_id &&
ip->ip_src.s_addr == fp->ipq_src.s_addr &&
ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
ip->ip_p == fp->ipq_p)
goto found;
fp = 0;
found:
/*
* Adjust ip_len to not reflect header,
* set ip_mff if more fragments are expected,
* convert offset of this to bytes.
*/
ip->ip_len -= hlen;
if (ip->ip_off & IP_MF)
((struct ipasfrag *)ip)->ipf_mff |= 1;
else
((struct ipasfrag *)ip)->ipf_mff &= ~1;
ip->ip_off <<= 3;
/*
* If datagram marked as having more fragments
* or if this is not the first fragment,
* attempt reassembly; if it succeeds, proceed.
*/
if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
ipstat.ips_fragments++;
ip = ip_reass((struct ipasfrag *)ip, fp);
if (ip == 0)
return;
ipstat.ips_reassembled++;
m = dtom(ip);
} else
if (fp)
ip_freef(fp);
} else
ip->ip_len -= hlen;
/*
* Switch out to protocol's input routine.
*/
ipstat.ips_delivered++;
switch (ip->ip_p) {
case IPPROTO_TCP:
tcp_input(m, hlen, (struct SLIRPsocket *)NULL);
break;
case IPPROTO_UDP:
udp_input(m, hlen);
break;
case IPPROTO_ICMP:
icmp_input(m, hlen);
break;
default:
ipstat.ips_noproto++;
m_free(m);
}
return;
bad:
m_freem(m);
return;
}
/*
* Take incoming datagram fragment and try to
* reassemble it into whole datagram. If a chain for
* reassembly of this datagram already exists, then it
* is given as fp; otherwise have to make a chain.
*/
struct ip *
ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
{
register struct SLIRPmbuf *m = dtom(ip);
register struct ipasfrag *q;
int hlen = ip->ip_hl << 2;
int i, next;
DEBUG_CALL("ip_reass");
DEBUG_ARG("ip = %lx", (long)ip);
DEBUG_ARG("fp = %lx", (long)fp);
DEBUG_ARG("m = %lx", (long)m);
/*
* Presence of header sizes in SLIRPmbufs
* would confuse code below.
* Fragment m_data is concatenated.
*/
m->m_data += hlen;
m->m_len -= hlen;
/*
* If first fragment to arrive, create a reassembly queue.
*/
if (fp == 0) {
struct SLIRPmbuf *t;
if ((t = m_get()) == NULL) goto dropfrag;
fp = mtod(t, struct ipq *);
insque_32(fp, &ipq);
fp->ipq_ttl = IPFRAGTTL;
fp->ipq_p = ip->ip_p;
fp->ipq_id = ip->ip_id;
fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;
fp->ipq_src = ((struct ip *)ip)->ip_src;
fp->ipq_dst = ((struct ip *)ip)->ip_dst;
q = (struct ipasfrag *)fp;
goto insert;
}
/*
* Find a segment which begins after this one does.
*/
for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;
q = (struct ipasfrag *)q->ipf_next)
if (q->ip_off > ip->ip_off)
break;
/*
* If there is a preceding segment, it may provide some of
* our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
*/
if (q->ipf_prev != (ipasfragp_32)fp) {
i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +
((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;
if (i > 0) {
if (i >= ip->ip_len)
goto dropfrag;
m_adj(dtom(ip), i);
ip->ip_off += i;
ip->ip_len -= i;
}
}
/*
* While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them.
*/
while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
i = (ip->ip_off + ip->ip_len) - q->ip_off;
if (i < q->ip_len) {
q->ip_len -= i;
q->ip_off += i;
m_adj(dtom(q), i);
break;
}
q = (struct ipasfrag *) q->ipf_next;
m_freem(dtom((struct ipasfrag *) q->ipf_prev));
ip_deq((struct ipasfrag *) q->ipf_prev);
}
insert:
/*
* Stick new segment in its place;
* check for complete reassembly.
*/
ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
next = 0;
for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
q = (struct ipasfrag *) q->ipf_next) {
if (q->ip_off != next)
return (0);
next += q->ip_len;
}
if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
return (0);
/*
* Reassembly is complete; concatenate fragments.
*/
q = (struct ipasfrag *) fp->ipq_next;
m = dtom(q);
q = (struct ipasfrag *) q->ipf_next;
while (q != (struct ipasfrag *)fp) {
struct SLIRPmbuf *t;
t = dtom(q);
q = (struct ipasfrag *) q->ipf_next;
m_cat(m, t);
}
/*
* Create header for new ip packet by
* modifying header of first packet;
* dequeue and discard fragment reassembly header.
* Make header visible.
*/
ip = (struct ipasfrag *) fp->ipq_next;
/*
* If the fragments concatenated to an SLIRPmbuf that's
* bigger than the total size of the fragment, then and
* m_ext buffer was alloced. But fp->ipq_next points to
* the old buffer (in the SLIRPmbuf), so we must point ip
* into the new buffer.
*/
if (m->m_flags & M_EXT) {
int delta;
delta = (char *)ip - m->m_dat;
ip = (struct ipasfrag *)(m->m_ext + delta);
}
/* DEBUG_ARG("ip = %lx", (long)ip);
* ip=(struct ipasfrag *)m->m_data; */
ip->ip_len = next;
ip->ipf_mff &= ~1;
((struct ip *)ip)->ip_src = fp->ipq_src;
((struct ip *)ip)->ip_dst = fp->ipq_dst;
remque_32(fp);
(void) m_free(dtom(fp));
m = dtom(ip);
m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2);
return ((struct ip *)ip);
dropfrag:
ipstat.ips_fragdropped++;
m_freem(m);
return (0);
}
/*
* Free a fragment reassembly header and all
* associated datagrams.
*/
void
ip_freef(struct ipq *fp)
{
register struct ipasfrag *q, *p;
for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
q = p) {
p = (struct ipasfrag *) q->ipf_next;
ip_deq(q);
m_freem(dtom(q));
}
remque_32(fp);
(void) m_free(dtom(fp));
}
/*
* Put an ip fragment on a reassembly chain.
* Like insque, but pointers in middle of structure.
*/
void
ip_enq(struct ipasfrag *p, struct ipasfrag *prev)
{
DEBUG_CALL("ip_enq");
DEBUG_ARG("prev = %lx", (long)prev);
p->ipf_prev = (ipasfragp_32) prev;
p->ipf_next = prev->ipf_next;
((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
prev->ipf_next = (ipasfragp_32) p;
}
/*
* To ip_enq as remque is to insque.
*/
void
ip_deq(register struct ipasfrag *p)
{
((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
}
/*
* IP timer processing;
* if a timer expires on a reassembly
* queue, discard it.
*/
void
ip_slowtimo(void)
{
register struct ipq *fp;
DEBUG_CALL("ip_slowtimo");
fp = (struct ipq *) ipq.next;
if (fp == 0)
return;
while (fp != &ipq) {
--fp->ipq_ttl;
fp = (struct ipq *) fp->next;
if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
ipstat.ips_fragtimeout++;
ip_freef((struct ipq *) fp->prev);
}
}
}
/*
* Do option processing on a datagram,
* possibly discarding it if bad options are encountered,
* or forwarding it if source-routed.
* Returns 1 if packet has been forwarded/freed,
* 0 if the packet should be processed further.
*/
#ifdef notdef
int
ip_dooptions(struct SLIRPmbuf *m)
{
register struct ip *ip = mtod(m, struct ip *);
register u_char *cp;
register struct ip_timestamp *ipt;
register struct in_ifaddr *ia;
/* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */
int opt, optlen, cnt, off, code, type, forward = 0;
struct in_addr *sin, dst;
typedef u_int32_t n_time;
n_time ntime;
dst = ip->ip_dst;
cp = (u_char *)(ip + 1);
cnt = (ip->ip_hl << 2) - sizeof (struct ip);
for (; cnt > 0; cnt -= optlen, cp += optlen) {
opt = cp[IPOPT_OPTVAL];
if (opt == IPOPT_EOL)
break;
if (opt == IPOPT_NOP)
optlen = 1;
else {
optlen = cp[IPOPT_OLEN];
if (optlen <= 0 || optlen > cnt) {
code = &cp[IPOPT_OLEN] - (u_char *)ip;
goto bad;
}
}
switch (opt) {
default:
break;
/*
* Source routing with record.
* Find interface with current destination address.
* If none on this machine then drop if strictly routed,
* or do nothing if loosely routed.
* Record interface address and bring up next address
* component. If strictly routed make sure next
* address is on directly accessible net.
*/
case IPOPT_LSRR:
case IPOPT_SSRR:
if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
code = &cp[IPOPT_OFFSET] - (u_char *)ip;
goto bad;
}
ipaddr.sin_addr = ip->ip_dst;
ia = (struct in_ifaddr *)
ifa_ifwithaddr((struct sockaddr *)&ipaddr);
if (ia == 0) {
if (opt == IPOPT_SSRR) {
type = ICMP_UNREACH;
code = ICMP_UNREACH_SRCFAIL;
goto bad;
}
/*
* Loose routing, and not at next destination
* yet; nothing to do except forward.
*/
break;
}
off--; / * 0 origin * /
if (off > optlen - sizeof(struct in_addr)) {
/*
* End of source route. Should be for us.
*/
save_rte(cp, ip->ip_src);
break;
}
/*
* locate outgoing interface
*/
bcopy((SLIRPcaddr_t)(cp + off), (SLIRPcaddr_t)&ipaddr.sin_addr,
sizeof(ipaddr.sin_addr));
if (opt == IPOPT_SSRR) {
#define INA struct in_ifaddr *
#define SA struct sockaddr *
if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
ia = (INA)ifa_ifwithnet((SA)&ipaddr);
} else
ia = ip_rtaddr(ipaddr.sin_addr);
if (ia == 0) {
type = ICMP_UNREACH;
code = ICMP_UNREACH_SRCFAIL;
goto bad;
}
ip->ip_dst = ipaddr.sin_addr;
bcopy((SLIRPcaddr_t)&(IA_SIN(ia)->sin_addr),
(SLIRPcaddr_t)(cp + off), sizeof(struct in_addr));
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
/*
* Let ip_intr's mcast routing check handle mcast pkts
*/
forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
break;
case IPOPT_RR:
if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
code = &cp[IPOPT_OFFSET] - (u_char *)ip;
goto bad;
}
/*
* If no space remains, ignore.
*/
off--; * 0 origin *
if (off > optlen - sizeof(struct in_addr))
break;
bcopy((SLIRPcaddr_t)(&ip->ip_dst), (SLIRPcaddr_t)&ipaddr.sin_addr,
sizeof(ipaddr.sin_addr));
/*
* locate outgoing interface; if we're the destination,
* use the incoming interface (should be same).
*/
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
(ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
type = ICMP_UNREACH;
code = ICMP_UNREACH_HOST;
goto bad;
}
bcopy((SLIRPcaddr_t)&(IA_SIN(ia)->sin_addr),
(SLIRPcaddr_t)(cp + off), sizeof(struct in_addr));
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
break;
case IPOPT_TS:
code = cp - (u_char *)ip;
ipt = (struct ip_timestamp *)cp;
if (ipt->ipt_len < 5)
goto bad;
if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
if (++ipt->ipt_oflw == 0)
goto bad;
break;
}
sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
switch (ipt->ipt_flg) {
case IPOPT_TS_TSONLY:
break;
case IPOPT_TS_TSANDADDR:
if (ipt->ipt_ptr + sizeof(n_time) +
sizeof(struct in_addr) > ipt->ipt_len)
goto bad;
ipaddr.sin_addr = dst;
ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,
m->m_pkthdr.rcvif);
if (ia == 0)
continue;
bcopy((SLIRPcaddr_t)&IA_SIN(ia)->sin_addr,
(SLIRPcaddr_t)sin, sizeof(struct in_addr));
ipt->ipt_ptr += sizeof(struct in_addr);
break;
case IPOPT_TS_PRESPEC:
if (ipt->ipt_ptr + sizeof(n_time) +
sizeof(struct in_addr) > ipt->ipt_len)
goto bad;
bcopy((SLIRPcaddr_t)sin, (SLIRPcaddr_t)&ipaddr.sin_addr,
sizeof(struct in_addr));
if (ifa_ifwithaddr((SA)&ipaddr) == 0)
continue;
ipt->ipt_ptr += sizeof(struct in_addr);
break;
default:
goto bad;
}
ntime = iptime();
bcopy((SLIRPcaddr_t)&ntime, (SLIRPcaddr_t)cp + ipt->ipt_ptr - 1,
sizeof(n_time));
ipt->ipt_ptr += sizeof(n_time);
}
}
if (forward) {
ip_forward(m, 1);
return (1);
}
}
}
return (0);
bad:
/* ip->ip_len -= ip->ip_hl << 2; XXX icmp_error adds in hdr length */
/* Not yet */
icmp_error(m, type, code, 0, 0);
ipstat.ips_badoptions++;
return (1);
}
#endif /* notdef */
/*
* Strip out IP options, at higher
* level protocol in the kernel.
* Second argument is buffer to which options
* will be moved, and return value is their length.
* (XXX) should be deleted; last arg currently ignored.
*/
void
ip_stripoptions(struct SLIRPmbuf *m, struct SLIRPmbuf *mopt)
{
register int i;
struct ip *ip = mtod(m, struct ip *);
register SLIRPcaddr_t opts;
int olen;
olen = (ip->ip_hl<<2) - sizeof (struct ip);
opts = (SLIRPcaddr_t)(ip + 1);
i = m->m_len - (sizeof (struct ip) + olen);
memcpy(opts, opts + olen, (unsigned)i);
m->m_len -= olen;
ip->ip_hl = sizeof(struct ip) >> 2;
}

220
src/ip_output.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94
* ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
#include "if.h"
#include "ip.h"
/*
* Changes and additions relating to SLiRP are
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
uint16_t ip_id;
/*
* IP output. The packet in SLIRPmbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst).
* The SLIRPmbuf chain containing the packet will be freed.
* The SLIRPmbuf opt, if present, will not be freed.
*/
int
ip_output(struct SLIRPsocket *so, struct SLIRPmbuf *m0)
{
u_int hlen = sizeof(struct ip);
struct SLIRPmbuf **mnext;
struct SLIRPmbuf *m = m0;
struct ip *ip, *mhip;
int mhlen, firstlen;
u_int len, off;
int error = 0;
DEBUG_CALL("ip_output");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m0 = %lx", (long)m0);
/* We do no options */
#if 0
if (opt) {
m = ip_insertoptions(m, opt, &len);
hlen = len;
}
#endif
/* Fill in IP header. */
ip = mtod(m, struct ip *);
ip->ip_v = IPVERSION;
ip->ip_off &= IP_DF;
ip->ip_id = htons(ip_id++);
ip->ip_hl = hlen >> 2;
ipstat.ips_localout++;
/*
* Verify that we have any chance at all of being able to queue
* the packet or packet fragments
*/
#if 0
/* XXX Hmmm... */
if (if_queued > if_thresh && towrite <= 0) {
error = ENOBUFS;
goto bad;
}
#endif
/* If small enough for interface, can just send directly. */
if ((uint16_t)ip->ip_len <= if_mtu) {
ip->ip_len = htons((uint16_t)ip->ip_len);
ip->ip_off = htons((uint16_t)ip->ip_off);
ip->ip_sum = 0;
ip->ip_sum = cksum(m, hlen);
if_output(so, m);
goto done;
}
/*
* Too large for interface; fragment if possible.
* Must be able to put at least 8 bytes per fragment.
*/
if (ip->ip_off & IP_DF) {
error = -1;
ipstat.ips_cantfrag++;
goto bad;
}
len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
if (len < 8) {
error = -1;
goto bad;
}
mnext = &m->m_nextpkt;
firstlen = len;
/*
* Loop through length of segment after first fragment,
* make new header and copy data of each part and link onto chain.
*/
m0 = m;
mhlen = sizeof (struct ip);
for (off = hlen + len; off < ip->ip_len; off += len) {
m = m_get();
if (m == 0) {
error = -1;
ipstat.ips_odropped++;
goto sendorfree;
}
m->m_data += if_maxlinkhdr;
mhip = mtod(m, struct ip *);
*mhip = *ip;
/* No options */
#if 0
if (hlen > sizeof (struct ip)) {
mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
mhip->ip_hl = mhlen >> 2;
}
#endif
m->m_len = mhlen;
mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
if (ip->ip_off & IP_MF)
mhip->ip_off |= IP_MF;
if (off + len >= (uint16_t)ip->ip_len)
len = (uint16_t)ip->ip_len - off;
else
mhip->ip_off |= IP_MF;
mhip->ip_len = htons((uint16_t)(len + mhlen));
if (m_copy(m, m0, off, len) < 0) {
error = -1;
goto sendorfree;
}
mhip->ip_off = htons((uint16_t)mhip->ip_off);
mhip->ip_sum = 0;
mhip->ip_sum = cksum(m, mhlen);
*mnext = m;
mnext = &m->m_nextpkt;
ipstat.ips_ofragments++;
}
/*
* Update first fragment by trimming what's been copied out
* and updating header, then send each fragment (in order).
*/
m = m0;
m_adj(m, hlen + firstlen - ip->ip_len);
ip->ip_len = htons((uint16_t)m->m_len);
ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF));
ip->ip_sum = 0;
ip->ip_sum = cksum(m, hlen);
sendorfree:
for (m = m0; m; m = m0) {
m0 = m->m_nextpkt;
m->m_nextpkt = 0;
if (error == 0)
if_output(so, m);
else
m_freem(m);
}
if (error == 0)
ipstat.ips_fragmented++;
done:
return(error);
bad:
m_freem(m0);
goto done;
}

245
src/mbuf.c Normal file
View File

@@ -0,0 +1,245 @@
/*
* Copyright (c) 1995 Danny Gasparovski
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "misc.h" // merge with slirp.h
#include "mbuf.h"
#include "if.h"
/*
* mbuf's in SLiRP are much simpler than the real mbufs in
* FreeBSD. They are fixed size, determined by the MTU,
* so that one whole packet can fit. Mbuf's cannot be
* chained together. If there's more data than the mbuf
* could hold, an external malloced buffer is pointed to
* by m_ext (and the data pointers) and M_EXT is set in
* the flags
*/
struct mbuf *mbutl;
char *mclrefcnt;
int mbuf_alloced = 0;
struct SLIRPmbuf m_freelist, m_usedlist;
int mbuf_thresh = 30;
int mbuf_max = 0;
size_t msize;
void
m_init(void)
{
m_freelist.m_next = m_freelist.m_prev = &m_freelist;
m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
msize_init();
}
void msize_init(void)
{
/*
* Find a nice value for msize
* XXX if_maxlinkhdr already in mtu
*/
msize = (if_mtu>if_mru?if_mtu:if_mru) +
if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
}
/*
* Get an mbuf from the free list, if there are none
* malloc one
*
* Because fragmentation can occur if we alloc new mbufs and
* free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
* which tells m_free to actually free() it
*/
struct SLIRPmbuf * m_get(void)
{
struct SLIRPmbuf *m;
int flags = 0;
DEBUG_CALL("m_get");
if (m_freelist.m_next == &m_freelist) {
m = (struct SLIRPmbuf *)malloc(msize);
if (m == NULL) goto end_error;
mbuf_alloced++;
if (mbuf_alloced > mbuf_thresh)
flags = M_DOFREE;
if (mbuf_alloced > mbuf_max)
mbuf_max = mbuf_alloced;
} else {
m = m_freelist.m_next;
remque(m);
}
/* Insert it in the used list */
insque(m,&m_usedlist);
m->m_flags = (flags | M_USEDLIST);
/* Initialise it */
m->m_size = msize - sizeof(struct m_hdr);
m->m_data = m->m_dat;
m->m_len = 0;
m->m_nextpkt = 0;
m->m_prevpkt = 0;
end_error:
DEBUG_ARG("m = %lx", (long )m);
return m;
}
//For some reason this fails in GDB saying tehre is no m_flags member
void
m_free(struct SLIRPmbuf *m)
{
DEBUG_CALL("m_free");
DEBUG_ARG("m = %lx", (long )m);
if(m) {
/* Remove from m_usedlist */
if (m->m_flags & M_USEDLIST)
remque(m);
/* If it's M_EXT, free() it */
if (m->m_flags & M_EXT)
free(m->m_ext);
/*
* Either free() it or put it on the free list
*/
if (m->m_flags & M_DOFREE) {
free(m);
mbuf_alloced--;
} else if ((m->m_flags & M_FREELIST) == 0) {
insque(m,&m_freelist);
m->m_flags = M_FREELIST; /* Clobber other flags */
}
} /* if(m) */
}
/*
* Copy data from one mbuf to the end of
* the other.. if result is too big for one mbuf, malloc()
* an M_EXT data segment
*/
void
m_cat(struct SLIRPmbuf *m, struct SLIRPmbuf *n)
{
/*
* If there's no room, realloc
*/
if (M_FREEROOM(m) < n->m_len)
m_inc(m,m->m_size+MINCSIZE);
memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
m->m_len += n->m_len;
m_free(n);
}
/* make m size bytes large */
void
m_inc(struct SLIRPmbuf *m, int size)
{
int datasize;
/* some compiles throw up on gotos. This one we can fake. */
if (m->m_size > (u_int)size) return;
if (m->m_flags & M_EXT) {
datasize = m->m_data - m->m_ext;
m->m_ext = (char *)realloc(m->m_ext,size);
/* if (m->m_ext == NULL)
* return (struct SLIRPmbuf *)NULL;
*/
m->m_data = m->m_ext + datasize;
} else {
char *dat;
datasize = m->m_data - m->m_dat;
dat = (char *)malloc(size);
/* if (dat == NULL)
* return (struct SLIRPmbuf *)NULL;
*/
memcpy(dat, m->m_dat, m->m_size);
m->m_ext = dat;
m->m_data = m->m_ext + datasize;
m->m_flags |= M_EXT;
}
m->m_size = size;
}
void
m_adj(struct SLIRPmbuf *m, int len)
{
if (m == NULL)
return;
if (len >= 0) {
/* Trim from head */
m->m_data += len;
m->m_len -= len;
} else {
/* Trim from tail */
len = -len;
m->m_len -= len;
}
}
/*
* Copy len bytes from m, starting off bytes into n
*/
int
m_copy(struct SLIRPmbuf *n, struct SLIRPmbuf *m, int off, int len)
{
if (len > M_FREEROOM(n))
return -1;
memcpy((n->m_data + n->m_len), (m->m_data + off), len);
n->m_len += len;
return 0;
}
/*
* Given a pointer into an mbuf, return the mbuf
* XXX This is a kludge, I should eliminate the need for it
* Fortunately, it's not used often
*/
struct SLIRPmbuf *
dtom(void *dat)
{
struct SLIRPmbuf *m;
DEBUG_CALL("dtom");
DEBUG_ARG("dat = %lx", (long )dat);
/* bug corrected for M_EXT buffers */
for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) {
if (m->m_flags & M_EXT) {
if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
return m;
} else {
if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
return m;
}
}
DEBUG_ERROR((dfd, "dtom failed"));
return (struct SLIRPmbuf *)0;
}

146
src/mbuf.h Normal file
View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mbuf.h 8.3 (Berkeley) 1/21/94
* mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp
*/
#ifndef SLIRP_MBUF_H
# define SLIRP_MBUF_H
#define m_freem m_free
#define MINCSIZE 4096 /* Amount to increase mbuf if too small */
/*
* Macros for type conversion
* mtod(m,t) - convert mbuf pointer to data pointer of correct type
* dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX)
*/
#define mtod(m,t) ((t)(m)->m_data)
/* #define dtom(x) ((struct SLIRPmbuf *)((int)(x) & ~(M_SIZE-1))) */
/* XXX About mbufs for slirp:
* Only one mbuf is ever used in a chain, for each "cell" of data.
* m_nextpkt points to the next packet, if fragmented.
* If the data is too large, the M_EXT is used, and a larger block
* is alloced. Therefore, m_free[m] must check for M_EXT and if set
* free the m_ext. This is inefficient memory-wise, but who cares.
*/
/* XXX should union some of these! */
/* header at beginning of each mbuf: */
struct m_hdr {
struct SLIRPmbuf *mh_next; /* Linked list of mbufs */
struct SLIRPmbuf *mh_prev;
struct SLIRPmbuf *mh_nextpkt; /* Next packet in queue/record */
struct SLIRPmbuf *mh_prevpkt; /* Flags aren't used in the output queue */
int mh_flags; /* Misc flags */
size_t mh_size; /* Size of data */
struct SLIRPsocket *mh_so;
SLIRPcaddr_t mh_data; /* Location of data */
int32_t mh_len; /* Amount of data in this mbuf */
};
/*
* How much room is in the mbuf, from m_data to the end of the mbuf
*/
#define M_ROOM(m) ((m->m_flags & M_EXT)? \
(((m)->m_ext + (m)->m_size) - (m)->m_data) \
: \
(((m)->m_dat + (m)->m_size) - (m)->m_data))
/*
* How much free room there is
*/
#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len)
#define M_TRAILINGSPACE M_FREEROOM
struct SLIRPmbuf {
struct m_hdr m_hdr;
union M_dat {
char m_dat_[1]; /* ANSI don't like 0 sized arrays */
char *m_ext_;
} M_dat;
};
#define m_next m_hdr.mh_next
#define m_prev m_hdr.mh_prev
#define m_nextpkt m_hdr.mh_nextpkt
#define m_prevpkt m_hdr.mh_prevpkt
#define m_flags m_hdr.mh_flags
#define m_len m_hdr.mh_len
#define m_data m_hdr.mh_data
#define m_size m_hdr.mh_size
#define m_dat M_dat.m_dat_
#define m_ext M_dat.m_ext_
#define m_so m_hdr.mh_so
#define ifq_prev m_prev
#define ifq_next m_next
#define ifs_prev m_prevpkt
#define ifs_next m_nextpkt
#define ifq_so m_so
#define M_EXT 0x01 /* m_ext points to more (malloced) data */
#define M_FREELIST 0x02 /* mbuf is on free list */
#define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */
#define M_DOFREE 0x08 /* when m_free is called on the mbuf, free()
* it rather than putting it on the free list */
/*
* Mbuf statistics. XXX
*/
struct mbstat {
int mbs_alloced; /* Number of mbufs allocated */
};
extern struct mbstat mbstat;
extern int mbuf_alloced;
extern struct SLIRPmbuf m_freelist, m_usedlist;
extern int mbuf_max;
extern void m_init(void);
extern void msize_init(void);
extern struct SLIRPmbuf *m_get(void);
extern void m_free(struct SLIRPmbuf *);
extern void m_cat(register struct SLIRPmbuf *, register struct SLIRPmbuf *);
extern void m_inc(struct SLIRPmbuf *, int);
extern void m_adj(struct SLIRPmbuf *, int);
extern int m_copy(struct SLIRPmbuf *, struct SLIRPmbuf *, int, int);
extern struct SLIRPmbuf *dtom(void *);
#endif /*SLIRP_MBUF_H*/

135
src/misc.c Normal file
View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include "slirp.h"
#include "debug.h" // merge with slirp.h
//#if SIZEOF_CHAR_P == 8
struct quehead_32 {
uintptr_t qh_link;
uintptr_t qh_rlink;
};
inline void
insque_32(void *a, void *b)
{
register struct quehead_32 *el = (struct quehead_32 *) a;
register struct quehead_32 *head = (struct quehead_32 *) b;
el->qh_link = head->qh_link;
head->qh_link = (uintptr_t)el;
el->qh_rlink = (uintptr_t)head;
((struct quehead_32 *)(el->qh_link))->qh_rlink = (uintptr_t)el;
}
inline void
remque_32(void *a)
{
register struct quehead_32 *el = (struct quehead_32 *) a;
((struct quehead_32 *)(el->qh_link))->qh_rlink = el->qh_rlink;
((struct quehead_32 *)(el->qh_rlink))->qh_link = el->qh_link;
el->qh_rlink = 0;
}
//#endif /* SIZEOF_CHAR_P == 8 */
struct quehead {
struct quehead *qh_link;
struct quehead *qh_rlink;
};
void
insque(void *a, void *b)
{
register struct quehead *el = (struct quehead *) a;
register struct quehead *head = (struct quehead *) b;
el->qh_link = head->qh_link;
head->qh_link = (struct quehead *)el;
el->qh_rlink = (struct quehead *)head;
((struct quehead *)(el->qh_link))->qh_rlink = (struct quehead *)el;
}
void
remque(void *a)
{
register struct quehead *el = (struct quehead *) a;
((struct quehead *)(el->qh_link))->qh_rlink = el->qh_rlink;
((struct quehead *)(el->qh_rlink))->qh_link = el->qh_link;
el->qh_rlink = NULL;
#if 0
el->qh_link = NULL; /* TCP FIN1 crashes if you do this. Why ? */
#endif
}
#ifndef HAVE_STRERROR
/* For systems with no strerror. */
char *
SLIRPstrerror(int error)
{
if (error < sys_nerr)
return sys_errlist[error];
return "Unknown error.";
}
#endif
/* Set fd blocking and non-blocking. */
void
fd_nonblock(int fd)
{
#if defined(USE_FIONBIO) && defined(FIONBIO)
ioctlsockopt_t opt = 1;
ioctlsocket(fd, FIONBIO, &opt);
#else
int opt;
opt = fcntl(fd, F_GETFL, 0);
opt |= O_NONBLOCK;
fcntl(fd, F_SETFL, opt);
#endif
}
void
fd_block(int fd)
{
#if defined(USE_FIONBIO) && defined(FIONBIO)
ioctlsockopt_t opt = 0;
ioctlsocket(fd, FIONBIO, &opt);
#else
int opt;
opt = fcntl(fd, F_GETFL, 0);
opt &= ~O_NONBLOCK;
fcntl(fd, F_SETFL, opt);
#endif
}

74
src/misc.h Normal file
View File

@@ -0,0 +1,74 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifndef SLIRP_MISC_H
# define SLIRP_MISC_H
#ifdef USE_REDIR
struct ex_list {
int ex_pty; /* Do we want a pty? */
int ex_addr; /* The last byte of the address */
int ex_fport; /* Port to telnet to */
char *ex_exec; /* Command line of what to exec */
struct ex_list *ex_next;
};
struct emu_t {
uint16_t lport;
uint16_t fport;
uint8_t tos;
uint8_t emu;
struct emu_t *next;
};
extern struct emu_t *tcpemu;
extern int x_port, x_server, x_display;
extern struct ex_list *exec_list;
#endif
#define EMU_NONE 0x0
/* TCP emulations */
#define EMU_CTL 0x1
#define EMU_FTP 0x2
#define EMU_KSH 0x3
#define EMU_IRC 0x4
#define EMU_REALAUDIO 0x5
#define EMU_RLOGIN 0x6
#define EMU_IDENT 0x7
#define EMU_RSH 0x8
#define EMU_NOCONNECT 0x10 /* Don't connect */
/* UDP emulations */
#define EMU_TALK 0x1
#define EMU_NTALK 0x2
#define EMU_CUSEEME 0x3
struct tos_t {
uint16_t lport;
uint16_t fport;
uint8_t tos;
uint8_t emu;
};
extern u_int curtime, detach_time, detach_wait;
extern void slirp_insque(void *, void *);
extern void slirp_remque(void *);
extern void fd_nonblock(int);
extern void fd_block(int);
#endif /*SLIRP_MISC_H*/

342
src/poll.c Normal file
View File

@@ -0,0 +1,342 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#ifdef _WIN32
# include <windows.h>
# ifdef _MSC_VER
# include <time.h>
# else
# include <sys/time.h>
# endif
#else
# include <sys/ioctl.h>
# include <sys/time.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "mbuf.h"
#include "if.h"
#include "socket.h"
#include "mbuf.h"
#include "ip.h"
#include "tcp.h"
#include "udp.h"
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
u_int curtime;
fd_set *global_readfds,
*global_writefds,
*global_xfds;
/* curtime kept to an accuracy of 1ms */
static void
updtime(void)
{
#ifdef _WIN32
struct _timeb tb;
_ftime(&tb);
curtime = (u_int)tb.time * (u_int)1000;
curtime += (u_int)tb.millitm;
#else
struct timeval tt;
gettimeofday(&tt, 0);
curtime = (u_int)tt.tv_sec * (u_int)1000;
curtime += (u_int)tt.tv_usec / (u_int)1000;
if ((tt.tv_usec % 1000) >= 500)
curtime++;
#endif
}
static int
poll_fill(slirp_t *slirp, int *pnfds, fd_set *rfds, fd_set *wfds, fd_set *xfds)
{
struct SLIRPsocket *so, *so_next;
int nfds, tmo, tmp_time;
/* fail safe */
global_readfds = NULL;
global_writefds = NULL;
global_xfds = NULL;
nfds = *pnfds;
/* First, TCP sockets. */
slirp->do_slowtimo = 0;
if (slirp->link_up) {
/*
* *_slowtimo needs calling if there are IP fragments
* in the fragment queue, or there are TCP connections active
*/
slirp->do_slowtimo = ((tcb.so_next != &tcb) ||
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
for (so = tcb.so_next; (so != &tcb); so = so_next) {
so_next = so->so_next;
/* See if we need a tcp_fasttimo. */
if (so->so_tcpcb != 0) {
/* This is to prevent a common lockup. */
if (slirp->time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
/* Flag when we want a fasttimo */
slirp->time_fasttimo = curtime;
}
/*
* NOFDREF can include still connecting to local-host,
* newly socreated() sockets etc. Don't want to select
* these.
*/
if (so->so_state & SS_NOFDREF || so->s == -1)
continue;
/* Set for reading sockets which are accepting. */
if (so->so_state & SS_FACCEPTCONN) {
FD_SET(so->s, rfds);
UPD_NFDS(so->s);
continue;
}
/* Set for writing sockets which are connecting. */
if (so->so_state & SS_ISFCONNECTING) {
FD_SET(so->s, wfds);
UPD_NFDS(so->s);
continue;
}
/*
* Set for writing if we are connected, can send more,
* and we have something to send.
*/
if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
FD_SET(so->s, wfds);
UPD_NFDS(so->s);
}
/*
* Set for reading (and urgent data) if we are
* connected, can receive more, and we have room
* for it XXX /2 ?
*/
if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
FD_SET(so->s, rfds);
FD_SET(so->s, xfds);
UPD_NFDS(so->s);
}
}
/* UDP sockets. */
for (so = udb.so_next; so != &udb; so = so_next) {
so_next = so->so_next;
/* See if it's timed out. */
if (so->so_expire) {
if (so->so_expire <= curtime) {
udp_detach(so);
continue;
} else
slirp->do_slowtimo = 1; /* Let socket expire */
}
/*
* When UDP packets are received from over the
* link, they're sendto()'d straight away, so
* no need for setting for writing
* Limit the number of packets queued by this session
* to 4. Note that even though we try and limit this
* to 4 packets, the session could have more queued
* if the packets needed to be fragmented
* (XXX <= 4 ?)
*/
if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
FD_SET(so->s, rfds);
UPD_NFDS(so->s);
}
}
}
/* Setup timeout to use minimum CPU usage, especially when idle. */
tmo = -1;
/*
* If a slowtimo is needed, set timeout to 5ms from the last
* slow timeout. If a fast timeout is needed, set timeout within
* 2ms of when it was requested.
*/
#define SLOW_TIMO 5
#define FAST_TIMO 2
if (slirp->do_slowtimo) {
tmo = (SLOW_TIMO - (curtime - slirp->last_slowtimo)) * 1000;
if (tmo < 0)
tmo = 0;
else if (tmo > (SLOW_TIMO * 1000))
tmo = SLOW_TIMO * 1000;
/* Can only fasttimo if we also slowtimo */
if (slirp->time_fasttimo) {
tmp_time = (FAST_TIMO - (curtime - slirp->time_fasttimo)) * 1000;
if (tmp_time < 0)
tmp_time = 0;
/* Choose the smallest of the 2 */
if (tmp_time < tmo)
tmo = tmp_time;
}
}
*pnfds = nfds;
/*
* Adjust the timeout to make the minimum timeout
* 2ms (XXX?) to lessen the CPU load
*/
if (tmo < (FAST_TIMO * 1000))
tmo = FAST_TIMO * 1000;
return tmo;
}
static void
poll_select(slirp_t *slirp, fd_set *rfds, fd_set *wfds, fd_set *xfds)
{
struct SLIRPsocket *so, *so_next;
int ret;
global_readfds = rfds;
global_writefds = wfds;
global_xfds = xfds;
/* Update time */
updtime();
/* See if anything has timed out. */
if (slirp->link_up) {
if (slirp->time_fasttimo && ((curtime - slirp->time_fasttimo) >= FAST_TIMO)) {
tcp_fasttimo();
slirp->time_fasttimo = 0;
}
if (slirp->do_slowtimo && ((curtime - slirp->last_slowtimo) >= SLOW_TIMO)) {
ip_slowtimo();
tcp_slowtimo();
slirp->last_slowtimo = curtime;
}
}
/* Check sockets. */
if (slirp->link_up) {
/* Check TCP sockets. */
for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next;
/*
* FD_ISSET is meaningless on these sockets
* (and they can crash the program)
*/
if (so->so_state & SS_NOFDREF || so->s == -1)
continue;
/*
* Check for URG data
* This will soread as well, so no need to
* test for readfds below if this succeeds
*/
if (FD_ISSET(so->s, xfds))
sorecvoob(so);
/* Check sockets for reading. */
else if (FD_ISSET(so->s, rfds)) {
/* Check for incoming connections. */
if (so->so_state & SS_FACCEPTCONN) {
tcp_connect(so);
continue;
} /* else */
ret = soread(so);
/* Output it if we read something */
if (ret > 0)
tcp_output(sototcpcb(so));
}
/* Check sockets for writing. */
if (FD_ISSET(so->s, wfds)) {
/* Check for non-blocking, still-connecting sockets. */
if (so->so_state & SS_ISFCONNECTING) {
/* Connected */
so->so_state &= ~SS_ISFCONNECTING;
}
}
/*
* Now UDP sockets.
* Incoming packets are sent straight away, they're not
* buffered. Incoming UDP data isn't buffered either.
*/
for (so = udb.so_next; so != &udb; so = so_next) {
so_next = so->so_next;
if (so->s != -1 && FD_ISSET(so->s, rfds)) {
sorecvfrom(so);
}
}
}
}
/* See if we can start outputting. */
if (if_queued && slirp->link_up)
if_start();
/* Clear global file descriptor sets. */
global_readfds = NULL;
global_writefds = NULL;
global_xfds = NULL;
}
/* API: poll an instance for any work. */
int
slirp_poll(slirp_t *slirp)
{
fd_set rfds, wfds, xfds;
struct timeval tv;
int ret, nfds, tmo;
/* Create a list of all open sockets. */
nfds = -1;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&xfds);
tmo = poll_fill(slirp, &nfds, &rfds, &wfds, &xfds);
if (tmo < 0)
tmo = 500;
tv.tv_sec = 0;
tv.tv_usec = tmo;
/* Now wait for something to happen, or at most 'tmo' usec. */
ret = select(nfds+1, &rfds, &wfds, &xfds, &tv);
if (ret < 0)
return -1;
/* If something happened, let SLiRP handle it. */
if (ret >= 0)
poll_select(slirp, &rfds, &wfds, &xfds);
return ret;
}

115
src/queue.c Normal file
View File

@@ -0,0 +1,115 @@
/*
* File: queue.c
* Author: Robert I. Pitts <rip@cs.bu.edu>
* Last Modified: March 9, 2000
* Topic: Queue - Array Implementation
* ----------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
/*
* Constants
* ---------
* MAX_QUEUE_SIZE = Largest number of items queue can hold.
*/
#define MAX_QUEUE_SIZE 100
/*
* struct queueCDT gives the implementation of a queue.
* It holds the information that we need for each queue.
*/
typedef struct queueCDT {
queueElementT contents[MAX_QUEUE_SIZE];
int front;
int count;
} queueCDT;
queueADT QueueCreate(void)
{
queueADT queue;
queue = (queueADT)malloc(sizeof(queueCDT));
if (queue == NULL) {
fprintf(stderr, "Insufficient Memory for new Queue.\n");
exit(ERROR_MEMORY); /* Exit program, returning error code. */
}
queue->front = 0;
queue->count = 0;
return queue;
}
void QueueDestroy(queueADT queue)
{
free(queue);
}
void QueueEnter(queueADT queue, queueElementT element)
{
int newElementIndex;
if (queue->count >= MAX_QUEUE_SIZE) {
// fprintf(stderr, "QueueEnter on Full Queue.\n");
// exit(ERROR_QUEUE); /* Exit program, returning error code. */
return;
}
/*
* Calculate index at which to put
* next element.
*/
newElementIndex = (queue->front + queue->count)
% MAX_QUEUE_SIZE;
queue->contents[newElementIndex] = element;
//printf("element %d, pointer to %d, [%s]\n",newElementIndex,element,element);
queue->count++;
}
int QueuePeek(queueADT queue)
{
return queue->count;
}
queueElementT QueueDelete(queueADT queue)
{
queueElementT oldElement;
if (queue->count <= 0) {
//fprintf(stderr, "QueueDelete on Empty Queue.\n");
//exit(ERROR_QUEUE); /* Exit program, returning error code. */
return NULL;
}
/* Save the element so we can return it. */
oldElement = queue->contents[queue->front];
/*
* Advance the index of the front,
* making sure it wraps around the
* array properly.
*/
queue->front++;
queue->front %= MAX_QUEUE_SIZE;
//printf("dequing @%d [%s]\n",oldElement,oldElement);
queue->count--;
return oldElement;
}
int QueueIsEmpty(queueADT queue)
{
return queue->count <= 0;
}
int QueueIsFull(queueADT queue)
{
return queue->count >= MAX_QUEUE_SIZE;
}

101
src/queue.h Normal file
View File

@@ -0,0 +1,101 @@
/*
* File: queue.h
* Author: Robert I. Pitts <rip@cs.bu.edu>
* Last Modified: March 9, 2000
* Topic: Queue - Array Implementation
* ----------------------------------------------------------------
*/
#ifndef _QUEUE_H
#define _QUEUE_H
/*
* Constants
* ---------
* ERROR_* These signal error conditions in queue functions
* and are used as exit codes for the program.
*/
#define ERROR_QUEUE 2
#define ERROR_MEMORY 3
/*
* Type: queueElementT
* -------------------
* This is the type of objects held in the queue.
*/
/*typedef char queueElementT;
typedef unsigned char *queueElementT;
*/
struct queuepacket{
int len;
unsigned char data[2000];
};
typedef struct queuepacket *queueElementT;
/*
* Type: queueADT
* --------------
* The actual implementation of a queue is completely
* hidden. Client will work with queueADT which is a
* pointer to underlying queueCDT.
*/
/*
* NOTE: need word struct below so that the compiler
* knows at least that a queueCDT will be some sort
* of struct.
*/
typedef struct queueCDT *queueADT;
/*
* Function: QueueCreate
* Usage: queue = QueueCreate();
* -------------------------
* A new empty queue is created and returned.
*/
queueADT QueueCreate(void);
/* Function: QueueDestroy
* Usage: QueueDestroy(queue);
* -----------------------
* This function frees all memory associated with
* the queue. "queue" may not be used again unless
* queue = QueueCreate() is called first.
*/
void QueueDestroy(queueADT queue);
/*
* Functions: QueueEnter, QueueDelete
* Usage: QueueEnter(queue, element);
* element = QueueDelete(queue);
* --------------------------------------------
* These are the fundamental queue operations that enter
* elements in and delete elements from the queue. A call
* to QueueDelete() on an empty queue or to QueueEnter()
* on a full queue is an error. Make use of QueueIsFull()
* and QueueIsEmpty() (see below) to avoid these errors.
*/
void QueueEnter(queueADT queue, queueElementT element);
queueElementT QueueDelete(queueADT queue);
/*
* Functions: QueueIsEmpty, QueueIsFull
* Usage: if (QueueIsEmpty(queue)) ...
* -----------------------------------
* These return a true/false value based on whether
* the queue is empty or full, respectively.
*/
int QueueIsEmpty(queueADT queue);
int QueueIsFull(queueADT queue);
int QueuePeek(queueADT queue);
#endif /* not defined _QUEUE_H */

204
src/sbuf.c Normal file
View File

@@ -0,0 +1,204 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "misc.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
/* Done as a macro in socket.h */
/* int
* sbspace(struct sockbuff *sb)
* {
* return SB_DATALEN - sb->sb_cc;
* }
*/
void
sbfree(struct sbuf *sb)
{
free(sb->sb_data);
}
void
sbdrop(struct sbuf *sb, int num)
{
/*
* We can only drop how much we have
* This should never succeed
*/
if (num > (int)sb->sb_cc)
num = sb->sb_cc;
sb->sb_cc -= num;
sb->sb_rptr += num;
if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
sb->sb_rptr -= sb->sb_datalen;
}
void
sbreserve(struct sbuf *sb, int size)
{
if (sb->sb_data) {
/* Already alloced, realloc if necessary */
if (sb->sb_datalen != size) {
sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
sb->sb_cc = 0;
if (sb->sb_wptr)
sb->sb_datalen = size;
else
sb->sb_datalen = 0;
}
} else {
sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
sb->sb_cc = 0;
if (sb->sb_wptr)
sb->sb_datalen = size;
else
sb->sb_datalen = 0;
}
}
/*
* Try and write() to the socket, whatever doesn't get written
* append to the buffer... for a host with a fast net connection,
* this prevents an unnecessary copy of the data
* (the socket is non-blocking, so we won't hang)
*/
void
sbappend(struct SLIRPsocket *so, struct SLIRPmbuf *m)
{
int ret = 0;
DEBUG_CALL("sbappend");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("m->m_len = %d", m->m_len);
/* Shouldn't happen, but... e.g. foreign host closes connection */
if (m->m_len <= 0) {
m_free(m);
return;
}
/*
* If there is urgent data, call sosendoob
* if not all was sent, sowrite will take care of the rest
* (The rest of this function is just an optimisation)
*/
if (so->so_urgc) {
sbappendsb(&so->so_rcv, m);
m_free(m);
sosendoob(so);
return;
}
/*
* We only write if there's nothing in the buffer,
* ottherwise it'll arrive out of order, and hence corrupt
*/
if (!so->so_rcv.sb_cc)
ret = send(so->s, m->m_data, m->m_len, 0);
if (ret <= 0) {
/*
* Nothing was written
* It's possible that the socket has closed, but
* we don't need to check because if it has closed,
* it will be detected in the normal way by soread()
*/
sbappendsb(&so->so_rcv, m);
} else if (ret != m->m_len) {
/*
* Something was written, but not everything..
* sbappendsb the rest
*/
m->m_len -= ret;
m->m_data += ret;
sbappendsb(&so->so_rcv, m);
} /* else */
/* Whatever happened, we free the SLIRPmbuf */
m_free(m);
}
/*
* Copy the data from m into sb
* The caller is responsible to make sure there's enough room
*/
void
sbappendsb(struct sbuf *sb, struct SLIRPmbuf *m)
{
int len, n, nn;
len = m->m_len;
if (sb->sb_wptr < sb->sb_rptr) {
n = sb->sb_rptr - sb->sb_wptr;
if (n > len) n = len;
memcpy(sb->sb_wptr, m->m_data, n);
} else {
/* Do the right edge first */
n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
if (n > len) n = len;
memcpy(sb->sb_wptr, m->m_data, n);
len -= n;
if (len) {
/* Now the left edge */
nn = sb->sb_rptr - sb->sb_data;
if (nn > len) nn = len;
memcpy(sb->sb_data,m->m_data+n,nn);
n += nn;
}
}
sb->sb_cc += n;
sb->sb_wptr += n;
if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
sb->sb_wptr -= sb->sb_datalen;
}
/*
* Copy data from sbuf to a normal, straight buffer
* Don't update the sbuf rptr, this will be
* done in sbdrop when the data is acked
*/
void
sbcopy(struct sbuf *sb, int off, int len, char *to)
{
char *from;
from = sb->sb_rptr + off;
if (from >= sb->sb_data + sb->sb_datalen)
from -= sb->sb_datalen;
if (from < sb->sb_wptr) {
if (len > (int)sb->sb_cc) len = sb->sb_cc;
memcpy(to,from,len);
} else {
/* re-use off */
off = (sb->sb_data + sb->sb_datalen) - from;
if (off > len) off = len;
memcpy(to,from,off);
len -= off;
if (len)
memcpy(to+off,sb->sb_data,len);
}
}

294
src/slirp.c Normal file
View File

@@ -0,0 +1,294 @@
#ifdef _WIN32
# include <winsock2.h> /* on top otherwise, it'll pull in winsock1 */
#else
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "host.h"
#include "mbuf.h"
#include "if.h"
#include "socket.h"
#include "arp.h"
#include "ip.h"
#ifdef USE_REDIR
# include "redir.h"
#endif
/* Our actual addresses. */
char slirp_hostname[32];
char slirp_domainname[128];
struct in_addr our_addr; /* host IP address */
struct in_addr dns_addr; /* host DNS server */
struct in_addr loopback_addr; /* host loopback address */
/* Our virtual addresses. */
const uint8_t special_macaddr[ETH_ALEN] = {
0x52, 0x54, 0x00, 0x12, 0x35, 0x00 /* virtual MAC address. */
};
struct in_addr special_addr; /* virtual IP address */
struct in_addr router_addr; /* virtual address alias for router */
struct in_addr server_addr; /* virtual address alias for server */
//struct in_addr alias_addr; /* virtual address alias for host */
//struct in_addr myaddr;
uint8_t client_macaddr[ETH_ALEN]; /* guest's MAC address */
int link_up;
u_int detach_time;
u_int detach_wait = 600000; /* 10 minutes */
/* API: return the library version. */
int
slirp_version(char *bufp, int max_len)
{
char temp[128];
sprintf(temp, "%s", SLIRP_VERSION);
strncpy(bufp, temp, max_len);
return(strlen(temp));
}
/* API: initialize an instance for use. */
slirp_t *
slirp_init(void)
{
slirp_t *slirp;
#if 0
char *sp;
#endif
/* First of all, initialize any host stuff. */
if (host_init() != 0) return(NULL);
/* Allocate an instance, and initialize it. */
slirp = (slirp_t *)malloc(sizeof(slirp_t));
if (slirp == NULL)
return(NULL);
memset(slirp, 0x00, sizeof(slirp_t));
slirp->instance = 1;
slirp->link_up = 1;
if_init(slirp);
ip_init();
/* Initialize mbufs *after* setting the MTU. */
m_init();
/* Set default addresses. */
memset(&our_addr, 0x00, sizeof(our_addr));
memset(&dns_addr, 0x00, sizeof(dns_addr));
inet_aton("127.0.0.1", &loopback_addr);
/* Get local hostname and domainname. */
memset(slirp_hostname, 0, sizeof(slirp_hostname));
memset(slirp_domainname, 0, sizeof(slirp_domainname));
#if 0
if (! gethostname(temp, sizeof(temp) - 1)) {
/* We got the hostname. Do an IP lookup on it. */
hp = gethostbyname(temp);
if (hp != NULL)
strncpy(temp, hp->h_name, sizeof(temp));
sp = strchr(temp, '.');
if (sp != NULL)
*sp++ = '\0';
strncpy(slirp_hostname, temp, sizeof(slirp_hostname));
strcat(slirp_hostname, "_slirp");
if (sp != NULL) {
strncpy(slirp_domainname, sp, sizeof(slirp_domainname));
strcat(slirp_hostname, ".");
strcat(slirp_hostname, slirp_domainname);
}
}
#endif
/* Get the host's network information. */
if (host_get_info(&dns_addr, slirp_hostname, slirp_domainname) < 0) {
free(slirp);
return NULL;
}
/*
* Initialize the virtual network.
*
* The default network configuration is:
*
* Network: 10.0.2.0/24 (255.255.255.0)
* Router: 10.0.2.1
* DHCP/DNS: 10.0.2.2
* Local: 10.0.2.15 (this may be removed later)
*/
inet_aton(CTL_SPECIAL, &special_addr);
router_addr.s_addr = special_addr.s_addr | htonl(CTL_ROUTER);
server_addr.s_addr = special_addr.s_addr | htonl(CTL_SERVER);
#ifdef CTL_LOCAL
myaddr.s_addr = special_addr.s_addr | htonl(CTL_LOCAL);
#endif
#ifdef USE_REDIR
redir_init();
#endif
return slirp;
}
/* API: close an instance, and release all resources. */
void
slirp_close(slirp_t *slirp)
{
if (slirp != NULL)
free(slirp);
/* Close down any host stuff. */
host_close();
}
/* API: receive a packet from the inbound queue. */
int
slirp_recv(slirp_t *slirp, uint8_t *bufp)
{
return 0;
}
/* API: send a packet to the outbound interface. */
int
slirp_send(slirp_t *slirp, uint8_t *bufp, int pkt_len)
{
return 0;
}
void
slirp_input(const uint8_t *pkt, int pkt_len)
{
struct SLIRPmbuf *m;
int proto;
if (pkt_len < ETH_HLEN)
return;
proto = (pkt[12] << 8) | pkt[13];
switch(proto) {
case ETH_P_ARP:
arp_input(pkt, pkt_len);
break;
case ETH_P_IP:
m = m_get();
if (!m)
return;
/* Note: we add to align the IP header */
m->m_len = pkt_len + 2;
memcpy(m->m_data + 2, pkt, pkt_len);
m->m_data += 2 + ETH_HLEN;
m->m_len -= 2 + ETH_HLEN;
ip_input(m);
break;
default:
break;
}
}
/* Output the IP packet to the client device. */
void
if_encap(const uint8_t *ip_data, int ip_data_len)
{
uint8_t buff[1600];
struct ethhdr *eh = (struct ethhdr *)buff;
if (ip_data_len + ETH_HLEN > sizeof(buff))
return;
/* Set the client device's MAC address. */
memcpy(eh->h_dest, client_macaddr, ETH_ALEN);
/* Set our MAC address. */
memcpy(eh->h_source, special_macaddr, ETH_ALEN - 1);
eh->h_source[5] = CTL_SERVER;
/* This works for IP, but not NetWare and such. */
eh->h_proto = htons(ETH_P_IP);
/* Now copy in the data to be sent. */
memcpy(buff + ETH_HLEN, ip_data, ip_data_len);
ip_data_len += ETH_HLEN;
slirp_output(buff, ip_data_len);
}
static void
purgesocks(void)
{
struct SLIRPsocket *so;
for (so = tcb.so_next; so != &tcb; so = so->so_next)
closesocket(so->s); //close the socket
}
void
slirp_exit(int exit_status)
{
DEBUG_CALL("slirp_exit");
DEBUG_ARG("exit_status = %d", exit_status);
if (dostats) {
ipstats();
tcpstats();
udpstats();
icmpstats();
mbufstats();
sockstats();
fclose(dfd);
}
purgesocks();
}
/* Needed by SLiRP library. */
void
slirp_output(const uint8_t *pkt, int pkt_len)
{
#if 0
struct queuepacket *qp;
if (slirpq != NULL) {
qp = (struct queuepacket *)mem_alloc(sizeof(struct queuepacket));
qp->len = pkt_len;
memcpy(qp->data, pkt, pkt_len);
QueueEnter(slirpq, qp);
}
#endif
}
/* Needed by SLiRP library. */
int
slirp_can_output(void)
{
// return((slirp != NULL)?1:0);
return 0;
}

133
src/slirp.h Normal file
View File

@@ -0,0 +1,133 @@
#ifndef SLIRP_H
# define SLIRP_H
# include "config.h"
#define SLIRP_VERSION "1.0.9"
#define CTL_SPECIAL "10.222.2.0"
//#define CTL_CMD 0
#define CTL_ROUTER 1
#define CTL_SERVER 2 /* handled BOOTP/DHCP and DNS */
//#define CTL_EXEC 4
//#define CTL_LOCAL 15
/* Define to 1 if you want KEEPALIVE timers */
#define DO_KEEPALIVE 0 /* tcp_timer.c */
#define MIN_MRU 128
#define MAX_MRU 16384
/* Avoid conflicting with the libc insque() and remque(), which
have different prototypes. */
#ifdef insque
# undef insque
#endif
#define insque slirp_insque
#ifdef remque
# undef remque
#endif
#define remque slirp_remque
#if SIZEOF_CHAR_P == 4
# define insque_32 insque
# define remque_32 remque
#else
# ifdef NEED_QUE32_INLINE
extern __inline void insque_32(void *, void *);
extern __inline void remque_32(void *);
# else
extern void insque_32(void *, void *);
extern void remque_32(void *);
# endif
#endif
#ifndef _WIN32
# define min(x,y) ((x) < (y) ? (x) : (y))
# define max(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int instance;
int link_up;
/* poll.c */
int do_slowtimo;
u_int time_fasttimo,
last_slowtimo;
} slirp_t;
typedef void (*log_func_t)(slirp_t *, const char *, ...);
extern char slirp_hostname[32];
extern char slirp_domainname[128];
extern uint8_t client_macaddr[6];
extern const uint8_t special_macaddr[];
extern int link_up;
extern u_int curtime;
#ifdef HAVE_SOCKET_H
extern fd_set *global_readfds, *global_writefds, *global_xfds;
#endif
#ifdef HAVE_INADDR_H
extern struct in_addr our_addr;
extern struct in_addr loopback_addr;
extern struct in_addr dns_addr;
extern struct in_addr special_addr;
extern struct in_addr router_addr;
extern struct in_addr ctl_addr;
#endif
extern int towrite_max;
extern int so_options;
extern int tcp_keepintvl;
extern int do_echo;
/* stats.c */
extern void mbufstats(void);
extern void sockstats(void);
extern void ipstats(void);
extern void icmpstats(void);
extern void tcpstats(void);
extern void udpstats(void);
extern int slirp_version(char *bufp, int max_len);
extern slirp_t *slirp_init(void);
extern void slirp_close(slirp_t *);
extern int slirp_poll(slirp_t *slirp);
#ifdef USE_REDIR
extern int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port);
extern int slirp_add_exec(int do_pty, const char *args,
int addr_low_byte, int guest_port);
#endif
extern int slirp_can_output(void);
extern void slirp_output(const uint8_t *pkt, int pkt_len);
extern void slirp_input(const uint8_t *pkt, int pkt_len);
#ifdef __cplusplus
}
#endif
#endif

769
src/socket.c Normal file
View File

@@ -0,0 +1,769 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifdef _WIN32
# include <windows.h>
# ifdef _DEBUG
# undef errno
# define errno (WSAGetLastError())
# endif
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
# ifdef _DEBUG
# include <errno.h>
# endif
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifndef FIONREAD
# include <sys/ioctl.h>
#endif
#define HAVE_SOCKET_H
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "misc.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
#include "if.h"
#include "ip.h"
#include "ip_icmp.h"
#include "tcp.h"
#include "udp.h"
void
so_init(void)
{
/* Nothing yet */
}
struct SLIRPsocket *
solookup(struct SLIRPsocket *head, struct in_addr laddr, u_int lport,
struct in_addr faddr, u_int fport)
{
struct SLIRPsocket *so;
for (so = head->so_next; so != head; so = so->so_next) {
if (so->so_lport == lport && so->so_laddr.s_addr == laddr.s_addr &&
so->so_faddr.s_addr == faddr.s_addr && so->so_fport == fport)
break;
}
if (so == head)
return (struct SLIRPsocket *)NULL;
return so;
}
/*
* Create a new socket, initialize the fields.
* It is the responsibility of the caller to
* insque() it into the correct linked-list
*/
struct SLIRPsocket *
socreate(void)
{
struct SLIRPsocket *so;
so = (struct SLIRPsocket *)malloc(sizeof(struct SLIRPsocket));
if (so) {
memset(so, 0, sizeof(struct SLIRPsocket));
so->so_state = SS_NOFDREF;
so->s = -1;
}
return(so);
}
/* remque and free a socket, clobber cache */
void
sofree(struct SLIRPsocket *so)
{
if (so->so_emu==EMU_RSH && so->extra) {
sofree((struct SLIRPsocket *)so->extra);
so->extra = NULL;
}
if (so == tcp_last_so)
tcp_last_so = &tcb;
else if (so == udp_last_so)
udp_last_so = &udb;
if (so->so_m != NULL)
m_free(so->so_m);
if (so->so_next && so->so_prev)
remque(so); /* crashes if so is not in a queue */
free(so);
}
/*
* Read from so's socket into sb_snd, updating all relevant sbuf fields
* NOTE: This will only be called if it is select()ed for reading, so
* a read() of 0 (or less) means it's disconnected
*/
int
soread(struct SLIRPsocket *so)
{
struct sbuf *sb = &so->so_snd;
struct iovec iov[2];
unsigned int len, mss;
unsigned int lss, total;
int n, nn, ret;
if (! so->so_tcpcb)
return 0;
len = sb->sb_datalen - sb->sb_cc;
mss = so->so_tcpcb->t_maxseg;
DEBUG_CALL("soread");
DEBUG_ARG("so = %lx", (long )so);
/*
* No need to check if there's enough room to read.
* soread wouldn't have been called if there weren't
*/
len = sb->sb_datalen - sb->sb_cc;
iov[0].iov_base = sb->sb_wptr;
if (sb->sb_wptr < sb->sb_rptr) {
iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
/* Should never succeed, but... */
if (iov[0].iov_len > len)
iov[0].iov_len = len;
if (iov[0].iov_len > mss)
iov[0].iov_len -= iov[0].iov_len%mss;
n = 1;
} else {
iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
/* Should never succeed, but... */
if (iov[0].iov_len > len)
iov[0].iov_len = len;
len -= iov[0].iov_len;
if (len) {
iov[1].iov_base = sb->sb_data;
iov[1].iov_len = sb->sb_rptr - sb->sb_data;
if (iov[1].iov_len > len)
iov[1].iov_len = len;
total = iov[0].iov_len + iov[1].iov_len;
if (total > mss) {
lss = total%mss;
if (iov[1].iov_len > lss) {
iov[1].iov_len -= lss;
n = 2;
} else {
lss -= iov[1].iov_len;
iov[0].iov_len -= lss;
n = 1;
}
} else
n = 2;
} else {
if (iov[0].iov_len > mss)
iov[0].iov_len -= iov[0].iov_len%mss;
n = 1;
}
}
#ifdef HAVE_READV
nn = readv(so->s, (struct iovec *)iov, n);
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#else
nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif
if (nn <= 0) {
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
return 0;
else {
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
sofcantrcvmore(so);
tcp_sockclosed(sototcpcb(so));
return -1;
}
}
#ifndef HAVE_READV
/*
* If there was no error, try and read the second time round
* We read again if n = 2 (ie, there's another part of the buffer)
* and we read as much as we could in the first read
* We don't test for <= 0 this time, because there legitimately
* might not be any more data (since the socket is non-blocking),
* a close will be detected on next iteration.
* A return of -1 wont (shouldn't) happen, since it didn't happen above
*/
if (n == 2 && nn == iov[0].iov_len) {
ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
if (ret > 0)
nn += ret;
}
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#endif
/* Update fields */
sb->sb_cc += nn;
sb->sb_wptr += nn;
if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
sb->sb_wptr -= sb->sb_datalen;
return nn;
}
/*
* Get urgent data
*
* When the socket is created, we set it SO_OOBINLINE,
* so when OOB data arrives, we soread() it and everything
* in the send buffer is sent as urgent data
*/
void
sorecvoob(struct SLIRPsocket *so)
{
struct tcpcb *tp = sototcpcb(so);
DEBUG_CALL("sorecvoob");
DEBUG_ARG("so = %lx", (long)so);
/*
* We take a guess at how much urgent data has arrived.
* In most situations, when urgent data arrives, the next
* read() should get all the urgent data. This guess will
* be wrong however if more data arrives just after the
* urgent data, or the read() doesn't return all the
* urgent data.
*/
soread(so);
tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
tp->t_force = 1;
tcp_output(tp);
tp->t_force = 0;
}
/*
* Send urgent data
* There's a lot duplicated code here, but...
*/
int
sosendoob(struct SLIRPsocket *so)
{
char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
struct sbuf *sb = &so->so_rcv;
int n, len;
DEBUG_CALL("sosendoob");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
if (so->so_urgc > sizeof(buff))
so->so_urgc = sizeof(buff); /* XXXX */
if (sb->sb_rptr < sb->sb_wptr) {
/* We can send it directly */
n = send(so->s, sb->sb_rptr, so->so_urgc, MSG_OOB /*|MSG_DONTWAIT*/);
so->so_urgc -= n;
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
} else {
/*
* Since there's no sendv or sendtov like writev,
* we must copy all data to a linear buffer then
* send it all
*/
len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
if (len > so->so_urgc)
len = so->so_urgc;
memcpy(buff, sb->sb_rptr, len);
so->so_urgc -= len;
if (so->so_urgc) {
n = sb->sb_wptr - sb->sb_data;
if (n > so->so_urgc)
n = so->so_urgc;
memcpy((buff + len), sb->sb_data, n);
so->so_urgc -= n;
len += n;
}
n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
#ifdef _DEBUG
if (n != len)
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
#endif
DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
}
sb->sb_cc -= n;
sb->sb_rptr += n;
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
sb->sb_rptr -= sb->sb_datalen;
return n;
}
/*
* Write data from so_rcv to so's socket,
* updating all sbuf field as necessary
*/
int
sowrite(struct SLIRPsocket *so)
{
struct sbuf *sb = &so->so_rcv;
struct iovec iov[2];
unsigned int len;
int n, nn, ret;
DEBUG_CALL("sowrite");
DEBUG_ARG("so = %lx", (long)so);
len = sb->sb_cc;
if (so->so_urgc) {
sosendoob(so);
if (sb->sb_cc == 0)
return 0;
}
/*
* No need to check if there's something to write,
* sowrite wouldn't have been called otherwise
*/
len = sb->sb_cc;
iov[0].iov_base = sb->sb_rptr;
if (sb->sb_rptr < sb->sb_wptr) {
iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
/* Should never succeed, but... */
if (iov[0].iov_len > len) iov[0].iov_len = len;
n = 1;
} else {
iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
if (iov[0].iov_len > len) iov[0].iov_len = len;
len -= iov[0].iov_len;
if (len) {
iov[1].iov_base = sb->sb_data;
iov[1].iov_len = sb->sb_wptr - sb->sb_data;
if (iov[1].iov_len > len) iov[1].iov_len = len;
n = 2;
} else
n = 1;
}
/* Check if there's urgent data to send, and if so, send it */
#ifdef HAVE_READV
nn = writev(so->s, (const struct iovec *)iov, n);
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#else
nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif
/* This should never happen, but people tell me it does *shrug* */
if (nn < 0 && (errno == EAGAIN || errno == EINTR))
return 0;
if (nn <= 0) {
DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
so->so_state, errno));
sofcantsendmore(so);
tcp_sockclosed(sototcpcb(so));
return -1;
}
#ifndef HAVE_READV
if (n == 2 && nn == iov[0].iov_len) {
ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0);
if (ret > 0)
nn += ret;
}
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#endif
/* Update sbuf */
sb->sb_cc -= nn;
sb->sb_rptr += nn;
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
sb->sb_rptr -= sb->sb_datalen;
/*
* If in DRAIN mode, and there's no more data, set
* it CANTSENDMORE
*/
if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
sofcantsendmore(so);
return nn;
}
/* recvfrom() a UDP socket */
void
sorecvfrom(struct SLIRPsocket *so)
{
char buff[256];
struct sockaddr_in addr;
struct SLIRPmbuf *m;
socklen_t addrlen;
ioctlsockopt_t n;
u_char code;
int len;
DEBUG_CALL("sorecvfrom");
DEBUG_ARG("so = %lx", (long)so);
addrlen = sizeof(struct sockaddr_in);
if (so->so_type == IPPROTO_ICMP) {
/* This is a "ping" reply */
len = recvfrom(so->s, buff, 256, 0, (struct sockaddr *)&addr, &addrlen);
/* XXX Check if reply is "correct"? */
if (len == -1 || len == 0) {
code = ICMP_UNREACH_PORT;
if (errno == EHOSTUNREACH)
code = ICMP_UNREACH_HOST;
else if (errno == ENETUNREACH)
code = ICMP_UNREACH_NET;
DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
errno,strerror(errno)));
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
} else {
icmp_reflect(so->so_m);
so->so_m = 0; /* Don't m_free() it again! */
}
/* No need for this socket anymore, udp_detach it */
udp_detach(so);
return;
}
/* A "normal" UDP packet */
if (!(m = m_get())) return;
m->m_data += if_maxlinkhdr;
/*
* XXX Shouldn't FIONREAD packets destined for port 53,
* but I don't know the max packet size for DNS lookups
*/
len = M_FREEROOM(m);
/* if (so->so_fport != htons(53)) { */
ioctlsocket(so->s, FIONREAD, &n);
if ((int)n > len) {
n = (m->m_data - m->m_dat) + m->m_len + n + 1;
m_inc(m, n);
len = M_FREEROOM(m);
}
/* } */
m->m_len = recvfrom(so->s, m->m_data, len, 0,
(struct sockaddr *)&addr, &addrlen);
DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
m->m_len, errno,strerror(errno)));
if (m->m_len < 0) {
code = ICMP_UNREACH_PORT;
if (errno == EHOSTUNREACH)
code = ICMP_UNREACH_HOST;
else if (errno == ENETUNREACH)
code = ICMP_UNREACH_NET;
DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
m_free(m);
} else {
/*
* Hack: domain name lookup will be used the most for UDP,
* and since they'll only be used once there's no need
* for the 4 minute (or whatever) timeout... So we time them
* out much quicker (10 seconds for now...)
*/
if (so->so_expire) {
if (so->so_fport == htons(53))
so->so_expire = curtime + SO_EXPIREFAST;
else
so->so_expire = curtime + SO_EXPIRE;
}
#if 0
if (m->m_len == len) {
m_inc(m, MINCSIZE);
m->m_len = 0;
}
#endif
/*
* If this packet was destined for CTL_ADDR,
* make it look like that's where it came from, done by udp_output
*/
udp_output(so, m, &addr);
}
}
/* sendto() a socket */
int
sosendto(struct SLIRPsocket *so, struct SLIRPmbuf *m)
{
struct sockaddr_in addr;
int ret;
DEBUG_CALL("sosendto");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m);
addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
/* It's an alias */
switch(ntohl(so->so_faddr.s_addr) & 0xff) {
case CTL_SERVER:
addr.sin_addr = dns_addr;
break;
case CTL_ROUTER:
default:
addr.sin_addr = loopback_addr;
break;
}
} else
addr.sin_addr = so->so_faddr;
addr.sin_port = so->so_fport;
DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
/* Don't care what port we get */
ret = sendto(so->s, m->m_data, m->m_len, 0,
(struct sockaddr *)&addr, sizeof (struct sockaddr));
if (ret < 0)
return -1;
/*
* Kill the socket if there's no reply in 4 minutes,
* but only if it's an expirable socket
*/
if (so->so_expire)
so->so_expire = curtime + SO_EXPIRE;
so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
return 0;
}
/*
* XXX This should really be tcp_listen
*/
struct SLIRPsocket *
solisten(u_int port, uint32_t laddr, u_int lport, int flags)
{
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
struct SLIRPsocket *so;
int s, opt = 1;
int tmperrno;
DEBUG_CALL("solisten");
DEBUG_ARG("port = %d", port);
DEBUG_ARG("laddr = %x", laddr);
DEBUG_ARG("lport = %d", lport);
DEBUG_ARG("flags = %x", flags);
if ((so = socreate()) == NULL) {
/* free(so); Not sofree() ??? free(NULL) == NOP */
return NULL;
}
/* Don't tcp_attach... we don't need so_snd nor so_rcv */
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
free(so);
return NULL;
}
insque(so,&tcb);
/* SS_FACCEPTONCE sockets must time out. */
if (flags & SS_FACCEPTONCE)
so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
so->so_state = (SS_FACCEPTCONN|flags);
so->so_lport = lport; /* Kept in network format */
so->so_laddr.s_addr = laddr; /* Ditto */
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = port;
if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
(listen(s,1) < 0)) {
tmperrno = errno; /* Don't clobber the real reason we failed */
#ifdef _WIN32
closesocket(s);
#else
close(s);
#endif
sofree(so);
/* Restore the real errno */
#ifdef _WIN32
WSASetLastError(tmperrno);
#else
errno = tmperrno;
#endif
return NULL;
}
setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
getsockname(s,(struct sockaddr *)&addr,&addrlen);
so->so_fport = addr.sin_port;
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
so->so_faddr = router_addr;
else
so->so_faddr = addr.sin_addr;
so->s = s;
return so;
}
/*
* Data is available in so_rcv
* Just write() the data to the socket
* XXX not yet...
*/
void
sorwakeup(struct SLIRPsocket *so)
{
#if 0
sowrite(so);
FD_CLR(so->s, &writefds);
#endif
}
/*
* Data has been freed in so_snd
* We have room for a read() if we want to
* For now, don't read, it'll be done in the main loop
*/
void
sowwakeup(struct SLIRPsocket *so)
{
/* Nothing, yet */
}
/*
* Various session state calls
* XXX Should be #define's
* The socket state stuff needs work, these often get call 2 or 3
* times each when only 1 was needed
*/
void
soisfconnecting(register struct SLIRPsocket *so)
{
so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
SS_FCANTSENDMORE|SS_FWDRAIN);
so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
}
void
soisfconnected(register struct SLIRPsocket *so)
{
so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
}
void
sofcantrcvmore(struct SLIRPsocket *so)
{
if ((so->so_state & SS_NOFDREF) == 0) {
shutdown(so->s, 0);
if (global_writefds) {
FD_CLR(so->s, global_writefds);
}
}
so->so_state &= ~(SS_ISFCONNECTING);
if (so->so_state & SS_FCANTSENDMORE)
so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */
else
so->so_state |= SS_FCANTRCVMORE;
}
void
sofcantsendmore(struct SLIRPsocket *so)
{
if ((so->so_state & SS_NOFDREF) == 0) {
shutdown(so->s, 1); /* send FIN to fhost */
if (global_readfds) {
FD_CLR(so->s, global_readfds);
}
if (global_xfds) {
FD_CLR(so->s,global_xfds);
}
}
so->so_state &= ~(SS_ISFCONNECTING);
if (so->so_state & SS_FCANTRCVMORE)
so->so_state = SS_NOFDREF; /* as above */
else
so->so_state |= SS_FCANTSENDMORE;
}
void
soisfdisconnected(struct SLIRPsocket *so)
{
#if 0
so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED);
close(so->s);
so->so_state = SS_ISFDISCONNECTED;
#endif
/* XXX Do nothing ... ? */
}
/*
* Set write drain mode
* Set CANTSENDMORE once all data has been write()n
*/
void
sofwdrain(struct SLIRPsocket *so)
{
if (so->so_rcv.sb_cc)
so->so_state |= SS_FWDRAIN;
else
sofcantsendmore(so);
}

130
src/socket.h Normal file
View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifndef SLIRP_SOCKET_H
# define SLIRP_SOCKET_H
#define SO_EXPIRE 240000
#define SO_EXPIREFAST 10000
#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
struct sbuf {
u_int sb_cc; /* actual chars in buffer */
u_int sb_datalen; /* Length of data */
char *sb_wptr; /* write pointer. points to where the next
* bytes should be written in the sbuf */
char *sb_rptr; /* read pointer. points to where the next
* byte should be read from the sbuf */
char *sb_data; /* Actual data */
};
/*
* Our socket structure
*/
struct SLIRPsocket {
struct SLIRPsocket *so_next,
*so_prev; /* For a linked list of sockets */
int s; /* The actual socket */
/* XXX union these with not-yet-used sbuf params */
struct SLIRPmbuf *so_m; /* Pointer to the original SYN packet,
* for non-blocking connect()'s, and
* PING reply's */
struct tcpiphdr *so_ti; /* Pointer to the original ti within
* so_mconn, for non-blocking connections */
int so_urgc;
struct in_addr so_faddr; /* foreign host table entry */
struct in_addr so_laddr; /* local host table entry */
uint16_t so_fport; /* foreign port */
uint16_t so_lport; /* local port */
uint8_t so_iptos; /* Type of service */
uint8_t so_emu; /* Is the socket emulated? */
uint8_t so_type; /* Type of socket, UDP or TCP */
int so_state; /* internal state flags SS_*, below */
struct tcpcb *so_tcpcb;/* pointer to TCP protocol control block */
u_int so_expire; /* When the socket will expire */
int so_queued; /* Number of packets queued from this socket */
int so_nqueued; /* Number of packets queued in a row
* Used to determine when to
* "downgrade" a session from fastq
* to batchq */
struct sbuf so_rcv; /* Receive buffer */
struct sbuf so_snd; /* Send buffer */
void *extra; /* Extra pointer */
};
/*
* Socket state bits. (peer means the host on the Internet,
* local host means the host on the other end of the modem)
*/
#define SS_NOFDREF 0x001 /* No fd reference */
#define SS_ISFCONNECTING 0x002 /* Socket is connecting to peer (non-blocking connect()'s) */
#define SS_ISFCONNECTED 0x004 /* Socket is connected to peer */
#define SS_FCANTRCVMORE 0x008 /* Socket can't receive more from peer (for half-closes) */
#define SS_FCANTSENDMORE 0x010 /* Socket can't send more to peer (for half-closes) */
/* #define SS_ISFDISCONNECTED 0x020*/ /* Socket has disconnected from peer, in 2MSL state */
#define SS_FWDRAIN 0x040 /* We received a FIN, drain data and set SS_FCANTSENDMORE */
#define SS_CTL 0x080
#define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */
#define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */
extern struct SLIRPsocket tcb;
#if defined(DECLARE_IOVEC) && !defined(HAVE_READV)
struct iovec {
char *iov_base;
size_t iov_len;
};
#endif
extern void sbfree(struct sbuf *);
extern void sbdrop(struct sbuf *, int);
extern void sbreserve(struct sbuf *, int);
extern void sbappend(struct SLIRPsocket *, struct SLIRPmbuf *);
extern void sbappendsb(struct sbuf *, struct SLIRPmbuf *);
extern void sbcopy(struct sbuf *, int, int, char *);
extern void so_init(void);
extern struct SLIRPsocket *solookup(struct SLIRPsocket *,
struct in_addr, u_int,
struct in_addr, u_int);
extern struct SLIRPsocket *socreate(void);
extern void sofree(struct SLIRPsocket *);
extern int soread(struct SLIRPsocket *);
extern void sorecvoob(struct SLIRPsocket *);
extern int sosendoob(struct SLIRPsocket *);
extern int sowrite(struct SLIRPsocket *);
extern void sorecvfrom(struct SLIRPsocket *);
extern int sosendto(struct SLIRPsocket *, struct SLIRPmbuf *);
extern struct SLIRPsocket *solisten(u_int, uint32_t, u_int, int);
extern void sorwakeup(struct SLIRPsocket *);
extern void sowwakeup(struct SLIRPsocket *);
extern void soisfconnecting(register struct SLIRPsocket *);
extern void soisfconnected(register struct SLIRPsocket *);
extern void sofcantrcvmore(struct SLIRPsocket *);
extern void sofcantsendmore(struct SLIRPsocket *);
extern void soisfdisconnected(struct SLIRPsocket *);
extern void sofwdrain(struct SLIRPsocket *);
#endif /*SLIRP_SOCKET_H*/

225
src/stats.c Normal file
View File

@@ -0,0 +1,225 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
* Portions copyright (c) 2000 Kelly Price.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
#include "if.h"
#include "ip.h"
#include "ip_icmp.h"
#include "icmp_var.h"
#include "tcp.h"
#include "udp.h"
void
ipstats(void)
{
lprint("\n");
lprint("IP stats:\n");
lprint(" %6d total packets received (%d were unaligned)\n",
ipstat.ips_total, ipstat.ips_unaligned);
lprint(" %6d with incorrect version\n", ipstat.ips_badvers);
lprint(" %6d with bad header checksum\n", ipstat.ips_badsum);
lprint(" %6d with length too short (len < sizeof(iphdr))\n",
ipstat.ips_tooshort);
lprint(" %6d with length too small (len < ip->len)\n",
ipstat.ips_toosmall);
lprint(" %6d with bad header length\n", ipstat.ips_badhlen);
lprint(" %6d with bad packet length\n", ipstat.ips_badlen);
lprint(" %6d fragments received\n", ipstat.ips_fragments);
lprint(" %6d fragments dropped\n", ipstat.ips_fragdropped);
lprint(" %6d fragments timed out\n", ipstat.ips_fragtimeout);
lprint(" %6d packets reassembled ok\n", ipstat.ips_reassembled);
lprint(" %6d outgoing packets fragmented", ipstat.ips_fragmented);
lprint(" %6d total outgoing fragments\n", ipstat.ips_ofragments);
lprint(" %6d with bad protocol field\n", ipstat.ips_noproto);
lprint(" %6d total packets delivered\n", ipstat.ips_delivered);
}
void
icmpstats(void)
{
lprint("\n");
lprint("ICMP stats:\n");
lprint(" %6d ICMP packets received\n", icmpstat.icps_received);
lprint(" %6d were too short\n", icmpstat.icps_tooshort);
lprint(" %6d with bad checksums\n", icmpstat.icps_checksum);
lprint(" %6d with type not supported\n", icmpstat.icps_notsupp);
lprint(" %6d with bad type feilds\n", icmpstat.icps_badtype);
lprint(" %6d ICMP packets sent in reply\n", icmpstat.icps_reflect);
}
void
tcpstats(void)
{
lprint("\n");
lprint("TCP stats:\n");
lprint(" %6d packets sent\n", tcpstat.tcps_sndtotal);
lprint(" %6d data packets (%d bytes)\n",
tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
lprint(" %6d data packets retransmitted (%d bytes)\n",
tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte);
lprint(" %6d ack-only packets (%d delayed)\n",
tcpstat.tcps_sndacks, tcpstat.tcps_delack);
lprint(" %6d URG only packets\n", tcpstat.tcps_sndurg);
lprint(" %6d window probe packets\n", tcpstat.tcps_sndprobe);
lprint(" %6d window update packets\n", tcpstat.tcps_sndwinup);
lprint(" %6d control (SYN/FIN/RST) packets\n",
tcpstat.tcps_sndctrl);
lprint(" %6d times tcp_output did nothing\n",
tcpstat.tcps_didnuttin);
lprint(" %6d packets received\n", tcpstat.tcps_rcvtotal);
lprint(" %6d acks (for %d bytes)\n",
tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
lprint(" %6d duplicate acks\n", tcpstat.tcps_rcvdupack);
lprint(" %6d acks for unsent data\n",
tcpstat.tcps_rcvacktoomuch);
lprint(" %6d packets received in sequence (%d bytes)\n",
tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
lprint(" %6d completely duplicate packets (%d bytes)\n",
tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
lprint(" %6d packets with some duplicate data (%d bytes duped)\n",
tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
lprint(" %6d out-of-order packets (%d bytes)\n",
tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte);
lprint(" %6d packets of data after window (%d bytes)\n",
tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin);
lprint(" %6d window probes\n", tcpstat.tcps_rcvwinprobe);
lprint(" %6d window update packets\n", tcpstat.tcps_rcvwinupd);
lprint(" %6d packets received after close\n",
tcpstat.tcps_rcvafterclose);
lprint(" %6d discarded for bad checksums\n",
tcpstat.tcps_rcvbadsum);
lprint(" %6d discarded for bad header offset fields\n",
tcpstat.tcps_rcvbadoff);
lprint(" %6d connection requests\n", tcpstat.tcps_connattempt);
lprint(" %6d connection accepts\n", tcpstat.tcps_accepts);
lprint(" %6d connections established (including accepts)\n",
tcpstat.tcps_connects);
lprint(" %6d connections closed (including %d drop)\n",
tcpstat.tcps_closed, tcpstat.tcps_drops);
lprint(" %6d embryonic connections dropped\n", tcpstat.tcps_conndrops);
lprint(" %6d segments we tried to get rtt (%d succeeded)\n",
tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated);
lprint(" %6d retransmit timeouts\n", tcpstat.tcps_rexmttimeo);
lprint(" %6d connections dropped by rxmt timeout\n",
tcpstat.tcps_timeoutdrop);
lprint(" %6d persist timeouts\n", tcpstat.tcps_persisttimeo);
lprint(" %6d keepalive timeouts\n", tcpstat.tcps_keeptimeo);
lprint(" %6d keepalive probes sent\n", tcpstat.tcps_keepprobe);
lprint(" %6d connections dropped by keepalive\n",
tcpstat.tcps_keepdrops);
lprint(" %6d correct ACK header predictions\n", tcpstat.tcps_predack);
lprint(" %6d correct data packet header predictions\n",
tcpstat.tcps_preddat);
lprint(" %6d TCP cache misses\n", tcpstat.tcps_socachemiss);
#if 0
lprint(" Packets received too short: %d\n", tcpstat.tcps_rcvshort);
lprint(" Segments dropped due to PAWS: %d\n",
tcpstat.tcps_pawsdrop);
#endif
}
void
udpstats(void)
{
lprint("\n");
lprint("UDP stats:\n");
lprint(" %6d datagrams received\n", udpstat.udps_ipackets);
lprint(" %6d with packets shorter than header\n", udpstat.udps_hdrops);
lprint(" %6d with bad checksums\n", udpstat.udps_badsum);
lprint(" %6d with data length larger than packet\n", udpstat.udps_badlen);
lprint(" %6d UDP socket cache misses\n", udpstat.udpps_pcbcachemiss);
lprint(" %6d datagrams sent\n", udpstat.udps_opackets);
}
void
mbufstats(void)
{
struct SLIRPmbuf *m;
int i;
lprint("\n");
lprint("Mbuf stats:\n");
lprint(" %6d mbufs allocated (%d max)\n", mbuf_alloced, mbuf_max);
i = 0;
for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
i++;
lprint(" %6d mbufs on free list\n", i);
i = 0;
for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
i++;
lprint(" %6d mbufs on used list\n", i);
lprint(" %6d mbufs queued as packets\n\n", if_queued);
}
void
sockstats(void)
{
char buff[256];
struct SLIRPsocket *so;
int n;
lprint("\n");
lprint("Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\n");
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
n = sprintf(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 ",
buff, so->s, inet_ntoa(so->so_laddr), ntohs(so->so_lport));
lprint("%15s %5d %5d %5d\n",
inet_ntoa(so->so_faddr), ntohs(so->so_fport),
so->so_rcv.sb_cc, so->so_snd.sb_cc);
}
for (so = udb.so_next; so != &udb; so = so->so_next) {
n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
while (n < 17)
buff[n++] = ' ';
buff[17] = 0;
lprint("%s %3d %15s %5d ",
buff, so->s, inet_ntoa(so->so_laddr), ntohs(so->so_lport));
lprint("%15s %5d %5d %5d\r\n",
inet_ntoa(so->so_faddr), ntohs(so->so_fport),
so->so_rcv.sb_cc, so->so_snd.sb_cc);
}
}

213
src/tcp.h Normal file
View File

@@ -0,0 +1,213 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcp.h 8.1 (Berkeley) 6/10/93
* tcp.h,v 1.3 1994/08/21 05:27:34 paul Exp
*/
#ifndef _TCP_H_
#define _TCP_H_
#ifdef __amd64__
typedef uintptr_t tcp_seq;
#else
typedef uint32_t tcp_seq;
#endif
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
extern int tcp_rcvspace;
extern int tcp_sndspace;
extern struct SLIRPsocket *tcp_last_so;
#define TCP_SNDSPACE 8192
#define TCP_RCVSPACE 8192
/*
* TCP header.
* Per RFC 793, September, 1981.
*/
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct tcphdr {
uint16_t th_sport; /* source port */
uint16_t th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
#ifdef WORDS_BIGENDIAN
uint8_t th_off:4, /* data offset */
th_x2:4; /* (unused) */
#else
uint8_t th_x2:4, /* (unused) */
th_off:4; /* data offset */
#endif
uint8_t th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
uint16_t th_win; /* window */
uint16_t th_sum; /* checksum */
uint16_t th_urp; /* urgent pointer */
} PACKED__;
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_END)
#endif
#include "tcp_var.h"
#define TCPOPT_EOL 0
#define TCPOPT_NOP 1
#define TCPOPT_MAXSEG 2
#define TCPOLEN_MAXSEG 4
#define TCPOPT_WINDOW 3
#define TCPOLEN_WINDOW 3
#define TCPOPT_SACK_PERMITTED 4 /* Experimental */
#define TCPOLEN_SACK_PERMITTED 2
#define TCPOPT_SACK 5 /* Experimental */
#define TCPOPT_TIMESTAMP 8
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
#define TCPOPT_TSTAMP_HDR \
(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
/*
* Default maximum segment size for TCP.
* With an IP MSS of 576, this is 536,
* but 512 is probably more convenient.
* This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)).
*
* We make this 1460 because we only care about Ethernet in the qemu context.
*/
#define TCP_MSS 1460
#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */
#define TCP_MAX_WINSHIFT 14 /* maximum window shift */
/*
* User-settable options (used with setsockopt).
*
* We don't use the system headers on unix because we have conflicting
* local structures. We can't avoid the system definitions on Windows,
* so we undefine them.
*/
#undef TCP_NODELAY
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
#undef TCP_MAXSEG
/* #define TCP_MAXSEG 0x02 */ /* set maximum segment size */
/*
* TCP FSM state definitions.
* Per RFC793, September, 1981.
*/
#define TCP_NSTATES 11
#define TCPS_CLOSED 0 /* closed */
#define TCPS_LISTEN 1 /* listening for connection */
#define TCPS_SYN_SENT 2 /* active, have sent syn */
#define TCPS_SYN_RECEIVED 3 /* have send and received syn */
/* states < TCPS_ESTABLISHED are those where connections not established */
#define TCPS_ESTABLISHED 4 /* established */
#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */
/* states > TCPS_CLOSE_WAIT are those where user has closed */
#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */
#define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */
#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */
/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */
#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */
#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */
#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED)
#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED)
#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT)
/*
* TCP sequence numbers are 32 bit integers operated
* on with modular arithmetic. These macros can be
* used to compare such integers.
*/
#define SEQ_LT(a,b) ((int)((a)-(b)) < 0)
#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
#define SEQ_GT(a,b) ((int)((a)-(b)) > 0)
#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0)
/*
* Macros to initialize tcp sequence numbers for
* send and receive from initial send and receive
* sequence numbers.
*/
#define tcp_rcvseqinit(tp) \
(tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1
#define tcp_sendseqinit(tp) \
(tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = (tp)->iss
#define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */
extern tcp_seq tcp_iss; /* tcp initial send seq # */
extern char *tcpstates[];
extern int tcp_reass(register struct tcpcb *, register struct tcpiphdr *,
struct SLIRPmbuf *);
extern void tcp_input(register struct SLIRPmbuf *, int,
struct SLIRPsocket *);
extern void tcp_dooptions(struct tcpcb *, uint8_t *, int,
struct tcpiphdr *);
extern void tcp_xmit_timer(register struct tcpcb *, int);
extern int tcp_mss(register struct tcpcb *, u_int);
extern int tcp_output(register struct tcpcb *);
extern void tcp_setpersist(register struct tcpcb *);
extern void tcp_init(void);
extern void tcp_template(struct tcpcb *);
extern void tcp_respond(struct tcpcb *, register struct tcpiphdr *,
register struct SLIRPmbuf *,tcp_seq,tcp_seq,int);
extern struct tcpcb *tcp_newtcpcb(struct SLIRPsocket *);
extern struct tcpcb *tcp_close(register struct tcpcb *);
extern void tcp_drain(void);
extern void tcp_sockclosed(struct tcpcb *);
extern int tcp_fconnect(struct SLIRPsocket *);
extern void tcp_connect(struct SLIRPsocket *);
extern int tcp_attach(struct SLIRPsocket *);
extern uint8_t tcp_tos(struct SLIRPsocket *);
extern int tcp_emu(struct SLIRPsocket *, struct SLIRPmbuf *);
extern int tcp_ctl(struct SLIRPsocket *);
extern struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
#endif

1735
src/tcp_input.c Normal file

File diff suppressed because it is too large Load Diff

618
src/tcp_output.c Normal file
View File

@@ -0,0 +1,618 @@
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcp_output.c 8.3 (Berkeley) 12/30/93
* tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg Exp
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
#include "if.h"
#include "ip.h"
#include "tcp.h"
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
/*
* Since this is only used in "stats socket", we give meaning
* names instead of the REAL names
*/
char *tcpstates[] = {
/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */
"REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD",
"ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
"LAST_ACK", "FIN_WAIT_2", "TIME_WAIT",
};
u_char tcp_outflags[TCP_NSTATES] = {
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
TH_FIN|TH_ACK, TH_ACK, TH_ACK,
};
#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */
/*
* Tcp output routine: figure out what should be sent and send it.
*/
int
tcp_output(struct tcpcb *tp)
{
struct SLIRPsocket *so = tp->t_socket;
register long len, win;
int off, flags, error;
struct SLIRPmbuf *m;
struct tcpiphdr *ti;
u_char opt[MAX_TCPOPTLEN];
unsigned optlen, hdrlen;
int idle, sendalot;
DEBUG_CALL("tcp_output");
DEBUG_ARG("tp = %lx", (long )tp);
/*
* Determine length of data that should be transmitted,
* and flags that will be used.
* If there is some data or critical controls (SYN, RST)
* to send, then transmit; otherwise, investigate further.
*/
idle = (tp->snd_max == tp->snd_una);
if (idle && tp->t_idle >= tp->t_rxtcur)
/*
* We have been idle for "a while" and no acks are
* expected to clock out any data we send --
* slow start to get ack "clock" running again.
*/
tp->snd_cwnd = tp->t_maxseg;
again:
sendalot = 0;
off = tp->snd_nxt - tp->snd_una;
win = min(tp->snd_wnd, tp->snd_cwnd);
flags = tcp_outflags[tp->t_state];
DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
/*
* If in persist timeout with window of 0, send 1 byte.
* Otherwise, if window is small but nonzero
* and timer expired, we will send what we can
* and go to transmit state.
*/
if (tp->t_force) {
if (win == 0) {
/*
* If we still have some data to send, then
* clear the FIN bit. Usually this would
* happen below when it realizes that we
* aren't sending all the data. However,
* if we have exactly 1 byte of unset data,
* then it won't clear the FIN bit below,
* and if we are in persist state, we wind
* up sending the packet without recording
* that we sent the FIN bit.
*
* We can't just blindly clear the FIN bit,
* because if we don't have any more data
* to send then the probe will be the FIN
* itself.
*/
if (off < (int)so->so_snd.sb_cc)
flags &= ~TH_FIN;
win = 1;
} else {
tp->t_timer[TCPT_PERSIST] = 0;
tp->t_rxtshift = 0;
}
}
len = min(so->so_snd.sb_cc, (u_int)win) - off;
if (len < 0) {
/*
* If FIN has been sent but not acked,
* but we haven't been called to retransmit,
* len will be -1. Otherwise, window shrank
* after we sent into it. If window shrank to 0,
* cancel pending retransmit and pull snd_nxt
* back to (closed) window. We will enter persist
* state below. If the window didn't close completely,
* just wait for an ACK.
*/
len = 0;
if (win == 0) {
tp->t_timer[TCPT_REXMT] = 0;
tp->snd_nxt = tp->snd_una;
}
}
if (len > tp->t_maxseg) {
len = tp->t_maxseg;
sendalot = 1;
}
if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
flags &= ~TH_FIN;
win = sbspace(&so->so_rcv);
/*
* Sender silly window avoidance. If connection is idle
* and can send all data, a maximum segment,
* at least a maximum default-size segment do it,
* or are forced, do it; otherwise don't bother.
* If peer's buffer is tiny, then send
* when window is at least half open.
* If retransmitting (possibly after persist timer forced us
* to send into a small window), then must resend.
*/
if (len) {
if (len == tp->t_maxseg)
goto send;
if ((1 || idle || tp->t_flags & TF_NODELAY) &&
(u_int)(len + off) >= so->so_snd.sb_cc)
goto send;
if (tp->t_force)
goto send;
if (len >= (long)(tp->max_sndwnd / 2) && tp->max_sndwnd > 0)
goto send;
if (SEQ_LT(tp->snd_nxt, tp->snd_max))
goto send;
}
/*
* Compare available window to amount of window
* known to peer (as advertised window less
* next expected input). If the difference is at least two
* max size segments, or at least 50% of the maximum possible
* window, then want to send a window update to peer.
*/
if (win > 0) {
/*
* "adv" is the amount we can increase the window,
* taking into account that we are limited by
* TCP_MAXWIN << tp->rcv_scale.
*/
long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
(tp->rcv_adv - tp->rcv_nxt);
if (adv >= (long) (2 * tp->t_maxseg))
goto send;
if (2 * adv >= (long) so->so_rcv.sb_datalen)
goto send;
}
/*
* Send if we owe peer an ACK.
*/
if (tp->t_flags & TF_ACKNOW)
goto send;
if (flags & (TH_SYN|TH_RST))
goto send;
if (SEQ_GT(tp->snd_up, tp->snd_una))
goto send;
/*
* If our state indicates that FIN should be sent
* and we have not yet done so, or we're retransmitting the FIN,
* then we need to send.
*/
if (flags & TH_FIN &&
((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
goto send;
/*
* TCP window updates are not reliable, rather a polling protocol
* using ``persist'' packets is used to insure receipt of window
* updates. The three ``states'' for the output side are:
* idle not doing retransmits or persists
* persisting to move a small or zero window
* (re)transmitting and thereby not persisting
*
* tp->t_timer[TCPT_PERSIST]
* is set when we are in persist state.
* tp->t_force
* is set when we are called to send a persist packet.
* tp->t_timer[TCPT_REXMT]
* is set when we are retransmitting
* The output side is idle when both timers are zero.
*
* If send window is too small, there is data to transmit, and no
* retransmit or persist is pending, then go to persist state.
* If nothing happens soon, send when timer expires:
* if window is nonzero, transmit what we can,
* otherwise force out a byte.
*/
if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&
tp->t_timer[TCPT_PERSIST] == 0) {
tp->t_rxtshift = 0;
tcp_setpersist(tp);
}
/*
* No reason to send a segment, just return.
*/
tcpstat.tcps_didnuttin++;
return (0);
send:
/*
* Before ESTABLISHED, force sending of initial options
* unless TCP set not to do any options.
* NOTE: we assume that the IP/TCP header plus TCP options
* always fit in a single SLIRPmbuf, leaving room for a maximum
* link header, i.e.
* max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
*/
optlen = 0;
hdrlen = sizeof (struct tcpiphdr);
if (flags & TH_SYN) {
tp->snd_nxt = tp->iss;
if ((tp->t_flags & TF_NOOPT) == 0) {
uint16_t mss;
opt[0] = TCPOPT_MAXSEG;
opt[1] = 4;
mss = htons((uint16_t) tcp_mss(tp, 0));
memcpy((SLIRPcaddr_t)(opt + 2), (SLIRPcaddr_t)&mss, sizeof(mss));
optlen = 4;
/* if ((tp->t_flags & TF_REQ_SCALE) &&
* ((flags & TH_ACK) == 0 ||
* (tp->t_flags & TF_RCVD_SCALE))) {
* *((uint32_t *) (opt + optlen)) = htonl(
* TCPOPT_NOP << 24 |
* TCPOPT_WINDOW << 16 |
* TCPOLEN_WINDOW << 8 |
* tp->request_r_scale);
* optlen += 4;
* }
*/
}
}
/*
* Send a timestamp and echo-reply if this is a SYN and our side
* wants to use timestamps (TF_REQ_TSTMP is set) or both our side
* and our peer have sent timestamps in our SYN's.
*/
/* if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
* (flags & TH_RST) == 0 &&
* ((flags & (TH_SYN|TH_ACK)) == TH_SYN ||
* (tp->t_flags & TF_RCVD_TSTMP))) {
* uint32_t *lp = (uint32_t *)(opt + optlen);
*
* / * Form timestamp option as shown in appendix A of RFC 1323. * /
* *lp++ = htonl(TCPOPT_TSTAMP_HDR);
* *lp++ = htonl(tcp_now);
* *lp = htonl(tp->ts_recent);
* optlen += TCPOLEN_TSTAMP_APPA;
* }
*/
hdrlen += optlen;
/*
* Adjust data length if insertion of options will
* bump the packet length beyond the t_maxseg length.
*/
if (len > (long)(tp->t_maxseg - optlen)) {
len = tp->t_maxseg - optlen;
sendalot = 1;
}
/*
* Grab a header SLIRPmbuf, attaching a copy of data to
* be transmitted, and initialize the header from
* the template for sends on this connection.
*/
if (len) {
if (tp->t_force && len == 1)
tcpstat.tcps_sndprobe++;
else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
tcpstat.tcps_sndrexmitpack++;
tcpstat.tcps_sndrexmitbyte += len;
} else {
tcpstat.tcps_sndpack++;
tcpstat.tcps_sndbyte += len;
}
m = m_get();
if (m == NULL) {
/* error = ENOBUFS; */
error = 1;
goto out;
}
m->m_data += if_maxlinkhdr;
m->m_len = hdrlen;
/*
* This will always succeed, since we make sure our SLIRPmbufs
* are big enough to hold one MSS packet + header + ... etc.
*/
/* if (len <= MHLEN - hdrlen - max_linkhdr) { */
sbcopy(&so->so_snd, off, (int) len, mtod(m, SLIRPcaddr_t) + hdrlen);
m->m_len += len;
/* } else {
* m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
* if (m->m_next == 0)
* len = 0;
* }
*/
/*
* If we're sending everything we've got, set PUSH.
* (This will keep happy those implementations which only
* give data to the user when a buffer fills or
* a PUSH comes in.)
*/
if (off + len == so->so_snd.sb_cc)
flags |= TH_PUSH;
} else {
if (tp->t_flags & TF_ACKNOW)
tcpstat.tcps_sndacks++;
else if (flags & (TH_SYN|TH_FIN|TH_RST))
tcpstat.tcps_sndctrl++;
else if (SEQ_GT(tp->snd_up, tp->snd_una))
tcpstat.tcps_sndurg++;
else
tcpstat.tcps_sndwinup++;
m = m_get();
if (m == NULL) {
/* error = ENOBUFS; */
error = 1;
goto out;
}
m->m_data += if_maxlinkhdr;
m->m_len = hdrlen;
}
ti = mtod(m, struct tcpiphdr *);
memcpy((SLIRPcaddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
/*
* Fill in fields, remembering maximum advertised
* window for use in delaying messages about window sizes.
* If resending a FIN, be sure not to use a new sequence number.
*/
if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
tp->snd_nxt == tp->snd_max)
tp->snd_nxt--;
/*
* If we are doing retransmissions, then snd_nxt will
* not reflect the first unsent octet. For ACK only
* packets, we do not want the sequence number of the
* retransmitted packet, we want the sequence number
* of the next unsent octet. So, if there is no data
* (and no SYN or FIN), use snd_max instead of snd_nxt
* when filling in ti_seq. But if we are in persist
* state, snd_max might reflect one byte beyond the
* right edge of the window, so use snd_nxt in that
* case, since we know we aren't doing a retransmission.
* (retransmit and persist are mutually exclusive...)
*/
if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
ti->ti_seq = htonl(tp->snd_nxt);
else
ti->ti_seq = htonl(tp->snd_max);
ti->ti_ack = htonl(tp->rcv_nxt);
if (optlen) {
memcpy((SLIRPcaddr_t)(ti + 1), (SLIRPcaddr_t)opt, optlen);
ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
}
ti->ti_flags = flags;
/*
* Calculate receive window. Don't shrink window,
* but avoid silly window syndrome.
*/
if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
win = 0;
if (win > (long)TCP_MAXWIN << tp->rcv_scale)
win = (long)TCP_MAXWIN << tp->rcv_scale;
if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
win = (long)(tp->rcv_adv - tp->rcv_nxt);
ti->ti_win = htons((uint16_t) (win>>tp->rcv_scale));
if (SEQ_GT(tp->snd_up, tp->snd_una)) {
ti->ti_urp = htons((uint16_t)(tp->snd_up - ntohl(ti->ti_seq)));
#ifdef notdef
if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
ti->ti_urp = htons((uint16_t)(tp->snd_up - tp->snd_nxt));
#endif
ti->ti_flags |= TH_URG;
} else
/*
* If no urgent pointer to send, then we pull
* the urgent pointer to the left edge of the send window
* so that it doesn't drift into the send window on sequence
* number wraparound.
*/
tp->snd_up = tp->snd_una; /* drag it along */
/*
* Put TCP length in extended header, and then
* checksum extended header and data.
*/
if (len + optlen)
ti->ti_len = htons((uint16_t)(sizeof (struct tcphdr) +
optlen + len));
ti->ti_sum = cksum(m, (int)(hdrlen + len));
/*
* In transmit state, time the transmission and arrange for
* the retransmit. In persist state, just set snd_max.
*/
if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
tcp_seq startseq = tp->snd_nxt;
/*
* Advance snd_nxt over sequence space of this segment.
*/
if (flags & (TH_SYN|TH_FIN)) {
if (flags & TH_SYN)
tp->snd_nxt++;
if (flags & TH_FIN) {
tp->snd_nxt++;
tp->t_flags |= TF_SENTFIN;
}
}
tp->snd_nxt += len;
if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
tp->snd_max = tp->snd_nxt;
/*
* Time this transmission if not a retransmission and
* not currently timing anything.
*/
if (tp->t_rtt == 0) {
tp->t_rtt = 1;
tp->t_rtseq = startseq;
tcpstat.tcps_segstimed++;
}
}
/*
* Set retransmit timer if not currently set,
* and not doing an ack or a keep-alive probe.
* Initial value for retransmit timer is smoothed
* round-trip time + 2 * round-trip time variance.
* Initialize shift counter which is used for backoff
* of retransmit time.
*/
if (tp->t_timer[TCPT_REXMT] == 0 &&
tp->snd_nxt != tp->snd_una) {
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
if (tp->t_timer[TCPT_PERSIST]) {
tp->t_timer[TCPT_PERSIST] = 0;
tp->t_rxtshift = 0;
}
}
} else
if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
tp->snd_max = tp->snd_nxt + len;
/*
* Fill in IP length and desired time to live and
* send to IP level. There should be a better way
* to handle ttl and tos; we could keep them in
* the template, but need a way to checksum without them.
*/
m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
{
((struct ip *)ti)->ip_len = m->m_len;
((struct ip *)ti)->ip_ttl = ip_defttl;
((struct ip *)ti)->ip_tos = so->so_iptos;
/* #if BSD >= 43 */
/* Don't do IP options... */
/* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
* so->so_options & SO_DONTROUTE, 0);
*/
error = ip_output(so, m);
/* #else
* error = ip_output(m, (struct SLIRPmbuf *)0, &tp->t_inpcb->inp_route,
* so->so_options & SO_DONTROUTE);
* #endif
*/
}
if (error) {
out:
/* if (error == ENOBUFS) {
* tcp_quench(tp->t_inpcb, 0);
* return (0);
* }
*/
/* if ((error == EHOSTUNREACH || error == ENETDOWN)
* && TCPS_HAVERCVDSYN(tp->t_state)) {
* tp->t_softerror = error;
* return (0);
* }
*/
return (error);
}
tcpstat.tcps_sndtotal++;
/*
* Data sent (as far as we can tell).
* If this advertises a larger window than any other segment,
* then remember the size of the advertised window.
* Any pending ACK has now been sent.
*/
if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
tp->rcv_adv = tp->rcv_nxt + win;
tp->last_ack_sent = tp->rcv_nxt;
tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
if (sendalot)
goto again;
return (0);
}
void
tcp_setpersist(struct tcpcb *tp)
{
int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
/* if (tp->t_timer[TCPT_REXMT])
* panic("tcp_output REXMT");
*/
/*
* Start/restart persistence timer.
*/
TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
t * tcp_backoff[tp->t_rxtshift],
TCPTV_PERSMIN, TCPTV_PERSMAX);
if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
tp->t_rxtshift++;
}

714
src/tcp_subr.c Normal file
View File

@@ -0,0 +1,714 @@
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93
* tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp
*/
#ifdef _WIN32
# include <windows.h>
# ifdef _DEBUG
# undef errno
# define errno (WSAGetLastError())
# endif
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
# ifdef _DEBUG
# include <errno.h>
# endif
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "misc.h"
#include "socket.h"
#include "mbuf.h"
#include "if.h"
#include "ip.h"
#include "tcp.h"
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
/* patchable/settable parameters for tcp */
int tcp_mssdflt = TCP_MSS;
int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */
int tcp_rcvspace; /* You may want to change this */
int tcp_sndspace; /* Keep small if you have an error prone link */
/* Set the socket's type of service field. */
static const struct tos_t tcptos[] = {
{ 0, 20, IPTOS_THROUGHPUT, 0 }, /* ftp data */
{ 21, 21, IPTOS_LOWDELAY, EMU_FTP }, /* ftp control */
{ 0, 23, IPTOS_LOWDELAY, 0 }, /* telnet */
{ 0, 80, IPTOS_THROUGHPUT, 0 }, /* WWW */
{ 0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT}, /* rlogin */
{ 0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT}, /* shell */
{ 0, 544, IPTOS_LOWDELAY, EMU_KSH }, /* kshell */
{ 0, 543, IPTOS_LOWDELAY, 0 }, /* klogin */
{ 0, 6667, IPTOS_THROUGHPUT, EMU_IRC }, /* IRC */
{ 0, 6668, IPTOS_THROUGHPUT, EMU_IRC }, /* IRC undernet */
{ 0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO }, /* RealAudio */
{ 0, 113, IPTOS_LOWDELAY, EMU_IDENT }, /* identd */
{ 0, 0, 0, 0}
};
/* Return TOS according to the above table. */
uint8_t
tcp_tos(struct SLIRPsocket *so)
{
#ifdef USE_REDIR
struct emu_t *emup;
#endif
int i = 0;
while (tcptos[i].tos) {
if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
(tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
so->so_emu = tcptos[i].emu;
return tcptos[i].tos;
}
i++;
}
#ifdef USE_REDIR
/* Nope, lets see if there's a user-added one */
for (emup = tcpemu; emup; emup = emup->next) {
if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||
(emup->lport && (ntohs(so->so_lport) == emup->lport))) {
so->so_emu = emup->emu;
return emup->tos;
}
}
#endif
return 0;
}
/* TCP initialization. */
void
tcp_init(void)
{
tcp_iss = 1; /* wrong */
tcb.so_next = tcb.so_prev = &tcb;
/* tcp_rcvspace = our Window we advertise to the remote */
tcp_rcvspace = TCP_RCVSPACE;
tcp_sndspace = TCP_SNDSPACE;
/* Make sure tcp_sndspace is at least 2*MSS */
if (tcp_sndspace < (int)(2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr))))
tcp_sndspace = (int)(2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)));
}
/*
* Create template to be used to send tcp packets on a connection.
* Call after host entry created, fills
* in a skeletal tcp/ip header, minimizing the amount of work
* necessary when the connection is used.
*/
/* struct tcpiphdr * */
void
tcp_template(struct tcpcb *tp)
{
struct SLIRPsocket *so = tp->t_socket;
struct tcpiphdr *n = &tp->t_template;
n->ti_next = n->ti_prev = 0;
n->ti_x1 = 0;
n->ti_pr = IPPROTO_TCP;
n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
n->ti_src = so->so_faddr;
n->ti_dst = so->so_laddr;
n->ti_sport = so->so_fport;
n->ti_dport = so->so_lport;
n->ti_seq = 0;
n->ti_ack = 0;
n->ti_x2 = 0;
n->ti_off = 5;
n->ti_flags = 0;
n->ti_win = 0;
n->ti_sum = 0;
n->ti_urp = 0;
}
/*
* Send a single message to the TCP at address specified by
* the given TCP/IP header. If m == 0, then we make a copy
* of the tcpiphdr at ti and send directly to the addressed host.
* This is used to force keep alive messages out using the TCP
* template for a connection tp->t_template. If flags are given
* then we send a message back to the TCP which originated the
* segment ti, and discard the SLIRPmbuf containing it and any other
* attached SLIRPmbufs.
*
* In any case the ack and sequence number of the transmitted
* segment are as specified by the parameters.
*/
void
tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct SLIRPmbuf *m, tcp_seq ack, tcp_seq seq, int flags)
{
register int tlen;
int win = 0;
DEBUG_CALL("tcp_respond");
DEBUG_ARG("tp = %lx", (long)tp);
DEBUG_ARG("ti = %lx", (long)ti);
DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("ack = %u", ack);
DEBUG_ARG("seq = %u", seq);
DEBUG_ARG("flags = %x", flags);
if (tp)
win = sbspace(&tp->t_socket->so_rcv);
if (m == 0) {
if ((m = m_get()) == NULL)
return;
#ifdef TCP_COMPAT_42
tlen = 1;
#else
tlen = 0;
#endif
m->m_data += if_maxlinkhdr;
*mtod(m, struct tcpiphdr *) = *ti;
ti = mtod(m, struct tcpiphdr *);
flags = TH_ACK;
} else {
/*
* ti points into m so the next line is just making
* the SLIRPmbuf point to ti
*/
m->m_data = (SLIRPcaddr_t)ti;
m->m_len = sizeof (struct tcpiphdr);
tlen = 0;
#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
xchg(ti->ti_dport, ti->ti_sport, uint16_t);
#undef xchg
}
ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
tlen += sizeof (struct tcpiphdr);
m->m_len = tlen;
ti->ti_next = ti->ti_prev = 0;
ti->ti_x1 = 0;
ti->ti_seq = htonl(seq);
ti->ti_ack = htonl(ack);
ti->ti_x2 = 0;
ti->ti_off = sizeof (struct tcphdr) >> 2;
ti->ti_flags = flags;
if (tp)
ti->ti_win = htons((uint16_t) (win >> tp->rcv_scale));
else
ti->ti_win = htons((uint16_t)win);
ti->ti_urp = 0;
ti->ti_sum = 0;
ti->ti_sum = cksum(m, tlen);
((struct ip *)ti)->ip_len = tlen;
if (flags & TH_RST)
((struct ip *)ti)->ip_ttl = MAXTTL;
else
((struct ip *)ti)->ip_ttl = ip_defttl;
(void) ip_output((struct SLIRPsocket *)0, m);
}
/*
* Create a new TCP control block, making an
* empty reassembly queue and hooking it to the argument
* protocol control block.
*/
struct tcpcb *
tcp_newtcpcb(struct SLIRPsocket *so)
{
struct tcpcb *tp;
tp = (struct tcpcb *)malloc(sizeof(*tp));
if (tp == NULL)
return ((struct tcpcb *)0);
memset((char *) tp, 0, sizeof(struct tcpcb));
tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
tp->t_maxseg = tcp_mssdflt;
tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
tp->t_socket = so;
/*
* Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
* rtt estimate. Set rttvar so that srtt + 2 * rttvar gives
* reasonable initial retransmit time.
*/
tp->t_srtt = TCPTV_SRTTBASE;
tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
tp->t_rttmin = TCPTV_MIN;
TCPT_RANGESET(tp->t_rxtcur,
((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
TCPTV_MIN, TCPTV_REXMTMAX);
tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
tp->t_state = TCPS_CLOSED;
so->so_tcpcb = tp;
return (tp);
}
/*
* Drop a TCP connection, reporting the specified error.
* If connection is synchronized, then send a RST to peer.
*/
struct tcpcb *
tcp_drop(struct tcpcb *tp, int err)
{
DEBUG_CALL("tcp_drop");
DEBUG_ARG("tp = %lx", (long)tp);
DEBUG_ARG("errno = %d", errno);
if (TCPS_HAVERCVDSYN(tp->t_state)) {
tp->t_state = TCPS_CLOSED;
(void) tcp_output(tp);
tcpstat.tcps_drops++;
} else
tcpstat.tcps_conndrops++;
#if 0
if (errno == ETIMEDOUT && tp->t_softerror)
errno = tp->t_softerror;
so->so_error = errno;
#endif
return (tcp_close(tp));
}
/*
* Close a TCP control block:
* discard all space held by the tcp
* discard internet protocol block
* wake up any sleepers
*/
struct tcpcb *
tcp_close(struct tcpcb *tp)
{
struct tcpiphdr *t;
struct SLIRPsocket *so = tp->t_socket;
struct SLIRPmbuf *m;
DEBUG_CALL("tcp_close");
DEBUG_ARG("tp = %lx", (long )tp);
/* free the reassembly queue, if any */
t = (struct tcpiphdr *) tp->seg_next;
while (t != (struct tcpiphdr *)tp) {
t = (struct tcpiphdr *)t->ti_next;
m = (struct SLIRPmbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev);
remque_32((struct tcpiphdr *) t->ti_prev);
m_freem(m);
}
/* It's static */
#if 0
if (tp->t_template)
(void) m_free(dtom(tp->t_template));
free(tp, M_PCB);
#endif
free(tp);
so->so_tcpcb = 0;
soisfdisconnected(so);
/* clobber input socket cache if we're closing the cached connection */
if (so == tcp_last_so)
tcp_last_so = &tcb;
closesocket(so->s);
sbfree(&so->so_rcv);
sbfree(&so->so_snd);
sofree(so);
tcpstat.tcps_closed++;
return ((struct tcpcb *)0);
}
void
tcp_drain(void)
{
/* XXX */
}
/*
* When a source quench is received, close congestion window
* to one segment. We will gradually open it again as we proceed.
*/
#ifdef notdef
void
tcp_quench(int i, int errno)
{
struct tcpcb *tp = intotcpcb(inp);
if (tp)
tp->snd_cwnd = tp->t_maxseg;
}
#endif
/*
* TCP protocol interface to socket abstraction.
*/
/*
* User issued close, and wish to trail through shutdown states:
* if never received SYN, just forget it. If got a SYN from peer,
* but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
* If already got a FIN from peer, then almost done; go to LAST_ACK
* state. In all other cases, have already sent FIN to peer (e.g.
* after PRU_SHUTDOWN), and just have to play tedious game waiting
* for peer to send FIN or not respond to keep-alives, etc.
* We can let the user exit from the close as soon as the FIN is acked.
*/
void
tcp_sockclosed(struct tcpcb *tp)
{
DEBUG_CALL("tcp_sockclosed");
DEBUG_ARG("tp = %lx", (long)tp);
switch (tp->t_state) {
case TCPS_CLOSED:
case TCPS_LISTEN:
case TCPS_SYN_SENT:
tp->t_state = TCPS_CLOSED;
tp = tcp_close(tp);
break;
case TCPS_SYN_RECEIVED:
case TCPS_ESTABLISHED:
tp->t_state = TCPS_FIN_WAIT_1;
break;
case TCPS_CLOSE_WAIT:
tp->t_state = TCPS_LAST_ACK;
break;
}
/* soisfdisconnecting(tp->t_socket); */
if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
soisfdisconnected(tp->t_socket);
if (tp)
tcp_output(tp);
}
/*
* Connect to a host on the Internet
* Called by tcp_input
* Only do a connect, the tcp fields will be set in tcp_input
* return 0 if there's a result of the connect,
* else return -1 means we're still connecting
* The return value is almost always -1 since the socket is
* nonblocking. Connect returns after the SYN is sent, and does
* not wait for ACK+SYN.
*/
int tcp_fconnect(struct SLIRPsocket *so)
{
int ret=0;
DEBUG_CALL("tcp_fconnect");
DEBUG_ARG("so = %lx", (long )so);
if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) {
int opt, s=so->s;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
fd_nonblock(s);
opt = 1;
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
opt = 1;
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
/* It's an alias */
switch(ntohl(so->so_faddr.s_addr) & 0xff) {
case CTL_SERVER:
addr.sin_addr = dns_addr;
break;
case CTL_ROUTER:
default:
addr.sin_addr = loopback_addr;
break;
}
} else
addr.sin_addr = so->so_faddr;
addr.sin_port = so->so_fport;
DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
"addr.sin_addr.s_addr=%.16s\n",
ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
/* We don't care what port we get */
ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
/*
* If it's not in progress, it failed, so we just return 0,
* without clearing SS_NOFDREF
*/
soisfconnecting(so);
}
return(ret);
}
/*
* Accept the socket and connect to the local-host
*
* We have a problem. The correct thing to do would be
* to first connect to the local-host, and only if the
* connection is accepted, then do an accept() here.
* But, a) we need to know who's trying to connect
* to the socket to be able to SYN the local-host, and
* b) we are already connected to the foreign host by
* the time it gets to accept(), so... We simply accept
* here and SYN the local-host.
*/
void
tcp_connect(struct SLIRPsocket *inso)
{
struct SLIRPsocket *so;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(struct sockaddr_in);
struct tcpcb *tp;
int s, opt;
DEBUG_CALL("tcp_connect");
DEBUG_ARG("inso = %lx", (long)inso);
/*
* If it's an SS_ACCEPTONCE socket, no need to socreate()
* another socket, just use the accept() socket.
*/
if (inso->so_state & SS_FACCEPTONCE) {
/* FACCEPTONCE already have a tcpcb */
so = inso;
} else {
if ((so = socreate()) == NULL) {
/* If it failed, get rid of the pending connection */
closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
return;
}
if (tcp_attach(so) < 0) {
free(so); /* NOT sofree */
return;
}
so->so_laddr = inso->so_laddr;
so->so_lport = inso->so_lport;
}
(void) tcp_mss(sototcpcb(so), 0);
if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
tcp_close(sototcpcb(so)); /* This will sofree() as well */
return;
}
fd_nonblock(s);
opt = 1;
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
opt = 1;
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
opt = 1;
setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
so->so_fport = addr.sin_port;
so->so_faddr = addr.sin_addr;
/* Translate connections from localhost to the real hostname */
if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
so->so_faddr = router_addr;
/* Close the accept() socket, set right state */
if (inso->so_state & SS_FACCEPTONCE) {
closesocket(so->s); /* If we only accept once, close the accept() socket */
so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
/* if it's not FACCEPTONCE, it's already NOFDREF */
}
so->s = s;
so->so_iptos = tcp_tos(so);
tp = sototcpcb(so);
tcp_template(tp);
/* Compute window scaling to request. */
/* while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
* (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
* tp->request_r_scale++;
*/
/* soisconnecting(so); */ /* NOFDREF used instead */
tcpstat.tcps_connattempt++;
tp->t_state = TCPS_SYN_SENT;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
tp->iss = tcp_iss;
tcp_iss += TCP_ISSINCR/2;
tcp_sendseqinit(tp);
tcp_output(tp);
}
/*
* Attach a TCPCB to a socket.
*/
int
tcp_attach(struct SLIRPsocket *so)
{
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
return -1;
insque(so, &tcb);
return 0;
}
/*
* Do misc. config of SLiRP while its running.
* Return 0 if this connections is to be closed, 1 otherwise,
* return 2 if this is a command-line connection
*/
int
tcp_ctl(struct SLIRPsocket *so)
{
struct sbuf *sb = &so->so_snd;
#if 0
struct SLIRPsocket *tmpso;
#endif
#ifdef USE_REDIR
struct ex_list *ex_ptr;
int do_pty;
#endif
int command;
DEBUG_CALL("tcp_ctl");
DEBUG_ARG("so = %lx", (long )so);
#if 0
/*
* Check if they're authorised
*/
if (ctl_addr.s_addr && (ctl_addr.s_addr == -1 || (so->so_laddr.s_addr != ctl_addr.s_addr))) {
sb->sb_cc = sprintf(sb->sb_wptr,"Error: Permission denied.\r\n");
sb->sb_wptr += sb->sb_cc;
return 0;
}
#endif
command = (ntohl(so->so_faddr.s_addr) & 0xff);
switch(command) {
default: /* Check for exec's */
#ifdef USE_REDIR
/*
* Check if it's pty_exec
*/
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if (ex_ptr->ex_fport == so->so_fport &&
command == ex_ptr->ex_addr) {
do_pty = ex_ptr->ex_pty;
goto do_exec;
}
}
#endif
/*
* Nothing bound..
*/
/* tcp_fconnect(so); */
/* FALLTHROUGH */
case CTL_ROUTER:
sb->sb_cc = sprintf(sb->sb_wptr,
"Error: No application configured.\r\n");
sb->sb_wptr += sb->sb_cc;
return(0);
#ifdef USE_REDIR
do_exec:
DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
return(fork_exec(so, ex_ptr->ex_exec, do_pty));
#endif
#if 0
case CTL_CMD:
for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
if (tmpso->so_emu == EMU_CTL &&
!(tmpso->so_tcpcb?
(tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK))
:0)) {
/* Ooops, control connection already active */
sb->sb_cc = sprintf(sb->sb_wptr,"Sorry, already connected.\r\n");
sb->sb_wptr += sb->sb_cc;
return 0;
}
}
so->so_emu = EMU_CTL;
ctl_password_ok = 0;
sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> ");
sb->sb_wptr += sb->sb_cc;
do_echo=-1;
return(2);
#endif
}
}

337
src/tcp_timer.c Normal file
View File

@@ -0,0 +1,337 @@
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcp_timer.c 8.1 (Berkeley) 6/10/93
* tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp
*/
#ifdef _WIN32
# include <windows.h>
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "socket.h"
#include "mbuf.h"
#include "ip.h"
#include "tcp.h"
int tcp_keepidle = TCPTV_KEEP_IDLE;
int tcp_keepintvl = TCPTV_KEEPINTVL;
int tcp_maxidle;
int so_options = DO_KEEPALIVE;
struct tcpstat tcpstat; /* tcp statistics */
uint32_t tcp_now; /* for RFC 1323 timestamps */
/*
* Fast timeout routine for processing delayed acks
*/
void
tcp_fasttimo()
{
register struct SLIRPsocket *so;
register struct tcpcb *tp;
DEBUG_CALL("tcp_fasttimo");
so = tcb.so_next;
if (so)
for (; so != &tcb; so = so->so_next)
if ((tp = (struct tcpcb *)so->so_tcpcb) &&
(tp->t_flags & TF_DELACK)) {
tp->t_flags &= ~TF_DELACK;
tp->t_flags |= TF_ACKNOW;
tcpstat.tcps_delack++;
(void) tcp_output(tp);
}
}
/*
* Tcp protocol timeout routine called every 500 ms.
* Updates the timers in all active tcb's and
* causes finite state machine actions if timers expire.
*/
void
tcp_slowtimo()
{
register struct SLIRPsocket *ip, *ipnxt;
register struct tcpcb *tp;
register int i;
DEBUG_CALL("tcp_slowtimo");
tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
/*
* Search through tcb's and update active timers.
*/
ip = tcb.so_next;
if (ip == 0)
return;
for (; ip != &tcb; ip = ipnxt) {
ipnxt = ip->so_next;
tp = sototcpcb(ip);
if (tp == 0)
continue;
for (i = 0; i < TCPT_NTIMERS; i++) {
if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
tcp_timers(tp,i);
if (ipnxt->so_prev != ip)
goto tpgone;
}
}
tp->t_idle++;
if (tp->t_rtt)
tp->t_rtt++;
tpgone:
;
}
tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
#ifdef TCP_COMPAT_42
if ((int)tcp_iss < 0)
tcp_iss = 0; /* XXX */
#endif
tcp_now++; /* for timestamps */
}
/*
* Cancel all timers for TCP tp.
*/
void
tcp_canceltimers(struct tcpcb *tp)
{
register int i;
for (i = 0; i < TCPT_NTIMERS; i++)
tp->t_timer[i] = 0;
}
int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
{ 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
/*
* TCP timer processing.
*/
struct tcpcb *
tcp_timers(struct tcpcb *tp, int timer)
{
int rexmt;
DEBUG_CALL("tcp_timers");
switch (timer) {
/*
* 2 MSL timeout in shutdown went off. If we're closed but
* still waiting for peer to close and connection has been idle
* too long, or if 2MSL time is up from TIME_WAIT, delete connection
* control block. Otherwise, check again in a bit.
*/
case TCPT_2MSL:
if (tp->t_state != TCPS_TIME_WAIT &&
tp->t_idle <= tcp_maxidle)
tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
else
tp = tcp_close(tp);
break;
/*
* Retransmission timer went off. Message has not
* been acked within retransmit interval. Back off
* to a longer retransmit interval and retransmit one segment.
*/
case TCPT_REXMT:
/*
* XXXXX If a packet has timed out, then remove all the queued
* packets for that session.
*/
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
/*
* This is a hack to suit our terminal server here at the uni of canberra
* since they have trouble with zeroes... It usually lets them through
* unharmed, but under some conditions, it'll eat the zeros. If we
* keep retransmitting it, it'll keep eating the zeroes, so we keep
* retransmitting, and eventually the connection dies...
* (this only happens on incoming data)
*
* So, if we were gonna drop the connection from too many retransmits,
* don't... instead halve the t_maxseg, which might break up the NULLs and
* let them through
*
* *sigh*
*/
tp->t_maxseg >>= 1;
if (tp->t_maxseg < 32) {
/*
* We tried our best, now the connection must die!
*/
tp->t_rxtshift = TCP_MAXRXTSHIFT;
tcpstat.tcps_timeoutdrop++;
tp = tcp_drop(tp, tp->t_softerror);
/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
return (tp); /* XXX */
}
/*
* Set rxtshift to 6, which is still at the maximum
* backoff time
*/
tp->t_rxtshift = 6;
}
tcpstat.tcps_rexmttimeo++;
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
TCPT_RANGESET(tp->t_rxtcur, rexmt,
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
/*
* If losing, let the lower level know and try for
* a better route. Also, if we backed off this far,
* our srtt estimate is probably bogus. Clobber it
* so we'll take the next rtt measurement as our srtt;
* move the current srtt into rttvar to keep the current
* retransmit times until then.
*/
if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
/* in_losing(tp->t_inpcb); */
tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
tp->t_srtt = 0;
}
tp->snd_nxt = tp->snd_una;
/*
* If timing a segment in this window, stop the timer.
*/
tp->t_rtt = 0;
/*
* Close the congestion window down to one segment
* (we'll open it by one segment for each ack we get).
* Since we probably have a window's worth of unacked
* data accumulated, this "slow start" keeps us from
* dumping all that data as back-to-back packets (which
* might overwhelm an intermediate gateway).
*
* There are two phases to the opening: Initially we
* open by one mss on each ack. This makes the window
* size increase exponentially with time. If the
* window is larger than the path can handle, this
* exponential growth results in dropped packet(s)
* almost immediately. To get more time between
* drops but still "push" the network to take advantage
* of improving conditions, we switch from exponential
* to linear window opening at some threshold size.
* For a threshold, we use half the current window
* size, truncated to a multiple of the mss.
*
* (the minimum cwnd that will give us exponential
* growth is 2 mss. We don't allow the threshold
* to go below this.)
*/
{
u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
if (win < 2)
win = 2;
tp->snd_cwnd = tp->t_maxseg;
tp->snd_ssthresh = win * tp->t_maxseg;
tp->t_dupacks = 0;
}
(void) tcp_output(tp);
break;
/*
* Persistence timer into zero window.
* Force a byte to be output, if possible.
*/
case TCPT_PERSIST:
tcpstat.tcps_persisttimeo++;
tcp_setpersist(tp);
tp->t_force = 1;
(void) tcp_output(tp);
tp->t_force = 0;
break;
/*
* Keep-alive timer went off; send something
* or drop connection if idle for too long.
*/
case TCPT_KEEP:
tcpstat.tcps_keeptimeo++;
if (tp->t_state < TCPS_ESTABLISHED)
goto dropit;
/* if (tp->t_socket->so_options & SO_KEEPALIVE && */
if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) {
if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
goto dropit;
/*
* Send a packet designed to force a response
* if the peer is up and reachable:
* either an ACK if the connection is still alive,
* or an RST if the peer has closed the connection
* due to timeout or reboot.
* Using sequence number tp->snd_una-1
* causes the transmitted zero-length segment
* to lie outside the receive window;
* by the protocol spec, this requires the
* correspondent TCP to respond.
*/
tcpstat.tcps_keepprobe++;
#ifdef TCP_COMPAT_42
/*
* The keepalive packet must have nonzero length
* to get a 4.2 host to respond.
*/
tcp_respond(tp, &tp->t_template, (struct SLIRPmbuf *)NULL,
tp->rcv_nxt - 1, tp->snd_una - 1, 0);
#else
tcp_respond(tp, &tp->t_template, (struct SLIRPmbuf *)NULL,
tp->rcv_nxt, tp->snd_una - 1, 0);
#endif
tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
} else
tp->t_timer[TCPT_KEEP] = tcp_keepidle;
break;
dropit:
tcpstat.tcps_keepdrops++;
tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
break;
}
return (tp);
}

138
src/tcp_timer.h Normal file
View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93
* tcp_timer.h,v 1.4 1994/08/21 05:27:38 paul Exp
*/
#ifndef _TCP_TIMER_H_
#define _TCP_TIMER_H_
/*
* Definitions of the TCP timers. These timers are counted
* down PR_SLOWHZ times a second.
*/
#define TCPT_NTIMERS 4
#define TCPT_REXMT 0 /* retransmit */
#define TCPT_PERSIST 1 /* retransmit persistence */
#define TCPT_KEEP 2 /* keep alive */
#define TCPT_2MSL 3 /* 2*msl quiet time timer */
/*
* The TCPT_REXMT timer is used to force retransmissions.
* The TCP has the TCPT_REXMT timer set whenever segments
* have been sent for which ACKs are expected but not yet
* received. If an ACK is received which advances tp->snd_una,
* then the retransmit timer is cleared (if there are no more
* outstanding segments) or reset to the base value (if there
* are more ACKs expected). Whenever the retransmit timer goes off,
* we retransmit one unacknowledged segment, and do a backoff
* on the retransmit timer.
*
* The TCPT_PERSIST timer is used to keep window size information
* flowing even if the window goes shut. If all previous transmissions
* have been acknowledged (so that there are no retransmissions in progress),
* and the window is too small to bother sending anything, then we start
* the TCPT_PERSIST timer. When it expires, if the window is nonzero,
* we go to transmit state. Otherwise, at intervals send a single byte
* into the peer's window to force him to update our window information.
* We do this at most as often as TCPT_PERSMIN time intervals,
* but no more frequently than the current estimate of round-trip
* packet time. The TCPT_PERSIST timer is cleared whenever we receive
* a window update from the peer.
*
* The TCPT_KEEP timer is used to keep connections alive. If an
* connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time,
* but not yet established, then we drop the connection. Once the connection
* is established, if the connection is idle for TCPTV_KEEP_IDLE time
* (and keepalives have been enabled on the socket), we begin to probe
* the connection. We force the peer to send us a segment by sending:
* <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
* This segment is (deliberately) outside the window, and should elicit
* an ack segment in response from the peer. If, despite the TCPT_KEEP
* initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
* amount of time probing, then we drop the connection.
*/
/*
* Time constants.
*/
#define TCPTV_MSL ( 5*PR_SLOWHZ) /* max seg lifetime (hah!) */
#define TCPTV_SRTTBASE 0 /* base roundtrip time;
if 0, no idea yet */
#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */
#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistence */
#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */
#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */
#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */
#define TCPTV_KEEPCNT 8 /* max probes before drop */
#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */
/* #define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) */ /* max allowable REXMT value */
#define TCPTV_REXMTMAX ( 12*PR_SLOWHZ) /* max allowable REXMT value */
#define TCP_LINGERTIME 120 /* linger at most 2 minutes */
#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */
#ifdef TCPTIMERS
char *tcptimers[] =
{ "REXMT", "PERSIST", "KEEP", "2MSL" };
#endif
/*
* Force a time value to be in a certain range.
*/
#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \
(tv) = (value); \
if ((tv) < (tvmin)) \
(tv) = (tvmin); \
else if ((tv) > (tvmax)) \
(tv) = (tvmax); \
}
extern int tcp_keepidle; /* time before keepalive probes begin */
extern int tcp_keepintvl; /* time between keepalive probes */
extern int tcp_maxidle; /* time to drop after starting probes */
extern int tcp_ttl; /* time to live for TCP segs */
extern int tcp_backoff[];
struct tcpcb;
extern void tcp_fasttimo(void);
extern void tcp_slowtimo(void);
extern void tcp_canceltimers(struct tcpcb *);
extern struct tcpcb * tcp_timers(register struct tcpcb *, int);
#endif

256
src/tcp_var.h Normal file
View File

@@ -0,0 +1,256 @@
/*
* Copyright (c) 1982, 1986, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcp_var.h 8.3 (Berkeley) 4/10/94
* tcp_var.h,v 1.3 1994/08/21 05:27:39 paul Exp
*/
#ifndef _TCP_VAR_H_
#define _TCP_VAR_H_
#include "tcpip.h"
#include "tcp_timer.h"
#ifdef __amd64__
typedef uintptr_t tcpiphdrp_32;
#else
#if SIZEOF_CHAR_P == 4
typedef struct tcpiphdr *tcpiphdrp_32;
#else
typedef uint32_t tcpiphdrp_32;
#endif
#endif
/*
* Tcp control block, one per tcp; fields:
*/
struct tcpcb {
tcpiphdrp_32 seg_next; /* sequencing queue */
tcpiphdrp_32 seg_prev;
short t_state; /* state of this connection */
short t_timer[TCPT_NTIMERS]; /* tcp timers */
short t_rxtshift; /* log(2) of rexmt exp. backoff */
short t_rxtcur; /* current retransmit value */
short t_dupacks; /* consecutive dup acks recd */
uint16_t t_maxseg; /* maximum segment size */
char t_force; /* 1 if forcing out a byte */
uint16_t t_flags;
#define TF_ACKNOW 0x0001 /* ack peer immediately */
#define TF_DELACK 0x0002 /* ack, but try to delay it */
#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */
#define TF_NOOPT 0x0008 /* don't use tcp options */
#define TF_SENTFIN 0x0010 /* have sent FIN */
#define TF_REQ_SCALE 0x0020 /* have/will request window scaling */
#define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */
#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */
#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */
#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */
/* Make it static for now */
/* struct tcpiphdr *t_template; / * skeletal packet for transmit */
struct tcpiphdr t_template;
struct SLIRPsocket *t_socket; /* back pointer to socket */
/*
* The following fields are used as in the protocol specification.
* See RFC783, Dec. 1981, page 21.
*/
/* send sequence variables */
tcp_seq snd_una; /* send unacknowledged */
tcp_seq snd_nxt; /* send next */
tcp_seq snd_up; /* send urgent pointer */
tcp_seq snd_wl1; /* window update seg seq number */
tcp_seq snd_wl2; /* window update seg ack number */
tcp_seq iss; /* initial send sequence number */
uint32_t snd_wnd; /* send window */
/* receive sequence variables */
uint32_t rcv_wnd; /* receive window */
tcp_seq rcv_nxt; /* receive next */
tcp_seq rcv_up; /* receive urgent pointer */
tcp_seq irs; /* initial receive sequence number */
/*
* Additional variables for this implementation.
*/
/* receive variables */
tcp_seq rcv_adv; /* advertised window */
/* retransmit variables */
tcp_seq snd_max; /* highest sequence number sent;
* used to recognize retransmits
*/
/* congestion control (for slow start, source quench, retransmit after loss) */
uint32_t snd_cwnd; /* congestion-controlled window */
uint32_t snd_ssthresh; /* snd_cwnd size threshold for
* for slow start exponential to
* linear switch
*/
/*
* transmit timing stuff. See below for scale of srtt and rttvar.
* "Variance" is actually smoothed difference.
*/
short t_idle; /* inactivity time */
short t_rtt; /* round trip time */
tcp_seq t_rtseq; /* sequence number being timed */
short t_srtt; /* smoothed round-trip time */
short t_rttvar; /* variance in round-trip time */
uint16_t t_rttmin; /* minimum rtt allowed */
uint32_t max_sndwnd; /* largest window peer has offered */
/* out-of-band data */
char t_oobflags; /* have some */
char t_iobc; /* input character */
#define TCPOOB_HAVEDATA 0x01
#define TCPOOB_HADDATA 0x02
short t_softerror; /* possible error not yet reported */
/* RFC 1323 variables */
u_char snd_scale; /* window scaling for send window */
u_char rcv_scale; /* window scaling for recv window */
u_char request_r_scale; /* pending window scaling */
u_char requested_s_scale;
uint32_t ts_recent; /* timestamp echo data */
uint32_t ts_recent_age; /* when last updated */
tcp_seq last_ack_sent;
};
#define sototcpcb(so) ((so)->so_tcpcb)
/*
* The smoothed round-trip time and estimated variance
* are stored as fixed point numbers scaled by the values below.
* For convenience, these scales are also used in smoothing the average
* (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed).
* With these scales, srtt has 3 bits to the right of the binary point,
* and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the
* binary point, and is smoothed with an ALPHA of 0.75.
*/
#define TCP_RTT_SCALE 8 /* multiplier for srtt; 3 bits frac. */
#define TCP_RTT_SHIFT 3 /* shift for srtt; 3 bits frac. */
#define TCP_RTTVAR_SCALE 4 /* multiplier for rttvar; 2 bits */
#define TCP_RTTVAR_SHIFT 2 /* multiplier for rttvar; 2 bits */
/*
* The initial retransmission should happen at rtt + 4 * rttvar.
* Because of the way we do the smoothing, srtt and rttvar
* will each average +1/2 tick of bias. When we compute
* the retransmit timer, we want 1/2 tick of rounding and
* 1 extra tick because of +-1/2 tick uncertainty in the
* firing of the timer. The bias will give us exactly the
* 1.5 tick we need. But, because the bias is
* statistical, we have to test that we don't drop below
* the minimum feasible timer (which is 2 ticks).
* This macro assumes that the value of TCP_RTTVAR_SCALE
* is the same as the multiplier for rttvar.
*/
#define TCP_REXMTVAL(tp) \
(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
/* XXX
* We want to avoid doing m_pullup on incoming packets but that
* means avoiding dtom on the tcp reassembly code. That in turn means
* keeping an mbuf pointer in the reassembly queue (since we might
* have a cluster). As a quick hack, the source & destination
* port numbers (which are no longer needed once we've located the
* tcpcb) are overlayed with an mbuf pointer.
*/
#ifdef __amd64__
typedef uintptr_t mbufp_32;
#else
#if SIZEOF_CHAR_P == 4
typedef struct SLIRPmbuf *mbufp_32;
#else
typedef uint32_t mbufp_32;
#endif
#endif
#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
/*
* TCP statistics.
* Many of these should be kept per connection,
* but that's inconvenient at the moment.
*/
struct tcpstat {
uint32_t tcps_connattempt; /* connections initiated */
uint32_t tcps_accepts; /* connections accepted */
uint32_t tcps_connects; /* connections established */
uint32_t tcps_drops; /* connections dropped */
uint32_t tcps_conndrops; /* embryonic connections dropped */
uint32_t tcps_closed; /* conn. closed (includes drops) */
uint32_t tcps_segstimed; /* segs where we tried to get rtt */
uint32_t tcps_rttupdated; /* times we succeeded */
uint32_t tcps_delack; /* delayed acks sent */
uint32_t tcps_timeoutdrop; /* conn. dropped in rxmt timeout */
uint32_t tcps_rexmttimeo; /* retransmit timeouts */
uint32_t tcps_persisttimeo; /* persist timeouts */
uint32_t tcps_keeptimeo; /* keepalive timeouts */
uint32_t tcps_keepprobe; /* keepalive probes sent */
uint32_t tcps_keepdrops; /* connections dropped in keepalive */
uint32_t tcps_sndtotal; /* total packets sent */
uint32_t tcps_sndpack; /* data packets sent */
uint32_t tcps_sndbyte; /* data bytes sent */
uint32_t tcps_sndrexmitpack; /* data packets retransmitted */
uint32_t tcps_sndrexmitbyte; /* data bytes retransmitted */
uint32_t tcps_sndacks; /* ack-only packets sent */
uint32_t tcps_sndprobe; /* window probes sent */
uint32_t tcps_sndurg; /* packets sent with URG only */
uint32_t tcps_sndwinup; /* window update-only packets sent */
uint32_t tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */
uint32_t tcps_rcvtotal; /* total packets received */
uint32_t tcps_rcvpack; /* packets received in sequence */
uint32_t tcps_rcvbyte; /* bytes received in sequence */
uint32_t tcps_rcvbadsum; /* packets received with ccksum errs */
uint32_t tcps_rcvbadoff; /* packets received with bad offset */
/* uint32_t tcps_rcvshort; */ /* packets received too short */
uint32_t tcps_rcvduppack; /* duplicate-only packets received */
uint32_t tcps_rcvdupbyte; /* duplicate-only bytes received */
uint32_t tcps_rcvpartduppack; /* packets with some duplicate data */
uint32_t tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */
uint32_t tcps_rcvoopack; /* out-of-order packets received */
uint32_t tcps_rcvoobyte; /* out-of-order bytes received */
uint32_t tcps_rcvpackafterwin; /* packets with data after window */
uint32_t tcps_rcvbyteafterwin; /* bytes rcvd after window */
uint32_t tcps_rcvafterclose; /* packets rcvd after "close" */
uint32_t tcps_rcvwinprobe; /* rcvd window probe packets */
uint32_t tcps_rcvdupack; /* rcvd duplicate acks */
uint32_t tcps_rcvacktoomuch; /* rcvd acks for unsent data */
uint32_t tcps_rcvackpack; /* rcvd ack packets */
uint32_t tcps_rcvackbyte; /* bytes acked by rcvd acks */
uint32_t tcps_rcvwinupd; /* rcvd window update packets */
/* uint32_t tcps_pawsdrop; */ /* segments dropped due to PAWS */
uint32_t tcps_predack; /* times hdr predict ok for acks */
uint32_t tcps_preddat; /* times hdr predict ok for data pkts */
uint32_t tcps_socachemiss; /* tcp_last_so misses */
uint32_t tcps_didnuttin; /* Times tcp_output didn't do anything XXX */
};
extern struct tcpstat tcpstat; /* tcp statistics */
extern uint32_t tcp_now; /* for RFC 1323 timestamps */
#endif

70
src/tcpip.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcpip.h 8.1 (Berkeley) 6/10/93
* tcpip.h,v 1.3 1994/08/21 05:27:40 paul Exp
*/
#ifndef _TCPIP_H_
#define _TCPIP_H_
/*
* Tcp+ip header, after ip options removed.
*/
struct tcpiphdr {
struct ipovly ti_i; /* overlaid ip structure */
struct tcphdr ti_t; /* tcp header */
};
#define ti_next ti_i.ih_next
#define ti_prev ti_i.ih_prev
#define ti_x1 ti_i.ih_x1
#define ti_pr ti_i.ih_pr
#define ti_len ti_i.ih_len
#define ti_src ti_i.ih_src
#define ti_dst ti_i.ih_dst
#define ti_sport ti_t.th_sport
#define ti_dport ti_t.th_dport
#define ti_seq ti_t.th_seq
#define ti_ack ti_t.th_ack
#define ti_x2 ti_t.th_x2
#define ti_off ti_t.th_off
#define ti_flags ti_t.th_flags
#define ti_win ti_t.th_win
#define ti_sum ti_t.th_sum
#define ti_urp ti_t.th_urp
/*
* Just a clean way to get to the first byte
* of the packet
*/
struct tcpiphdr_2 {
struct tcpiphdr dummy;
char first_char;
};
#endif

1
src/tftp.h Normal file
View File

@@ -0,0 +1 @@
/* Dummy */

452
src/udp.c Normal file
View File

@@ -0,0 +1,452 @@
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
* udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
*/
#ifdef _WIN32
# include <windows.h>
# undef errno
# define errno (WSAGetLastError())
#else
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <unistd.h>
# include <errno.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "slirp.h"
#include "debug.h" // merge with slirp.h
#include "misc.h"
#include "socket.h"
#include "mbuf.h"
#include "if.h"
#include "ip.h"
#include "ip_icmp.h"
#include "udp.h"
#include "bootp.h"
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
struct udpstat udpstat;
struct SLIRPsocket *udp_last_so = &udb;
struct SLIRPsocket udb;
/*
* UDP protocol implementation.
* Per RFC 768, August, 1980.
*/
#ifndef COMPAT_42
int udpcksum = 1;
#else
int udpcksum = 0; /* XXX */
#endif
static const struct tos_t udptos[] = {
{ 0, 53, IPTOS_LOWDELAY, 0 }, /* DNS */
{ 517, 517, IPTOS_LOWDELAY, EMU_TALK }, /* talk */
{ 518, 518, IPTOS_LOWDELAY, EMU_NTALK }, /* ntalk */
{ 0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME }, /* Cu-Seeme */
{ 0, 0, 0, 0 }
};
uint8_t
udp_tos(struct SLIRPsocket *so)
{
int i = 0;
while (udptos[i].tos) {
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
so->so_emu = udptos[i].emu;
return udptos[i].tos;
}
i++;
}
return 0;
}
void
udp_init(void)
{
udb.so_next = udb.so_prev = &udb;
}
/* m->m_data points at ip packet header
* m->m_len length ip packet
* ip->ip_len length data (IPDU)
*/
void
udp_input(struct SLIRPmbuf *m, int iphlen)
{
struct SLIRPsocket *so, *tmp;
#if 0
struct SLIRPmbuf *opts = 0;
#endif
struct ip save_ip;
struct udphdr *uh;
struct ip *ip;
int len;
udpstat.udps_ipackets++;
/*
* Strip IP options, if any; should skip this,
* make available to user, and use on returned packets,
* but we don't yet have a way to check the checksum
* with options still present.
*/
if (iphlen > sizeof(struct ip)) {
ip_stripoptions(m, (struct SLIRPmbuf *)0);
iphlen = sizeof(struct ip);
}
/* Get IP and UDP header together in first SLIRPmbuf. */
ip = mtod(m, struct ip *);
uh = (struct udphdr *)((SLIRPcaddr_t)ip + iphlen);
/*
* Make SLIRPmbuf data length reflect UDP length.
* If not enough data to reflect UDP length, drop.
*/
len = ntohs((uint16_t)uh->uh_ulen);
if (ip->ip_len != len) {
if (len > ip->ip_len) {
udpstat.udps_badlen++;
goto bad;
}
m_adj(m, len - ip->ip_len);
ip->ip_len = len;
}
/*
* Save a copy of the IP header in case we want restore it
* for sending an ICMP error message in response.
*/
save_ip = *ip;
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
/* Checksum extended UDP header and data. */
if (udpcksum && uh->uh_sum) {
((struct ipovly *)ip)->ih_next = 0;
((struct ipovly *)ip)->ih_prev = 0;
((struct ipovly *)ip)->ih_x1 = 0;
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
/* keep uh_sum for ICMP reply
* uh->uh_sum = cksum(m, len + sizeof (struct ip));
* if (uh->uh_sum) {
*/
if (cksum(m, len + sizeof(struct ip))) {
udpstat.udps_badsum++;
goto bad;
}
}
/* Handle DHCP/BOOTP. */
if (ntohs(uh->uh_dport) == BOOTP_SERVER) {
bootp_input(m);
goto bad;
}
#ifdef NEED_TFTP
/* Handle TFTP. */
if (ntohs(uh->uh_dport) == TFTP_SERVER) {
tftp_input(m);
goto bad;
}
#endif
/* Locate pcb for datagram. */
so = udp_last_so;
if (so->so_lport != uh->uh_sport ||
so->so_laddr.s_addr != ip->ip_src.s_addr) {
for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
if (tmp->so_lport == uh->uh_sport &&
tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
tmp->so_faddr.s_addr = ip->ip_dst.s_addr;
tmp->so_fport = uh->uh_dport;
so = tmp;
break;
}
}
if (tmp != &udb) {
udpstat.udpps_pcbcachemiss++;
udp_last_so = so;
} else
so = NULL;
}
if (so == NULL) {
/* If there's no socket for this packet, create one. */
if ((so = socreate()) == NULL) goto bad;
if (udp_attach(so) == -1) {
DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
errno,strerror(errno)));
sofree(so);
goto bad;
}
/* Set up fields. */
#if 0
udp_last_so = so;
#endif
so->so_laddr = ip->ip_src;
so->so_lport = uh->uh_sport;
if ((so->so_iptos = udp_tos(so)) == 0)
so->so_iptos = ip->ip_tos;
/*
* XXXXX Here, check if it's in udpexec_list,
* and if it is, do the fork_exec() etc.
*/
}
so->so_faddr = ip->ip_dst; /* XXX */
so->so_fport = uh->uh_dport; /* XXX */
iphlen += sizeof(struct udphdr);
m->m_len -= iphlen;
m->m_data += iphlen;
#ifdef NEED_EMU
/* Now we sendto() the packet. */
if (so->so_emu)
udp_emu(so, m);
#endif
if (sosendto(so,m) == -1) {
m->m_len += iphlen;
m->m_data -= iphlen;
*ip = save_ip;
DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
}
m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
/* restore the orig SLIRPmbuf packet */
m->m_len += iphlen;
m->m_data -= iphlen;
*ip = save_ip;
so->so_m = m; /* ICMP backup */
return;
bad:
m_freem(m);
#if 0
if (opts) m_freem(opts);
#endif
}
int
udp_output2(struct SLIRPsocket *so, struct SLIRPmbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos)
{
struct udpiphdr *ui;
int error = 0;
/* Adjust for header. */
m->m_data -= sizeof(struct udpiphdr);
m->m_len += sizeof(struct udpiphdr);
/*
* Fill in SLIRPmbuf with extended UDP header
* and addresses and length put into network format.
*/
ui = mtod(m, struct udpiphdr *);
ui->ui_next = ui->ui_prev = 0;
ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP;
ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
ui->ui_src = saddr->sin_addr;
ui->ui_dst = daddr->sin_addr;
ui->ui_sport = saddr->sin_port;
ui->ui_dport = daddr->sin_port;
ui->ui_ulen = ui->ui_len;
/* Stuff checksum and output datagram. */
ui->ui_sum = 0;
if (udpcksum) {
if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
ui->ui_sum = 0xffff;
}
((struct ip *)ui)->ip_len = m->m_len;
((struct ip *)ui)->ip_ttl = ip_defttl;
((struct ip *)ui)->ip_tos = iptos;
udpstat.udps_opackets++;
error = ip_output(so, m);
return(error);
}
int
udp_output(struct SLIRPsocket *so, struct SLIRPmbuf *m,
struct sockaddr_in *addr)
{
struct sockaddr_in saddr, daddr;
saddr = *addr;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
saddr.sin_addr.s_addr = so->so_faddr.s_addr;
if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))
saddr.sin_addr.s_addr = router_addr.s_addr;
}
daddr.sin_addr = so->so_laddr;
daddr.sin_port = so->so_lport;
return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
}
int
udp_attach(struct SLIRPsocket *so)
{
struct sockaddr_in addr;
if ((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
/*
* Here, we bind() the socket. Although not really needed
* (sendto() on an unbound socket will bind it), it's done
* here so that emulation of ytalk etc. don't have to do it
*/
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(so->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
int lasterrno = errno;
closesocket(so->s);
so->s = -1;
#ifdef _WIN32
WSASetLastError(lasterrno);
#else
errno = lasterrno;
#endif
} else {
/* success, insert in queue */
so->so_expire = curtime + SO_EXPIRE;
insque(so,&udb);
}
}
return(so->s);
}
void
udp_detach(struct SLIRPsocket *so)
{
closesocket(so->s);
#if 0
if (so->so_m)
/* done by sofree */
m_free(so->so_m);
#endif
sofree(so);
}
#ifdef USE_REDIR
struct SLIRPsocket *
udp_listen(u_int port, uint32_t laddr, u_int lport, int flags)
{
socklen_t addrlen = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
struct SLIRPsocket *so;
int opt = 1;
if ((so = socreate()) == NULL) {
free(so);
return NULL;
}
so->s = socket(AF_INET,SOCK_DGRAM,0);
so->so_expire = curtime + SO_EXPIRE;
insque(so,&udb);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = port;
if (bind(so->s, (struct sockaddr *)&addr, addrlen) < 0) {
udp_detach(so);
return NULL;
}
setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
#if 0
setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
#endif
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
so->so_fport = addr.sin_port;
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
so->so_faddr = alias_addr;
else
so->so_faddr = addr.sin_addr;
so->so_lport = lport;
so->so_laddr.s_addr = laddr;
if (flags != SS_FACCEPTONCE)
so->so_expire = 0;
so->so_state = SS_ISFCONNECTED;
return so;
}
#endif /*USE_REDIR*/

117
src/udp.h Normal file
View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)udp.h 8.1 (Berkeley) 6/10/93
* udp.h,v 1.3 1994/08/21 05:27:41 paul Exp
*/
#ifndef _UDP_H_
#define _UDP_H_
#define UDP_TTL 0x60
#define UDP_UDPDATALEN 16192
extern struct SLIRPsocket *udp_last_so;
/*
* Udp protocol header.
* Per RFC 768, September, 1981.
*/
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct udphdr {
uint16_t uh_sport; /* source port */
uint16_t uh_dport; /* destination port */
int16_t uh_ulen; /* udp length */
uint16_t uh_sum; /* udp checksum */
} PACKED__;
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_END)
#endif
/*
* UDP kernel structures and variables.
*/
struct udpiphdr {
struct ipovly ui_i; /* overlaid ip structure */
struct udphdr ui_u; /* udp header */
};
#define ui_next ui_i.ih_next
#define ui_prev ui_i.ih_prev
#define ui_x1 ui_i.ih_x1
#define ui_pr ui_i.ih_pr
#define ui_len ui_i.ih_len
#define ui_src ui_i.ih_src
#define ui_dst ui_i.ih_dst
#define ui_sport ui_u.uh_sport
#define ui_dport ui_u.uh_dport
#define ui_ulen ui_u.uh_ulen
#define ui_sum ui_u.uh_sum
struct udpstat {
/* input statistics: */
u_long udps_ipackets; /* total input packets */
u_long udps_hdrops; /* packet shorter than header */
u_long udps_badsum; /* checksum error */
u_long udps_badlen; /* data length larger than packet */
u_long udps_noport; /* no socket on port */
u_long udps_noportbcast; /* of above, arrived as broadcast */
u_long udps_fullsock; /* not delivered, input socket full */
u_long udpps_pcbcachemiss; /* input packets missing pcb cache */
/* output statistics: */
u_long udps_opackets; /* total output packets */
};
/*
* Names for UDP sysctl objects
*/
#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
#define UDPCTL_MAXID 2
extern struct udpstat udpstat;
extern struct SLIRPsocket udb;
struct SLIRPmbuf;
extern void udp_init(void);
extern void udp_input(register struct SLIRPmbuf *, int);
extern int udp_output(struct SLIRPsocket *, struct SLIRPmbuf *,
struct sockaddr_in *);
extern int udp_attach(struct SLIRPsocket *);
extern void udp_detach(struct SLIRPsocket *);
extern uint8_t udp_tos(struct SLIRPsocket *);
extern void udp_emu(struct SLIRPsocket *, struct SLIRPmbuf *);
extern struct SLIRPsocket * udp_listen(u_int, uint32_t, u_int, int);
extern int udp_output2(struct SLIRPsocket *so, struct SLIRPmbuf *m,
struct sockaddr_in *saddr,
struct sockaddr_in *daddr, int iptos);
#endif

271
src/unix/Makefile.linux Normal file
View File

@@ -0,0 +1,271 @@
#
# VARCem Virtual ARchaeological Computer EMulator.
# An emulator of (mostly) x86-based PC systems and devices,
# using the ISA,EISA,VLB,MCA and PCI system buses, roughly
# spanning the era between 1981 and 1995.
#
# This file is part of the VARCem Project.
#
# Makefile for Debian (Jessie 8.9, 32bit) Linux.
#
# Since many UNIX-ish systems share common stuff, this file is
# also a template for systems similar to Debian Linux and the
# GCC compiler. See the "PLAT" and "PLATDIR" definitions below.
#
# Version: @(#)Makefile.linux 1.0.1 2018/11/02
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
# Copyright 2017,2018 Fred N. van Kempen.
#
# Redistribution and use in source and binary forms, with
# or without modification, are permitted provided that the
# following conditions are met:
#
# 1. Redistributions of source code must retain the entire
# above notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names
# of its contributors may be used to endorse or promote
# products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Defaults for several build options (possibly defined in a chained file.)
ifndef AUTODEP
AUTODEP := n
endif
ifndef DEBUG
DEBUG := n
endif
ifndef OPTIM
OPTIM := n
endif
ifndef RELEASE
RELEASE := n
endif
ifndef X64
X64 := n
endif
# Name of the executable.
ifndef PROG
PROG := libslirp
endif
ifeq ($(DEBUG), y)
PROG := $(PROG)-d
endif
# Select the desired platform.
PLAT := Linux
PLATDEFS := -DLINUX -DPLAT=\"$(PLAT)\"
PLATNAME := linux
PLATDIR := unix
#########################################################################
# Nothing should need changing from here on.. #
#########################################################################
VPATH := $(EXPATH) . unix
ifeq ($(X64), y)
CXX := g++ -m64
CC := gcc -m64
else
CXX := g++ -m32
CC := gcc -m32
endif
PREPROC := cpp -P
STRIP := strip
DEPS = -MMD -MF $*.d -c $<
DEPFILE := $(PLATDIR)/.depends-$(PLATNAME)
# Set up the correct toolchain flags.
OPTS := -DUNIX $(PLATDEFS)
ifdef BUILD
OPTS += -DBUILD=$(BUILD)
endif
ifdef COMMIT
OPTS += -DCOMMIT=0x$(COMMIT)
endif
ifdef EXFLAGS
OPTS += $(EXFLAGS)
endif
ifdef EXINC
OPTS += -I$(EXINC)
endif
ifeq ($(X64), y)
ifeq ($(OPTIM), y)
DFLAGS := -march=native
else
DFLAGS :=
endif
else
ifeq ($(OPTIM), y)
DFLAGS := -march=native
else
DFLAGS := -march=i686
endif
endif
ifeq ($(DEBUG), y)
DFLAGS += -ggdb -D_DEBUG
AOPTIM :=
ifndef COPTIM
COPTIM := -Og
endif
else
ifeq ($(OPTIM), y)
AOPTIM := -mtune=native
ifndef COPTIM
COPTIM := -O3
endif
else
ifndef COPTIM
COPTIM := -O3
endif
endif
endif
AFLAGS := -msse2 -mfpmath=sse
LDFLAGS := -pthread
LIBS :=
# Fix up the flags based on selected features.
ifeq ($(RELEASE), y)
OPTS += -DRELEASE_BUILD
endif
# Finalize the list of libraries to link in.
LIBS += -ldl -lpthread -lgcc
#ifneq ($(X64), y)
#LIBS += -Wl,--large-address-aware
#endif
# Final versions of the toolchain flags.
CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \
$(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \
-Wno-unused-result
CXXFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \
$(AFLAGS) -fno-strict-aliasing -fvisibility=hidden \
-Wall -Wundef -fvisibility-inlines-hidden \
-Wunused-parameter -Wno-ctor-dtor-privacy \
-Woverloaded-virtual
#########################################################################
# Create the (final) list of objects to build. #
#########################################################################
OBJ := slirp.o host.o misc.o poll.o \
cksum.o if.o mbuf.o queue.o sbuf.o socket.o \
debug.o stats.o \
arp.o bootp.o \
ip_icmp.o ip_input.o ip_output.o \
tcp_input.o tcp_output.o tcp_subr.o tcp_timer.o \
udp.o
ifdef EXOBJ
OBJ += $(EXOBJ)
endif
# Build module rules.
ifeq ($(AUTODEP), y)
%.o: %.c
@echo $<
@$(CC) $(CFLAGS) $(DEPS) -c $<
%.o: %.cpp
@echo $<
@$(CXX) $(CXXFLAGS) $(DEPS) -c $<
else
%.o: %.c
@echo $<
@$(CC) $(CFLAGS) -c $<
%.i: %.c
@echo $<
@$(PREPROC) $(CFLAGS) -P $<
%.o: %.cpp
@echo $<
@$(CXX) $(CXXFLAGS) -c $<
%.d: %.c $(wildcard $*.d)
@echo $<
@$(CC) $(CFLAGS) $(DEPS) -E $< >/dev/null
%.d: %.cpp $(wildcard $*.d)
@echo $<
@$(CXX) $(CXXFLAGS) $(DEPS) -E $< >/dev/null
endif
all: $(PREBUILD) $(PROG).so $(POSTBUILD)
$(PROG).so: $(OBJ)
@echo Linking $(PROG).so
@$(CXX) $(LDFLAGS) -shared -o $(PROG).so $(OBJ) $(LIBS)
#ifneq ($(DEBUG), y)
# @strip $(PROG).so
#endif
clean:
@echo Cleaning objects..
@-rm -f *.o 2>/dev/null
clobber: clean
@echo Cleaning executables..
@-rm -f *.d 2>/dev/null
@-rm -f $(PROG).so 2>/dev/null
# @-rm -f $(DEPFILE) 2>/dev/null
ifneq ($(AUTODEP), y)
depclean:
@-rm -f $(DEPFILE) 2>/dev/null
@echo Creating dependencies..
@echo # Run "make depends" to re-create this file. >$(DEPFILE)
depends: DEPOBJ=$(OBJ:%.o=%.d)
depends: depclean $(OBJ:%.o=%.d)
@-cat $(DEPOBJ) >>$(DEPFILE)
@-rm -f $(DEPOBJ)
$(DEPFILE):
endif
# Module dependencies.
ifeq ($(AUTODEP), y)
#-include $(OBJ:%.o=%.d) (better, but sloooowwwww)
-include *.d
else
include $(wildcard $(DEPFILE))
endif
# End of Makefile.linux.

81
src/unix/host.c Normal file
View File

@@ -0,0 +1,81 @@
#ifdef _WIN32
# include <windows.h>
#else
# include <unistd.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <netdb.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_INADDR_H
#include "../slirp.h"
#include "../debug.h"
int
host_get_info(struct in_addr *dns, char *hostname, char *domainname)
{
char buff[512], buff2[256];
struct in_addr addr;
struct hostent *he;
int found = 0;
FILE *f;
f = fopen("/etc/resolv.conf", "r");
if (!f)
return -1;
/* Set up hostname, domainname and IP address. */
if (! gethostname(buff, sizeof(buff))) {
he = gethostbyname(buff);
if (he)
our_addr = *(struct in_addr *)he->h_addr;
strcpy(hostname, buff);
strcpy(domainname, "");
}
strcpy(domainname, "homenet.lan");
lprint("My name: %s.%s\n", hostname, domainname);
lprint("My IP address: %s\n", inet_ntoa(our_addr));
lprint(" DNS Servers:\n" );
while (fgets(buff, 512, f) != NULL) {
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
if (! inet_aton(buff2, &addr))
continue;
if (addr.s_addr == loopback_addr.s_addr)
addr = our_addr;
/* If it's the first one, set it to dns_addr */
if (! found++)
*dns = addr;
lprint(" Address: %s\n", inet_ntoa(addr));
}
}
fclose(f);
if (! found)
return -1;
return 0;
}
int
host_init(void)
{
/* Nothing to do, usually. */
return 0;
}
void
host_close(void)
{
/* Nothing to do. */
}

21
src/unused/main.h Normal file
View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#define TOWRITEMAX 512
/*
* Get the difference in 2 times from updtim()
* Allow for wraparound times, "just in case"
* x is the greater of the 2 (current time) and y is
* what it's being compared against.
*/
#define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y)

128
src/unused/misc.c Normal file
View File

@@ -0,0 +1,128 @@
void
snooze(void)
{
sigset_t s;
int i;
/* Don't need our data anymore */
/* XXX This makes SunOS barf */
/* brk(0); */
/* Close all fd's */
for (i = 255; i >= 0; i--)
close(i);
signal(SIGQUIT, slirp_exit);
signal(SIGHUP, snooze_hup);
sigemptyset(&s);
/* Wait for any signal */
sigsuspend(&s);
/* Just in case ... */
exit(255);
}
void
relay(int s)
{
char buf[8192];
int n;
fd_set readfds;
struct ttys *ttyp;
/* Don't need our data anymore */
/* XXX This makes SunOS barf */
/* brk(0); */
signal(SIGQUIT, slirp_exit);
signal(SIGHUP, slirp_exit);
signal(SIGINT, slirp_exit);
signal(SIGTERM, slirp_exit);
/* Fudge to get term_raw and term_restore to work */
if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
slirp_exit (1);
}
ttyp->fd = 0;
ttyp->flags |= TTY_CTTY;
term_raw(ttyp);
while (1) {
FD_ZERO(&readfds);
FD_SET(0, &readfds);
FD_SET(s, &readfds);
n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
if (n <= 0)
slirp_exit(0);
if (FD_ISSET(0, &readfds)) {
n = read(0, buf, 8192);
if (n <= 0)
slirp_exit(0);
n = writen(s, buf, n);
if (n <= 0)
slirp_exit(0);
}
if (FD_ISSET(s, &readfds)) {
n = read(s, buf, 8192);
if (n <= 0)
slirp_exit(0);
n = writen(0, buf, n);
if (n <= 0)
slirp_exit(0);
}
}
/* Just in case.... */
exit(1);
}
#ifdef BAD_SPRINTF
# undef vsprintf
# undef sprintf
/* Some BSD-derived systems have a sprintf which returns char *. */
int
vsprintf_len(char *string, const char *format, va_list args)
{
vsprintf(string, format, args);
return strlen(string);
}
int
sprintf_len(char *string, const char *format, ...)
{
va_list args;
va_start(args, format);
vsprintf(string, format, args);
return strlen(string);
}
#endif
void
u_sleep(int usec)
{
struct timeval t;
fd_set fdset;
FD_ZERO(&fdset);
t.tv_sec = 0;
t.tv_usec = usec * 1000;
select(0, &fdset, &fdset, &fdset, &t);
}

65
src/unused/redir.c Normal file
View File

@@ -0,0 +1,65 @@
#include "slirp.h"
#ifdef USE_REDIR
#include "redir.h"
struct ex_list *exec_list = NULL;
int
redir_init(void)
{
const char *cat = "SLiRP Port Forwarding";
char temp[256];
int rc, udp, from, to;
int i = 0;
for (;;) {
sprintf(temp, "%d_udp", i);
udp = config_get_int(cat, temp, 0);
sprintf(temp, "%d_from", i);
from = config_get_int(cat, temp, 0);
if (from < 1)
break;
sprintf(temp, "%d_to", i);
to = config_get_int(cat, temp, from);
rc = slirp_redir(udp, from, myaddr, to);
if (rc == 0)
pclog(1, "slirp redir %d -> %d successful\n", from, to);
else
pclog(1, "slirp redir %d -> %d failed (%d)\n", from, to, rc);
i++;
}
}
int
slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port)
{
if (is_udp) {
if (! udp_listen(htons(host_port), guest_addr.s_addr,
htons(guest_port), 0))
return -1;
} else {
if (! solisten(htons(host_port), guest_addr.s_addr,
htons(guest_port), 0))
return -1;
}
return 0;
}
int
slirp_add_exec(int do_pty, const char *args, int addr_low_byte, int guest_port)
{
return add_exec(&exec_list, do_pty, (char *)args,
addr_low_byte, htons(guest_port));
}
#endif /*USE_REDIR*/

12
src/unused/redir.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef SLIRP_REDIR_H
# define SLIRP_REDIR_H
extern int redir_init(void);
extern int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port);
extern int slirp_add_exec(int do_pty, const char *args,
int addr_low_byte, int guest_port);
#endif /*SLIRP_REDIR_H*/

654
src/unused/tcp_emu.c Normal file
View File

@@ -0,0 +1,654 @@
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#define WANT_SYS_IOCTL_H
#include <stdlib.h>
#ifndef _WIN32
# include <unistd.h>
#endif
#include "slirp.h"
#ifdef USE_REDIR
struct emu_t *tcpemu = 0;
int do_echo = -1;
/*
* Emulate programs that try and connect to us
* This includes ftp (the data connection is
* initiated by the server) and IRC (DCC CHAT and
* DCC SEND) for now
*
* NOTE: It's possible to crash SLiRP by sending it
* unstandard strings to emulate... if this is a problem,
* more checks are needed here
*
* XXX Assumes the whole command came in one packet
*
* XXX Some ftp clients will have their TOS set to
* LOWDELAY and so Nagel will kick in. Because of this,
* we'll get the first letter, followed by the rest, so
* we simply scan for ORT instead of PORT...
* DCC doesn't have this problem because there's other stuff
* in the packet before the DCC command.
*
* Return 1 if the SLIRPmbuf m is still valid and should be
* sbappend()ed
*
* NOTE: if you return 0 you MUST m_free() the SLIRPmbuf!
*/
int
tcp_emu(struct SLIRPsocket *so, struct SLIRPmbuf *m)
{
u_int n1, n2, n3, n4, n5, n6;
char buff[256];
u_int32_t laddr;
u_int lport;
char *bptr;
DEBUG_CALL("tcp_emu");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m);
switch(so->so_emu) {
int x, i;
case EMU_IDENT:
/*
* Identification protocol as per rfc-1413
*/
{
struct SLIRPsocket *tmpso;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(struct sockaddr_in);
struct sbuf *so_rcv = &so->so_rcv;
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
so_rcv->sb_wptr += m->m_len;
so_rcv->sb_rptr += m->m_len;
m->m_data[m->m_len] = 0; /* NULL terminate */
if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) {
HTONS(n1);
HTONS(n2);
/* n2 is the one on our host */
for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
tmpso->so_lport == n2 &&
tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
tmpso->so_fport == n1) {
if (getsockname(tmpso->s,
(struct sockaddr *)&addr, &addrlen) == 0)
n2 = ntohs(addr.sin_port);
break;
}
}
}
so_rcv->sb_cc = sprintf(so_rcv->sb_data, "%d,%d\r\n", n1, n2);
so_rcv->sb_rptr = so_rcv->sb_data;
so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
}
m_free(m);
return 0;
}
#if 0
case EMU_RLOGIN:
/*
* Rlogin emulation
* First we accumulate all the initial option negotiation,
* then fork_exec() rlogin according to the options
*/
{
int i, i2, n;
char *ptr;
char args[100];
char term[100];
struct sbuf *so_snd = &so->so_snd;
struct sbuf *so_rcv = &so->so_rcv;
/* First check if they have a priveladged port, or too much data has arrived */
if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
(m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
so_snd->sb_wptr += 18;
so_snd->sb_cc += 18;
tcp_sockclosed(sototcpcb(so));
m_free(m);
return 0;
}
/* Append the current data */
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
so_rcv->sb_wptr += m->m_len;
so_rcv->sb_rptr += m->m_len;
m_free(m);
/*
* Check if we have all the initial options,
* and build argument list to rlogin while we're here
*/
n = 0;
ptr = so_rcv->sb_data;
args[0] = 0;
term[0] = 0;
while (ptr < so_rcv->sb_wptr) {
if (*ptr++ == 0) {
n++;
if (n == 2) {
sprintf(args, "rlogin -l %s %s",
ptr, inet_ntoa(so->so_faddr));
} else if (n == 3) {
i2 = so_rcv->sb_wptr - ptr;
for (i = 0; i < i2; i++) {
if (ptr[i] == '/') {
ptr[i] = 0;
#ifdef HAVE_SETENV
sprintf(term, "%s", ptr);
#else
sprintf(term, "TERM=%s", ptr);
#endif
ptr[i] = '/';
break;
}
}
}
}
}
if (n != 4)
return 0;
/* We have it, set our term variable and fork_exec() */
#ifdef HAVE_SETENV
setenv("TERM", term, 1);
#else
putenv(term);
#endif
fork_exec(so, args, 2);
term[0] = 0;
so->so_emu = 0;
/* And finally, send the client a 0 character */
so_snd->sb_wptr[0] = 0;
so_snd->sb_wptr++;
so_snd->sb_cc++;
return 0;
}
case EMU_RSH:
/*
* rsh emulation
* First we accumulate all the initial option negotiation,
* then rsh_exec() rsh according to the options
*/
{
int n;
char *ptr;
char *user;
char *args;
struct sbuf *so_snd = &so->so_snd;
struct sbuf *so_rcv = &so->so_rcv;
/* First check if they have a priveladged port, or too much data has arrived */
if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
(m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
so_snd->sb_wptr += 18;
so_snd->sb_cc += 18;
tcp_sockclosed(sototcpcb(so));
m_free(m);
return 0;
}
/* Append the current data */
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
so_rcv->sb_wptr += m->m_len;
so_rcv->sb_rptr += m->m_len;
m_free(m);
/*
* Check if we have all the initial options,
* and build argument list to rlogin while we're here
*/
n = 0;
ptr = so_rcv->sb_data;
user="";
args="";
if (so->extra==NULL) {
struct SLIRPsocket *ns;
struct tcpcb* tp;
int port=atoi(ptr);
if (port <= 0) return 0;
if (port > 1023 || port < 512) {
memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
so_snd->sb_wptr += 18;
so_snd->sb_cc += 18;
tcp_sockclosed(sototcpcb(so));
return 0;
}
if ((ns=socreate()) == NULL)
return 0;
if (tcp_attach(ns)<0) {
free(ns);
return 0;
}
ns->so_laddr=so->so_laddr;
ns->so_lport=htons(port);
(void) tcp_mss(sototcpcb(ns), 0);
ns->so_faddr=so->so_faddr;
ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */
if (ns->so_faddr.s_addr == 0 ||
ns->so_faddr.s_addr == loopback_addr.s_addr)
ns->so_faddr = alias_addr;
ns->so_iptos = tcp_tos(ns);
tp = sototcpcb(ns);
tcp_template(tp);
/* Compute window scaling to request. */
/* while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
* (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
* tp->request_r_scale++;
*/
/*soisfconnecting(ns);*/
tcpstat.tcps_connattempt++;
tp->t_state = TCPS_SYN_SENT;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
tp->iss = tcp_iss;
tcp_iss += TCP_ISSINCR/2;
tcp_sendseqinit(tp);
tcp_output(tp);
so->extra=ns;
}
while (ptr < so_rcv->sb_wptr) {
if (*ptr++ == 0) {
n++;
if (n == 2) {
user=ptr;
} else if (n == 3) {
args=ptr;
}
}
}
if (n != 4)
return 0;
rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args);
so->so_emu = 0;
so->extra=NULL;
/* And finally, send the client a 0 character */
so_snd->sb_wptr[0] = 0;
so_snd->sb_wptr++;
so_snd->sb_cc++;
return 0;
}
case EMU_CTL:
{
int num;
struct sbuf *so_snd = &so->so_snd;
struct sbuf *so_rcv = &so->so_rcv;
/*
* If there is binary data here, we save it in so->so_m
*/
if (!so->so_m) {
int rxlen;
char *rxdata;
rxdata=mtod(m, char *);
for (rxlen=m->m_len; rxlen; rxlen--) {
if (*rxdata++ & 0x80) {
so->so_m = m;
return 0;
}
}
} /* if(so->so_m==NULL) */
/*
* Append the line
*/
sbappendsb(so_rcv, m);
/* To avoid going over the edge of the buffer, we reset it */
if (so_snd->sb_cc == 0)
so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data;
/*
* A bit of a hack:
* If the first packet we get here is 1 byte long, then it
* was done in telnet character mode, therefore we must echo
* the characters as they come. Otherwise, we echo nothing,
* because in linemode, the line is already echoed
* XXX two or more control connections won't work
*/
if (do_echo == -1) {
if (m->m_len == 1) do_echo = 1;
else do_echo = 0;
}
if (do_echo) {
sbappendsb(so_snd, m);
m_free(m);
tcp_output(sototcpcb(so)); /* XXX */
} else
m_free(m);
num = 0;
while (num < so->so_rcv.sb_cc) {
if (*(so->so_rcv.sb_rptr + num) == '\n' ||
*(so->so_rcv.sb_rptr + num) == '\r') {
int n;
*(so_rcv->sb_rptr + num) = 0;
if (ctl_password && !ctl_password_ok) {
/* Need a password */
if (sscanf(so_rcv->sb_rptr, "pass %256s", buff) == 1) {
if (strcmp(buff, ctl_password) == 0) {
ctl_password_ok = 1;
n = sprintf(so_snd->sb_wptr,
"Password OK.\r\n");
goto do_prompt;
}
}
n = sprintf(so_snd->sb_wptr,
"Error: Password required, log on with \"pass PASSWORD\"\r\n");
goto do_prompt;
}
cfg_quitting = 0;
n = do_config(so_rcv->sb_rptr, so, PRN_SPRINTF);
if (!cfg_quitting) {
/* Register the printed data */
do_prompt:
so_snd->sb_cc += n;
so_snd->sb_wptr += n;
/* Add prompt */
n = sprintf(so_snd->sb_wptr, "Slirp> ");
so_snd->sb_cc += n;
so_snd->sb_wptr += n;
}
/* Drop so_rcv data */
so_rcv->sb_cc = 0;
so_rcv->sb_wptr = so_rcv->sb_rptr = so_rcv->sb_data;
tcp_output(sototcpcb(so)); /* Send the reply */
}
num++;
}
return 0;
}
#endif
case EMU_FTP: /* ftp */
*(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */
if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
/*
* Need to emulate the PORT command
*/
x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]",
&n1, &n2, &n3, &n4, &n5, &n6, buff);
if (x < 6)
return 1;
laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
lport = htons((n5 << 8) | (n6));
if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
n6 = ntohs(so->so_fport);
n5 = (n6 >> 8) & 0xff;
n6 &= 0xff;
laddr = ntohl(so->so_faddr.s_addr);
n1 = ((laddr >> 24) & 0xff);
n2 = ((laddr >> 16) & 0xff);
n3 = ((laddr >> 8) & 0xff);
n4 = (laddr & 0xff);
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr,"ORT %d,%d,%d,%d,%d,%d\r\n%s",
n1, n2, n3, n4, n5, n6, x==7?buff:"");
return 1;
} else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
/*
* Need to emulate the PASV response
*/
x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]",
&n1, &n2, &n3, &n4, &n5, &n6, buff);
if (x < 6)
return 1;
laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
lport = htons((n5 << 8) | (n6));
if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
return 1;
n6 = ntohs(so->so_fport);
n5 = (n6 >> 8) & 0xff;
n6 &= 0xff;
laddr = ntohl(so->so_faddr.s_addr);
n1 = ((laddr >> 24) & 0xff);
n2 = ((laddr >> 16) & 0xff);
n3 = ((laddr >> 8) & 0xff);
n4 = (laddr & 0xff);
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr,"27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
n1, n2, n3, n4, n5, n6, x==7?buff:"");
return 1;
}
return 1;
case EMU_KSH:
/*
* The kshell (Kerberos rsh) and shell services both pass
* a local port port number to carry signals to the server
* and stderr to the client. It is passed at the beginning
* of the connection as a NUL-terminated decimal ASCII string.
*/
so->so_emu = 0;
for (lport = 0, i = 0; i < m->m_len-1; ++i) {
if (m->m_data[i] < '0' || m->m_data[i] > '9')
return 1; /* invalid number */
lport *= 10;
lport += m->m_data[i] - '0';
}
if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
(so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1;
return 1;
case EMU_IRC:
/*
* Need to emulate DCC CHAT, DCC SEND and DCC MOVE
*/
*(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */
if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
return 1;
/* The %256s is for the broken mIRC */
if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n",
(unsigned long)ntohl(so->so_faddr.s_addr),
ntohs(so->so_fport), 1);
} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n",
buff, (unsigned long)ntohl(so->so_faddr.s_addr),
ntohs(so->so_fport), n1, 1);
} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
return 1;
m->m_len = bptr - m->m_data; /* Adjust length */
m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n",
buff, (unsigned long)ntohl(so->so_faddr.s_addr),
ntohs(so->so_fport), n1, 1);
}
return 1;
case EMU_REALAUDIO:
/*
* RealAudio emulation - JP. We must try to parse the incoming
* data and try to find the two characters that contain the
* port number. Then we redirect an udp port and replace the
* number with the real port we got.
*
* The 1.0 beta versions of the player are not supported
* any more.
*
* A typical packet for player version 1.0 (release version):
*
* 0000:50 4E 41 00 05
* 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....×..gælÜc..P
* 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
* 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
* 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
*
* Now the port number 0x1BD7 is found at offset 0x04 of the
* Now the port number 0x1BD7 is found at offset 0x04 of the
* second packet. This time we received five bytes first and
* then the rest. You never know how many bytes you get.
*
* A typical packet for player version 2.0 (beta):
*
* 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........Á.
* 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .guxõc..Win2.0.0
* 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
* 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
* 0040:65 2E 72 61 79 53 00 00 06 36 42 e.rayS...6B
*
* Port number 0x1BC1 is found at offset 0x0d.
*
* This is just a horrible switch statement. Variable ra tells
* us where we're going.
*/
bptr = m->m_data;
while (bptr < m->m_data + m->m_len) {
u_short p;
static int ra = 0;
char ra_tbl[4];
ra_tbl[0] = 0x50;
ra_tbl[1] = 0x4e;
ra_tbl[2] = 0x41;
ra_tbl[3] = 0;
switch (ra) {
case 0:
case 2:
case 3:
if (*bptr++ != ra_tbl[ra]) {
ra = 0;
continue;
}
break;
case 1:
/*
* We may get 0x50 several times, ignore them
*/
if (*bptr == 0x50) {
ra = 1;
bptr++;
continue;
} else if (*bptr++ != ra_tbl[ra]) {
ra = 0;
continue;
}
break;
case 4:
/*
* skip version number
*/
bptr++;
break;
case 5:
/*
* The difference between versions 1.0 and
* 2.0 is here. For future versions of
* the player this may need to be modified.
*/
if (*(bptr + 1) == 0x02)
bptr += 8;
else
bptr += 4;
break;
case 6:
/* This is the field containing the port
* number that RA-player is listening to.
*/
lport = (((u_char*)bptr)[0] << 8)
+ ((u_char *)bptr)[1];
if (lport < 6970)
lport += 256; /* don't know why */
if (lport < 6970 || lport > 7170)
return 1; /* failed */
/* try to get udp port between 6970 - 7170 */
for (p = 6970; p < 7071; p++) {
if (udp_listen( htons(p),
so->so_laddr.s_addr,
htons(lport),
SS_FACCEPTONCE)) {
break;
}
}
if (p == 7071)
p = 0;
*(u_char *)bptr++ = (p >> 8) & 0xff;
*(u_char *)bptr++ = p & 0xff;
ra = 0;
return 1; /* port redirected, we're done */
break;
default:
ra = 0;
}
ra++;
}
return 1;
default:
/* Ooops, not emulated, won't call tcp_emu again */
so->so_emu = 0;
return 1;
}
}
#endif /*USE_REDIR*/

40
src/unused/tftp.h Normal file
View File

@@ -0,0 +1,40 @@
/* tftp defines */
#define TFTP_SESSIONS_MAX 3
#define TFTP_SERVER 69
#define TFTP_RRQ 1
#define TFTP_WRQ 2
#define TFTP_DATA 3
#define TFTP_ACK 4
#define TFTP_ERROR 5
#define TFTP_FILENAME_MAX 512
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct tftp_t {
struct ip ip;
struct udphdr udp;
u_int16_t tp_op;
union {
struct {
u_int16_t tp_block_nr;
u_int8_t tp_buf[512];
} tp_data;
struct {
u_int16_t tp_error_code;
u_int8_t tp_msg[512];
} tp_error;
u_int8_t tp_buf[512 + 2];
} x;
} PACKED__;
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_END)
#endif
void tftp_input(struct SLIRPmbuf *m);

251
src/unused/udp_emu.c Normal file
View File

@@ -0,0 +1,251 @@
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#include <stdlib.h>
#ifndef _WIN32
# include <unistd.h>
#endif
#include "slirp.h"
#include "ip_icmp.h"
#ifdef EMULATE_TALK
# include "talkd.h"
#endif
#ifdef USE_REDIR
struct cu_header {
uint16_t d_family; // destination family
uint16_t d_port; // destination port
uint32_t d_addr; // destination address
uint16_t s_family; // source family
uint16_t s_port; // source port
uint32_t so_addr; // source address
uint32_t seqn; // sequence number
uint16_t message; // message
uint16_t data_type; // data type
uint16_t pkt_len; // packet length
};
#ifdef EMULATE_TALK
# define IS_OLD (so->so_emu == EMU_TALK)
# define COPY_MSG(dest, src) { \
dest->type = src->type; \
dest->id_num = src->id_num; \
dest->pid = src->pid; \
dest->addr = src->addr; \
dest->ctl_addr = src->ctl_addr; \
memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \
memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \
memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE); \
}
# define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field)
struct talk_request {
struct talk_request *next;
struct SLIRPsocket *udp_so;
struct SLIRPsocket *tcp_so;
} *req;
static struct talk_request *req_tbl = 0;
#endif
/* Here, talk/ytalk/ntalk requests must be emulated. */
void
udp_emu(struct SLIRPsocket *so, struct SLIRPmbuf *m)
{
socklen_t addrlen = sizeof(addr);
struct sockaddr_in addr;
#ifdef EMULATE_TALK
CTL_MSG_OLD *omsg;
CTL_MSG *nmsg;
char buff[sizeof(CTL_MSG)];
u_char type;
#endif
struct cu_header *cu_head;
switch(so->so_emu) {
#ifdef EMULATE_TALK
case EMU_TALK:
case EMU_NTALK:
/*
* Talk emulation. We always change the ctl_addr to get
* some answers from the daemon. When an ANNOUNCE comes,
* we send LEAVE_INVITE to the local daemons. Also when a
* DELETE comes, we send copies to the local daemons.
*/
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
return;
/* old_sockaddr to sockaddr_in */
if (IS_OLD) { /* old talk */
omsg = mtod(m, CTL_MSG_OLD*);
nmsg = (CTL_MSG *) buff;
type = omsg->type;
OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
} else { /* new talk */
omsg = (CTL_MSG_OLD *) buff;
nmsg = mtod(m, CTL_MSG *);
type = nmsg->type;
OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port;
OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
}
if (type == LOOK_UP)
return; /* for LOOK_UP this is enough */
if (IS_OLD) { /* make a copy of the message */
COPY_MSG(nmsg, omsg);
nmsg->vers = 1;
nmsg->answer = 0;
} else
COPY_MSG(omsg, nmsg);
/*
* If if is an ANNOUNCE message, we go through the
* request table to see if a tcp port has already
* been redirected for this socket. If not, we solisten()
* a new socket and add this entry to the table.
* The port number of the tcp socket and our IP
* are put to the addr field of the message structures.
* Then a LEAVE_INVITE is sent to both local daemon
* ports, 517 and 518. This is why we have two copies
* of the message, one in old talk and one in new talk
* format.
*/
if (type == ANNOUNCE) {
int s;
u_short temp_port;
for (req = req_tbl; req; req = req->next)
if (so == req->udp_so)
break; /* found it */
if (!req) { /* no entry for so, create new */
req = (struct talk_request *)
malloc(sizeof(struct talk_request));
req->udp_so = so;
req->tcp_so = solisten(0,
OTOSIN(omsg, addr)->sin_addr.s_addr,
OTOSIN(omsg, addr)->sin_port,
SS_FACCEPTONCE);
req->next = req_tbl;
req_tbl = req;
}
/* replace port number in addr field */
addrlen = sizeof(addr);
getsockname(req->tcp_so->s,
(struct sockaddr *) &addr,
&addrlen);
OTOSIN(omsg, addr)->sin_port = addr.sin_port;
OTOSIN(omsg, addr)->sin_addr = our_addr;
OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
OTOSIN(nmsg, addr)->sin_addr = our_addr;
/* send LEAVE_INVITEs */
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
OTOSIN(omsg, ctl_addr)->sin_port = 0;
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
omsg->type = nmsg->type = LEAVE_INVITE;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
addr.sin_addr = our_addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(517);
sendto(s, (char *)omsg, sizeof(*omsg), 0,
(struct sockaddr *)&addr, sizeof(addr));
addr.sin_port = htons(518);
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
(struct sockaddr *) &addr, sizeof(addr));
closesocket(s) ;
omsg->type = nmsg->type = ANNOUNCE;
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
}
/*
* If it is a DELETE message, we send a copy to the
* local daemons. Then we delete the entry corresponding
* to our socket from the request table.
*/
if (type == DELETE) {
struct talk_request *temp_req, *req_next;
int s;
u_short temp_port;
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
OTOSIN(omsg, ctl_addr)->sin_port = 0;
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
addr.sin_addr = our_addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(517);
sendto(s, (char *)omsg, sizeof(*omsg), 0,
(struct sockaddr *)&addr, sizeof(addr));
addr.sin_port = htons(518);
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
(struct sockaddr *)&addr, sizeof(addr));
closesocket(s);
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
/* delete table entry */
if (so == req_tbl->udp_so) {
temp_req = req_tbl;
req_tbl = req_tbl->next;
free(temp_req);
} else {
temp_req = req_tbl;
for(req = req_tbl->next; req; req = req_next) {
req_next = req->next;
if (so == req->udp_so) {
temp_req->next = req_next;
free(req);
break;
} else {
temp_req = req;
}
}
}
}
return;
#endif
case EMU_CUSEEME:
/*
* Cu-SeeMe emulation.
* Hopefully the packet is more that 16 bytes long. We don't
* do any other tests, just replace the address and port
* fields.
*/
if (m->m_len >= sizeof (*cu_head)) {
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
return;
cu_head = mtod(m, struct cu_header *);
cu_head->s_port = addr.sin_port;
cu_head->so_addr = our_addr.s_addr;
}
return;
}
}
#endif /*USE_REDIR*/

332
src/unused/udp_tftp.c Normal file
View File

@@ -0,0 +1,332 @@
/*
* tftp.c - a simple, read-only tftp server for qemu
*
* Copyright (c) 2004 Magnus Damm <damm@opensource.se>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "slirp.h"
#include "../ibm.h"
struct tftp_session {
int in_use;
char filename[TFTP_FILENAME_MAX];
struct in_addr client_ip;
u_int16_t client_port;
int timestamp;
};
struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
const char *tftp_prefix;
static void tftp_session_update(struct tftp_session *spt)
{
spt->timestamp = curtime;
spt->in_use = 1;
}
static void tftp_session_terminate(struct tftp_session *spt)
{
spt->in_use = 0;
}
static int tftp_session_allocate(struct tftp_t *tp)
{
struct tftp_session *spt;
int k;
for (k = 0; k < TFTP_SESSIONS_MAX; k++) {
spt = &tftp_sessions[k];
if (!spt->in_use)
goto found;
/* sessions time out after 5 inactive seconds */
if ((int)(curtime - spt->timestamp) > 5000)
goto found;
}
return -1;
found:
memset(spt, 0, sizeof(*spt));
memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip));
spt->client_port = tp->udp.uh_sport;
tftp_session_update(spt);
return k;
}
static int tftp_session_find(struct tftp_t *tp)
{
struct tftp_session *spt;
int k;
for (k = 0; k < TFTP_SESSIONS_MAX; k++) {
spt = &tftp_sessions[k];
if (spt->in_use) {
if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
if (spt->client_port == tp->udp.uh_sport) {
return k;
}
}
}
}
return -1;
}
static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
u_int8_t *buf, int len)
{
int fd;
int bytes_read = 0;
char file_path[sizeof(pcempath) + 5 + sizeof(spt->filename)];
strcpy(file_path, pcempath);
strcat(file_path, "tftp/");
strcat(file_path, spt->filename);
fd = open(file_path, O_RDONLY | O_BINARY);
if (fd < 0) {
return -1;
}
if (len) {
lseek(fd, block_nr * 512, SEEK_SET);
bytes_read = read(fd, buf, len);
}
close(fd);
return bytes_read;
}
static int tftp_send_error(struct tftp_session *spt,
u_int16_t errorcode, const char *msg,
struct tftp_t *recv_tp)
{
struct sockaddr_in saddr, daddr;
struct SLIRPmbuf *m;
struct tftp_t *tp;
int nobytes;
m = m_get();
if (!m) {
return -1;
}
memset(m->m_data, 0, m->m_size);
m->m_data += if_maxlinkhdr;
tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
tp->tp_op = htons(TFTP_ERROR);
tp->x.tp_error.tp_error_code = htons(errorcode);
strncpy((char *)tp->x.tp_error.tp_msg, msg, sizeof(tp->x.tp_error.tp_msg));
tp->x.tp_error.tp_msg[sizeof(tp->x.tp_error.tp_msg)-1] = 0;
saddr.sin_addr = recv_tp->ip.ip_dst;
saddr.sin_port = recv_tp->udp.uh_dport;
daddr.sin_addr = spt->client_ip;
daddr.sin_port = spt->client_port;
nobytes = 2;
m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
tftp_session_terminate(spt);
return 0;
}
static int tftp_send_data(struct tftp_session *spt,
u_int16_t block_nr,
struct tftp_t *recv_tp)
{
struct sockaddr_in saddr, daddr;
struct SLIRPmbuf *m;
struct tftp_t *tp;
int nobytes;
if (block_nr < 1) {
return -1;
}
m = m_get();
if (!m) {
return -1;
}
memset(m->m_data, 0, m->m_size);
m->m_data += if_maxlinkhdr;
tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
tp->tp_op = htons(TFTP_DATA);
tp->x.tp_data.tp_block_nr = htons(block_nr);
saddr.sin_addr = recv_tp->ip.ip_dst;
saddr.sin_port = recv_tp->udp.uh_dport;
daddr.sin_addr = spt->client_ip;
daddr.sin_port = spt->client_port;
nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512);
if (nobytes < 0) {
m_free(m);
/* send "file not found" error back */
tftp_send_error(spt, 1, "File not found", tp);
return -1;
}
m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
if (nobytes == 512) {
tftp_session_update(spt);
}
else {
tftp_session_terminate(spt);
}
return 0;
}
static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
{
struct tftp_session *spt;
int s, k, n;
u_int8_t *src, *dst;
s = tftp_session_allocate(tp);
if (s < 0) {
return;
}
spt = &tftp_sessions[s];
src = tp->x.tp_buf;
dst = (u_int8_t *)spt->filename;
n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
/* get name */
for (k = 0; k < n; k++) {
if (k < TFTP_FILENAME_MAX) {
dst[k] = src[k];
}
else {
return;
}
if (src[k] == '\0') {
break;
}
}
if (k >= n) {
return;
}
k++;
/* check mode */
if ((n - k) < 6) {
return;
}
if (memcmp(&src[k], "octet\0", 6) != 0) {
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
return;
}
pclog("tftp request: %s\n", spt->filename);
/* do sanity checks on the filename */
if (strstr(spt->filename, "../") || strstr(spt->filename, "..\\")) {
tftp_send_error(spt, 2, "Access violation", tp);
return;
}
/* check if the file exists */
if (tftp_read_data(spt, 0, (u_int8_t *)spt->filename, 0) < 0) {
tftp_send_error(spt, 1, "File not found", tp);
return;
}
tftp_send_data(spt, 1, tp);
}
static void tftp_handle_ack(struct tftp_t *tp, int pktlen)
{
int s;
s = tftp_session_find(tp);
if (s < 0) {
return;
}
if (tftp_send_data(&tftp_sessions[s],
ntohs(tp->x.tp_data.tp_block_nr) + 1,
tp) < 0) {
return;
}
}
void tftp_input(struct SLIRPmbuf *m)
{
struct tftp_t *tp = (struct tftp_t *)m->m_data;
switch(ntohs(tp->tp_op)) {
case TFTP_RRQ:
tftp_handle_rrq(tp, m->m_len);
break;
case TFTP_ACK:
tftp_handle_ack(tp, m->m_len);
break;
}
}

653
src/unused/x Normal file
View File

@@ -0,0 +1,653 @@
int
add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port)
{
struct ex_list *tmp_ptr;
/* First, check if the port is "bound" */
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
return -1;
}
tmp_ptr = *ex_ptr;
*ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
(*ex_ptr)->ex_fport = port;
(*ex_ptr)->ex_addr = addr;
(*ex_ptr)->ex_pty = do_pty;
(*ex_ptr)->ex_exec = strdup(exec);
(*ex_ptr)->ex_next = tmp_ptr;
return 0;
}
#ifdef _WIN32
int
fork_exec(struct SLIRPsocket *so, char *ex, int do_pty)
{
/* not implemented */
return 0;
}
#else
int
slirp_openpty(int *amaster, int *aslave)
{
register int master, slave;
#ifdef HAVE_GRANTPT
char *ptr;
if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
grantpt(master) < 0 ||
unlockpt(master) < 0 ||
(ptr = ptsname(master)) == NULL) {
close(master);
return -1;
}
if ((slave = open(ptr, O_RDWR)) < 0 ||
ioctl(slave, I_PUSH, "ptem") < 0 ||
ioctl(slave, I_PUSH, "ldterm") < 0 ||
ioctl(slave, I_PUSH, "ttcompat") < 0) {
close(master);
close(slave);
return -1;
}
*amaster = master;
*aslave = slave;
return 0;
#else
static char line[] = "/dev/ptyXX";
register const char *cp1, *cp2;
for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
line[8] = *cp1;
for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
line[9] = *cp2;
if ((master = open(line, O_RDWR, 0)) == -1) {
if (errno == ENOENT)
return (-1); /* out of ptys */
} else {
line[5] = 't';
/* These will fail */
(void) chown(line, getuid(), 0);
(void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
#ifdef HAVE_REVOKE
(void) revoke(line);
#endif
if ((slave = open(line, O_RDWR, 0)) != -1) {
*amaster = master;
*aslave = slave;
return 0;
}
(void) close(master);
line[5] = 'p';
}
}
}
errno = ENOENT; /* out of ptys */
return (-1);
#endif
}
/*
* XXX This is ugly
* We create and bind a socket, then fork off to another
* process, which connects to this socket, after which we
* exec the wanted program. If something (strange) happens,
* the accept() call could block us forever.
*
* do_pty = 0 Fork/exec inetd style
* do_pty = 1 Fork/exec using slirp.telnetd
* do_ptr = 2 Fork/exec using pty
*/
int
fork_exec(struct SLIRPsocket *so, char *ex, int do_pty)
{
int s;
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
int opt;
int master;
char *argv[256];
#if 0
char buff[256];
#endif
/* don't want to clobber the original */
char *bptr;
char *curarg;
int c, i, ret;
DEBUG_CALL("fork_exec");
DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("ex = %lx", (long)ex);
DEBUG_ARG("do_pty = %lx", (long)do_pty);
if (do_pty == 2) {
if (slirp_openpty(&master, &s) == -1) {
lprint("Error: openpty failed: %s\n", strerror(errno));
return 0;
}
} else {
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY;
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
listen(s, 1) < 0) {
lprint("Error: inet socket: %s\n", strerror(errno));
closesocket(s);
return 0;
}
}
switch(fork()) {
case -1:
lprint("Error: fork failed: %s\n", strerror(errno));
close(s);
if (do_pty == 2)
close(master);
return 0;
case 0:
/* Set the DISPLAY */
if (do_pty == 2) {
(void) close(master);
#ifdef TIOCSCTTY /* XXXXX */
(void) setsid();
ioctl(s, TIOCSCTTY, (char *)NULL);
#endif
} else {
getsockname(s, (struct sockaddr *)&addr, &addrlen);
close(s);
/*
* Connect to the socket
* XXX If any of these fail, we're in trouble!
*/
s = socket(AF_INET, SOCK_STREAM, 0);
addr.sin_addr = loopback_addr;
do {
ret = connect(s, (struct sockaddr *)&addr, addrlen);
} while (ret < 0 && errno == EINTR);
}
#if 0
if (x_port >= 0) {
#ifdef HAVE_SETENV
sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
setenv("DISPLAY", buff, 1);
#else
sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
putenv(buff);
#endif
}
#endif
dup2(s, 0);
dup2(s, 1);
dup2(s, 2);
for (s = 3; s <= 255; s++)
close(s);
i = 0;
bptr = strdup(ex); /* No need to free() this */
if (do_pty == 1) {
/* Setup "slirp.telnetd -x" */
argv[i++] = "slirp.telnetd";
argv[i++] = "-x";
argv[i++] = bptr;
} else
do {
/* Change the string into argv[] */
curarg = bptr;
while (*bptr != ' ' && *bptr != (char)0)
bptr++;
c = *bptr;
*bptr++ = (char)0;
argv[i++] = strdup(curarg);
} while (c);
argv[i] = 0;
execvp(argv[0], argv);
/* Ooops, failed, let's tell the user why */
{
char buff[256];
sprintf(buff, "Error: execvp of %s failed: %s\n",
argv[0], strerror(errno));
write(2, buff, strlen(buff)+1);
}
close(0); close(1); close(2); /* XXX */
exit(1);
default:
if (do_pty == 2) {
close(s);
so->s = master;
} else {
/*
* XXX this could block us...
* XXX Should set a timer here, and if accept() doesn't
* return after X seconds, declare it a failure
* The only reason this will block forever is if socket()
* of connect() fail in the child process
*/
do {
so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
} while (so->s < 0 && errno == EINTR);
closesocket(s);
opt = 1;
setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
opt = 1;
setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
}
fd_nonblock(so->s);
/* Append the telnet options now */
if (so->so_m != 0 && do_pty == 1) {
sbappend(so, so->so_m);
so->so_m = 0;
}
return 1;
}
}
#if 0
void
snooze_hup(int num)
{
int s, ret;
#ifndef NO_UNIX_SOCKETS
struct sockaddr_un sock_un;
#endif
struct sockaddr_in sock_in;
char buff[256];
ret = -1;
if (slirp_socket_passwd) {
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
slirp_exit(1);
sock_in.sin_family = AF_INET;
sock_in.sin_addr.s_addr = slirp_socket_addr;
sock_in.sin_port = htons(slirp_socket_port);
if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
slirp_exit(1); /* just exit...*/
sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
write(s, buff, strlen(buff)+1);
}
#ifndef NO_UNIX_SOCKETS
else {
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0)
slirp_exit(1);
sock_un.sun_family = AF_UNIX;
strcpy(sock_un.sun_path, socket_path);
if (connect(s, (struct sockaddr *)&sock_un,
sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
slirp_exit(1);
sprintf(buff, "kill none:%d", slirp_socket_unit);
write(s, buff, strlen(buff)+1);
}
#endif
slirp_exit(0);
}
void
snooze(void)
{
sigset_t s;
int i;
/* Don't need our data anymore */
/* XXX This makes SunOS barf */
/* brk(0); */
/* Close all fd's */
for (i = 255; i >= 0; i--)
close(i);
signal(SIGQUIT, slirp_exit);
signal(SIGHUP, snooze_hup);
sigemptyset(&s);
/* Wait for any signal */
sigsuspend(&s);
/* Just in case ... */
exit(255);
}
void
relay(int s)
{
char buf[8192];
int n;
fd_set readfds;
struct ttys *ttyp;
/* Don't need our data anymore */
/* XXX This makes SunOS barf */
/* brk(0); */
signal(SIGQUIT, slirp_exit);
signal(SIGHUP, slirp_exit);
signal(SIGINT, slirp_exit);
signal(SIGTERM, slirp_exit);
/* Fudge to get term_raw and term_restore to work */
if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
slirp_exit (1);
}
ttyp->fd = 0;
ttyp->flags |= TTY_CTTY;
term_raw(ttyp);
while (1) {
FD_ZERO(&readfds);
FD_SET(0, &readfds);
FD_SET(s, &readfds);
n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
if (n <= 0)
slirp_exit(0);
if (FD_ISSET(0, &readfds)) {
n = read(0, buf, 8192);
if (n <= 0)
slirp_exit(0);
n = writen(s, buf, n);
if (n <= 0)
slirp_exit(0);
}
if (FD_ISSET(s, &readfds)) {
n = read(s, buf, 8192);
if (n <= 0)
slirp_exit(0);
n = writen(0, buf, n);
if (n <= 0)
slirp_exit(0);
}
}
/* Just in case.... */
exit(1);
}
#endif
void
add_emu(char *buff)
{
u_int lport, fport;
u_int8_t tos = 0, emu = 0;
char buff1[256], buff2[256], buff4[128];
char *buff3 = buff4;
struct emu_t *emup;
struct SLIRPsocket *so;
if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
lprint("Error: Bad arguments\r\n");
return;
}
if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
lport = 0;
if (sscanf(buff1, "%d", &fport) != 1) {
lprint("Error: Bad first argument\r\n");
return;
}
}
if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
buff3 = 0;
if (sscanf(buff2, "%256s", buff1) != 1) {
lprint("Error: Bad second argument\r\n");
return;
}
}
if (buff3) {
if (strcmp(buff3, "lowdelay") == 0)
tos = IPTOS_LOWDELAY;
else if (strcmp(buff3, "throughput") == 0)
tos = IPTOS_THROUGHPUT;
else {
lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
return;
}
}
if (strcmp(buff1, "ftp") == 0)
emu = EMU_FTP;
else if (strcmp(buff1, "irc") == 0)
emu = EMU_IRC;
else if (strcmp(buff1, "none") == 0)
emu = EMU_NONE; /* ie: no emulation */
else {
lprint("Error: Unknown service\r\n");
return;
}
/* First, check that it isn't already emulated */
for (emup = tcpemu; emup; emup = emup->next) {
if (emup->lport == lport && emup->fport == fport) {
lprint("Error: port already emulated\r\n");
return;
}
}
/* link it */
emup = (struct emu_t *)malloc(sizeof (struct emu_t));
emup->lport = (u_int16_t)lport;
emup->fport = (u_int16_t)fport;
emup->tos = tos;
emup->emu = emu;
emup->next = tcpemu;
tcpemu = emup;
/* And finally, mark all current sessions, if any, as being emulated */
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
if ((lport && lport == ntohs(so->so_lport)) ||
(fport && fport == ntohs(so->so_fport))) {
if (emu)
so->so_emu = emu;
if (tos)
so->so_iptos = tos;
}
}
lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
}
#ifdef BAD_SPRINTF
#undef vsprintf
#undef sprintf
/*
* Some BSD-derived systems have a sprintf which returns char *
*/
int
vsprintf_len(char *string, const char *format, va_list args)
{
vsprintf(string, format, args);
return strlen(string);
}
int
#ifdef __STDC__
sprintf_len(char *string, const char *format, ...)
#else
sprintf_len(va_alist) va_dcl
#endif
{
va_list args;
#ifdef __STDC__
va_start(args, format);
#else
char *string;
char *format;
va_start(args);
string = va_arg(args, char *);
format = va_arg(args, char *);
#endif
vsprintf(string, format, args);
return strlen(string);
}
#endif
void
u_sleep(int usec)
{
struct timeval t;
fd_set fdset;
FD_ZERO(&fdset);
t.tv_sec = 0;
t.tv_usec = usec * 1000;
select(0, &fdset, &fdset, &fdset, &t);
}
/*
* Set fd blocking and non-blocking
*/
void
fd_nonblock(int fd)
{
#if defined USE_FIONBIO && defined FIONBIO
ioctlsockopt_t opt = 1;
ioctlsocket(fd, FIONBIO, &opt);
#else
int opt;
opt = fcntl(fd, F_GETFL, 0);
opt |= O_NONBLOCK;
fcntl(fd, F_SETFL, opt);
#endif
}
void
fd_block(int fd)
{
#if defined USE_FIONBIO && defined FIONBIO
ioctlsockopt_t opt = 0;
ioctlsocket(fd, FIONBIO, &opt);
#else
int opt;
opt = fcntl(fd, F_GETFL, 0);
opt &= ~O_NONBLOCK;
fcntl(fd, F_SETFL, opt);
#endif
}
#if 0
/*
* invoke RSH
*/
int
rsh_exec(so,ns, user, host, args)
struct SLIRPsocket *so;
struct SLIRPsocket *ns;
char *user;
char *host;
char *args;
{
int fd[2];
int fd0[2];
int s;
char buff[256];
DEBUG_CALL("rsh_exec");
DEBUG_ARG("so = %lx", (long)so);
if (pipe(fd)<0) {
lprint("Error: pipe failed: %s\n", strerror(errno));
return 0;
}
/* #ifdef HAVE_SOCKETPAIR */
#if 1
if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
close(fd[0]);
close(fd[1]);
lprint("Error: openpty failed: %s\n", strerror(errno));
return 0;
}
#else
if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
close(fd[0]);
close(fd[1]);
lprint("Error: openpty failed: %s\n", strerror(errno));
return 0;
}
#endif
switch(fork()) {
case -1:
lprint("Error: fork failed: %s\n", strerror(errno));
close(fd[0]);
close(fd[1]);
close(fd0[0]);
close(fd0[1]);
return 0;
case 0:
close(fd[0]);
close(fd0[0]);
/* Set the DISPLAY */
if (x_port >= 0) {
#ifdef HAVE_SETENV
sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
setenv("DISPLAY", buff, 1);
#else
sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
putenv(buff);
#endif
}
dup2(fd0[1], 0);
dup2(fd0[1], 1);
dup2(fd[1], 2);
for (s = 3; s <= 255; s++)
close(s);
execlp("rsh","rsh","-l", user, host, args, NULL);
/* Ooops, failed, let's tell the user why */
sprintf(buff, "Error: execlp of %s failed: %s\n",
"rsh", strerror(errno));
write(2, buff, strlen(buff)+1);
close(0); close(1); close(2); /* XXX */
exit(1);
default:
close(fd[1]);
close(fd0[1]);
ns->s=fd[0];
so->s=fd0[0];
return 1;
}
}
#endif

121
src/win/host.c Normal file
View File

@@ -0,0 +1,121 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <iphlpapi.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "../host.h"
#include "../debug.h"
#ifndef AI_FQDN
# define AI_FQDN 0x00020000
#endif
extern struct in_addr our_addr; /* host IP address */
extern struct in_addr dns_addr; /* host DNS server */
extern struct in_addr loopback_addr; /* host loopback address */
int
inet_aton(const char *cp, struct in_addr *ia)
{
uint32_t addr = inet_addr(cp);
if (addr == 0xffffffff)
return 0;
ia->s_addr = addr;
return 1;
}
int
host_get_info(struct in_addr *dns, char *hostname, char *domainname)
{
struct addrinfo hints, *ai;
IP_ADDR_STRING *pIPAddr;
FIXED_INFO *FixedInfo;
struct in_addr addr;
ULONG BufLen;
DWORD ret;
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
BufLen = sizeof(FIXED_INFO);
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
if (FixedInfo) {
GlobalFree(FixedInfo);
FixedInfo = NULL;
}
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, BufLen);
}
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
lprint("GetNetworkParams failed. ret = %08x\n", (u_int)ret);
if (FixedInfo) {
GlobalFree(FixedInfo);
FixedInfo = NULL;
}
return -1;
}
/* Set up hostname, domainname and IP address. */
strcpy(hostname, FixedInfo->HostName);
strcpy(domainname, FixedInfo->DomainName);
strcpy(domainname, "homenet.lan");
memset(&hints, 0x00, sizeof(hints));
ai = NULL;
#ifdef AI_FQDN
hints.ai_flags = AI_FQDN;
#else
hints.ai_flags = AI_CANONNAME;
#endif
hints.ai_family = AF_INET;
if (! getaddrinfo(hostname, NULL, &hints, &ai)) {
our_addr = ((struct sockaddr_in *)ai->ai_addr)->sin_addr;
strcpy(hostname, ai->ai_canonname);
freeaddrinfo(ai);
}
if (our_addr.s_addr == 0)
our_addr.s_addr = loopback_addr.s_addr;
lprint(" Hostname: %s.%s\n", hostname, domainname);
lprint(" IP address: %s\n", inet_ntoa(our_addr));
memset(&addr, 0x00, sizeof(addr));
pIPAddr = &FixedInfo->DnsServerList;
inet_aton(pIPAddr->IpAddress.String, &addr);
*dns = addr;
lprint(" DNS Servers:\n" );
while (pIPAddr) {
lprint(" Address: %s\n", pIPAddr->IpAddress.String);
pIPAddr = pIPAddr->Next;
}
if (FixedInfo)
GlobalFree(FixedInfo);
return 0;
}
int
host_init(void)
{
WSADATA Data;
WSAStartup(MAKEWORD(2,0), &Data);
return 0;
}
void
host_close(void)
{
WSACleanup();
}

1
src/win/host.d Normal file
View File

@@ -0,0 +1 @@
host.o: win/host.c win/../host.h win/../debug.h

BIN
src/win/icons/varcem.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

84
src/win/libslirp.rc Normal file
View File

@@ -0,0 +1,84 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Resource info for the SLiRP library.
*
* Version: @(#)libslirp.rc 1.0.1 2018/11/02
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2018 Fred N. van Kempen.
*
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the entire
* above notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names
* of its contributors may be used to endorse or promote
* products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
100 ICON DISCARDABLE "win/icons/varcem.ico"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,1,0
PRODUCTVERSION 1,0,1,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0409fde9"
BEGIN
VALUE "CompanyName", "IRC #VARCem on FreeNode"
VALUE "FileDescription", "SLiRP - Host Network Interface library."
VALUE "FileVersion", "1.0.1"
VALUE "InternalName", "libslirp"
VALUE "LegalCopyright", "Copyright 2017,2018 Fred N. van Kempen"
VALUE "OriginalFilename", "libslirp.dll"
VALUE "ProductName", "SLiRP Interface Library"
VALUE "ProductVersion", "1.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 65001
END
END

View File

@@ -0,0 +1,312 @@
#
# VARCem Virtual ARchaeological Computer EMulator.
# An emulator of (mostly) x86-based PC systems and devices,
# using the ISA,EISA,VLB,MCA and PCI system buses, roughly
# spanning the era between 1981 and 1995.
#
# This file is part of the VARCem Project.
#
# Makefile for Windows systems using the MinGW32 environment.
#
# Version: @(#)Makefile.mingw 1.0.1 2018/11/02
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
# Copyright 2017,2018 Fred N. van Kempen.
#
# Redistribution and use in source and binary forms, with
# or without modification, are permitted provided that the
# following conditions are met:
#
# 1. Redistributions of source code must retain the entire
# above notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names
# of its contributors may be used to endorse or promote
# products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Defaults for several build options (possibly defined in a chained file.)
ifndef AUTODEP
AUTODEP := n
endif
ifndef CROSS
CROSS := n
endif
ifndef DEBUG
DEBUG := n
endif
ifndef LOGGING
LOGGING := n
endif
ifndef OPTIM
OPTIM := n
endif
ifndef X64
X64 := n
endif
# Name of the library.
ifndef PROG
PROG := libslirp
endif
ifeq ($(DEBUG), y)
PROG := $(PROG)-d
endif
#########################################################################
# Nothing should need changing from here on.. #
#########################################################################
VPATH := win
#
# Select the required build environment. We have, uhm, many..
#
ifneq ($(CROSS), n)
# Cross-compiling (under Linux), select proper version.
ifeq ($(X64), y)
MINGW := x86_64-w64-mingw32
else
MINGW := i686-w64-mingw32
endif
ifeq ($(X64), y)
CPP := /usr/bin/$(MINGW)-g++ -m64
CC := /usr/bin/$(MINGW)-gcc -m64
else
CPP := /usr/bin/$(MINGW)-g++ -m32
CC := /usr/bin/$(MINGW)-gcc -m32
endif
PREPROC := /usr/bin/$(MINGW)-cpp
WINDRES := /usr/bin/$(MINGW)-windres
SYSINC := -I/usr/$(MINGW)/include -Iwin/mingw/include
SYSLIB := -L/usr/$(MINGW)/lib
else
# Native compilation using MinGW for Windows.
ifeq ($(X64), y)
CPP := g++ -m64
CC := gcc -m64
else
CPP := g++ -m32
CC := gcc -m32
endif
PREPROC := cpp
WINDRES := windres
ifndef CAT
CAT := cat
endif
SYSINC := -Iwin/mingw/include
SYSLIB :=
endif
DEPS = -MMD -MF $*.d -c $<
DEPFILE := win/mingw/.depends
# Set up the correct toolchain flags.
OPTS := -D_CRT_NON_CONFORMING_SWPRINTFS \
-D__USE_MINGW_ANSI_STDIO_X
AFLAGS := -msse2 -mfpmath=sse
RFLAGS := --input-format=rc -O coff
LDFLAGS :=
ifdef BUILD
OPTS += -DBUILD=$(BUILD)
endif
ifdef COMMIT
OPTS += -DCOMMIT=0x$(COMMIT)
endif
ifdef UPSTREAM
OPTS += -DUPSTREAM=0x$(UPSTREAM)
endif
ifdef EXFLAGS
OPTS += $(EXFLAGS)
endif
ifdef EXINC
OPTS += -I$(EXINC)
endif
OPTS += $(SYSINC)
ifneq ($(CROSS), n)
OPTS += -DUSE_CROSS
endif
ifeq ($(X64), y)
ifeq ($(OPTIM), y)
DFLAGS := -march=native
else
DFLAGS :=
endif
else
ifeq ($(OPTIM), y)
DFLAGS := -march=native
else
DFLAGS := -march=i686
endif
endif
ifeq ($(DEBUG), y)
DFLAGS += -ggdb -D_DEBUG
RFLAGS += -D_DEBUG
AOPTIM :=
ifndef COPTIM
COPTIM := -Og
endif
else
ifeq ($(OPTIM), y)
AOPTIM := -mtune=native
ifndef COPTIM
COPTIM := -O3
endif
else
ifndef COPTIM
COPTIM := -O3
endif
endif
endif
ifeq ($(RELEASE), y)
OPTS += -DRELEASE_BUILD
RFLAGS += -DRELEASE_BUILD
endif
LIBS := -mwindows \
-lversion -lcomctl32 -lwinmm
LIBS += -lws2_32 -lwsock32 -liphlpapi -lpsapi
LIBS += -static -lgcc
#ifneq ($(X64), y)
# LIBS += -Wl,--large-address-aware
#endif
# Final versions of the toolchain flags.
# FIXME: add the -Wsign-compare option soon!
CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \
$(AFLAGS) -fomit-frame-pointer -mstackrealign \
-Wall -Wundef #-Wshadow #-Wunused-parameter -Wmissing-declarations
CXXFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \
$(AFLAGS) -fno-strict-aliasing -fvisibility=hidden \
-fvisibility-inlines-hidden \
-Wall -Wundef -Wunused-parameter -Wmissing-declarations \
-Wno-ctor-dtor-privacy -Woverloaded-virtual
#########################################################################
# Create the (final) list of objects to build. #
#########################################################################
OBJ := slirp.o host.o misc.o poll.o \
cksum.o if.o mbuf.o queue.o sbuf.o socket.o \
debug.o stats.o \
arp.o bootp.o \
ip_icmp.o ip_input.o ip_output.o \
tcp_input.o tcp_output.o tcp_subr.o tcp_timer.o \
udp.o
ifdef EXOBJ
OBJ += $(EXOBJ)
endif
# Build module rules.
ifeq ($(AUTODEP), y)
%.o: %.c
@echo $<
@$(CC) $(CFLAGS) $(DEPS) -c $<
%.o: %.cpp
@echo $<
@$(CPP) $(CXXFLAGS) $(DEPS) -c $<
else
%.o: %.c
@echo $<
@$(CC) $(CFLAGS) -c $<
%.o: %.cpp
@echo $<
@$(CPP) $(CXXFLAGS) -c $<
%.d: %.c $(wildcard $*.d)
@echo $<
@$(CC) $(CFLAGS) $(DEPS) -E $< >NUL
%.d: %.cpp $(wildcard $*.d)
@echo $<
@$(CPP) $(CXXFLAGS) $(DEPS) -E $< >NUL
endif
all: $(PREBUILD) $(PROG).dll $(POSTBUILD)
$(PROG).res: win/libslirp.rc
@echo Processing $<
@$(WINDRES) $(RFLAGS) -i $< -o $@
$(PROG).dll: $(OBJ) $(PROG).res
@echo Linking $(PROG).dll ..
@$(CC) $(LDFLAGS) -shared -o $@ \
$(OBJ) $(PROG).res $(LIBS)
#ifneq ($(DEBUG), y)
# @strip $(PROG).dll
#endif
clean:
@echo Cleaning objects..
@-rm -f *.o
@-rm -f *.res
clobber: clean
@echo Cleaning executables..
@-rm -f *.d
@-rm -f *.dll
@-rm -f *.exe
ifeq ($(PROFILER), y)
@-rm -f *.map
endif
# @-rm -f $(DEPFILE)
ifneq ($(AUTODEP), y)
depclean:
@-rm -f $(DEPFILE)
@echo Creating dependencies..
@echo # Run "make depends" to re-create this file. >$(DEPFILE)
depends: DEPOBJ=$(OBJ:%.o=%.d)
depends: depclean $(OBJ:%.o=%.d)
@$(CAT) $(DEPOBJ) >>$(DEPFILE)
# @-rm -f $(DEPOBJ)
$(DEPFILE):
endif
# Module dependencies.
ifeq ($(AUTODEP), y)
#-include $(OBJ:%.o=%.d) (better, but sloooowwwww)
-include *.d
else
include $(wildcard $(DEPFILE))
endif
# End of Makefile.mingw.

View File

@@ -0,0 +1,300 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Microsoft Corporation. All Rights Reserved.
//
// File: d3dx9tex.h
// Content: D3DX texturing APIs
//
//////////////////////////////////////////////////////////////////////////////
//#include "d3dx9.h"
#ifndef __D3DX9TEX_H__
#define __D3DX9TEX_H__
//----------------------------------------------------------------------------
// D3DX_FILTER flags:
// ------------------
//
// A valid filter must contain one of these values:
//
// D3DX_FILTER_NONE
// No scaling or filtering will take place. Pixels outside the bounds
// of the source image are assumed to be transparent black.
// D3DX_FILTER_POINT
// Each destination pixel is computed by sampling the nearest pixel
// from the source image.
// D3DX_FILTER_LINEAR
// Each destination pixel is computed by linearly interpolating between
// the nearest pixels in the source image. This filter works best
// when the scale on each axis is less than 2.
// D3DX_FILTER_TRIANGLE
// Every pixel in the source image contributes equally to the
// destination image. This is the slowest of all the filters.
// D3DX_FILTER_BOX
// Each pixel is computed by averaging a 2x2(x2) box pixels from
// the source image. Only works when the dimensions of the
// destination are half those of the source. (as with mip maps)
//
// And can be OR'd with any of these optional flags:
//
// D3DX_FILTER_MIRROR_U
// Indicates that pixels off the edge of the texture on the U-axis
// should be mirrored, not wraped.
// D3DX_FILTER_MIRROR_V
// Indicates that pixels off the edge of the texture on the V-axis
// should be mirrored, not wraped.
// D3DX_FILTER_MIRROR_W
// Indicates that pixels off the edge of the texture on the W-axis
// should be mirrored, not wraped.
// D3DX_FILTER_MIRROR
// Same as specifying D3DX_FILTER_MIRROR_U | D3DX_FILTER_MIRROR_V |
// D3DX_FILTER_MIRROR_V
// D3DX_FILTER_DITHER
// Dithers the resulting image using a 4x4 order dither pattern.
// D3DX_FILTER_SRGB_IN
// Denotes that the input data is in sRGB (gamma 2.2) colorspace.
// D3DX_FILTER_SRGB_OUT
// Denotes that the output data is in sRGB (gamma 2.2) colorspace.
// D3DX_FILTER_SRGB
// Same as specifying D3DX_FILTER_SRGB_IN | D3DX_FILTER_SRGB_OUT
//
//----------------------------------------------------------------------------
#define D3DX_FILTER_NONE (1 << 0)
#define D3DX_FILTER_POINT (2 << 0)
#define D3DX_FILTER_LINEAR (3 << 0)
#define D3DX_FILTER_TRIANGLE (4 << 0)
#define D3DX_FILTER_BOX (5 << 0)
#define D3DX_FILTER_MIRROR_U (1 << 16)
#define D3DX_FILTER_MIRROR_V (2 << 16)
#define D3DX_FILTER_MIRROR_W (4 << 16)
#define D3DX_FILTER_MIRROR (7 << 16)
#define D3DX_FILTER_DITHER (1 << 19)
#define D3DX_FILTER_DITHER_DIFFUSION (2 << 19)
#define D3DX_FILTER_SRGB_IN (1 << 21)
#define D3DX_FILTER_SRGB_OUT (2 << 21)
#define D3DX_FILTER_SRGB (3 << 21)
//-----------------------------------------------------------------------------
// D3DX_SKIP_DDS_MIP_LEVELS is used to skip mip levels when loading a DDS file:
//-----------------------------------------------------------------------------
#define D3DX_SKIP_DDS_MIP_LEVELS_MASK 0x1F
#define D3DX_SKIP_DDS_MIP_LEVELS_SHIFT 26
#define D3DX_SKIP_DDS_MIP_LEVELS(levels, filter) ((((levels) & D3DX_SKIP_DDS_MIP_LEVELS_MASK) << D3DX_SKIP_DDS_MIP_LEVELS_SHIFT) | ((filter) == D3DX_DEFAULT ? D3DX_FILTER_BOX : (filter)))
//----------------------------------------------------------------------------
// D3DX_NORMALMAP flags:
// ---------------------
// These flags are used to control how D3DXComputeNormalMap generates normal
// maps. Any number of these flags may be OR'd together in any combination.
//
// D3DX_NORMALMAP_MIRROR_U
// Indicates that pixels off the edge of the texture on the U-axis
// should be mirrored, not wraped.
// D3DX_NORMALMAP_MIRROR_V
// Indicates that pixels off the edge of the texture on the V-axis
// should be mirrored, not wraped.
// D3DX_NORMALMAP_MIRROR
// Same as specifying D3DX_NORMALMAP_MIRROR_U | D3DX_NORMALMAP_MIRROR_V
// D3DX_NORMALMAP_INVERTSIGN
// Inverts the direction of each normal
// D3DX_NORMALMAP_COMPUTE_OCCLUSION
// Compute the per pixel Occlusion term and encodes it into the alpha.
// An Alpha of 1 means that the pixel is not obscured in anyway, and
// an alpha of 0 would mean that the pixel is completly obscured.
//
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#define D3DX_NORMALMAP_MIRROR_U (1 << 16)
#define D3DX_NORMALMAP_MIRROR_V (2 << 16)
#define D3DX_NORMALMAP_MIRROR (3 << 16)
#define D3DX_NORMALMAP_INVERTSIGN (8 << 16)
#define D3DX_NORMALMAP_COMPUTE_OCCLUSION (16 << 16)
//----------------------------------------------------------------------------
// D3DX_CHANNEL flags:
// -------------------
// These flags are used by functions which operate on or more channels
// in a texture.
//
// D3DX_CHANNEL_RED
// Indicates the red channel should be used
// D3DX_CHANNEL_BLUE
// Indicates the blue channel should be used
// D3DX_CHANNEL_GREEN
// Indicates the green channel should be used
// D3DX_CHANNEL_ALPHA
// Indicates the alpha channel should be used
// D3DX_CHANNEL_LUMINANCE
// Indicates the luminaces of the red green and blue channels should be
// used.
//
//----------------------------------------------------------------------------
#define D3DX_CHANNEL_RED (1 << 0)
#define D3DX_CHANNEL_BLUE (1 << 1)
#define D3DX_CHANNEL_GREEN (1 << 2)
#define D3DX_CHANNEL_ALPHA (1 << 3)
#define D3DX_CHANNEL_LUMINANCE (1 << 4)
//----------------------------------------------------------------------------
// D3DXIMAGE_FILEFORMAT:
// ---------------------
// This enum is used to describe supported image file formats.
//
//----------------------------------------------------------------------------
typedef enum _D3DXIMAGE_FILEFORMAT
{
D3DXIFF_BMP = 0,
D3DXIFF_JPG = 1,
D3DXIFF_TGA = 2,
D3DXIFF_PNG = 3,
D3DXIFF_DDS = 4,
D3DXIFF_PPM = 5,
D3DXIFF_DIB = 6,
D3DXIFF_HDR = 7, //high dynamic range formats
D3DXIFF_PFM = 8, //
D3DXIFF_FORCE_DWORD = 0x7fffffff
} D3DXIMAGE_FILEFORMAT;
#if 0
//----------------------------------------------------------------------------
// LPD3DXFILL2D and LPD3DXFILL3D:
// ------------------------------
// Function types used by the texture fill functions.
//
// Parameters:
// pOut
// Pointer to a vector which the function uses to return its result.
// X,Y,Z,W will be mapped to R,G,B,A respectivly.
// pTexCoord
// Pointer to a vector containing the coordinates of the texel currently
// being evaluated. Textures and VolumeTexture texcoord components
// range from 0 to 1. CubeTexture texcoord component range from -1 to 1.
// pTexelSize
// Pointer to a vector containing the dimensions of the current texel.
// pData
// Pointer to user data.
//
//----------------------------------------------------------------------------
typedef VOID (WINAPI *LPD3DXFILL2D)(D3DXVECTOR4 *pOut,
CONST D3DXVECTOR2 *pTexCoord, CONST D3DXVECTOR2 *pTexelSize, LPVOID pData);
typedef VOID (WINAPI *LPD3DXFILL3D)(D3DXVECTOR4 *pOut,
CONST D3DXVECTOR3 *pTexCoord, CONST D3DXVECTOR3 *pTexelSize, LPVOID pData);
#endif
//----------------------------------------------------------------------------
// D3DXIMAGE_INFO:
// ---------------
// This structure is used to return a rough description of what the
// the original contents of an image file looked like.
//
// Width
// Width of original image in pixels
// Height
// Height of original image in pixels
// Depth
// Depth of original image in pixels
// MipLevels
// Number of mip levels in original image
// Format
// D3D format which most closely describes the data in original image
// ResourceType
// D3DRESOURCETYPE representing the type of texture stored in the file.
// D3DRTYPE_TEXTURE, D3DRTYPE_VOLUMETEXTURE, or D3DRTYPE_CUBETEXTURE.
// ImageFileFormat
// D3DXIMAGE_FILEFORMAT representing the format of the image file.
//
//----------------------------------------------------------------------------
typedef struct _D3DXIMAGE_INFO
{
UINT Width;
UINT Height;
UINT Depth;
UINT MipLevels;
D3DFORMAT Format;
D3DRESOURCETYPE ResourceType;
D3DXIMAGE_FILEFORMAT ImageFileFormat;
} D3DXIMAGE_INFO;
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
//----------------------------------------------------------------------------
// D3DXSaveSurfaceToFile:
// ----------------------
// Save a surface to a image file.
//
// Parameters:
// pDestFile
// File name of the destination file
// DestFormat
// D3DXIMAGE_FILEFORMAT specifying file format to use when saving.
// pSrcSurface
// Source surface, containing the image to be saved
// pSrcPalette
// Source palette of 256 colors, or NULL
// pSrcRect
// Source rectangle, or NULL for the entire image
//
//----------------------------------------------------------------------------
HRESULT WINAPI
D3DXSaveSurfaceToFileA(
LPCSTR pDestFile,
D3DXIMAGE_FILEFORMAT DestFormat,
LPDIRECT3DSURFACE9 pSrcSurface,
CONST PALETTEENTRY* pSrcPalette,
CONST RECT* pSrcRect);
HRESULT WINAPI
D3DXSaveSurfaceToFileW(
LPCWSTR pDestFile,
D3DXIMAGE_FILEFORMAT DestFormat,
LPDIRECT3DSURFACE9 pSrcSurface,
CONST PALETTEENTRY* pSrcPalette,
CONST RECT* pSrcRect);
#ifdef UNICODE
#define D3DXSaveSurfaceToFile D3DXSaveSurfaceToFileW
#else
#define D3DXSaveSurfaceToFile D3DXSaveSurfaceToFileA
#endif
#ifdef __cplusplus
}
#endif //__cplusplus
#endif //__D3DX9TEX_H__

Binary file not shown.

Binary file not shown.

854
src/win/msvc/Makefile.VC Normal file
View File

@@ -0,0 +1,854 @@
#
# VARCem Virtual ARchaeological Computer EMulator.
# An emulator of (mostly) x86-based PC systems and devices,
# using the ISA,EISA,VLB,MCA and PCI system buses, roughly
# spanning the era between 1981 and 1995.
#
# This file is part of the VARCem Project.
#
# Makefile for Windows using Visual Studio 2015.
#
# Version: @(#)Makefile.VC 1.0.52 2018/10/30
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
#
# Copyright 2017,2018 Fred N. van Kempen.
#
# Redistribution and use in source and binary forms, with
# or without modification, are permitted provided that the
# following conditions are met:
#
# 1. Redistributions of source code must retain the entire
# above notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names
# of its contributors may be used to endorse or promote
# products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Various compile-time options.
ifndef STUFF
STUFF :=
endif
# Add feature selections here.
ifndef EXTRAS
EXTRAS :=
endif
# Defaults for several build options (possibly defined in a chained file.)
ifndef AUTODEP
AUTODEP := n
endif
ifndef CRASHDUMP
CRASHDUMP := n
endif
ifndef CROSS
CROSS := n
endif
ifndef DEBUG
DEBUG := n
endif
ifndef LOGGING
LOGGING := n
endif
ifndef PROFILER
PROFILER := n
endif
ifndef OPTIM
OPTIM := n
endif
ifndef RELEASE
RELEASE := n
endif
ifndef X64
X64 := n
endif
ifndef DYNAREC
DYNAREC := y
endif
ifndef WX
WX := n
endif
ifndef USB
USB := n
endif
ifndef SDL
SDL := n
endif
ifndef D2D
D2D := n
endif
ifndef VNC
VNC := n
endif
ifndef RDP
RDP := n
endif
ifndef PNG
PNG := n
endif
ifndef DEV_BUILD
DEV_BUILD := n
endif
ifndef DEV_BRANCH
DEV_BRANCH := n
endif
ifndef AMD_K
AMD_K := n
endif
ifndef LASERXT
LASERXT := n
endif
ifndef PORTABLE3
PORTABLE3 := n
endif
ifndef I686
I686 := n
endif
ifndef OPENAL
OPENAL := y
endif
ifndef FLUIDSYNTH
FLUIDSYNTH := y
endif
ifndef MUNT
MUNT := y
endif
ifndef PAS16
PAS16 := n
endif
ifndef XL24
XL24 := n
endif
ifndef WONDER
WONDER := n
endif
ifndef HOSTCD
HOSTCD := n
endif
ifndef PRINTER
PRINTER := n
endif
# Name of the executable.
NETIF := pcap_if
ifndef PROG
ifneq ($(WX), n)
PROG := WxVARCem
else
PROG := VARCem
endif
endif
ifeq ($(DEBUG), y)
PROG := $(PROG)-d
NETIF := $(NETIF)-d
LOGGING := y
else
ifeq ($(LOGGING), y)
PROG := $(PROG)-l
endif
endif
# Which modules to include a development build.
ifeq ($(DEV_BUILD), y)
CRASHDUMP := y
DEV_BRANCH := y
AMD_K := y
LASERXT := y
PORTABLE3 := y
I686 := y
PAS16 := y
XL24 := y
WONDER := y
HOSTCD := y
PRINTER := y
endif
# WxWidgets basic info. Extract using the config program.
ifneq ($(WX), n)
EXPATH += wx
WX_CONFIG := wx-config.exe
ifeq ($(WX), y)
WX_PATH := C:/MinGW32/WxWidgets
WX_FLAGS := -I$(WX_PATH)/lib/wx/include/msw-unicode-3.0 \
-I$(WX_PATH)/include/wx-3.0 \
-D__WXMSW__ -DWX_PRECOMP -D_FILE_OFFSET_BITS=64 -pthread
# -lwx_mswu_gl-3.0 -lwxtiff-3.0 -llzma
WX_LIBS := -mthreads -L$(WX_PATH)/lib \
-lwx_mswu-3.0.dll \
-lrpcrt4 -loleaut32 -lole32 -luuid \
-lwinspool -lwinmm -lshell32 -lcomctl32 \
-lcomdlg32 -ladvapi32 -lwsock32 -lgdi32
endif
ifeq ($(WX), static)
WX_PATH := C:/MinGW32/WxWidgets
WX_FLAGS := -I$(WX_PATH)/lib/wx/include/msw-unicode-3.0 \
-I$(WX_PATH)/include/wx-3.0 \
-D__WXMSW__ -DWX_PRECOMP -D_FILE_OFFSET_BITS=64 -pthread
# -lwx_mswu_gl-3.0 -lwxtiff-3.0 -llzma
WX_LIBS := -mthreads -L$(WX_PATH)/lib \
-lwx_mswu-3.0 -lwxscintilla-3.0 \
-lwxjpeg-3.0 -lwxpng-3.0 -lwxzlib-3.0 \
-lwxregexu-3.0 -lwxexpat-3.0 \
-lrpcrt4 -loleaut32 -lole32 -luuid \
-lwinspool -lwinmm -lshell32 -lcomctl32 \
-lcomdlg32 -ladvapi32 -lwsock32 -lgdi32
endif
endif
#########################################################################
# Nothing should need changing from here on.. #
#########################################################################
VPATH := $(EXPATH) . cpu \
devices \
devices/cdrom devices/disk devices/floppy \
devices/floppy/lzf devices/input devices/input/game \
devices/network devices/network/slirp devices/ports \
devices/printer devices/sio devices/system devices/scsi \
devices/misc \
devices/sound \
devices/sound/munt devices/sound/munt/c_interface \
devices/sound/munt/sha1 devices/sound/munt/srchelper \
devices/sound/resid-fp \
devices/video \
machines ui win
#
# Select the required build environment.
#
VCOPTS := -D_CRT_SECURE_NO_WARNINGS -D__MSC__
ifeq ($(X64), y)
ARCH := x64
CPP := cl -nologo
CC := cl -nologo
else
ARCH := x86
CPP := cl -nologo
CC := cl -nologo #-TP
endif
PREPROC := cl -nologo -EP
MCPP := mcpp.exe
LINK := link -nologo
WINDRES := rc -nologo -r -d_MSC_VER
SYSINC := -Iwin/msvc/Include -Iwin/mingw/include
SYSLIB :=
DEPS = -MMD -MF $*.d
DEPFILE := win\msvc\.depends
# Set up the correct toolchain flags.
OPTS := $(EXTRAS) $(STUFF) $(VCOPTS) \
-D_USE_MATH_DEFINES \
-D_CRT_NONSTDC_NO_DEPRECATE \
-D_WINSOCK_DEPRECATED_NO_WARNINGS \
-D_CRT_SECURE_NO_WARNINGS \
-D_CRT_STDIO_ISO_WIDE_SPECIFIERS \
$(WPCAPINC) $(SYSINC)
AFLAGS := #/arch:SSE2
RFLAGS := /n
COPTS := -W3
CXXOPTS := -EHsc
DOPTS :=
ifeq ($(X64), y)
LOPTS := -MACHINE:$(ARCH) -LIBPATH:win\msvc\Lib\$(ARCH)
LOPTS_C := -SUBSYSTEM:CONSOLE
LOPTS_W := -SUBSYSTEM:WINDOWS
else
LOPTS := -MACHINE:$(ARCH) -LIBPATH:win\msvc\Lib\$(ARCH)
LOPTS_C := -SUBSYSTEM:CONSOLE,5.01
LOPTS_W := -SUBSYSTEM:WINDOWS,5.01
endif
ifdef BUILD
OPTS += -DBUILD=$(BUILD)
endif
ifdef COMMIT
OPTS += -DCOMMIT=0x$(COMMIT)
endif
ifdef UPSTREAM
OPTS += -DUPSTREAM=0x$(UPSTREAM)
endif
ifdef EXFLAGS
OPTS += $(EXFLAGS)
endif
ifdef EXINC
OPTS += -I$(EXINC)
endif
OPTS += $(SYSINC)
ifeq ($(OPTIM), y)
AFLAGS := /arch:AVX2
endif
ifeq ($(DEBUG), y)
OPTS += -D_DEBUG
DOPTS += -MTd -Gs -Zi
RFLAGS += -D_DEBUG
LOPTS += -debug
ifndef COPTIM
COPTIM := -Od
endif
else
LOPTS += -LTCG
DOPTS := -MT -GL
ifndef COPTIM
COPTIM := -O2
endif
endif
ifeq ($(LOGGING), y)
OPTS += -D_LOGGING
RFLAGS += -D_LOGGING
endif
ifeq ($(CRASHDUMP), y)
OPTS += -DUSE_CRASHDUMP
endif
ifeq ($(RELEASE), y)
OPTS += -DRELEASE_BUILD
RFLAGS += -DRELEASE_BUILD
endif
ifeq ($(PROFILER), y)
LOPTS += /MAP
endif
ifeq ($(VRAMDUMP), y)
OPTS += -DENABLE_VRAM_DUMP
RFLAGS += -DENABLE_VRAM_DUMP
endif
ifeq ($(X64), y)
PLATCG := codegen_x86-64.obj
CGOPS := codegen_ops_x86-64.h
VCG := vid_voodoo_codegen_x86-64.h
else
PLATCG := codegen_x86.obj
CGOPS := codegen_ops_x86.h
VCG := vid_voodoo_codegen_x86.h
endif
LIBS := ddraw.lib dinput8.lib dxguid.lib d3d9.lib d3dx9.lib \
version.lib comctl32.lib winmm.lib comdlg32.lib \
advapi32.lib gdi32.lib shell32.lib user32.lib \
ws2_32.lib wsock32.lib iphlpapi.lib psapi.lib
ifeq ($(DEBUG), y)
LIBS += libcmtd.lib libvcruntimed.lib libucrtd.lib
endif
# Optional modules.
MISCOBJ :=
ifeq ($(DYNAREC), y)
OPTS += -DUSE_DYNAREC
RFLAGS += -DUSE_DYNAREC
DYNARECOBJ := 386_dynarec_ops.obj \
codegen.obj \
codegen_ops.obj \
codegen_timing_common.obj codegen_timing_486.obj \
codegen_timing_686.obj codegen_timing_pentium.obj \
codegen_timing_winchip.obj $(PLATCG)
endif
ifeq ($(OPENAL), y)
OPTS += -DUSE_OPENAL
endif
ifeq ($(FLUIDSYNTH), y)
OPTS += -DUSE_FLUIDSYNTH
MISCOBJ += midi_fluidsynth.obj
endif
ifeq ($(MUNT), y)
OPTS += -DUSE_MUNT
MISCOBJ += midi_mt32.obj \
Analog.obj BReverbModel.obj File.obj FileStream.obj \
LA32Ramp.obj LA32FloatWaveGenerator.obj \
LA32WaveGenerator.obj MidiStreamParser.obj Part.obj \
Partial.obj PartialManager.obj Poly.obj ROMInfo.obj \
SampleRateConverter_dummy.obj Synth.obj Tables.obj \
TVA.obj TVF.obj TVP.obj sha1.obj c_interface.obj
endif
# N=no, Y=yes,linked, D=yes,dynamic, S=yes,static
ifneq ($(SDL), n)
OPTS += -DUSE_SDL
RFLAGS += -DUSE_SDL
ifneq ($(SDL_PATH), )
OPTS += -I$(SDL_PATH)/include/msvc -I$(SDL_PATH)/include
ifeq ($(X64), y)
LOPTS += -LIBPATH:$(SDL_PATH)\lib\msvc\x64
else
LOPTS += -LIBPATH:$(SDL_PATH)\lib\msvc\x86
endif
endif
ifeq ($(SDL), y)
LIBS += sdl2.lib
endif
SDLOBJ := win_sdl.obj
endif
# N=no, Y=yes,linked, D=yes,dynamic, S=yes,static
ifneq ($(D2D), n)
ifeq ($(D2D), d)
OPTS += -DUSE_D2D=2
else
OPTS += -DUSE_D2D=1
endif
RFLAGS += -DUSE_D2D
ifneq ($(D2D_PATH), )
OPTS += -I$(D2D_PATH)/include/msvc -I$(D2D_PATH)/include
ifeq ($(X64), y)
LOPTS += -LIBPATH:$(D2D_PATH)\lib\msvc\x64
else
LOPTS += -LIBPATH:$(D2D_PATH)\lib\msvc\x86
endif
endif
ifeq ($(D2D), y)
LIBS += d2d1.lib
endif
D2DOBJ := win_d2d.obj
endif
# N=no, Y=yes,linked, D=yes,dynamic, S=yes,static
ifneq ($(VNC), n)
OPTS += -DUSE_VNC
RFLAGS += -DUSE_VNC
ifneq ($(VNC_PATH), )
OPTS += -I$(VNC_PATH)/include/msvc -I$(VNC_PATH)/include
ifeq ($(X64), y)
LOPTS += -LIBPATH:$(VNC_PATH)\lib\x64
else
LOPTS += -LIBPATH:$(VNC_PATH)\lib\x86
endif
endif
ifeq ($(VNC), y)
LIBS += libvncserver.lib
endif
MISCOBJ += vnc.obj vnc_keymap.obj
endif
# N=no, Y=yes,linked, D=yes,dynamic, S=yes,static
ifneq ($(RDP), n)
OPTS += -DUSE_RDP
RFLAGS += -DUSE_RDP
ifneq ($(RDP_PATH), )
OPTS += -I$(RDP_PATH)/include/msvc -I$(RDP_PATH)/include
ifeq ($(X64), y)
LOPTS += -LIBPATH:$(RDP_PATH)\lib\x64
else
LOPTS += -LIBPATH:$(RDP_PATH)\lib\x86
endif
endif
ifeq ($(RDP), y)
LIBS += rdpsrvr.lib
endif
MISCOBJ += rdp.obj
endif
# N=no, Y=yes,linked, D=yes,dynamic, S=yes,static
ifneq ($(PNG), n)
ifeq ($(PNG), d)
OPTS += -DUSE_LIBPNG=2
else
OPTS += -DUSE_LIBPNG=1
endif
RFLAGS += -DUSE_LIBPNG
ifneq ($(PNG_PATH), )
OPTS += -I$(PNG_PATH)/include/msvc -I$(PNG_PATH)/include
ifeq ($(X64), y)
LOPTS += -LIBPATH:$(PNG_PATH)\lib\x64
else
LOPTS += -LIBPATH:$(PNG_PATH)\lib\x86
endif
endif
ifeq ($(PNG), y)
LIBS += libpng16_dll.lib #zlib.lib
endif
MISCOBJ += png.obj
endif
# N=no, Y=yes,linked, D=yes,dynamic, S=yes,static
ifneq ($(WX), n)
OPTS += -DUSE_WX $(WX_FLAGS)
LIBS += $(WX_LIBS) -lm
UIOBJ := wx_main.obj wx_ui.obj wx_stbar.obj wx_render.obj
else
UIOBJ := win_ui.obj \
win_ddraw.obj win_d3d.obj $(SDLOBJ) $(D2DOBJ) \
win_dialog.obj win_about.obj win_settings.obj \
win_devconf.obj win_snd_gain.obj win_new_image.obj
endif
# Options for the DEV branch.
ifeq ($(DEV_BRANCH), y)
OPTS += -DDEV_BRANCH
DEVBROBJ :=
ifeq ($(AMD_K), y)
OPTS += -DUSE_AMD_K
endif
ifeq ($(LASERXT), y)
OPTS += -DUSE_LASERXT
DEVBROBJ += m_xt_laserxt.obj
endif
ifeq ($(PORTABLE3), y)
OPTS += -DUSE_PORTABLE3
endif
ifeq ($(I686), y)
OPTS += -DUSE_I686
endif
ifeq ($(PAS16), y)
OPTS += -DUSE_PAS16
DEVBROBJ += snd_pas16.obj
endif
ifeq ($(XL24), y)
OPTS += -DUSE_XL24
endif
ifeq ($(WONDER), y)
OPTS += -DUSE_WONDER
endif
ifeq ($(HOSTCD), y)
OPTS += -DUSE_HOST_CDROM
endif
ifeq ($(PRINTER), y)
OPTS += -DUSE_PRINTER
DEVBROBJ += prt_parallel.obj
endif
endif
# Final versions of the toolchain flags.
LDFLAGS := $(LOPTS)
CFLAGS := $(WX_FLAGS) $(OPTS) $(COPTS) $(COPTIM) $(DOPTS) $(AFLAGS)
CXXFLAGS := $(WX_FLAGS) $(OPTS) $(CXXOPTS) $(COPTS) $(COPTIM) $(DOPTS) $(AFLAGS)
#########################################################################
# Create the (final) list of objects to build. #
#########################################################################
RESDLL := VARCem-$(LANG)
MAINOBJ := pc.obj config.obj misc.obj random.obj timer.obj io.obj \
mem.obj rom.obj rom_load.obj device.obj nvr.obj
UIOBJ += ui_main.obj ui_lang.obj ui_stbar.obj ui_vidapi.obj \
ui_cdrom.obj ui_new_image.obj ui_misc.obj
SYSOBJ := dma.obj nmi.obj pic.obj pit.obj ppi.obj pci.obj mca.obj \
mcr.obj memregs.obj nvr_at.obj nvr_ps2.obj
CPUOBJ := cpu.obj cpu_table.obj \
808x.obj 386.obj x86seg.obj x87.obj \
386_dynarec.obj $(DYNARECOBJ)
MCHOBJ := machine.obj machine_table.obj \
m_xt.obj m_xt_compaq.obj \
m_xt_t1000.obj m_xt_t1000_vid.obj \
m_xt_xi8088.obj \
m_pcjr.obj \
m_amstrad.obj m_europc.obj \
m_olivetti_m24.obj m_tandy.obj \
m_at.obj \
m_at_ali1429.obj m_at_commodore.obj \
m_at_neat.obj m_at_headland.obj \
m_at_t3100e.obj m_at_t3100e_vid.obj \
m_ps1.obj m_ps1_hdc.obj \
m_ps2_isa.obj m_ps2_mca.obj \
m_at_opti495.obj m_at_scat.obj \
m_at_compaq.obj m_at_wd76c10.obj \
m_at_sis_85c471.obj m_at_sis_85c496.obj \
m_at_4x0.obj
INTELOBJ := intel.obj \
intel_flash.obj \
intel_sio.obj \
intel_piix.obj
DEVOBJ := bugger.obj \
isamem.obj isartc.obj \
game.obj game_dev.obj \
parallel.obj parallel_dev.obj \
prt_text.obj prt_cpmap.obj prt_escp.obj \
serial.obj \
sio_fdc37c66x.obj sio_fdc37c669.obj sio_fdc37c93x.obj \
sio_pc87306.obj sio_w83877f.obj sio_um8669f.obj \
keyboard.obj \
keyboard_xt.obj keyboard_at.obj \
mouse.obj \
mouse_serial.obj mouse_ps2.obj mouse_bus.obj \
joystick.obj \
js_standard.obj js_ch_fs_pro.obj \
js_sw_pad.obj js_tm_fcs.obj
FDDOBJ := fdc.obj \
fdd.obj \
fdd_common.obj fdd_86f.obj \
fdd_fdi.obj fdi2raw.obj lzf_c.obj lzf_d.obj \
fdd_imd.obj fdd_img.obj fdd_json.obj fdd_td0.obj
HDDOBJ := hdd.obj \
hdd_image.obj hdd_table.obj \
hdc.obj \
hdc_st506_xt.obj hdc_st506_at.obj \
hdc_esdi_at.obj hdc_esdi_mca.obj \
hdc_ide_ata.obj hdc_ide_xta.obj hdc_xtide.obj
CDROMOBJ := cdrom.obj \
cdrom_speed.obj \
cdrom_dosbox.obj cdrom_image.obj
ZIPOBJ := zip.obj
ifeq ($(USB), y)
USBOBJ := usb.obj
endif
SCSIOBJ := scsi.obj \
scsi_device.obj scsi_disk.obj scsi_cdrom.obj \
scsi_x54x.obj scsi_aha154x.obj scsi_buslogic.obj \
scsi_ncr5380.obj scsi_ncr53c810.obj
NETOBJ := network.obj \
net_pcap.obj \
net_slirp.obj \
slirp.obj slirp_misc.obj \
cksum.obj debug.obj if.obj mbuf.obj queue.obj sbuf.obj \
socket.obj \
arp.obj bootp.obj \
ip_icmp.obj ip_input.obj ip_output.obj \
tcp_input.obj tcp_output.obj tcp_subr.obj tcp_timer.obj \
udp.obj \
net_dp8390.obj \
net_ne2000.obj net_wd80x3.obj net_3c503.obj
SNDOBJ := sound.obj \
sound_dev.obj \
openal.obj \
snd_opl.obj snd_dbopl.obj \
dbopl.obj nukedopl.obj \
snd_resid.obj \
convolve.obj convolve-sse.obj envelope.obj extfilt.obj \
filter.obj pot.obj sid.obj voice.obj wave6581__ST.obj \
wave6581_P_T.obj wave6581_PS_.obj wave6581_PST.obj \
wave8580__ST.obj wave8580_P_T.obj wave8580_PS_.obj \
wave8580_PST.obj wave.obj \
midi.obj midi_system.obj \
snd_speaker.obj \
snd_lpt_dac.obj snd_lpt_dss.obj \
snd_adlib.obj snd_adlibgold.obj snd_ad1848.obj snd_audiopci.obj \
snd_cms.obj \
snd_gus.obj \
snd_sb.obj snd_sb_dsp.obj \
snd_emu8k.obj snd_mpu401.obj \
snd_sn76489.obj snd_ssi2001.obj \
snd_wss.obj \
snd_ym7128.obj
VIDOBJ := video.obj \
video_dev.obj \
vid_cga.obj vid_cga_comp.obj \
vid_cga_compaq.obj \
vid_mda.obj \
vid_hercules.obj vid_herculesplus.obj vid_incolor.obj \
vid_colorplus.obj \
vid_genius.obj \
vid_sigma.obj \
vid_wy700.obj \
vid_ega.obj vid_ega_render.obj \
vid_svga.obj vid_svga_render.obj \
vid_vga.obj \
vid_ati_eeprom.obj \
vid_ati18800.obj vid_ati28800.obj \
vid_ati_mach64.obj vid_ati68860_ramdac.obj \
vid_bt48x_ramdac.obj vid_icd2061.obj vid_ics2595.obj \
vid_cl54xx.obj \
vid_et4000.obj vid_sc1502x_ramdac.obj \
vid_et4000w32.obj vid_stg_ramdac.obj \
vid_oak_oti.obj \
vid_paradise.obj \
vid_ti_cf62011.obj \
vid_tvga.obj \
vid_tgui9440.obj vid_tkd8001_ramdac.obj \
vid_s3.obj vid_s3_virge.obj \
vid_sdac_ramdac.obj \
vid_voodoo.obj
PLATOBJ := win.obj \
win_lang.obj win_opendir.obj win_dynld.obj win_thread.obj \
win_cdrom.obj win_keyboard.obj win_mouse.obj \
win_joystick.obj win_midi.obj
ifeq ($(CRASHDUMP), y)
PLATOBJ += win_crashdump.obj
endif
OBJ := $(MAINOBJ) $(CPUOBJ) $(MCHOBJ) $(SYSOBJ) $(DEVOBJ) \
$(INTELOBJ) $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \
$(USBOBJ) $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \
$(UIOBJ) $(PLATOBJ) $(MISCOBJ) $(DEVBROBJ)
ifdef EXOBJ
OBJ += $(EXOBJ)
endif
# Build module rules.
ifeq ($(AUTODEP), y)
%.obj: %.c
@$(CC) $(CFLAGS) -Fo$@ -c $<
@$(MCPP) $(OPTS) $(DEPS) $<
%.obj: %.cpp
@$(CPP) $(CXXFLAGS) -Fo$@ -c $<
@$(MCPP) $(OPTS) $(DEPS) $<
else
%.obj: %.c
@$(CC) $(CFLAGS) -Fo$@ -c $<
%.obj: %.cpp
@$(CPP) $(CXXFLAGS) -Fo$@ -c $<
%.d: %.c $(wildcard $*.d)
$(MCPP) $(OPTS) $(DEPS) $< >NUL
%.d: %.cpp $(wildcard $*.d)
$(MCPP) $(OPTS) $(DEPS) $< >NUL
endif
all: $(PREBUILD) $(PROG).exe $(NETIF).exe $(POSTBUILD)
#
# This rule creates a script (command file) that figures out which
# language we want to make (its argument is the 2-letter language
# name, or none) by looking it up in the database of supported ones,
# and then it calls the (this) Makefile back with the proper args
# for that target.
#
# We do it this way so it can also be used by the VC project files.
#
win/Mklang.cmd: win/msvc/Makefile.VC
@echo @SET PATH=$(PATH) >>win\Mklang.cmd
@echo @SETLOCAL >>win\Mklang.cmd
@echo @SET LANG=none >>win\Mklang.cmd
@echo @FOR /F "eol=# tokens=1,2,3,4* delims=, " %%%%i in (ui\lang\VARCem.lang) do @if "%%1"=="%%%%i" set LANG=%%%%i LANGID=%%%%j PRILANG=%%%%k SUBLANG=%%%%l >>win\Mklang.cmd
@echo @IF NOT "%%LANG%%"=="none" @$(MAKE) -fwin/msvc/Makefile.VC "RFLAGS=$(RFLAGS) $(EXTRAS)" LANG=%%LANG%% VARCem-%%1.dll >>win\Mklang.cmd
langs: win/Mklang.cmd
ifdef LANG
@echo Generating localization $(LANG) ..
else
@echo Generating localizations..
@FOR /F "eol=# tokens=1 delims=, " %%i in (ui\lang\VARCem.lang) do @win\Mklang %%i
endif
@-del win\Mklang.cmd
win/$(RESDLL).rc: VARCem.rpp VARCem-common.rc
@$(PREPROC) -DPREAMBLE= -DLANG=$(LANG) -DLANGID=$(LANGID) -DPRILANG=$(PRILANG) -DSUBLANG=$(SUBLANG) $< >win\$(RESDLL).rc 2>NUL
$(RESDLL).res: win/$(RESDLL).rc VARCem-common.rc
@echo Processing $(RESDLL).rc ..
@$(WINDRES) $(RFLAGS) -fo$@ $<
$(RESDLL).dll: $(RESDLL).res
@echo Linking $(RESDLL).dll ..
@$(LINK) /DLL /NOENTRY $(LDFLAGS) -OUT:$@ $(RESDLL).res
@-del win\$(RESDLL).rc
VARCem.res: win/VARCem.rc win/VARCem.mpp
@echo Generating Manifest file..
@del win\VARCem.manifest 2>NUL
@$(PREPROC) win\VARCem.mpp >win\VARCem.manifest 2>NUL
@echo Processing $<
@$(WINDRES) $(RFLAGS) $(EXTRAS) -fo$@ $<
$(PROG).exe: $(OBJ) VARCem.res
@echo Linking $(PROG).exe ..
@$(LINK) $(LDFLAGS) $(LOPTS_W) -OUT:$(PROG).exe \
$(OBJ) VARCem.res $(LIBS)
pcap_if.res: pcap_if.rc
@echo Processing $<
@$(WINDRES) $(RFLAGS) -fo$@ $<
$(NETIF).exe: pcap_if.obj win_dynld.obj pcap_if.res
@echo Linking $(NETIF).exe ..
@$(LINK) $(LDFLAGS) $(LOPTS_C) -OUT:$@ \
pcap_if.obj win_dynld.obj pcap_if.res
clean:
@echo Cleaning objects..
@-del *.obj 2>NUL
@-del *.res 2>NUL
clobber: Mklang.cmd clean
@echo Cleaning executables..
@-del *.d 2>NUL
@-del *.exe 2>NUL
ifeq ($(DEBUG), y)
@-del *.ilk 2>NUL
@-del *.pdb 2>NUL
endif
ifeq ($(PROFILER), y)
@-del *.map 2>NUL
endif
@-del win\*.manifest 2>NUL
@-del *.dll 2>NUL
@-del win\Mklang.cmd
# @del $(DEPFILE) 2>NUL
ifneq ($(AUTODEP), y)
depclean:
@del $(DEPFILE) 2>NUL
@echo Creating dependencies..
@echo # Run "make depends" to re-create this file. >$(DEPFILE)
depends: DEPOBJ=$(OBJ:%.obj=%.d)
depends: depclean $(OBJ:%.obj=%.d)
@-cat $(DEPOBJ) >>$(DEPFILE)
@del $(DEPOBJ)
$(DEPFILE):
endif
# Module dependencies.
ifeq ($(AUTODEP), y)
#-include $(OBJ:%.obj=%.d) (better, but sloooowwwww)
-include *.d
else
include $(wildcard $(DEPFILE))
endif
# End of Makefile.VC.

View File

@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VARCem", "VARCem.vcxproj", "{6E445F28-CA8F-430F-8CCF-C59C53516AC5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Debug|x64.ActiveCfg = Debug|x64
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Debug|x64.Build.0 = Debug|x64
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Debug|x86.ActiveCfg = Debug|Win32
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Debug|x86.Build.0 = Debug|Win32
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Release|x64.ActiveCfg = Release|x64
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Release|x64.Build.0 = Release|x64
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Release|x86.ActiveCfg = Release|Win32
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {85A5962B-0218-472C-A361-6E55D8FE7E9B}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,774 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\devices\misc\bugger.c" />
<ClCompile Include="..\..\..\devices\cdrom\cdrom.c" />
<ClCompile Include="..\..\..\devices\cdrom\cdrom_dosbox.cpp" />
<ClCompile Include="..\..\..\devices\cdrom\cdrom_image.cpp" />
<ClCompile Include="..\..\..\devices\cdrom\cdrom_null.c" />
<ClCompile Include="..\..\..\config.c" />
<ClCompile Include="..\..\..\cpu\386.c" />
<ClCompile Include="..\..\..\cpu\386_dynarec.c" />
<ClCompile Include="..\..\..\cpu\386_dynarec_ops.c" />
<ClCompile Include="..\..\..\cpu\808x.c" />
<ClCompile Include="..\..\..\cpu\codegen.c" />
<ClCompile Include="..\..\..\cpu\codegen_ops.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_486.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_686.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_common.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_pentium.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_winchip.c" />
<ClCompile Include="..\..\..\cpu\codegen_x86-64.c" />
<ClCompile Include="..\..\..\cpu\codegen_x86.c" />
<ClCompile Include="..\..\..\cpu\cpu.c" />
<ClCompile Include="..\..\..\cpu\cpu_table.c" />
<ClCompile Include="..\..\..\cpu\x86seg.c" />
<ClCompile Include="..\..\..\cpu\x87.c" />
<ClCompile Include="..\..\..\device.c" />
<ClCompile Include="..\..\..\devices\disk\hdc.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_esdi_at.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_esdi_mca.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_ide_ata.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_ide_xta.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_st506_at.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_st506_xt.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_xtide.c" />
<ClCompile Include="..\..\..\devices\disk\hdd.c" />
<ClCompile Include="..\..\..\devices\disk\hdd_image.c" />
<ClCompile Include="..\..\..\devices\disk\hdd_table.c" />
<ClCompile Include="..\..\..\devices\disk\zip.c" />
<ClCompile Include="..\..\..\devices\network\slirp\bootp.c" />
<ClCompile Include="..\..\..\devices\network\slirp\cksum.c" />
<ClCompile Include="..\..\..\devices\network\slirp\debug.c" />
<ClCompile Include="..\..\..\devices\network\slirp\if.c" />
<ClCompile Include="..\..\..\devices\network\slirp\ip_icmp.c" />
<ClCompile Include="..\..\..\devices\network\slirp\ip_input.c" />
<ClCompile Include="..\..\..\devices\network\slirp\ip_output.c" />
<ClCompile Include="..\..\..\devices\network\slirp\mbuf.c" />
<ClCompile Include="..\..\..\devices\network\slirp\slirp_misc.c" />
<ClCompile Include="..\..\..\devices\network\slirp\queue.c" />
<ClCompile Include="..\..\..\devices\network\slirp\sbuf.c" />
<ClCompile Include="..\..\..\devices\network\slirp\slirp.c" />
<ClCompile Include="..\..\..\devices\network\slirp\socket.c" />
<ClCompile Include="..\..\..\devices\network\slirp\tcp_input.c" />
<ClCompile Include="..\..\..\devices\network\slirp\tcp_output.c" />
<ClCompile Include="..\..\..\devices\network\slirp\tcp_subr.c" />
<ClCompile Include="..\..\..\devices\network\slirp\tcp_timer.c" />
<ClCompile Include="..\..\..\devices\network\slirp\udp.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_aha154x.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_bus.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_buslogic.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_device.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_disk.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_ncr5380.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_ncr53c810.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_x54x.c" />
<ClCompile Include="..\..\..\devices\sio\sio_detect.c" />
<ClCompile Include="..\..\..\devices\sio\sio_fdc37c669.c" />
<ClCompile Include="..\..\..\devices\sio\sio_fdc37c66x.c" />
<ClCompile Include="..\..\..\devices\sio\sio_fdc37c93x.c" />
<ClCompile Include="..\..\..\devices\sio\sio_pc87306.c" />
<ClCompile Include="..\..\..\devices\sio\sio_um8669f.c" />
<ClCompile Include="..\..\..\devices\sio\sio_w83877f.c" />
<ClCompile Include="..\..\..\devices\sound\dbopl.cpp" />
<ClCompile Include="..\..\..\devices\sound\midi.c" />
<ClCompile Include="..\..\..\devices\sound\midi_fluidsynth.c" />
<ClCompile Include="..\..\..\devices\sound\midi_mt32.c" />
<ClCompile Include="..\..\..\devices\sound\midi_system.c" />
<ClCompile Include="..\..\..\devices\sound\munt\Analog.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\BReverbModel.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\File.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\FileStream.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\LA32FloatWaveGenerator.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\LA32Ramp.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\LA32WaveGenerator.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\MidiStreamParser.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Part.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Partial.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\PartialManager.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Poly.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\ROMInfo.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\SampleRateConverter_dummy.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Synth.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Tables.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\TVA.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\TVF.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\TVP.cpp" />
<ClCompile Include="..\..\..\devices\sound\nukedopl.cpp" />
<ClCompile Include="..\..\..\devices\sound\openal.c" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\convolve-sse.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\convolve.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\envelope.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\extfilt.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\filter.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\pot.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\sid.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\voice.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave6581_PST.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave6581_PS_.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave6581_P_T.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave6581__ST.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave8580_PST.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave8580_PS_.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave8580_P_T.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave8580__ST.cpp" />
<ClCompile Include="..\..\..\devices\sound\snd_ad1848.c" />
<ClCompile Include="..\..\..\devices\sound\snd_adlib.c" />
<ClCompile Include="..\..\..\devices\sound\snd_adlibgold.c" />
<ClCompile Include="..\..\..\devices\sound\snd_audiopci.c" />
<ClCompile Include="..\..\..\devices\sound\snd_cms.c" />
<ClCompile Include="..\..\..\devices\sound\snd_dbopl.cpp" />
<ClCompile Include="..\..\..\devices\sound\snd_emu8k.c" />
<ClCompile Include="..\..\..\devices\sound\snd_gus.c" />
<ClCompile Include="..\..\..\devices\sound\snd_lpt_dac.c" />
<ClCompile Include="..\..\..\devices\sound\snd_lpt_dss.c" />
<ClCompile Include="..\..\..\devices\sound\snd_mpu401.c" />
<ClCompile Include="..\..\..\devices\sound\snd_opl.c" />
<ClCompile Include="..\..\..\devices\sound\snd_pas16.c" />
<ClCompile Include="..\..\..\devices\sound\snd_resid.cpp" />
<ClCompile Include="..\..\..\devices\sound\snd_sb.c" />
<ClCompile Include="..\..\..\devices\sound\snd_sb_dsp.c" />
<ClCompile Include="..\..\..\devices\sound\snd_sn76489.c" />
<ClCompile Include="..\..\..\devices\sound\snd_speaker.c" />
<ClCompile Include="..\..\..\devices\sound\snd_ssi2001.c" />
<ClCompile Include="..\..\..\devices\sound\snd_wss.c" />
<ClCompile Include="..\..\..\devices\sound\snd_ym7128.c" />
<ClCompile Include="..\..\..\devices\sound\sound.c" />
<ClCompile Include="..\..\..\devices\sound\sound_dev.c" />
<ClCompile Include="..\..\..\devices\system\dma.c" />
<ClCompile Include="..\..\..\devices\system\i82335.c" />
<ClCompile Include="..\..\..\devices\system\intel.c" />
<ClCompile Include="..\..\..\devices\system\intel_flash.c" />
<ClCompile Include="..\..\..\devices\system\intel_piix.c" />
<ClCompile Include="..\..\..\devices\system\intel_piix4.c" />
<ClCompile Include="..\..\..\devices\system\intel_sio.c" />
<ClCompile Include="..\..\..\devices\system\mca.c" />
<ClCompile Include="..\..\..\devices\system\mcr.c" />
<ClCompile Include="..\..\..\devices\system\memregs.c" />
<ClCompile Include="..\..\..\devices\system\nmi.c" />
<ClCompile Include="..\..\..\devices\system\nvr_at.c" />
<ClCompile Include="..\..\..\devices\system\nvr_ps2.c" />
<ClCompile Include="..\..\..\devices\system\pci.c" />
<ClCompile Include="..\..\..\devices\system\pic.c" />
<ClCompile Include="..\..\..\devices\system\pit.c" />
<ClCompile Include="..\..\..\devices\system\ppi.c" />
<ClCompile Include="..\..\..\devices\floppy\fdc.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_86f.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_common.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_fdi.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_imd.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_img.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_json.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_td0.c" />
<ClCompile Include="..\..\..\devices\floppy\fdi2raw.c" />
<ClCompile Include="..\..\..\devices\floppy\lzf\lzf_c.c" />
<ClCompile Include="..\..\..\devices\floppy\lzf\lzf_d.c" />
<ClCompile Include="..\..\..\devices\input\game\joystick.c" />
<ClCompile Include="..\..\..\devices\input\game\js_ch_fs_pro.c" />
<ClCompile Include="..\..\..\devices\input\game\js_standard.c" />
<ClCompile Include="..\..\..\devices\input\game\js_sw_pad.c" />
<ClCompile Include="..\..\..\devices\input\game\js_tm_fcs.c" />
<ClCompile Include="..\..\..\devices\input\keyboard.c" />
<ClCompile Include="..\..\..\devices\input\keyboard_at.c" />
<ClCompile Include="..\..\..\devices\input\keyboard_xt.c" />
<ClCompile Include="..\..\..\devices\input\mouse.c" />
<ClCompile Include="..\..\..\devices\input\mouse_bus.c" />
<ClCompile Include="..\..\..\devices\input\mouse_ps2.c" />
<ClCompile Include="..\..\..\devices\input\mouse_serial.c" />
<ClCompile Include="..\..\..\devices\video\video_dev.c" />
<ClCompile Include="..\..\..\io.c" />
<ClCompile Include="..\..\..\machines\machine.c" />
<ClCompile Include="..\..\..\machines\machine_table.c" />
<ClCompile Include="..\..\..\machines\m_amstrad.c" />
<ClCompile Include="..\..\..\machines\m_at.c" />
<ClCompile Include="..\..\..\machines\m_at_430fx.c" />
<ClCompile Include="..\..\..\machines\m_at_430hx.c" />
<ClCompile Include="..\..\..\machines\m_at_430lx_nx.c" />
<ClCompile Include="..\..\..\machines\m_at_430vx.c" />
<ClCompile Include="..\..\..\machines\m_at_440fx.c" />
<ClCompile Include="..\..\..\machines\m_at_4gpv31.c" />
<ClCompile Include="..\..\..\machines\m_at_ali1429.c" />
<ClCompile Include="..\..\..\machines\m_at_commodore.c" />
<ClCompile Include="..\..\..\machines\m_at_compaq.c" />
<ClCompile Include="..\..\..\machines\m_at_headland.c" />
<ClCompile Include="..\..\..\machines\m_at_neat.c" />
<ClCompile Include="..\..\..\machines\m_at_opti495.c" />
<ClCompile Include="..\..\..\machines\m_at_scat.c" />
<ClCompile Include="..\..\..\machines\m_at_sis_85c471.c" />
<ClCompile Include="..\..\..\machines\m_at_sis_85c496.c" />
<ClCompile Include="..\..\..\machines\m_at_sis_85c50x.c" />
<ClCompile Include="..\..\..\machines\m_at_t3100e.c" />
<ClCompile Include="..\..\..\machines\m_at_t3100e_vid.c" />
<ClCompile Include="..\..\..\machines\m_at_wd76c10.c" />
<ClCompile Include="..\..\..\machines\m_europc.c" />
<ClCompile Include="..\..\..\machines\m_olivetti_m24.c" />
<ClCompile Include="..\..\..\machines\m_pcjr.c" />
<ClCompile Include="..\..\..\machines\m_ps1.c" />
<ClCompile Include="..\..\..\machines\m_ps1_hdc.c" />
<ClCompile Include="..\..\..\machines\m_ps2_isa.c" />
<ClCompile Include="..\..\..\machines\m_ps2_mca.c" />
<ClCompile Include="..\..\..\machines\m_tandy.c" />
<ClCompile Include="..\..\..\machines\m_xt.c" />
<ClCompile Include="..\..\..\machines\m_xt_compaq.c" />
<ClCompile Include="..\..\..\machines\m_xt_laserxt.c" />
<ClCompile Include="..\..\..\machines\m_xt_t1000.c" />
<ClCompile Include="..\..\..\machines\m_xt_t1000_vid.c" />
<ClCompile Include="..\..\..\machines\m_xt_xi8088.c" />
<ClCompile Include="..\..\..\mem.c" />
<ClCompile Include="..\..\..\devices\network\network.c" />
<ClCompile Include="..\..\..\devices\network\net_ne2000.c" />
<ClCompile Include="..\..\..\devices\network\net_pcap.c" />
<ClCompile Include="..\..\..\devices\network\net_slirp.c" />
<ClCompile Include="..\..\..\misc.c" />
<ClCompile Include="..\..\..\nvr.c" />
<ClCompile Include="..\..\..\pc.c" />
<ClCompile Include="..\..\..\devices\ports\game.c" />
<ClCompile Include="..\..\..\devices\ports\game_dev.c" />
<ClCompile Include="..\..\..\devices\ports\parallel.c" />
<ClCompile Include="..\..\..\devices\ports\parallel_dev.c" />
<ClCompile Include="..\..\..\devices\ports\serial.c" />
<ClCompile Include="..\..\..\random.c" />
<ClCompile Include="..\..\..\rom.c" />
<ClCompile Include="..\..\..\rom_load.c" />
<ClCompile Include="..\..\..\devices\sound\munt\c_interface\c_interface.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\sha1\sha1.cpp" />
<ClCompile Include="..\..\..\timer.c" />
<ClCompile Include="..\..\..\ui\ui_main.c" />
<ClCompile Include="..\..\..\ui\ui_new_image.c" />
<ClCompile Include="..\..\..\ui\ui_stbar.c" />
<ClCompile Include="..\..\..\devices\video\video.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati18800.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati28800.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati68860_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati_eeprom.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati_mach64.c" />
<ClCompile Include="..\..\..\devices\video\vid_bt485_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_cga.c" />
<ClCompile Include="..\..\..\devices\video\vid_cga_comp.c" />
<ClCompile Include="..\..\..\devices\video\vid_cl54xx.c" />
<ClCompile Include="..\..\..\devices\video\vid_colorplus.c" />
<ClCompile Include="..\..\..\devices\video\vid_compaq_cga.c" />
<ClCompile Include="..\..\..\devices\video\vid_ega.c" />
<ClCompile Include="..\..\..\devices\video\vid_ega_render.c" />
<ClCompile Include="..\..\..\devices\video\vid_et4000.c" />
<ClCompile Include="..\..\..\devices\video\vid_et4000w32.c" />
<ClCompile Include="..\..\..\devices\video\vid_genius.c" />
<ClCompile Include="..\..\..\devices\video\vid_hercules.c" />
<ClCompile Include="..\..\..\devices\video\vid_herculesplus.c" />
<ClCompile Include="..\..\..\devices\video\vid_icd2061.c" />
<ClCompile Include="..\..\..\devices\video\vid_ics2595.c" />
<ClCompile Include="..\..\..\devices\video\vid_incolor.c" />
<ClCompile Include="..\..\..\devices\video\vid_mda.c" />
<ClCompile Include="..\..\..\devices\video\vid_oak_oti.c" />
<ClCompile Include="..\..\..\devices\video\vid_paradise.c" />
<ClCompile Include="..\..\..\devices\video\vid_s3.c" />
<ClCompile Include="..\..\..\devices\video\vid_s3_virge.c" />
<ClCompile Include="..\..\..\devices\video\vid_sc1502x_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_sdac_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_stg_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_svga.c" />
<ClCompile Include="..\..\..\devices\video\vid_svga_render.c" />
<ClCompile Include="..\..\..\devices\video\vid_tgui9440.c" />
<ClCompile Include="..\..\..\devices\video\vid_ti_cf62011.c" />
<ClCompile Include="..\..\..\devices\video\vid_tkd8001_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_tvga.c" />
<ClCompile Include="..\..\..\devices\video\vid_vga.c" />
<ClCompile Include="..\..\..\devices\video\vid_voodoo.c" />
<ClCompile Include="..\..\..\devices\video\vid_wy700.c" />
<ClCompile Include="..\..\..\ui\ui_vidapi.c" />
<ClCompile Include="..\..\..\win\win.c" />
<ClCompile Include="..\..\..\win\win_about.c" />
<ClCompile Include="..\..\..\win\win_cdrom.c" />
<ClCompile Include="..\..\..\win\win_cdrom_ioctl.c" />
<ClCompile Include="..\..\..\win\win_crashdump.c" />
<ClCompile Include="..\..\..\win\win_d3d.cpp" />
<ClCompile Include="..\..\..\win\win_ddraw.cpp" />
<ClCompile Include="..\..\..\win\win_devconf.c" />
<ClCompile Include="..\..\..\win\win_dialog.c" />
<ClCompile Include="..\..\..\win\win_dynld.c" />
<ClCompile Include="..\..\..\win\win_joystick.cpp" />
<ClCompile Include="..\..\..\win\win_keyboard.c" />
<ClCompile Include="..\..\..\win\win_midi.c" />
<ClCompile Include="..\..\..\win\win_mouse.cpp" />
<ClCompile Include="..\..\..\win\win_opendir.c" />
<ClCompile Include="..\..\..\win\win_settings.c" />
<ClCompile Include="..\..\..\win\win_snd_gain.c" />
<ClCompile Include="..\..\..\win\win_status.c" />
<ClCompile Include="..\..\..\win\win_thread.c" />
<ClCompile Include="..\..\..\win\win_ui.c" />
<ClCompile Include="..\..\win_lang.c" />
<ClCompile Include="..\..\win_new_image.c" />
<ClCompile Include="..\..\win_sdl.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\devices\misc\bugger.h" />
<ClInclude Include="..\..\..\devices\cdrom\cdrom.h" />
<ClInclude Include="..\..\..\devices\cdrom\cdrom_dosbox.h" />
<ClInclude Include="..\..\..\devices\cdrom\cdrom_image.h" />
<ClInclude Include="..\..\..\devices\cdrom\cdrom_null.h" />
<ClInclude Include="..\..\..\config.h" />
<ClInclude Include="..\..\..\cpu\386.h" />
<ClInclude Include="..\..\..\cpu\386_common.h" />
<ClInclude Include="..\..\..\cpu\386_ops.h" />
<ClInclude Include="..\..\..\cpu\codegen.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_arith.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_fpu.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_jump.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_logic.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_misc.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_mmx.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_mov.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_shift.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_stack.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_x86-64.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_x86.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_xchg.h" />
<ClInclude Include="..\..\..\cpu\codegen_timing_common.h" />
<ClInclude Include="..\..\..\cpu\codegen_x86-64.h" />
<ClInclude Include="..\..\..\cpu\codegen_x86.h" />
<ClInclude Include="..\..\..\cpu\cpu.h" />
<ClInclude Include="..\..\..\cpu\x86.h" />
<ClInclude Include="..\..\..\cpu\x86seg.h" />
<ClInclude Include="..\..\..\cpu\x86_flags.h" />
<ClInclude Include="..\..\..\cpu\x86_ops.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_amd.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_arith.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_atomic.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_bcd.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_bit.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_bitscan.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_call.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_flag.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_fpu.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_i686.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_inc_dec.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_int.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_io.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_jump.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_misc.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_arith.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_cmp.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_logic.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_mov.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_pack.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_shift.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mov.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_movx.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mov_ctrl.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mov_seg.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_msr.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mul.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_pmode.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_prefix.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_rep.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_ret.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_set.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_shift.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_stack.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_string.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_xchg.h" />
<ClInclude Include="..\..\..\cpu\x87.h" />
<ClInclude Include="..\..\..\cpu\x87_ops.h" />
<ClInclude Include="..\..\..\cpu\x87_ops_arith.h" />
<ClInclude Include="..\..\..\cpu\x87_ops_loadstore.h" />
<ClInclude Include="..\..\..\cpu\x87_ops_misc.h" />
<ClInclude Include="..\..\..\device.h" />
<ClInclude Include="..\..\..\devices\disk\hdc.h" />
<ClInclude Include="..\..\..\devices\disk\hdc_ide.h" />
<ClInclude Include="..\..\..\devices\disk\hdd.h" />
<ClInclude Include="..\..\..\devices\disk\zip.h" />
<ClInclude Include="..\..\..\devices\network\slirp\bootp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\ctl.h" />
<ClInclude Include="..\..\..\devices\network\slirp\debug.h" />
<ClInclude Include="..\..\..\devices\network\slirp\icmp_var.h" />
<ClInclude Include="..\..\..\devices\network\slirp\if.h" />
<ClInclude Include="..\..\..\devices\network\slirp\ip.h" />
<ClInclude Include="..\..\..\devices\network\slirp\ip_icmp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\libslirp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\main.h" />
<ClInclude Include="..\..\..\devices\network\slirp\mbuf.h" />
<ClInclude Include="..\..\..\devices\network\slirp\misc.h" />
<ClInclude Include="..\..\..\devices\network\slirp\queue.h" />
<ClInclude Include="..\..\..\devices\network\slirp\sbuf.h" />
<ClInclude Include="..\..\..\devices\network\slirp\slirp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\slirp_config.h" />
<ClInclude Include="..\..\..\devices\network\slirp\socket.h" />
<ClInclude Include="..\..\..\devices\network\slirp\tcp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\tcpip.h" />
<ClInclude Include="..\..\..\devices\network\slirp\tcp_timer.h" />
<ClInclude Include="..\..\..\devices\network\slirp\tcp_var.h" />
<ClInclude Include="..\..\..\devices\network\slirp\udp.h" />
<ClInclude Include="..\..\..\devices\scsi\queue.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_aha154x.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_buslogic.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_device.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_disk.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_ncr5380.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_ncr53c810.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_x54x.h" />
<ClInclude Include="..\..\..\devices\sio\sio.h" />
<ClInclude Include="..\..\..\devices\sound\dbopl.h" />
<ClInclude Include="..\..\..\devices\sound\filters.h" />
<ClInclude Include="..\..\..\devices\sound\midi.h" />
<ClInclude Include="..\..\..\devices\sound\midi_fluidsynth.h" />
<ClInclude Include="..\..\..\devices\sound\midi_mt32.h" />
<ClInclude Include="..\..\..\devices\sound\midi_system.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Analog.h" />
<ClInclude Include="..\..\..\devices\sound\munt\BReverbModel.h" />
<ClInclude Include="..\..\..\devices\sound\munt\config.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Enumerations.h" />
<ClInclude Include="..\..\..\devices\sound\munt\File.h" />
<ClInclude Include="..\..\..\devices\sound\munt\FileStream.h" />
<ClInclude Include="..\..\..\devices\sound\munt\globals.h" />
<ClInclude Include="..\..\..\devices\sound\munt\internals.h" />
<ClInclude Include="..\..\..\devices\sound\munt\LA32FloatWaveGenerator.h" />
<ClInclude Include="..\..\..\devices\sound\munt\LA32Ramp.h" />
<ClInclude Include="..\..\..\devices\sound\munt\LA32WaveGenerator.h" />
<ClInclude Include="..\..\..\devices\sound\munt\MemoryRegion.h" />
<ClInclude Include="..\..\..\devices\sound\munt\MidiEventQueue.h" />
<ClInclude Include="..\..\..\devices\sound\munt\MidiStreamParser.h" />
<ClInclude Include="..\..\..\devices\sound\munt\mmath.h" />
<ClInclude Include="..\..\..\devices\sound\munt\mt32emu.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Part.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Partial.h" />
<ClInclude Include="..\..\..\devices\sound\munt\PartialManager.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Poly.h" />
<ClInclude Include="..\..\..\devices\sound\munt\ROMInfo.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Structures.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Synth.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Tables.h" />
<ClInclude Include="..\..\..\devices\sound\munt\TVA.h" />
<ClInclude Include="..\..\..\devices\sound\munt\TVF.h" />
<ClInclude Include="..\..\..\devices\sound\munt\TVP.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Types.h" />
<ClInclude Include="..\..\..\devices\sound\nukedopl.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\envelope.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\extfilt.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\filter.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\pot.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\sid.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\siddefs-fp.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\voice.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\wave.h" />
<ClInclude Include="..\..\..\devices\sound\snd_ad1848.h" />
<ClInclude Include="..\..\..\devices\sound\snd_dbopl.h" />
<ClInclude Include="..\..\..\devices\sound\snd_emu8k.h" />
<ClInclude Include="..\..\..\devices\sound\snd_lpt_dac.h" />
<ClInclude Include="..\..\..\devices\sound\snd_lpt_dss.h" />
<ClInclude Include="..\..\..\devices\sound\snd_mpu401.h" />
<ClInclude Include="..\..\..\devices\sound\snd_opl.h" />
<ClInclude Include="..\..\..\devices\sound\snd_resid.h" />
<ClInclude Include="..\..\..\devices\sound\snd_sb.h" />
<ClInclude Include="..\..\..\devices\sound\snd_sb_dsp.h" />
<ClInclude Include="..\..\..\devices\sound\snd_sn76489.h" />
<ClInclude Include="..\..\..\devices\sound\snd_speaker.h" />
<ClInclude Include="..\..\..\devices\sound\snd_ym7128.h" />
<ClInclude Include="..\..\..\devices\sound\sound.h" />
<ClInclude Include="..\..\..\devices\system\dma.h" />
<ClInclude Include="..\..\..\devices\system\i82335.h" />
<ClInclude Include="..\..\..\devices\system\intel.h" />
<ClInclude Include="..\..\..\devices\system\intel_flash.h" />
<ClInclude Include="..\..\..\devices\system\intel_piix.h" />
<ClInclude Include="..\..\..\devices\system\intel_sio.h" />
<ClInclude Include="..\..\..\devices\system\mca.h" />
<ClInclude Include="..\..\..\devices\system\memregs.h" />
<ClInclude Include="..\..\..\devices\system\nmi.h" />
<ClInclude Include="..\..\..\devices\system\nvr_ps2.h" />
<ClInclude Include="..\..\..\devices\system\pci.h" />
<ClInclude Include="..\..\..\devices\system\pic.h" />
<ClInclude Include="..\..\..\devices\system\pit.h" />
<ClInclude Include="..\..\..\devices\system\ppi.h" />
<ClInclude Include="..\..\..\emu.h" />
<ClInclude Include="..\..\..\devices\floppy\fdc.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_86f.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_common.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_fdi.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_imd.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_img.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_json.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_td0.h" />
<ClInclude Include="..\..\..\devices\floppy\fdi2raw.h" />
<ClInclude Include="..\..\..\devices\floppy\lzf\config.h" />
<ClInclude Include="..\..\..\devices\floppy\lzf\crc32.h" />
<ClInclude Include="..\..\..\devices\floppy\lzf\lzf.h" />
<ClInclude Include="..\..\..\devices\floppy\lzf\lzfP.h" />
<ClInclude Include="..\..\..\devices\input\game\joystick.h" />
<ClInclude Include="..\..\..\devices\input\keyboard.h" />
<ClInclude Include="..\..\..\devices\input\mouse.h" />
<ClInclude Include="..\..\..\io.h" />
<ClInclude Include="..\..\..\machines\machine.h" />
<ClInclude Include="..\..\..\machines\m_at_t3100e.h" />
<ClInclude Include="..\..\..\machines\m_xt_t1000.h" />
<ClInclude Include="..\..\..\machines\m_xt_xi8088.h" />
<ClInclude Include="..\..\..\mem.h" />
<ClInclude Include="..\..\..\devices\network\bswap.h" />
<ClInclude Include="..\..\..\devices\network\network.h" />
<ClInclude Include="..\..\..\devices\network\net_ne2000.h" />
<ClInclude Include="..\..\..\nvr.h" />
<ClInclude Include="..\..\..\plat.h" />
<ClInclude Include="..\..\..\devices\ports\game.h" />
<ClInclude Include="..\..\..\devices\ports\game_dev.h" />
<ClInclude Include="..\..\..\devices\ports\parallel.h" />
<ClInclude Include="..\..\..\devices\ports\parallel_dev.h" />
<ClInclude Include="..\..\..\devices\ports\serial.h" />
<ClInclude Include="..\..\..\random.h" />
<ClInclude Include="..\..\..\rom.h" />
<ClInclude Include="..\..\..\devices\sound\munt\c_interface\cpp_interface.h" />
<ClInclude Include="..\..\..\devices\sound\munt\c_interface\c_interface.h" />
<ClInclude Include="..\..\..\devices\sound\munt\c_interface\c_types.h" />
<ClInclude Include="..\..\..\devices\sound\munt\sha1\sha1.h" />
<ClInclude Include="..\..\..\timer.h" />
<ClInclude Include="..\..\..\ui\ui.h" />
<ClInclude Include="..\..\..\ui\ui_resource.h" />
<ClInclude Include="..\..\..\version.h" />
<ClInclude Include="..\..\..\devices\video\video.h" />
<ClInclude Include="..\..\..\devices\video\vid_ati68860_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_ati_eeprom.h" />
<ClInclude Include="..\..\..\devices\video\vid_bt485_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_cga.h" />
<ClInclude Include="..\..\..\devices\video\vid_cga_comp.h" />
<ClInclude Include="..\..\..\devices\video\vid_ega.h" />
<ClInclude Include="..\..\..\devices\video\vid_ega_render.h" />
<ClInclude Include="..\..\..\devices\video\vid_icd2061.h" />
<ClInclude Include="..\..\..\devices\video\vid_ics2595.h" />
<ClInclude Include="..\..\..\devices\video\vid_sc1502x_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_sdac_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_stg_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_svga.h" />
<ClInclude Include="..\..\..\devices\video\vid_svga_render.h" />
<ClInclude Include="..\..\..\devices\video\vid_tkd8001_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_voodoo_codegen_x86-64.h" />
<ClInclude Include="..\..\..\devices\video\vid_voodoo_codegen_x86.h" />
<ClInclude Include="..\..\..\devices\video\vid_voodoo_dither.h" />
<ClInclude Include="..\..\..\win\plat_dir.h" />
<ClInclude Include="..\..\..\win\resource.h" />
<ClInclude Include="..\..\..\win\win.h" />
<ClInclude Include="..\..\win_opendir.h" />
<ClInclude Include="..\..\win_sdl.h" />
<ClInclude Include="..\..\win_settings_disk.h" />
<ClInclude Include="..\..\win_settings_floppy.h" />
<ClInclude Include="..\..\win_settings_input.h" />
<ClInclude Include="..\..\win_settings_machine.h" />
<ClInclude Include="..\..\win_settings_network.h" />
<ClInclude Include="..\..\win_settings_periph.h" />
<ClInclude Include="..\..\win_settings_ports.h" />
<ClInclude Include="..\..\win_settings_remov.h" />
<ClInclude Include="..\..\win_settings_sound.h" />
<ClInclude Include="..\..\win_settings_video.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\VARCem.rc">
<ShowProgress Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ShowProgress>
<ShowProgress Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ShowProgress>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_MSC_VER</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_MSC_VER</PreprocessorDefinitions>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\VARCem.mpp">
<FileType>Document</FileType>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Generating Manifest file...</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Generating Manifest file...</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Generating Manifest file...</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Generating Manifest file...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">VARCem.manifest</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">VARCem.manifest</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">VARCem.manifest</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">VARCem.manifest</Outputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">VARCem.rc</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">VARCem.rc</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">VARCem.rc</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">VARCem.rc</AdditionalInputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cl -nologo -EP %(FullPath) &gt; $(SolutionDir)..\..\%(Outputs)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cl -nologo -EP %(FullPath) &gt; $(SolutionDir)..\..\%(Outputs)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -nologo -EP %(FullPath) &gt; $(SolutionDir)..\..\%(Outputs)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -nologo -EP %(FullPath) &gt; $(SolutionDir)..\..\%(Outputs)</Command>
</CustomBuild>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>14.0</VCProjectVersion>
<ProjectGuid>{6E445F28-CA8F-430F-8CCF-C59C53516AC5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>VARCem</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="global.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="global.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="global.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="global.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;iphlpapi.lib;psapi.lib;Comctl32.lib;DInput8.lib;d3d9.lib;d3dx9.lib;ddraw.lib;dxguid.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SKIP_MANIFEST</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;iphlpapi.lib;psapi.lib;Comctl32.lib;DInput8.lib;d3d9.lib;d3dx9.lib;ddraw.lib;dxguid.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;iphlpapi.lib;psapi.lib;Comctl32.lib;DInput8.lib;d3d9.lib;d3dx9.lib;ddraw.lib;dxguid.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SKIP_MANIFEST</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;iphlpapi.lib;psapi.lib;Comctl32.lib;DInput8.lib;d3d9.lib;d3dx9.lib;ddraw.lib;dxguid.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommandArguments>-L varcem.log</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerCommandArguments>-L varcem.log</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>-L varcem.log</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommandArguments>-L varcem.log</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>$(ProjectDir)\..\Include;$(ProjectDir)\..\..\mingw\include;$(ProjectDir)\..\..\mingw\include\pcap;P:\SDL\include\msvc;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>_USE_MATH_DEFINES;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;USE_DYNAREC;USE_OPENAL;USE_SDL</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

View File

@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VARCem", "VARCem.vcxproj", "{6E445F28-CA8F-430F-8CCF-C59C53516AC5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Debug|x64.ActiveCfg = Debug|x64
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Debug|x64.Build.0 = Debug|x64
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Debug|x86.ActiveCfg = Debug|Win32
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Debug|x86.Build.0 = Debug|Win32
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Release|x64.ActiveCfg = Release|x64
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Release|x64.Build.0 = Release|x64
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Release|x86.ActiveCfg = Release|Win32
{6E445F28-CA8F-430F-8CCF-C59C53516AC5}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {85A5962B-0218-472C-A361-6E55D8FE7E9B}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,783 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\devices\cdrom\cdrom_speed.c" />
<ClCompile Include="..\..\..\devices\misc\bugger.c" />
<ClCompile Include="..\..\..\devices\cdrom\cdrom.c" />
<ClCompile Include="..\..\..\devices\cdrom\cdrom_dosbox.cpp" />
<ClCompile Include="..\..\..\devices\cdrom\cdrom_image.cpp" />
<ClCompile Include="..\..\..\devices\cdrom\cdrom_null.c" />
<ClCompile Include="..\..\..\config.c" />
<ClCompile Include="..\..\..\cpu\386.c" />
<ClCompile Include="..\..\..\cpu\386_dynarec.c" />
<ClCompile Include="..\..\..\cpu\386_dynarec_ops.c" />
<ClCompile Include="..\..\..\cpu\808x.c" />
<ClCompile Include="..\..\..\cpu\codegen.c" />
<ClCompile Include="..\..\..\cpu\codegen_ops.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_486.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_686.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_common.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_pentium.c" />
<ClCompile Include="..\..\..\cpu\codegen_timing_winchip.c" />
<ClCompile Include="..\..\..\cpu\codegen_x86-64.c" />
<ClCompile Include="..\..\..\cpu\codegen_x86.c" />
<ClCompile Include="..\..\..\cpu\cpu.c" />
<ClCompile Include="..\..\..\cpu\cpu_table.c" />
<ClCompile Include="..\..\..\cpu\x86seg.c" />
<ClCompile Include="..\..\..\cpu\x87.c" />
<ClCompile Include="..\..\..\device.c" />
<ClCompile Include="..\..\..\devices\disk\hdc.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_esdi_at.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_esdi_mca.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_ide_ata.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_ide_xta.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_st506_at.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_st506_xt.c" />
<ClCompile Include="..\..\..\devices\disk\hdc_xtide.c" />
<ClCompile Include="..\..\..\devices\disk\hdd.c" />
<ClCompile Include="..\..\..\devices\disk\hdd_image.c" />
<ClCompile Include="..\..\..\devices\disk\hdd_table.c" />
<ClCompile Include="..\..\..\devices\disk\zip.c" />
<ClCompile Include="..\..\..\devices\misc\isamem.c" />
<ClCompile Include="..\..\..\devices\misc\isartc.c" />
<ClCompile Include="..\..\..\devices\network\net_3c503.c" />
<ClCompile Include="..\..\..\devices\network\net_dp8390.c" />
<ClCompile Include="..\..\..\devices\network\net_wd80x3.c" />
<ClCompile Include="..\..\..\devices\network\slirp\bootp.c" />
<ClCompile Include="..\..\..\devices\network\slirp\cksum.c" />
<ClCompile Include="..\..\..\devices\network\slirp\debug.c" />
<ClCompile Include="..\..\..\devices\network\slirp\if.c" />
<ClCompile Include="..\..\..\devices\network\slirp\ip_icmp.c" />
<ClCompile Include="..\..\..\devices\network\slirp\ip_input.c" />
<ClCompile Include="..\..\..\devices\network\slirp\ip_output.c" />
<ClCompile Include="..\..\..\devices\network\slirp\mbuf.c" />
<ClCompile Include="..\..\..\devices\network\slirp\slirp_misc.c" />
<ClCompile Include="..\..\..\devices\network\slirp\queue.c" />
<ClCompile Include="..\..\..\devices\network\slirp\sbuf.c" />
<ClCompile Include="..\..\..\devices\network\slirp\slirp.c" />
<ClCompile Include="..\..\..\devices\network\slirp\socket.c" />
<ClCompile Include="..\..\..\devices\network\slirp\tcp_input.c" />
<ClCompile Include="..\..\..\devices\network\slirp\tcp_output.c" />
<ClCompile Include="..\..\..\devices\network\slirp\tcp_subr.c" />
<ClCompile Include="..\..\..\devices\network\slirp\tcp_timer.c" />
<ClCompile Include="..\..\..\devices\network\slirp\udp.c" />
<ClCompile Include="..\..\..\devices\printer\prt_cpmap.c" />
<ClCompile Include="..\..\..\devices\printer\prt_escp.c" />
<ClCompile Include="..\..\..\devices\printer\prt_text.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_aha154x.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_buslogic.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_device.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_disk.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_ncr5380.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_ncr53c810.c" />
<ClCompile Include="..\..\..\devices\scsi\scsi_x54x.c" />
<ClCompile Include="..\..\..\devices\sio\sio_detect.c" />
<ClCompile Include="..\..\..\devices\sio\sio_fdc37c669.c" />
<ClCompile Include="..\..\..\devices\sio\sio_fdc37c66x.c" />
<ClCompile Include="..\..\..\devices\sio\sio_fdc37c93x.c" />
<ClCompile Include="..\..\..\devices\sio\sio_pc87306.c" />
<ClCompile Include="..\..\..\devices\sio\sio_um8669f.c" />
<ClCompile Include="..\..\..\devices\sio\sio_w83877f.c" />
<ClCompile Include="..\..\..\devices\sound\dbopl.cpp" />
<ClCompile Include="..\..\..\devices\sound\midi.c" />
<ClCompile Include="..\..\..\devices\sound\midi_fluidsynth.c" />
<ClCompile Include="..\..\..\devices\sound\midi_mt32.c" />
<ClCompile Include="..\..\..\devices\sound\midi_system.c" />
<ClCompile Include="..\..\..\devices\sound\munt\Analog.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\BReverbModel.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\File.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\FileStream.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\LA32FloatWaveGenerator.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\LA32Ramp.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\LA32WaveGenerator.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\MidiStreamParser.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Part.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Partial.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\PartialManager.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Poly.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\ROMInfo.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\SampleRateConverter_dummy.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Synth.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\Tables.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\TVA.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\TVF.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\TVP.cpp" />
<ClCompile Include="..\..\..\devices\sound\nukedopl.cpp" />
<ClCompile Include="..\..\..\devices\sound\openal.c" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\convolve-sse.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\convolve.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\envelope.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\extfilt.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\filter.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\pot.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\sid.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\voice.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave6581_PST.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave6581_PS_.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave6581_P_T.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave6581__ST.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave8580_PST.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave8580_PS_.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave8580_P_T.cpp" />
<ClCompile Include="..\..\..\devices\sound\resid-fp\wave8580__ST.cpp" />
<ClCompile Include="..\..\..\devices\sound\snd_ad1848.c" />
<ClCompile Include="..\..\..\devices\sound\snd_adlib.c" />
<ClCompile Include="..\..\..\devices\sound\snd_adlibgold.c" />
<ClCompile Include="..\..\..\devices\sound\snd_audiopci.c" />
<ClCompile Include="..\..\..\devices\sound\snd_cms.c" />
<ClCompile Include="..\..\..\devices\sound\snd_dbopl.cpp" />
<ClCompile Include="..\..\..\devices\sound\snd_emu8k.c" />
<ClCompile Include="..\..\..\devices\sound\snd_gus.c" />
<ClCompile Include="..\..\..\devices\sound\snd_lpt_dac.c" />
<ClCompile Include="..\..\..\devices\sound\snd_lpt_dss.c" />
<ClCompile Include="..\..\..\devices\sound\snd_mpu401.c" />
<ClCompile Include="..\..\..\devices\sound\snd_opl.c" />
<ClCompile Include="..\..\..\devices\sound\snd_pas16.c" />
<ClCompile Include="..\..\..\devices\sound\snd_resid.cpp" />
<ClCompile Include="..\..\..\devices\sound\snd_sb.c" />
<ClCompile Include="..\..\..\devices\sound\snd_sb_dsp.c" />
<ClCompile Include="..\..\..\devices\sound\snd_sn76489.c" />
<ClCompile Include="..\..\..\devices\sound\snd_speaker.c" />
<ClCompile Include="..\..\..\devices\sound\snd_ssi2001.c" />
<ClCompile Include="..\..\..\devices\sound\snd_wss.c" />
<ClCompile Include="..\..\..\devices\sound\snd_ym7128.c" />
<ClCompile Include="..\..\..\devices\sound\sound.c" />
<ClCompile Include="..\..\..\devices\sound\sound_dev.c" />
<ClCompile Include="..\..\..\devices\system\dma.c" />
<ClCompile Include="..\..\..\devices\system\i82335.c" />
<ClCompile Include="..\..\..\devices\system\intel.c" />
<ClCompile Include="..\..\..\devices\system\intel_flash.c" />
<ClCompile Include="..\..\..\devices\system\intel_piix.c" />
<ClCompile Include="..\..\..\devices\system\intel_sio.c" />
<ClCompile Include="..\..\..\devices\system\mca.c" />
<ClCompile Include="..\..\..\devices\system\mcr.c" />
<ClCompile Include="..\..\..\devices\system\memregs.c" />
<ClCompile Include="..\..\..\devices\system\nmi.c" />
<ClCompile Include="..\..\..\devices\system\nvr_at.c" />
<ClCompile Include="..\..\..\devices\system\nvr_ps2.c" />
<ClCompile Include="..\..\..\devices\system\pci.c" />
<ClCompile Include="..\..\..\devices\system\pic.c" />
<ClCompile Include="..\..\..\devices\system\pit.c" />
<ClCompile Include="..\..\..\devices\system\ppi.c" />
<ClCompile Include="..\..\..\devices\floppy\fdc.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_86f.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_common.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_fdi.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_imd.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_img.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_json.c" />
<ClCompile Include="..\..\..\devices\floppy\fdd_td0.c" />
<ClCompile Include="..\..\..\devices\floppy\fdi2raw.c" />
<ClCompile Include="..\..\..\devices\floppy\lzf\lzf_c.c" />
<ClCompile Include="..\..\..\devices\floppy\lzf\lzf_d.c" />
<ClCompile Include="..\..\..\devices\input\game\joystick.c" />
<ClCompile Include="..\..\..\devices\input\game\js_ch_fs_pro.c" />
<ClCompile Include="..\..\..\devices\input\game\js_standard.c" />
<ClCompile Include="..\..\..\devices\input\game\js_sw_pad.c" />
<ClCompile Include="..\..\..\devices\input\game\js_tm_fcs.c" />
<ClCompile Include="..\..\..\devices\input\keyboard.c" />
<ClCompile Include="..\..\..\devices\input\keyboard_at.c" />
<ClCompile Include="..\..\..\devices\input\keyboard_xt.c" />
<ClCompile Include="..\..\..\devices\input\mouse.c" />
<ClCompile Include="..\..\..\devices\input\mouse_bus.c" />
<ClCompile Include="..\..\..\devices\input\mouse_ps2.c" />
<ClCompile Include="..\..\..\devices\input\mouse_serial.c" />
<ClCompile Include="..\..\..\devices\video\video_dev.c" />
<ClCompile Include="..\..\..\devices\video\vid_bt48x_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_cga_compaq.c" />
<ClCompile Include="..\..\..\io.c" />
<ClCompile Include="..\..\..\machines\machine.c" />
<ClCompile Include="..\..\..\machines\machine_table.c" />
<ClCompile Include="..\..\..\machines\m_amstrad.c" />
<ClCompile Include="..\..\..\machines\m_at.c" />
<ClCompile Include="..\..\..\machines\m_at_4x0.c" />
<ClCompile Include="..\..\..\machines\m_at_ali1429.c" />
<ClCompile Include="..\..\..\machines\m_at_commodore.c" />
<ClCompile Include="..\..\..\machines\m_at_compaq.c" />
<ClCompile Include="..\..\..\machines\m_at_headland.c" />
<ClCompile Include="..\..\..\machines\m_at_neat.c" />
<ClCompile Include="..\..\..\machines\m_at_opti495.c" />
<ClCompile Include="..\..\..\machines\m_at_scat.c" />
<ClCompile Include="..\..\..\machines\m_at_sis_85c471.c" />
<ClCompile Include="..\..\..\machines\m_at_sis_85c496.c" />
<ClCompile Include="..\..\..\machines\m_at_t3100e.c" />
<ClCompile Include="..\..\..\machines\m_at_t3100e_vid.c" />
<ClCompile Include="..\..\..\machines\m_at_wd76c10.c" />
<ClCompile Include="..\..\..\machines\m_europc.c" />
<ClCompile Include="..\..\..\machines\m_olivetti_m24.c" />
<ClCompile Include="..\..\..\machines\m_pcjr.c" />
<ClCompile Include="..\..\..\machines\m_ps1.c" />
<ClCompile Include="..\..\..\machines\m_ps1_hdc.c" />
<ClCompile Include="..\..\..\machines\m_ps2_isa.c" />
<ClCompile Include="..\..\..\machines\m_ps2_mca.c" />
<ClCompile Include="..\..\..\machines\m_tandy.c" />
<ClCompile Include="..\..\..\machines\m_xt.c" />
<ClCompile Include="..\..\..\machines\m_xt_compaq.c" />
<ClCompile Include="..\..\..\machines\m_xt_laserxt.c" />
<ClCompile Include="..\..\..\machines\m_xt_t1000.c" />
<ClCompile Include="..\..\..\machines\m_xt_t1000_vid.c" />
<ClCompile Include="..\..\..\machines\m_xt_xi8088.c" />
<ClCompile Include="..\..\..\mem.c" />
<ClCompile Include="..\..\..\devices\network\network.c" />
<ClCompile Include="..\..\..\devices\network\net_ne2000.c" />
<ClCompile Include="..\..\..\devices\network\net_pcap.c" />
<ClCompile Include="..\..\..\devices\network\net_slirp.c" />
<ClCompile Include="..\..\..\misc.c" />
<ClCompile Include="..\..\..\nvr.c" />
<ClCompile Include="..\..\..\pc.c" />
<ClCompile Include="..\..\..\devices\ports\game.c" />
<ClCompile Include="..\..\..\devices\ports\game_dev.c" />
<ClCompile Include="..\..\..\devices\ports\parallel.c" />
<ClCompile Include="..\..\..\devices\ports\parallel_dev.c" />
<ClCompile Include="..\..\..\devices\ports\serial.c" />
<ClCompile Include="..\..\..\png.c" />
<ClCompile Include="..\..\..\random.c" />
<ClCompile Include="..\..\..\rom.c" />
<ClCompile Include="..\..\..\rom_load.c" />
<ClCompile Include="..\..\..\devices\sound\munt\c_interface\c_interface.cpp" />
<ClCompile Include="..\..\..\devices\sound\munt\sha1\sha1.cpp" />
<ClCompile Include="..\..\..\timer.c" />
<ClCompile Include="..\..\..\ui\ui_cdrom.c" />
<ClCompile Include="..\..\..\ui\ui_lang.c" />
<ClCompile Include="..\..\..\ui\ui_main.c" />
<ClCompile Include="..\..\..\ui\ui_misc.c" />
<ClCompile Include="..\..\..\ui\ui_new_image.c" />
<ClCompile Include="..\..\..\ui\ui_stbar.c" />
<ClCompile Include="..\..\..\devices\video\video.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati18800.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati28800.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati68860_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati_eeprom.c" />
<ClCompile Include="..\..\..\devices\video\vid_ati_mach64.c" />
<ClCompile Include="..\..\..\devices\video\vid_cga.c" />
<ClCompile Include="..\..\..\devices\video\vid_cga_comp.c" />
<ClCompile Include="..\..\..\devices\video\vid_cl54xx.c" />
<ClCompile Include="..\..\..\devices\video\vid_colorplus.c" />
<ClCompile Include="..\..\..\devices\video\vid_ega.c" />
<ClCompile Include="..\..\..\devices\video\vid_ega_render.c" />
<ClCompile Include="..\..\..\devices\video\vid_et4000.c" />
<ClCompile Include="..\..\..\devices\video\vid_et4000w32.c" />
<ClCompile Include="..\..\..\devices\video\vid_genius.c" />
<ClCompile Include="..\..\..\devices\video\vid_hercules.c" />
<ClCompile Include="..\..\..\devices\video\vid_herculesplus.c" />
<ClCompile Include="..\..\..\devices\video\vid_icd2061.c" />
<ClCompile Include="..\..\..\devices\video\vid_ics2595.c" />
<ClCompile Include="..\..\..\devices\video\vid_incolor.c" />
<ClCompile Include="..\..\..\devices\video\vid_mda.c" />
<ClCompile Include="..\..\..\devices\video\vid_oak_oti.c" />
<ClCompile Include="..\..\..\devices\video\vid_paradise.c" />
<ClCompile Include="..\..\..\devices\video\vid_s3.c" />
<ClCompile Include="..\..\..\devices\video\vid_s3_virge.c" />
<ClCompile Include="..\..\..\devices\video\vid_sc1502x_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_sdac_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_stg_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_svga.c" />
<ClCompile Include="..\..\..\devices\video\vid_svga_render.c" />
<ClCompile Include="..\..\..\devices\video\vid_tgui9440.c" />
<ClCompile Include="..\..\..\devices\video\vid_ti_cf62011.c" />
<ClCompile Include="..\..\..\devices\video\vid_tkd8001_ramdac.c" />
<ClCompile Include="..\..\..\devices\video\vid_tvga.c" />
<ClCompile Include="..\..\..\devices\video\vid_vga.c" />
<ClCompile Include="..\..\..\devices\video\vid_voodoo.c" />
<ClCompile Include="..\..\..\devices\video\vid_wy700.c" />
<ClCompile Include="..\..\..\ui\ui_vidapi.c" />
<ClCompile Include="..\..\..\win\win.c" />
<ClCompile Include="..\..\..\win\win_about.c" />
<ClCompile Include="..\..\..\win\win_cdrom.c" />
<ClCompile Include="..\..\..\win\win_crashdump.c" />
<ClCompile Include="..\..\..\win\win_d3d.cpp" />
<ClCompile Include="..\..\..\win\win_ddraw.cpp" />
<ClCompile Include="..\..\..\win\win_devconf.c" />
<ClCompile Include="..\..\..\win\win_dialog.c" />
<ClCompile Include="..\..\..\win\win_dynld.c" />
<ClCompile Include="..\..\..\win\win_joystick.cpp" />
<ClCompile Include="..\..\..\win\win_keyboard.c" />
<ClCompile Include="..\..\..\win\win_midi.c" />
<ClCompile Include="..\..\..\win\win_mouse.cpp" />
<ClCompile Include="..\..\..\win\win_opendir.c" />
<ClCompile Include="..\..\..\win\win_settings.c" />
<ClCompile Include="..\..\..\win\win_snd_gain.c" />
<ClCompile Include="..\..\..\win\win_thread.c" />
<ClCompile Include="..\..\..\win\win_ui.c" />
<ClCompile Include="..\..\win_lang.c" />
<ClCompile Include="..\..\win_new_image.c" />
<ClCompile Include="..\..\win_sdl.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\devices\misc\bugger.h" />
<ClInclude Include="..\..\..\devices\cdrom\cdrom.h" />
<ClInclude Include="..\..\..\devices\cdrom\cdrom_dosbox.h" />
<ClInclude Include="..\..\..\devices\cdrom\cdrom_image.h" />
<ClInclude Include="..\..\..\devices\cdrom\cdrom_null.h" />
<ClInclude Include="..\..\..\config.h" />
<ClInclude Include="..\..\..\cpu\386.h" />
<ClInclude Include="..\..\..\cpu\386_common.h" />
<ClInclude Include="..\..\..\cpu\386_ops.h" />
<ClInclude Include="..\..\..\cpu\codegen.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_arith.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_fpu.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_jump.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_logic.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_misc.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_mmx.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_mov.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_shift.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_stack.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_x86-64.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_x86.h" />
<ClInclude Include="..\..\..\cpu\codegen_ops_xchg.h" />
<ClInclude Include="..\..\..\cpu\codegen_timing_common.h" />
<ClInclude Include="..\..\..\cpu\codegen_x86-64.h" />
<ClInclude Include="..\..\..\cpu\codegen_x86.h" />
<ClInclude Include="..\..\..\cpu\cpu.h" />
<ClInclude Include="..\..\..\cpu\x86.h" />
<ClInclude Include="..\..\..\cpu\x86seg.h" />
<ClInclude Include="..\..\..\cpu\x86_flags.h" />
<ClInclude Include="..\..\..\cpu\x86_ops.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_amd.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_arith.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_atomic.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_bcd.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_bit.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_bitscan.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_call.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_flag.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_fpu.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_i686.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_inc_dec.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_int.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_io.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_jump.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_misc.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_arith.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_cmp.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_logic.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_mov.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_pack.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mmx_shift.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mov.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_movx.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mov_ctrl.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mov_seg.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_msr.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_mul.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_pmode.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_prefix.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_rep.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_ret.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_set.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_shift.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_stack.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_string.h" />
<ClInclude Include="..\..\..\cpu\x86_ops_xchg.h" />
<ClInclude Include="..\..\..\cpu\x87.h" />
<ClInclude Include="..\..\..\cpu\x87_ops.h" />
<ClInclude Include="..\..\..\cpu\x87_ops_arith.h" />
<ClInclude Include="..\..\..\cpu\x87_ops_loadstore.h" />
<ClInclude Include="..\..\..\cpu\x87_ops_misc.h" />
<ClInclude Include="..\..\..\device.h" />
<ClInclude Include="..\..\..\devices\disk\hdc.h" />
<ClInclude Include="..\..\..\devices\disk\hdc_ide.h" />
<ClInclude Include="..\..\..\devices\disk\hdd.h" />
<ClInclude Include="..\..\..\devices\disk\zip.h" />
<ClInclude Include="..\..\..\devices\misc\isamem.h" />
<ClInclude Include="..\..\..\devices\misc\isartc.h" />
<ClInclude Include="..\..\..\devices\network\net_3com.h" />
<ClInclude Include="..\..\..\devices\network\net_dp8390.h" />
<ClInclude Include="..\..\..\devices\network\net_wd80x3.h" />
<ClInclude Include="..\..\..\devices\network\slirp\bootp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\ctl.h" />
<ClInclude Include="..\..\..\devices\network\slirp\debug.h" />
<ClInclude Include="..\..\..\devices\network\slirp\icmp_var.h" />
<ClInclude Include="..\..\..\devices\network\slirp\if.h" />
<ClInclude Include="..\..\..\devices\network\slirp\ip.h" />
<ClInclude Include="..\..\..\devices\network\slirp\ip_icmp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\libslirp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\main.h" />
<ClInclude Include="..\..\..\devices\network\slirp\mbuf.h" />
<ClInclude Include="..\..\..\devices\network\slirp\misc.h" />
<ClInclude Include="..\..\..\devices\network\slirp\queue.h" />
<ClInclude Include="..\..\..\devices\network\slirp\sbuf.h" />
<ClInclude Include="..\..\..\devices\network\slirp\slirp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\slirp_config.h" />
<ClInclude Include="..\..\..\devices\network\slirp\socket.h" />
<ClInclude Include="..\..\..\devices\network\slirp\tcp.h" />
<ClInclude Include="..\..\..\devices\network\slirp\tcpip.h" />
<ClInclude Include="..\..\..\devices\network\slirp\tcp_timer.h" />
<ClInclude Include="..\..\..\devices\network\slirp\tcp_var.h" />
<ClInclude Include="..\..\..\devices\network\slirp\udp.h" />
<ClInclude Include="..\..\..\devices\printer\printer.h" />
<ClInclude Include="..\..\..\devices\scsi\queue.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_aha154x.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_buslogic.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_device.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_disk.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_ncr5380.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_ncr53c810.h" />
<ClInclude Include="..\..\..\devices\scsi\scsi_x54x.h" />
<ClInclude Include="..\..\..\devices\sio\sio.h" />
<ClInclude Include="..\..\..\devices\sound\dbopl.h" />
<ClInclude Include="..\..\..\devices\sound\filters.h" />
<ClInclude Include="..\..\..\devices\sound\midi.h" />
<ClInclude Include="..\..\..\devices\sound\midi_fluidsynth.h" />
<ClInclude Include="..\..\..\devices\sound\midi_mt32.h" />
<ClInclude Include="..\..\..\devices\sound\midi_system.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Analog.h" />
<ClInclude Include="..\..\..\devices\sound\munt\BReverbModel.h" />
<ClInclude Include="..\..\..\devices\sound\munt\config.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Enumerations.h" />
<ClInclude Include="..\..\..\devices\sound\munt\File.h" />
<ClInclude Include="..\..\..\devices\sound\munt\FileStream.h" />
<ClInclude Include="..\..\..\devices\sound\munt\globals.h" />
<ClInclude Include="..\..\..\devices\sound\munt\internals.h" />
<ClInclude Include="..\..\..\devices\sound\munt\LA32FloatWaveGenerator.h" />
<ClInclude Include="..\..\..\devices\sound\munt\LA32Ramp.h" />
<ClInclude Include="..\..\..\devices\sound\munt\LA32WaveGenerator.h" />
<ClInclude Include="..\..\..\devices\sound\munt\MemoryRegion.h" />
<ClInclude Include="..\..\..\devices\sound\munt\MidiEventQueue.h" />
<ClInclude Include="..\..\..\devices\sound\munt\MidiStreamParser.h" />
<ClInclude Include="..\..\..\devices\sound\munt\mmath.h" />
<ClInclude Include="..\..\..\devices\sound\munt\mt32emu.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Part.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Partial.h" />
<ClInclude Include="..\..\..\devices\sound\munt\PartialManager.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Poly.h" />
<ClInclude Include="..\..\..\devices\sound\munt\ROMInfo.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Structures.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Synth.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Tables.h" />
<ClInclude Include="..\..\..\devices\sound\munt\TVA.h" />
<ClInclude Include="..\..\..\devices\sound\munt\TVF.h" />
<ClInclude Include="..\..\..\devices\sound\munt\TVP.h" />
<ClInclude Include="..\..\..\devices\sound\munt\Types.h" />
<ClInclude Include="..\..\..\devices\sound\nukedopl.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\envelope.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\extfilt.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\filter.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\pot.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\sid.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\siddefs-fp.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\voice.h" />
<ClInclude Include="..\..\..\devices\sound\resid-fp\wave.h" />
<ClInclude Include="..\..\..\devices\sound\snd_ad1848.h" />
<ClInclude Include="..\..\..\devices\sound\snd_dbopl.h" />
<ClInclude Include="..\..\..\devices\sound\snd_emu8k.h" />
<ClInclude Include="..\..\..\devices\sound\snd_lpt_dac.h" />
<ClInclude Include="..\..\..\devices\sound\snd_lpt_dss.h" />
<ClInclude Include="..\..\..\devices\sound\snd_mpu401.h" />
<ClInclude Include="..\..\..\devices\sound\snd_opl.h" />
<ClInclude Include="..\..\..\devices\sound\snd_resid.h" />
<ClInclude Include="..\..\..\devices\sound\snd_sb.h" />
<ClInclude Include="..\..\..\devices\sound\snd_sb_dsp.h" />
<ClInclude Include="..\..\..\devices\sound\snd_sn76489.h" />
<ClInclude Include="..\..\..\devices\sound\snd_speaker.h" />
<ClInclude Include="..\..\..\devices\sound\snd_ym7128.h" />
<ClInclude Include="..\..\..\devices\sound\sound.h" />
<ClInclude Include="..\..\..\devices\system\dma.h" />
<ClInclude Include="..\..\..\devices\system\i82335.h" />
<ClInclude Include="..\..\..\devices\system\intel.h" />
<ClInclude Include="..\..\..\devices\system\intel_flash.h" />
<ClInclude Include="..\..\..\devices\system\intel_piix.h" />
<ClInclude Include="..\..\..\devices\system\intel_sio.h" />
<ClInclude Include="..\..\..\devices\system\mca.h" />
<ClInclude Include="..\..\..\devices\system\memregs.h" />
<ClInclude Include="..\..\..\devices\system\nmi.h" />
<ClInclude Include="..\..\..\devices\system\nvr_ps2.h" />
<ClInclude Include="..\..\..\devices\system\pci.h" />
<ClInclude Include="..\..\..\devices\system\pic.h" />
<ClInclude Include="..\..\..\devices\system\pit.h" />
<ClInclude Include="..\..\..\devices\system\ppi.h" />
<ClInclude Include="..\..\..\devices\video\vid_bt48x_ramdac.h" />
<ClInclude Include="..\..\..\emu.h" />
<ClInclude Include="..\..\..\devices\floppy\fdc.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_86f.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_common.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_fdi.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_imd.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_img.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_json.h" />
<ClInclude Include="..\..\..\devices\floppy\fdd_td0.h" />
<ClInclude Include="..\..\..\devices\floppy\fdi2raw.h" />
<ClInclude Include="..\..\..\devices\floppy\lzf\config.h" />
<ClInclude Include="..\..\..\devices\floppy\lzf\crc32.h" />
<ClInclude Include="..\..\..\devices\floppy\lzf\lzf.h" />
<ClInclude Include="..\..\..\devices\floppy\lzf\lzfP.h" />
<ClInclude Include="..\..\..\devices\input\game\joystick.h" />
<ClInclude Include="..\..\..\devices\input\keyboard.h" />
<ClInclude Include="..\..\..\devices\input\mouse.h" />
<ClInclude Include="..\..\..\io.h" />
<ClInclude Include="..\..\..\machines\machine.h" />
<ClInclude Include="..\..\..\machines\m_at_t3100e.h" />
<ClInclude Include="..\..\..\machines\m_xt_t1000.h" />
<ClInclude Include="..\..\..\machines\m_xt_xi8088.h" />
<ClInclude Include="..\..\..\mem.h" />
<ClInclude Include="..\..\..\devices\network\bswap.h" />
<ClInclude Include="..\..\..\devices\network\network.h" />
<ClInclude Include="..\..\..\devices\network\net_ne2000.h" />
<ClInclude Include="..\..\..\nvr.h" />
<ClInclude Include="..\..\..\plat.h" />
<ClInclude Include="..\..\..\devices\ports\game.h" />
<ClInclude Include="..\..\..\devices\ports\game_dev.h" />
<ClInclude Include="..\..\..\devices\ports\parallel.h" />
<ClInclude Include="..\..\..\devices\ports\parallel_dev.h" />
<ClInclude Include="..\..\..\devices\ports\serial.h" />
<ClInclude Include="..\..\..\png.h" />
<ClInclude Include="..\..\..\random.h" />
<ClInclude Include="..\..\..\rom.h" />
<ClInclude Include="..\..\..\devices\sound\munt\c_interface\cpp_interface.h" />
<ClInclude Include="..\..\..\devices\sound\munt\c_interface\c_interface.h" />
<ClInclude Include="..\..\..\devices\sound\munt\c_interface\c_types.h" />
<ClInclude Include="..\..\..\devices\sound\munt\sha1\sha1.h" />
<ClInclude Include="..\..\..\timer.h" />
<ClInclude Include="..\..\..\ui\ui.h" />
<ClInclude Include="..\..\..\ui\ui_resource.h" />
<ClInclude Include="..\..\..\version.h" />
<ClInclude Include="..\..\..\devices\video\video.h" />
<ClInclude Include="..\..\..\devices\video\vid_ati68860_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_ati_eeprom.h" />
<ClInclude Include="..\..\..\devices\video\vid_cga.h" />
<ClInclude Include="..\..\..\devices\video\vid_cga_comp.h" />
<ClInclude Include="..\..\..\devices\video\vid_ega.h" />
<ClInclude Include="..\..\..\devices\video\vid_ega_render.h" />
<ClInclude Include="..\..\..\devices\video\vid_icd2061.h" />
<ClInclude Include="..\..\..\devices\video\vid_ics2595.h" />
<ClInclude Include="..\..\..\devices\video\vid_sc1502x_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_sdac_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_stg_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_svga.h" />
<ClInclude Include="..\..\..\devices\video\vid_svga_render.h" />
<ClInclude Include="..\..\..\devices\video\vid_tkd8001_ramdac.h" />
<ClInclude Include="..\..\..\devices\video\vid_voodoo_codegen_x86-64.h" />
<ClInclude Include="..\..\..\devices\video\vid_voodoo_codegen_x86.h" />
<ClInclude Include="..\..\..\devices\video\vid_voodoo_dither.h" />
<ClInclude Include="..\..\..\win\resource.h" />
<ClInclude Include="..\..\..\win\win.h" />
<ClInclude Include="..\..\win_opendir.h" />
<ClInclude Include="..\..\win_sdl.h" />
<ClInclude Include="..\..\win_settings_disk.h" />
<ClInclude Include="..\..\win_settings_floppy.h" />
<ClInclude Include="..\..\win_settings_input.h" />
<ClInclude Include="..\..\win_settings_machine.h" />
<ClInclude Include="..\..\win_settings_network.h" />
<ClInclude Include="..\..\win_settings_periph.h" />
<ClInclude Include="..\..\win_settings_ports.h" />
<ClInclude Include="..\..\win_settings_remov.h" />
<ClInclude Include="..\..\win_settings_sound.h" />
<ClInclude Include="..\..\win_settings_video.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\VARCem.rc">
<ShowProgress Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ShowProgress>
<ShowProgress Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ShowProgress>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_MSC_VER</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_MSC_VER</PreprocessorDefinitions>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\VARCem.mpp">
<FileType>Document</FileType>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Generating Manifest file...</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Generating Manifest file...</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Generating Manifest file...</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Generating Manifest file...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">VARCem.manifest</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">VARCem.manifest</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">VARCem.manifest</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">VARCem.manifest</Outputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">VARCem.rc</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">VARCem.rc</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">VARCem.rc</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">VARCem.rc</AdditionalInputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">cl -nologo -EP %(FullPath) &gt; $(SolutionDir)..\..\%(Outputs)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cl -nologo -EP %(FullPath) &gt; $(SolutionDir)..\..\%(Outputs)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -nologo -EP %(FullPath) &gt; $(SolutionDir)..\..\%(Outputs)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -nologo -EP %(FullPath) &gt; $(SolutionDir)..\..\%(Outputs)</Command>
</CustomBuild>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{6E445F28-CA8F-430F-8CCF-C59C53516AC5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>VARCem</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="global.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="global.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="global.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="global.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Lib\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;iphlpapi.lib;psapi.lib;Comctl32.lib;DInput8.lib;d3d9.lib;d3dx9.lib;ddraw.lib;dxguid.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SKIP_MANIFEST</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;iphlpapi.lib;psapi.lib;Comctl32.lib;DInput8.lib;d3d9.lib;d3dx9.lib;ddraw.lib;dxguid.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;iphlpapi.lib;psapi.lib;Comctl32.lib;DInput8.lib;d3d9.lib;d3dx9.lib;ddraw.lib;dxguid.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SKIP_MANIFEST</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<AdditionalDependencies>winmm.lib;ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;iphlpapi.lib;psapi.lib;Comctl32.lib;DInput8.lib;d3d9.lib;d3dx9.lib;ddraw.lib;dxguid.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(ProjectDir)\..\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommandArguments>-L varcem.log</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerCommandArguments>-L varcem.log</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>-L varcem.log</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommandArguments>-L varcem.log</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>$(ProjectDir)\..\Include;$(ProjectDir)\..\..\mingw\include;$(ProjectDir)\..\..\mingw\include\pcap;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>_USE_MATH_DEFINES;_CRT_NONSTDC_NO_DEPRECATE;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CRT_STDIO_ISO_WIDE_SPECIFIERS;USE_DYNAREC;USE_OPENAL;USE_SDL;USE_FLUIDSYNTH</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>