mirror of
https://github.com/VARCem/SLiRP.git
synced 2026-09-23 07:15:08 +00:00
Initial upload of modified SLiRP
This commit is contained in:
37
.gitattributes
vendored
Normal file
37
.gitattributes
vendored
Normal 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
82
.travis-build.sh
Normal 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
86
.travis-deploy.sh
Normal 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
91
.travis.yml
Normal 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
61
COPYRIGHT.txt
Normal 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
44
README.md
Normal 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 [](https://travis-ci.org/VARCem/SLiRP)
|
||||
|
||||
Last Updated: 11/04/2018
|
||||
75
src/arp.c
Normal file
75
src/arp.c
Normal 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
42
src/arp.h
Normal 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
359
src/bootp.c
Normal 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
122
src/bootp.h
Normal 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
145
src/cksum.c
Normal 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
71
src/config.h
Normal 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
90
src/debug.c
Normal 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
70
src/debug.h
Normal 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
14
src/host.h
Normal 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
65
src/icmp_var.h
Normal 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
250
src/if.c
Normal 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
44
src/if.h
Normal 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
365
src/ip.h
Normal 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
378
src/ip_icmp.c
Normal 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
170
src/ip_icmp.h
Normal 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
704
src/ip_input.c
Normal 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
220
src/ip_output.c
Normal 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
245
src/mbuf.c
Normal 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
146
src/mbuf.h
Normal 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
135
src/misc.c
Normal 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
74
src/misc.h
Normal 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
342
src/poll.c
Normal 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
115
src/queue.c
Normal 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
101
src/queue.h
Normal 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
204
src/sbuf.c
Normal 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
294
src/slirp.c
Normal 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
133
src/slirp.h
Normal 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
769
src/socket.c
Normal 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
130
src/socket.h
Normal 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
225
src/stats.c
Normal 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
213
src/tcp.h
Normal 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
1735
src/tcp_input.c
Normal file
File diff suppressed because it is too large
Load Diff
618
src/tcp_output.c
Normal file
618
src/tcp_output.c
Normal 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
714
src/tcp_subr.c
Normal 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
337
src/tcp_timer.c
Normal 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
138
src/tcp_timer.h
Normal 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
256
src/tcp_var.h
Normal 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
70
src/tcpip.h
Normal 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
1
src/tftp.h
Normal file
@@ -0,0 +1 @@
|
||||
/* Dummy */
|
||||
452
src/udp.c
Normal file
452
src/udp.c
Normal 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
117
src/udp.h
Normal 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
271
src/unix/Makefile.linux
Normal 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
81
src/unix/host.c
Normal 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
21
src/unused/main.h
Normal 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
128
src/unused/misc.c
Normal 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
65
src/unused/redir.c
Normal 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
12
src/unused/redir.h
Normal 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
654
src/unused/tcp_emu.c
Normal 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
40
src/unused/tftp.h
Normal 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
251
src/unused/udp_emu.c
Normal 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
332
src/unused/udp_tftp.c
Normal 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
653
src/unused/x
Normal 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
121
src/win/host.c
Normal 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
1
src/win/host.d
Normal file
@@ -0,0 +1 @@
|
||||
host.o: win/host.c win/../host.h win/../debug.h
|
||||
BIN
src/win/icons/varcem.ico
Normal file
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
84
src/win/libslirp.rc
Normal 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
|
||||
312
src/win/mingw/Makefile.MinGW
Normal file
312
src/win/mingw/Makefile.MinGW
Normal 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.
|
||||
300
src/win/msvc/Include/d3dx9tex.h
Normal file
300
src/win/msvc/Include/d3dx9tex.h
Normal 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__
|
||||
BIN
src/win/msvc/Lib/x64/d3dx9.lib
Normal file
BIN
src/win/msvc/Lib/x64/d3dx9.lib
Normal file
Binary file not shown.
BIN
src/win/msvc/Lib/x86/d3dx9.lib
Normal file
BIN
src/win/msvc/Lib/x86/d3dx9.lib
Normal file
Binary file not shown.
854
src/win/msvc/Makefile.VC
Normal file
854
src/win/msvc/Makefile.VC
Normal 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.
|
||||
31
src/win/msvc/vc14/VARCem.sln
Normal file
31
src/win/msvc/vc14/VARCem.sln
Normal 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
|
||||
774
src/win/msvc/vc14/VARCem.vcxproj
Normal file
774
src/win/msvc/vc14/VARCem.vcxproj
Normal 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) > $(SolutionDir)..\..\%(Outputs)</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cl -nologo -EP %(FullPath) > $(SolutionDir)..\..\%(Outputs)</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -nologo -EP %(FullPath) > $(SolutionDir)..\..\%(Outputs)</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -nologo -EP %(FullPath) > $(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>
|
||||
1724
src/win/msvc/vc14/VARCem.vcxproj.filters
Normal file
1724
src/win/msvc/vc14/VARCem.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
19
src/win/msvc/vc14/VARCem.vcxproj.user
Normal file
19
src/win/msvc/vc14/VARCem.vcxproj.user
Normal 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>
|
||||
14
src/win/msvc/vc14/global.props
Normal file
14
src/win/msvc/vc14/global.props
Normal 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>
|
||||
31
src/win/msvc/vc15/VARCem.sln
Normal file
31
src/win/msvc/vc15/VARCem.sln
Normal 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
|
||||
783
src/win/msvc/vc15/VARCem.vcxproj
Normal file
783
src/win/msvc/vc15/VARCem.vcxproj
Normal 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) > $(SolutionDir)..\..\%(Outputs)</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">cl -nologo -EP %(FullPath) > $(SolutionDir)..\..\%(Outputs)</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">cl -nologo -EP %(FullPath) > $(SolutionDir)..\..\%(Outputs)</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">cl -nologo -EP %(FullPath) > $(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>
|
||||
1750
src/win/msvc/vc15/VARCem.vcxproj.filters
Normal file
1750
src/win/msvc/vc15/VARCem.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
19
src/win/msvc/vc15/VARCem.vcxproj.user
Normal file
19
src/win/msvc/vc15/VARCem.vcxproj.user
Normal 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>
|
||||
14
src/win/msvc/vc15/global.props
Normal file
14
src/win/msvc/vc15/global.props
Normal 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>
|
||||
Reference in New Issue
Block a user