mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging
slirp: move slirp as git submodule project Marc-André Lureau (2): build-sys: pass CFLAGS & LDFLAGS to subdir-slirp build-sys: move slirp as git submodule project # gpg: Signature made Thu 02 May 2019 23:20:52 BST # gpg: using RSA key E61DBB15D4172BDEC97E92D9DB550E89F0FA54F3 # gpg: Good signature from "Samuel Thibault <samuel.thibault@aquilenet.fr>" [unknown] # gpg: aka "Samuel Thibault <sthibault@debian.org>" [marginal] # gpg: aka "Samuel Thibault <samuel.thibault@gnu.org>" [unknown] # gpg: aka "Samuel Thibault <samuel.thibault@inria.fr>" [marginal] # gpg: aka "Samuel Thibault <samuel.thibault@labri.fr>" [marginal] # gpg: aka "Samuel Thibault <samuel.thibault@ens-lyon.org>" [marginal] # gpg: aka "Samuel Thibault <samuel.thibault@u-bordeaux.fr>" [unknown] # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 900C B024 B679 31D4 0F82 304B D017 8C76 7D06 9EE6 # Subkey fingerprint: E61D BB15 D417 2BDE C97E 92D9 DB55 0E89 F0FA 54F3 * remotes/thibault/tags/samuel-thibault: build-sys: move slirp as git submodule project build-sys: pass CFLAGS & LDFLAGS to subdir-slirp Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -52,3 +52,6 @@
|
||||
[submodule "roms/edk2"]
|
||||
path = roms/edk2
|
||||
url = https://github.com/tianocore/edk2.git
|
||||
[submodule "slirp"]
|
||||
path = slirp
|
||||
url = https://gitlab.freedesktop.org/slirp/libslirp.git
|
||||
|
||||
@@ -480,7 +480,7 @@ subdir-capstone: .git-submodule-status
|
||||
$(call quiet-command,$(MAKE) -C $(SRC_PATH)/capstone CAPSTONE_SHARED=no BUILDDIR="$(BUILD_DIR)/capstone" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(CAP_CFLAGS)" $(SUBDIR_MAKEFLAGS) $(BUILD_DIR)/capstone/$(LIBCAPSTONE))
|
||||
|
||||
subdir-slirp: .git-submodule-status
|
||||
$(call quiet-command,$(MAKE) -C $(SRC_PATH)/slirp BUILD_DIR="$(BUILD_DIR)/slirp" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(QEMU_CFLAGS)")
|
||||
$(call quiet-command,$(MAKE) -C $(SRC_PATH)/slirp BUILD_DIR="$(BUILD_DIR)/slirp" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(QEMU_CFLAGS) $(CFLAGS)" LDFLAGS="$(LDFLAGS)")
|
||||
|
||||
$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) \
|
||||
$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
|
||||
|
||||
@@ -1115,6 +1115,8 @@ for opt do
|
||||
;;
|
||||
--disable-slirp) slirp="no"
|
||||
;;
|
||||
--enable-slirp=git) slirp="git"
|
||||
;;
|
||||
--enable-slirp=system) slirp="system"
|
||||
;;
|
||||
--disable-vde) vde="no"
|
||||
@@ -5868,6 +5870,8 @@ case "$slirp" in
|
||||
"" | yes)
|
||||
if $pkg_config slirp; then
|
||||
slirp=system
|
||||
elif test -e "${source_path}/.git" && test $git_update = 'yes' ; then
|
||||
slirp=git
|
||||
elif test -e "${source_path}/slirp/Makefile" ; then
|
||||
slirp=internal
|
||||
elif test -z "$slirp" ; then
|
||||
@@ -5885,7 +5889,10 @@ case "$slirp" in
|
||||
esac
|
||||
|
||||
case "$slirp" in
|
||||
internal)
|
||||
git | internal)
|
||||
if test "$slirp" = git; then
|
||||
git_submodules="${git_submodules} slirp"
|
||||
fi
|
||||
mkdir -p slirp
|
||||
slirp_cflags="-I\$(SRC_PATH)/slirp/src -I\$(BUILD_DIR)/slirp/src"
|
||||
slirp_libs="-L\$(BUILD_DIR)/slirp -lslirp"
|
||||
@@ -6548,7 +6555,7 @@ if test "$slirp" != "no"; then
|
||||
echo "SLIRP_CFLAGS=$slirp_cflags" >> $config_host_mak
|
||||
echo "SLIRP_LIBS=$slirp_libs" >> $config_host_mak
|
||||
fi
|
||||
if [ "$slirp" = "internal" ]; then
|
||||
if [ "$slirp" = "git" -o "$slirp" = "internal" ]; then
|
||||
echo "config-host.h: subdir-slirp" >> $config_host_mak
|
||||
fi
|
||||
if test "$vde" = "yes" ; then
|
||||
|
||||
@@ -26,7 +26,7 @@ vroot_dir="${tar_file}.vroot"
|
||||
# independent of what the developer currently has initialized
|
||||
# in their checkout, because the build environment is completely
|
||||
# different to the host OS.
|
||||
submodules="dtc ui/keycodemapdb tests/fp/berkeley-softfloat-3 tests/fp/berkeley-testfloat-3"
|
||||
submodules="dtc slirp ui/keycodemapdb tests/fp/berkeley-softfloat-3 tests/fp/berkeley-testfloat-3"
|
||||
|
||||
trap "status=$?; rm -rf \"$list_file\" \"$vroot_dir\"; exit \$status" 0 1 2 3 15
|
||||
|
||||
|
||||
Submodule
+1
Submodule slirp added at 59a1b1f165
@@ -1,62 +0,0 @@
|
||||
Slirp was written by Danny Gasparovski.
|
||||
Copyright (c), 1995,1996 All Rights Reserved.
|
||||
|
||||
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.
|
||||
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 ``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.
|
||||
@@ -1,47 +0,0 @@
|
||||
ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
BUILD_DIR ?= .
|
||||
|
||||
LIBSLIRP = $(BUILD_DIR)/libslirp.a
|
||||
|
||||
all: $(LIBSLIRP)
|
||||
|
||||
SRCS := $(wildcard src/*.c)
|
||||
OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
|
||||
DEPS := $(OBJS:%.o=%.d)
|
||||
|
||||
INC_DIRS := $(BUILD_DIR)/src
|
||||
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
|
||||
|
||||
override CFLAGS += \
|
||||
-DG_LOG_DOMAIN='"Slirp"' \
|
||||
$(shell $(PKG_CONFIG) --cflags glib-2.0) \
|
||||
$(INC_FLAGS) \
|
||||
-MMD -MP
|
||||
override LDFLAGS += $(shell $(PKG_CONFIG) --libs glib-2.0)
|
||||
|
||||
$(LIBSLIRP): $(OBJS)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -r $(OBJS) $(DEPS) $(LIBSLIRP)
|
||||
|
||||
$(BUILD_DIR)/src/%.o: $(ROOT_DIR)/src/%.c
|
||||
@$(MKDIR_P) $(dir $@)
|
||||
$(call quiet-command,$(CC) $(CFLAGS) -c -o $@ $<,"CC","$@")
|
||||
|
||||
%.a:
|
||||
$(call quiet-command,rm -f $@ && $(AR) rcs $@ $^,"AR","$@")
|
||||
|
||||
PKG_CONFIG ?= pkg-config
|
||||
MKDIR_P ?= mkdir -p
|
||||
quiet-command-run = $(if $(V),,$(if $2,printf " %-7s %s\n" $2 $3 && ))$1
|
||||
quiet-@ = $(if $(V),,@)
|
||||
quiet-command = $(quiet-@)$(call quiet-command-run,$1,$2,$3)
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
-include $(DEPS)
|
||||
@@ -1,92 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* ARP table
|
||||
*
|
||||
* Copyright (c) 2011 AdaCore
|
||||
*
|
||||
* 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 <string.h>
|
||||
|
||||
void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
|
||||
{
|
||||
const uint32_t broadcast_addr =
|
||||
~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
|
||||
ArpTable *arptbl = &slirp->arp_table;
|
||||
int i;
|
||||
|
||||
DEBUG_CALL("arp_table_add");
|
||||
DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr}));
|
||||
DEBUG_ARG("hw addr = %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ethaddr[0], ethaddr[1], ethaddr[2],
|
||||
ethaddr[3], ethaddr[4], ethaddr[5]);
|
||||
|
||||
if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
|
||||
/* Do not register broadcast addresses */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Search for an entry */
|
||||
for (i = 0; i < ARP_TABLE_SIZE; i++) {
|
||||
if (arptbl->table[i].ar_sip == ip_addr) {
|
||||
/* Update the entry */
|
||||
memcpy(arptbl->table[i].ar_sha, ethaddr, ETH_ALEN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No entry found, create a new one */
|
||||
arptbl->table[arptbl->next_victim].ar_sip = ip_addr;
|
||||
memcpy(arptbl->table[arptbl->next_victim].ar_sha, ethaddr, ETH_ALEN);
|
||||
arptbl->next_victim = (arptbl->next_victim + 1) % ARP_TABLE_SIZE;
|
||||
}
|
||||
|
||||
bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
|
||||
uint8_t out_ethaddr[ETH_ALEN])
|
||||
{
|
||||
const uint32_t broadcast_addr =
|
||||
~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
|
||||
ArpTable *arptbl = &slirp->arp_table;
|
||||
int i;
|
||||
|
||||
DEBUG_CALL("arp_table_search");
|
||||
DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr}));
|
||||
|
||||
/* If broadcast address */
|
||||
if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
|
||||
/* return Ethernet broadcast address */
|
||||
memset(out_ethaddr, 0xff, ETH_ALEN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARP_TABLE_SIZE; i++) {
|
||||
if (arptbl->table[i].ar_sip == ip_addr) {
|
||||
memcpy(out_ethaddr, arptbl->table[i].ar_sha, ETH_ALEN);
|
||||
DEBUG_ARG("found hw addr = %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
|
||||
out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include "slirp.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* Windows ntohl() returns an u_long value.
|
||||
* Add a type cast to match the format strings. */
|
||||
# define ntohl(n) ((uint32_t)ntohl(n))
|
||||
#endif
|
||||
|
||||
/* XXX: only DHCP is supported */
|
||||
|
||||
#define LEASE_TIME (24 * 3600)
|
||||
|
||||
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
|
||||
|
||||
#define DPRINTF(fmt, ...) DEBUG_CALL(fmt, ##__VA_ARGS__)
|
||||
|
||||
static BOOTPClient *get_new_addr(Slirp *slirp, struct in_addr *paddr,
|
||||
const uint8_t *macaddr)
|
||||
{
|
||||
BOOTPClient *bc;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < NB_BOOTP_CLIENTS; i++) {
|
||||
bc = &slirp->bootp_clients[i];
|
||||
if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6))
|
||||
goto found;
|
||||
}
|
||||
return NULL;
|
||||
found:
|
||||
bc = &slirp->bootp_clients[i];
|
||||
bc->allocated = 1;
|
||||
paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i);
|
||||
return bc;
|
||||
}
|
||||
|
||||
static BOOTPClient *request_addr(Slirp *slirp, const struct in_addr *paddr,
|
||||
const uint8_t *macaddr)
|
||||
{
|
||||
uint32_t req_addr = ntohl(paddr->s_addr);
|
||||
uint32_t dhcp_addr = ntohl(slirp->vdhcp_startaddr.s_addr);
|
||||
BOOTPClient *bc;
|
||||
|
||||
if (req_addr >= dhcp_addr &&
|
||||
req_addr < (dhcp_addr + NB_BOOTP_CLIENTS)) {
|
||||
bc = &slirp->bootp_clients[req_addr - dhcp_addr];
|
||||
if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) {
|
||||
bc->allocated = 1;
|
||||
return bc;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr,
|
||||
const uint8_t *macaddr)
|
||||
{
|
||||
BOOTPClient *bc;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < NB_BOOTP_CLIENTS; i++) {
|
||||
if (!memcmp(macaddr, slirp->bootp_clients[i].macaddr, 6))
|
||||
goto found;
|
||||
}
|
||||
return NULL;
|
||||
found:
|
||||
bc = &slirp->bootp_clients[i];
|
||||
bc->allocated = 1;
|
||||
paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i);
|
||||
return bc;
|
||||
}
|
||||
|
||||
static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
||||
struct in_addr *preq_addr)
|
||||
{
|
||||
const uint8_t *p, *p_end;
|
||||
int len, tag;
|
||||
|
||||
*pmsg_type = 0;
|
||||
preq_addr->s_addr = htonl(0L);
|
||||
|
||||
p = bp->bp_vend;
|
||||
p_end = p + DHCP_OPT_LEN;
|
||||
if (memcmp(p, rfc1533_cookie, 4) != 0)
|
||||
return;
|
||||
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++;
|
||||
if (p + len > p_end) {
|
||||
break;
|
||||
}
|
||||
DPRINTF("dhcp: tag=%d len=%d\n", tag, len);
|
||||
|
||||
switch(tag) {
|
||||
case RFC2132_MSG_TYPE:
|
||||
if (len >= 1)
|
||||
*pmsg_type = p[0];
|
||||
break;
|
||||
case RFC2132_REQ_ADDR:
|
||||
if (len >= 4) {
|
||||
memcpy(&(preq_addr->s_addr), p, 4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
p += len;
|
||||
}
|
||||
}
|
||||
if (*pmsg_type == DHCPREQUEST && preq_addr->s_addr == htonl(0L) &&
|
||||
bp->bp_ciaddr.s_addr) {
|
||||
memcpy(&(preq_addr->s_addr), &bp->bp_ciaddr, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||
{
|
||||
BOOTPClient *bc = NULL;
|
||||
struct mbuf *m;
|
||||
struct bootp_t *rbp;
|
||||
struct sockaddr_in saddr, daddr;
|
||||
struct in_addr preq_addr;
|
||||
int dhcp_msg_type, val;
|
||||
uint8_t *q;
|
||||
uint8_t *end;
|
||||
uint8_t client_ethaddr[ETH_ALEN];
|
||||
|
||||
/* extract exact DHCP msg type */
|
||||
dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
|
||||
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
|
||||
if (preq_addr.s_addr != htonl(0L))
|
||||
DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr));
|
||||
else {
|
||||
DPRINTF("\n");
|
||||
}
|
||||
|
||||
if (dhcp_msg_type == 0)
|
||||
dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
|
||||
|
||||
if (dhcp_msg_type != DHCPDISCOVER &&
|
||||
dhcp_msg_type != DHCPREQUEST)
|
||||
return;
|
||||
|
||||
/* Get client's hardware address from bootp request */
|
||||
memcpy(client_ethaddr, bp->bp_hwaddr, ETH_ALEN);
|
||||
|
||||
m = m_get(slirp);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
rbp = (struct bootp_t *)m->m_data;
|
||||
m->m_data += sizeof(struct udpiphdr);
|
||||
memset(rbp, 0, sizeof(struct bootp_t));
|
||||
|
||||
if (dhcp_msg_type == DHCPDISCOVER) {
|
||||
if (preq_addr.s_addr != htonl(0L)) {
|
||||
bc = request_addr(slirp, &preq_addr, client_ethaddr);
|
||||
if (bc) {
|
||||
daddr.sin_addr = preq_addr;
|
||||
}
|
||||
}
|
||||
if (!bc) {
|
||||
new_addr:
|
||||
bc = get_new_addr(slirp, &daddr.sin_addr, client_ethaddr);
|
||||
if (!bc) {
|
||||
DPRINTF("no address left\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
memcpy(bc->macaddr, client_ethaddr, ETH_ALEN);
|
||||
} else if (preq_addr.s_addr != htonl(0L)) {
|
||||
bc = request_addr(slirp, &preq_addr, client_ethaddr);
|
||||
if (bc) {
|
||||
daddr.sin_addr = preq_addr;
|
||||
memcpy(bc->macaddr, client_ethaddr, ETH_ALEN);
|
||||
} else {
|
||||
/* DHCPNAKs should be sent to broadcast */
|
||||
daddr.sin_addr.s_addr = 0xffffffff;
|
||||
}
|
||||
} else {
|
||||
bc = find_addr(slirp, &daddr.sin_addr, bp->bp_hwaddr);
|
||||
if (!bc) {
|
||||
/* if never assigned, behaves as if it was already
|
||||
assigned (windows fix because it remembers its address) */
|
||||
goto new_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update ARP table for this IP address */
|
||||
arp_table_add(slirp, daddr.sin_addr.s_addr, client_ethaddr);
|
||||
|
||||
saddr.sin_addr = slirp->vhost_addr;
|
||||
saddr.sin_port = htons(BOOTP_SERVER);
|
||||
|
||||
daddr.sin_port = htons(BOOTP_CLIENT);
|
||||
|
||||
rbp->bp_op = BOOTP_REPLY;
|
||||
rbp->bp_xid = bp->bp_xid;
|
||||
rbp->bp_htype = 1;
|
||||
rbp->bp_hlen = 6;
|
||||
memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, ETH_ALEN);
|
||||
|
||||
rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */
|
||||
rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
|
||||
|
||||
q = rbp->bp_vend;
|
||||
end = (uint8_t *)&rbp[1];
|
||||
memcpy(q, rfc1533_cookie, 4);
|
||||
q += 4;
|
||||
|
||||
if (bc) {
|
||||
DPRINTF("%s addr=%08" PRIx32 "\n",
|
||||
(dhcp_msg_type == DHCPDISCOVER) ? "offered" : "ack'ed",
|
||||
ntohl(daddr.sin_addr.s_addr));
|
||||
|
||||
if (dhcp_msg_type == DHCPDISCOVER) {
|
||||
*q++ = RFC2132_MSG_TYPE;
|
||||
*q++ = 1;
|
||||
*q++ = DHCPOFFER;
|
||||
} else /* DHCPREQUEST */ {
|
||||
*q++ = RFC2132_MSG_TYPE;
|
||||
*q++ = 1;
|
||||
*q++ = DHCPACK;
|
||||
}
|
||||
|
||||
if (slirp->bootp_filename)
|
||||
snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s",
|
||||
slirp->bootp_filename);
|
||||
|
||||
*q++ = RFC2132_SRV_ID;
|
||||
*q++ = 4;
|
||||
memcpy(q, &saddr.sin_addr, 4);
|
||||
q += 4;
|
||||
|
||||
*q++ = RFC1533_NETMASK;
|
||||
*q++ = 4;
|
||||
memcpy(q, &slirp->vnetwork_mask, 4);
|
||||
q += 4;
|
||||
|
||||
if (!slirp->restricted) {
|
||||
*q++ = RFC1533_GATEWAY;
|
||||
*q++ = 4;
|
||||
memcpy(q, &saddr.sin_addr, 4);
|
||||
q += 4;
|
||||
|
||||
*q++ = RFC1533_DNS;
|
||||
*q++ = 4;
|
||||
memcpy(q, &slirp->vnameserver_addr, 4);
|
||||
q += 4;
|
||||
}
|
||||
|
||||
*q++ = RFC2132_LEASE_TIME;
|
||||
*q++ = 4;
|
||||
val = htonl(LEASE_TIME);
|
||||
memcpy(q, &val, 4);
|
||||
q += 4;
|
||||
|
||||
if (*slirp->client_hostname) {
|
||||
val = strlen(slirp->client_hostname);
|
||||
if (q + val + 2 >= end) {
|
||||
g_warning("DHCP packet size exceeded, "
|
||||
"omitting host name option.");
|
||||
} else {
|
||||
*q++ = RFC1533_HOSTNAME;
|
||||
*q++ = val;
|
||||
memcpy(q, slirp->client_hostname, val);
|
||||
q += val;
|
||||
}
|
||||
}
|
||||
|
||||
if (slirp->vdomainname) {
|
||||
val = strlen(slirp->vdomainname);
|
||||
if (q + val + 2 >= end) {
|
||||
g_warning("DHCP packet size exceeded, "
|
||||
"omitting domain name option.");
|
||||
} else {
|
||||
*q++ = RFC1533_DOMAINNAME;
|
||||
*q++ = val;
|
||||
memcpy(q, slirp->vdomainname, val);
|
||||
q += val;
|
||||
}
|
||||
}
|
||||
|
||||
if (slirp->tftp_server_name) {
|
||||
val = strlen(slirp->tftp_server_name);
|
||||
if (q + val + 2 >= end) {
|
||||
g_warning("DHCP packet size exceeded, "
|
||||
"omitting tftp-server-name option.");
|
||||
} else {
|
||||
*q++ = RFC2132_TFTP_SERVER_NAME;
|
||||
*q++ = val;
|
||||
memcpy(q, slirp->tftp_server_name, val);
|
||||
q += val;
|
||||
}
|
||||
}
|
||||
|
||||
if (slirp->vdnssearch) {
|
||||
val = slirp->vdnssearch_len;
|
||||
if (q + val >= end) {
|
||||
g_warning("DHCP packet size exceeded, "
|
||||
"omitting domain-search option.");
|
||||
} else {
|
||||
memcpy(q, slirp->vdnssearch, val);
|
||||
q += val;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
static const char nak_msg[] = "requested address not available";
|
||||
|
||||
DPRINTF("nak'ed addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr));
|
||||
|
||||
*q++ = RFC2132_MSG_TYPE;
|
||||
*q++ = 1;
|
||||
*q++ = DHCPNAK;
|
||||
|
||||
*q++ = RFC2132_MESSAGE;
|
||||
*q++ = sizeof(nak_msg) - 1;
|
||||
memcpy(q, nak_msg, sizeof(nak_msg) - 1);
|
||||
q += sizeof(nak_msg) - 1;
|
||||
}
|
||||
assert(q < end);
|
||||
*q = RFC1533_END;
|
||||
|
||||
daddr.sin_addr.s_addr = 0xffffffffu;
|
||||
|
||||
m->m_len = sizeof(struct bootp_t) -
|
||||
sizeof(struct ip) - sizeof(struct udphdr);
|
||||
udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
||||
}
|
||||
|
||||
void bootp_input(struct mbuf *m)
|
||||
{
|
||||
struct bootp_t *bp = mtod(m, struct bootp_t *);
|
||||
|
||||
if (bp->bp_op == BOOTP_REQUEST) {
|
||||
bootp_reply(m->slirp, bp);
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/* bootp/dhcp defines */
|
||||
|
||||
#ifndef SLIRP_BOOTP_H
|
||||
#define SLIRP_BOOTP_H
|
||||
|
||||
#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_MESSAGE 56
|
||||
#define RFC2132_MAX_SIZE 57
|
||||
#define RFC2132_RENEWAL_TIME 58
|
||||
#define RFC2132_REBIND_TIME 59
|
||||
#define RFC2132_TFTP_SERVER_NAME 66
|
||||
|
||||
#define DHCPDISCOVER 1
|
||||
#define DHCPOFFER 2
|
||||
#define DHCPREQUEST 3
|
||||
#define DHCPACK 5
|
||||
#define DHCPNAK 6
|
||||
|
||||
#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
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16_t allocated;
|
||||
uint8_t macaddr[6];
|
||||
} BOOTPClient;
|
||||
|
||||
#define NB_BOOTP_CLIENTS 16
|
||||
|
||||
void bootp_input(struct mbuf *m);
|
||||
|
||||
#endif
|
||||
@@ -1,161 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* 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 "slirp.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 mbuf, 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]; \
|
||||
(void)ADDCARRY(sum);}
|
||||
|
||||
int cksum(struct mbuf *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 & (uintptr_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;
|
||||
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:
|
||||
if (len) {
|
||||
DEBUG_ERROR("cksum: out of data");
|
||||
DEBUG_ERROR(" len = %d", len);
|
||||
}
|
||||
if (mlen == -1) {
|
||||
/* The last mbuf 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);
|
||||
}
|
||||
|
||||
int ip6_cksum(struct mbuf *m)
|
||||
{
|
||||
/* TODO: Optimize this by being able to pass the ip6_pseudohdr to cksum
|
||||
* separately from the mbuf */
|
||||
struct ip6 save_ip, *ip = mtod(m, struct ip6 *);
|
||||
struct ip6_pseudohdr *ih = mtod(m, struct ip6_pseudohdr *);
|
||||
int sum;
|
||||
|
||||
save_ip = *ip;
|
||||
|
||||
ih->ih_src = save_ip.ip_src;
|
||||
ih->ih_dst = save_ip.ip_dst;
|
||||
ih->ih_pl = htonl((uint32_t)ntohs(save_ip.ip_pl));
|
||||
ih->ih_zero_hi = 0;
|
||||
ih->ih_zero_lo = 0;
|
||||
ih->ih_nh = save_ip.ip_nh;
|
||||
|
||||
sum = cksum(m, ((int)sizeof(struct ip6_pseudohdr))
|
||||
+ ntohl(ih->ih_pl));
|
||||
|
||||
*ip = save_ip;
|
||||
|
||||
return sum;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG_H_
|
||||
#define DEBUG_H_
|
||||
|
||||
#define DBG_CALL (1 << 0)
|
||||
#define DBG_MISC (1 << 1)
|
||||
#define DBG_ERROR (1 << 2)
|
||||
#define DBG_TFTP (1 << 3)
|
||||
|
||||
extern int slirp_debug;
|
||||
|
||||
#define DEBUG_CALL(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_CALL)) { \
|
||||
g_debug(fmt "...", ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_ARG(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_CALL)) { \
|
||||
g_debug(" " fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_MISC(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_MISC)) { \
|
||||
g_debug(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_ERROR(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_ERROR)) { \
|
||||
g_debug(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_TFTP(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_TFTP)) { \
|
||||
g_debug(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* DEBUG_H_ */
|
||||
@@ -1,224 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* SLIRP stateless DHCPv6
|
||||
*
|
||||
* We only support stateless DHCPv6, e.g. for network booting.
|
||||
* See RFC 3315, RFC 3736, RFC 3646 and RFC 5970 for details.
|
||||
*
|
||||
* Copyright 2016 Thomas Huth, Red Hat Inc.
|
||||
*
|
||||
* 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 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 "slirp.h"
|
||||
#include "dhcpv6.h"
|
||||
|
||||
/* DHCPv6 message types */
|
||||
#define MSGTYPE_REPLY 7
|
||||
#define MSGTYPE_INFO_REQUEST 11
|
||||
|
||||
/* DHCPv6 option types */
|
||||
#define OPTION_CLIENTID 1
|
||||
#define OPTION_IAADDR 5
|
||||
#define OPTION_ORO 6
|
||||
#define OPTION_DNS_SERVERS 23
|
||||
#define OPTION_BOOTFILE_URL 59
|
||||
|
||||
struct requested_infos {
|
||||
uint8_t *client_id;
|
||||
int client_id_len;
|
||||
bool want_dns;
|
||||
bool want_boot_url;
|
||||
};
|
||||
|
||||
/**
|
||||
* Analyze the info request message sent by the client to see what data it
|
||||
* provided and what it wants to have. The information is gathered in the
|
||||
* "requested_infos" struct. Note that client_id (if provided) points into
|
||||
* the odata region, thus the caller must keep odata valid as long as it
|
||||
* needs to access the requested_infos struct.
|
||||
*/
|
||||
static int dhcpv6_parse_info_request(Slirp *slirp, uint8_t *odata, int olen,
|
||||
struct requested_infos *ri)
|
||||
{
|
||||
int i, req_opt;
|
||||
|
||||
while (olen > 4) {
|
||||
/* Parse one option */
|
||||
int option = odata[0] << 8 | odata[1];
|
||||
int len = odata[2] << 8 | odata[3];
|
||||
|
||||
if (len + 4 > olen) {
|
||||
slirp->cb->guest_error("Guest sent bad DHCPv6 packet!", slirp->opaque);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
switch (option) {
|
||||
case OPTION_IAADDR:
|
||||
/* According to RFC3315, we must discard requests with IA option */
|
||||
return -EINVAL;
|
||||
case OPTION_CLIENTID:
|
||||
if (len > 256) {
|
||||
/* Avoid very long IDs which could cause problems later */
|
||||
return -E2BIG;
|
||||
}
|
||||
ri->client_id = odata + 4;
|
||||
ri->client_id_len = len;
|
||||
break;
|
||||
case OPTION_ORO: /* Option request option */
|
||||
if (len & 1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Check which options the client wants to have */
|
||||
for (i = 0; i < len; i += 2) {
|
||||
req_opt = odata[4 + i] << 8 | odata[4 + i + 1];
|
||||
switch (req_opt) {
|
||||
case OPTION_DNS_SERVERS:
|
||||
ri->want_dns = true;
|
||||
break;
|
||||
case OPTION_BOOTFILE_URL:
|
||||
ri->want_boot_url = true;
|
||||
break;
|
||||
default:
|
||||
DEBUG_MISC("dhcpv6: Unsupported option request %d",
|
||||
req_opt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG_MISC("dhcpv6 info req: Unsupported option %d, len=%d",
|
||||
option, len);
|
||||
}
|
||||
|
||||
odata += len + 4;
|
||||
olen -= len + 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle information request messages
|
||||
*/
|
||||
static void dhcpv6_info_request(Slirp *slirp, struct sockaddr_in6 *srcsas,
|
||||
uint32_t xid, uint8_t *odata, int olen)
|
||||
{
|
||||
struct requested_infos ri = { NULL };
|
||||
struct sockaddr_in6 sa6, da6;
|
||||
struct mbuf *m;
|
||||
uint8_t *resp;
|
||||
|
||||
if (dhcpv6_parse_info_request(slirp, odata, olen, &ri) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
m = m_get(slirp);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
memset(m->m_data, 0, m->m_size);
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
resp = (uint8_t *)m->m_data + sizeof(struct ip6) + sizeof(struct udphdr);
|
||||
|
||||
/* Fill in response */
|
||||
*resp++ = MSGTYPE_REPLY;
|
||||
*resp++ = (uint8_t)(xid >> 16);
|
||||
*resp++ = (uint8_t)(xid >> 8);
|
||||
*resp++ = (uint8_t)xid;
|
||||
|
||||
if (ri.client_id) {
|
||||
*resp++ = OPTION_CLIENTID >> 8; /* option-code high byte */
|
||||
*resp++ = OPTION_CLIENTID; /* option-code low byte */
|
||||
*resp++ = ri.client_id_len >> 8; /* option-len high byte */
|
||||
*resp++ = ri.client_id_len; /* option-len low byte */
|
||||
memcpy(resp, ri.client_id, ri.client_id_len);
|
||||
resp += ri.client_id_len;
|
||||
}
|
||||
if (ri.want_dns) {
|
||||
*resp++ = OPTION_DNS_SERVERS >> 8; /* option-code high byte */
|
||||
*resp++ = OPTION_DNS_SERVERS; /* option-code low byte */
|
||||
*resp++ = 0; /* option-len high byte */
|
||||
*resp++ = 16; /* option-len low byte */
|
||||
memcpy(resp, &slirp->vnameserver_addr6, 16);
|
||||
resp += 16;
|
||||
}
|
||||
if (ri.want_boot_url) {
|
||||
uint8_t *sa = slirp->vhost_addr6.s6_addr;
|
||||
int slen, smaxlen;
|
||||
|
||||
*resp++ = OPTION_BOOTFILE_URL >> 8; /* option-code high byte */
|
||||
*resp++ = OPTION_BOOTFILE_URL; /* option-code low byte */
|
||||
smaxlen = (uint8_t *)m->m_data + IF_MTU - (resp + 2);
|
||||
slen = snprintf((char *)resp + 2, smaxlen,
|
||||
"tftp://[%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
|
||||
"%02x%02x:%02x%02x:%02x%02x:%02x%02x]/%s",
|
||||
sa[0], sa[1], sa[2], sa[3], sa[4], sa[5], sa[6], sa[7],
|
||||
sa[8], sa[9], sa[10], sa[11], sa[12], sa[13], sa[14],
|
||||
sa[15], slirp->bootp_filename);
|
||||
slen = MIN(slen, smaxlen);
|
||||
*resp++ = slen >> 8; /* option-len high byte */
|
||||
*resp++ = slen; /* option-len low byte */
|
||||
resp += slen;
|
||||
}
|
||||
|
||||
sa6.sin6_addr = slirp->vhost_addr6;
|
||||
sa6.sin6_port = DHCPV6_SERVER_PORT;
|
||||
da6.sin6_addr = srcsas->sin6_addr;
|
||||
da6.sin6_port = srcsas->sin6_port;
|
||||
m->m_data += sizeof(struct ip6) + sizeof(struct udphdr);
|
||||
m->m_len = resp - (uint8_t *)m->m_data;
|
||||
udp6_output(NULL, m, &sa6, &da6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle DHCPv6 messages sent by the client
|
||||
*/
|
||||
void dhcpv6_input(struct sockaddr_in6 *srcsas, struct mbuf *m)
|
||||
{
|
||||
uint8_t *data = (uint8_t *)m->m_data + sizeof(struct udphdr);
|
||||
int data_len = m->m_len - sizeof(struct udphdr);
|
||||
uint32_t xid;
|
||||
|
||||
if (data_len < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
xid = ntohl(*(uint32_t *)data) & 0xffffff;
|
||||
|
||||
switch (data[0]) {
|
||||
case MSGTYPE_INFO_REQUEST:
|
||||
dhcpv6_info_request(m->slirp, srcsas, xid, &data[4], data_len - 4);
|
||||
break;
|
||||
default:
|
||||
DEBUG_MISC("dhcpv6_input: Unsupported message type 0x%x", data[0]);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Definitions and prototypes for SLIRP stateless DHCPv6
|
||||
*
|
||||
* Copyright 2016 Thomas Huth, Red Hat Inc.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
#ifndef SLIRP_DHCPV6_H
|
||||
#define SLIRP_DHCPV6_H
|
||||
|
||||
#define DHCPV6_SERVER_PORT 547
|
||||
|
||||
#define ALLDHCP_MULTICAST { .s6_addr = \
|
||||
{ 0xff, 0x02, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x01, 0x00, 0x02 } }
|
||||
|
||||
#define in6_dhcp_multicast(a)\
|
||||
in6_equal(a, &(struct in6_addr)ALLDHCP_MULTICAST)
|
||||
|
||||
void dhcpv6_input(struct sockaddr_in6 *srcsas, struct mbuf *m);
|
||||
|
||||
#endif
|
||||
@@ -1,311 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Domain search option for DHCP (RFC 3397)
|
||||
*
|
||||
* Copyright (c) 2012 Klaus Stengel
|
||||
*
|
||||
* 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"
|
||||
|
||||
static const uint8_t RFC3397_OPT_DOMAIN_SEARCH = 119;
|
||||
static const uint8_t MAX_OPT_LEN = 255;
|
||||
static const uint8_t OPT_HEADER_LEN = 2;
|
||||
static const uint8_t REFERENCE_LEN = 2;
|
||||
|
||||
struct compact_domain;
|
||||
|
||||
typedef struct compact_domain {
|
||||
struct compact_domain *self;
|
||||
struct compact_domain *refdom;
|
||||
uint8_t *labels;
|
||||
size_t len;
|
||||
size_t common_octets;
|
||||
} CompactDomain;
|
||||
|
||||
static size_t
|
||||
domain_suffix_diffoff(const CompactDomain *a, const CompactDomain *b)
|
||||
{
|
||||
size_t la = a->len, lb = b->len;
|
||||
uint8_t *da = a->labels + la, *db = b->labels + lb;
|
||||
size_t i, lm = (la < lb) ? la : lb;
|
||||
|
||||
for (i = 0; i < lm; i++) {
|
||||
da--; db--;
|
||||
if (*da != *db) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int domain_suffix_ord(const void *cva, const void *cvb)
|
||||
{
|
||||
const CompactDomain *a = cva, *b = cvb;
|
||||
size_t la = a->len, lb = b->len;
|
||||
size_t doff = domain_suffix_diffoff(a, b);
|
||||
uint8_t ca = a->labels[la - doff];
|
||||
uint8_t cb = b->labels[lb - doff];
|
||||
|
||||
if (ca < cb) {
|
||||
return -1;
|
||||
}
|
||||
if (ca > cb) {
|
||||
return 1;
|
||||
}
|
||||
if (la < lb) {
|
||||
return -1;
|
||||
}
|
||||
if (la > lb) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t domain_common_label(CompactDomain *a, CompactDomain *b)
|
||||
{
|
||||
size_t res, doff = domain_suffix_diffoff(a, b);
|
||||
uint8_t *first_eq_pos = a->labels + (a->len - doff);
|
||||
uint8_t *label = a->labels;
|
||||
|
||||
while (*label && label < first_eq_pos) {
|
||||
label += *label + 1;
|
||||
}
|
||||
res = a->len - (label - a->labels);
|
||||
/* only report if it can help to reduce the packet size */
|
||||
return (res > REFERENCE_LEN) ? res : 0;
|
||||
}
|
||||
|
||||
static void domain_fixup_order(CompactDomain *cd, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
CompactDomain *cur = cd + i, *next = cd[i].self;
|
||||
|
||||
while (!cur->common_octets) {
|
||||
CompactDomain *tmp = next->self; /* backup target value */
|
||||
|
||||
next->self = cur;
|
||||
cur->common_octets++;
|
||||
|
||||
cur = next;
|
||||
next = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void domain_mklabels(CompactDomain *cd, const char *input)
|
||||
{
|
||||
uint8_t *len_marker = cd->labels;
|
||||
uint8_t *output = len_marker; /* pre-incremented */
|
||||
const char *in = input;
|
||||
char cur_chr;
|
||||
size_t len = 0;
|
||||
|
||||
if (cd->len == 0) {
|
||||
goto fail;
|
||||
}
|
||||
cd->len++;
|
||||
|
||||
do {
|
||||
cur_chr = *in++;
|
||||
if (cur_chr == '.' || cur_chr == '\0') {
|
||||
len = output - len_marker;
|
||||
if ((len == 0 && cur_chr == '.') || len >= 64) {
|
||||
goto fail;
|
||||
}
|
||||
*len_marker = len;
|
||||
|
||||
output++;
|
||||
len_marker = output;
|
||||
} else {
|
||||
output++;
|
||||
*output = cur_chr;
|
||||
}
|
||||
} while (cur_chr != '\0');
|
||||
|
||||
/* ensure proper zero-termination */
|
||||
if (len != 0) {
|
||||
*len_marker = 0;
|
||||
cd->len++;
|
||||
}
|
||||
return;
|
||||
|
||||
fail:
|
||||
g_warning("failed to parse domain name '%s'\n", input);
|
||||
cd->len = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
domain_mkxrefs(CompactDomain *doms, CompactDomain *last, size_t depth)
|
||||
{
|
||||
CompactDomain *i = doms, *target = doms;
|
||||
|
||||
do {
|
||||
if (i->labels < target->labels) {
|
||||
target = i;
|
||||
}
|
||||
} while (i++ != last);
|
||||
|
||||
for (i = doms; i != last; i++) {
|
||||
CompactDomain *group_last;
|
||||
size_t next_depth;
|
||||
|
||||
if (i->common_octets == depth) {
|
||||
continue;
|
||||
}
|
||||
|
||||
next_depth = -1;
|
||||
for (group_last = i; group_last != last; group_last++) {
|
||||
size_t co = group_last->common_octets;
|
||||
if (co <= depth) {
|
||||
break;
|
||||
}
|
||||
if (co < next_depth) {
|
||||
next_depth = co;
|
||||
}
|
||||
}
|
||||
domain_mkxrefs(i, group_last, next_depth);
|
||||
|
||||
i = group_last;
|
||||
if (i == last) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
i = doms;
|
||||
do {
|
||||
if (i != target && i->refdom == NULL) {
|
||||
i->refdom = target;
|
||||
i->common_octets = depth;
|
||||
}
|
||||
} while (i++ != last);
|
||||
}
|
||||
|
||||
static size_t domain_compactify(CompactDomain *domains, size_t n)
|
||||
{
|
||||
uint8_t *start = domains->self->labels, *outptr = start;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
CompactDomain *cd = domains[i].self;
|
||||
CompactDomain *rd = cd->refdom;
|
||||
|
||||
if (rd != NULL) {
|
||||
size_t moff = (rd->labels - start)
|
||||
+ (rd->len - cd->common_octets);
|
||||
if (moff < 0x3FFFu) {
|
||||
cd->len -= cd->common_octets - 2;
|
||||
cd->labels[cd->len - 1] = moff & 0xFFu;
|
||||
cd->labels[cd->len - 2] = 0xC0u | (moff >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (cd->labels != outptr) {
|
||||
memmove(outptr, cd->labels, cd->len);
|
||||
cd->labels = outptr;
|
||||
}
|
||||
outptr += cd->len;
|
||||
}
|
||||
return outptr - start;
|
||||
}
|
||||
|
||||
int translate_dnssearch(Slirp *s, const char **names)
|
||||
{
|
||||
size_t blocks, bsrc_start, bsrc_end, bdst_start;
|
||||
size_t i, num_domains, memreq = 0;
|
||||
uint8_t *result = NULL, *outptr;
|
||||
CompactDomain *domains = NULL;
|
||||
const char **nameptr = names;
|
||||
|
||||
while (*nameptr != NULL) {
|
||||
nameptr++;
|
||||
}
|
||||
|
||||
num_domains = nameptr - names;
|
||||
if (num_domains == 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
domains = g_malloc(num_domains * sizeof(*domains));
|
||||
|
||||
for (i = 0; i < num_domains; i++) {
|
||||
size_t nlen = strlen(names[i]);
|
||||
memreq += nlen + 2; /* 1 zero octet + 1 label length octet */
|
||||
domains[i].self = domains + i;
|
||||
domains[i].len = nlen;
|
||||
domains[i].common_octets = 0;
|
||||
domains[i].refdom = NULL;
|
||||
}
|
||||
|
||||
/* reserve extra 2 header bytes for each 255 bytes of output */
|
||||
memreq += DIV_ROUND_UP(memreq, MAX_OPT_LEN) * OPT_HEADER_LEN;
|
||||
result = g_malloc(memreq * sizeof(*result));
|
||||
|
||||
outptr = result;
|
||||
for (i = 0; i < num_domains; i++) {
|
||||
domains[i].labels = outptr;
|
||||
domain_mklabels(domains + i, names[i]);
|
||||
outptr += domains[i].len;
|
||||
}
|
||||
|
||||
if (outptr == result) {
|
||||
g_free(domains);
|
||||
g_free(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qsort(domains, num_domains, sizeof(*domains), domain_suffix_ord);
|
||||
domain_fixup_order(domains, num_domains);
|
||||
|
||||
for (i = 1; i < num_domains; i++) {
|
||||
size_t cl = domain_common_label(domains + i - 1, domains + i);
|
||||
domains[i - 1].common_octets = cl;
|
||||
}
|
||||
|
||||
domain_mkxrefs(domains, domains + num_domains - 1, 0);
|
||||
memreq = domain_compactify(domains, num_domains);
|
||||
|
||||
blocks = DIV_ROUND_UP(memreq, MAX_OPT_LEN);
|
||||
bsrc_end = memreq;
|
||||
bsrc_start = (blocks - 1) * MAX_OPT_LEN;
|
||||
bdst_start = bsrc_start + blocks * OPT_HEADER_LEN;
|
||||
memreq += blocks * OPT_HEADER_LEN;
|
||||
|
||||
while (blocks--) {
|
||||
size_t len = bsrc_end - bsrc_start;
|
||||
memmove(result + bdst_start, result + bsrc_start, len);
|
||||
result[bdst_start - 2] = RFC3397_OPT_DOMAIN_SEARCH;
|
||||
result[bdst_start - 1] = len;
|
||||
bsrc_end = bsrc_start;
|
||||
bsrc_start -= MAX_OPT_LEN;
|
||||
bdst_start -= MAX_OPT_LEN + OPT_HEADER_LEN;
|
||||
}
|
||||
|
||||
g_free(domains);
|
||||
s->vdnssearch = result;
|
||||
s->vdnssearch_len = memreq;
|
||||
return 0;
|
||||
}
|
||||
-218
@@ -1,218 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*/
|
||||
|
||||
#include "slirp.h"
|
||||
|
||||
static void
|
||||
ifs_insque(struct mbuf *ifm, struct mbuf *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 mbuf *ifm)
|
||||
{
|
||||
ifm->ifs_prev->ifs_next = ifm->ifs_next;
|
||||
ifm->ifs_next->ifs_prev = ifm->ifs_prev;
|
||||
}
|
||||
|
||||
void
|
||||
if_init(Slirp *slirp)
|
||||
{
|
||||
slirp->if_fastq.qh_link = slirp->if_fastq.qh_rlink = &slirp->if_fastq;
|
||||
slirp->if_batchq.qh_link = slirp->if_batchq.qh_rlink = &slirp->if_batchq;
|
||||
}
|
||||
|
||||
/*
|
||||
* if_output: Queue packet into an output queue.
|
||||
* There are 2 output queue's, if_fastq and if_batchq.
|
||||
* Each output queue is a doubly linked list of double linked lists
|
||||
* of mbufs, 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 socket *so, struct mbuf *ifm)
|
||||
{
|
||||
Slirp *slirp = ifm->slirp;
|
||||
struct mbuf *ifq;
|
||||
int on_fastq = 1;
|
||||
|
||||
DEBUG_CALL("if_output");
|
||||
DEBUG_ARG("so = %p", so);
|
||||
DEBUG_ARG("ifm = %p", ifm);
|
||||
|
||||
/*
|
||||
* First remove the mbuf 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?
|
||||
*/
|
||||
if (so) {
|
||||
for (ifq = (struct mbuf *) slirp->if_batchq.qh_rlink;
|
||||
(struct quehead *) ifq != &slirp->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 = (struct mbuf *) slirp->if_fastq.qh_rlink;
|
||||
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 = (struct mbuf *) slirp->if_batchq.qh_rlink;
|
||||
}
|
||||
|
||||
/* Create a new doubly linked list for this session */
|
||||
ifm->ifq_so = so;
|
||||
ifs_init(ifm);
|
||||
insque(ifm, ifq);
|
||||
|
||||
diddit:
|
||||
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, &slirp->if_batchq);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This prevents us from malloc()ing too many mbufs
|
||||
*/
|
||||
if_start(ifm->slirp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send one packet from each session.
|
||||
* If there are packets on the fastq, they are sent FIFO, before
|
||||
* everything else. Then we choose the first packet from each
|
||||
* batchq session (socket) and send it.
|
||||
* For example, if there are 3 ftp sessions 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.
|
||||
*/
|
||||
void if_start(Slirp *slirp)
|
||||
{
|
||||
uint64_t now = slirp->cb->clock_get_ns(slirp->opaque);
|
||||
bool from_batchq = false;
|
||||
struct mbuf *ifm, *ifm_next, *ifqt;
|
||||
|
||||
DEBUG_CALL("if_start");
|
||||
|
||||
if (slirp->if_start_busy) {
|
||||
return;
|
||||
}
|
||||
slirp->if_start_busy = true;
|
||||
|
||||
struct mbuf *batch_head = NULL;
|
||||
if (slirp->if_batchq.qh_link != &slirp->if_batchq) {
|
||||
batch_head = (struct mbuf *) slirp->if_batchq.qh_link;
|
||||
}
|
||||
|
||||
if (slirp->if_fastq.qh_link != &slirp->if_fastq) {
|
||||
ifm_next = (struct mbuf *) slirp->if_fastq.qh_link;
|
||||
} else if (batch_head) {
|
||||
/* Nothing on fastq, pick up from batchq */
|
||||
ifm_next = batch_head;
|
||||
from_batchq = true;
|
||||
} else {
|
||||
ifm_next = NULL;
|
||||
}
|
||||
|
||||
while (ifm_next) {
|
||||
ifm = ifm_next;
|
||||
|
||||
ifm_next = ifm->ifq_next;
|
||||
if ((struct quehead *) ifm_next == &slirp->if_fastq) {
|
||||
/* No more packets in fastq, switch to batchq */
|
||||
ifm_next = batch_head;
|
||||
from_batchq = true;
|
||||
}
|
||||
if ((struct quehead *) ifm_next == &slirp->if_batchq) {
|
||||
/* end of batchq */
|
||||
ifm_next = NULL;
|
||||
}
|
||||
|
||||
/* Try to send packet unless it already expired */
|
||||
if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) {
|
||||
/* Packet is delayed due to pending ARP or NDP resolution */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove it from the queue */
|
||||
ifqt = ifm->ifq_prev;
|
||||
remque(ifm);
|
||||
|
||||
/* If there are more packets for this session, re-queue them */
|
||||
if (ifm->ifs_next != ifm) {
|
||||
struct mbuf *next = ifm->ifs_next;
|
||||
|
||||
insque(next, ifqt);
|
||||
ifs_remque(ifm);
|
||||
if (!from_batchq) {
|
||||
ifm_next = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update so_queued */
|
||||
if (ifm->ifq_so && --ifm->ifq_so->so_queued == 0) {
|
||||
/* If there's no more queued, reset nqueued */
|
||||
ifm->ifq_so->so_nqueued = 0;
|
||||
}
|
||||
|
||||
m_free(ifm);
|
||||
}
|
||||
|
||||
slirp->if_start_busy = false;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*/
|
||||
|
||||
#ifndef IF_H
|
||||
#define IF_H
|
||||
|
||||
#define IF_COMPRESS 0x01 /* We want compression */
|
||||
#define IF_NOCOMPRESS 0x02 /* Do not do compression */
|
||||
#define IF_AUTOCOMP 0x04 /* Autodetect (default) */
|
||||
#define IF_NOCIDCOMP 0x08 /* CID compression */
|
||||
|
||||
#define IF_MTU 1500
|
||||
#define IF_MRU 1500
|
||||
#define IF_COMP IF_AUTOCOMP /* Flags for compression */
|
||||
|
||||
/* 2 for alignment, 14 for ethernet */
|
||||
#define IF_MAXLINKHDR (2 + ETH_HLEN)
|
||||
|
||||
#endif
|
||||
-242
@@ -1,242 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* 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 IP_H
|
||||
#define IP_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
# undef NTOHL
|
||||
# undef NTOHS
|
||||
# undef HTONL
|
||||
# undef HTONS
|
||||
# define NTOHL(d)
|
||||
# define NTOHS(d)
|
||||
# define HTONL(d)
|
||||
# define HTONS(d)
|
||||
#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
|
||||
|
||||
/*
|
||||
* Structure of an internet header, naked of options.
|
||||
*/
|
||||
struct ip {
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
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 */
|
||||
} SLIRP_PACKED;
|
||||
|
||||
#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.
|
||||
*/
|
||||
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 */
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
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;
|
||||
} SLIRP_PACKED;
|
||||
|
||||
/* 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 */
|
||||
|
||||
#if GLIB_SIZEOF_VOID_P == 4
|
||||
struct mbuf_ptr {
|
||||
struct mbuf *mptr;
|
||||
uint32_t dummy;
|
||||
} SLIRP_PACKED;
|
||||
#else
|
||||
struct mbuf_ptr {
|
||||
struct mbuf *mptr;
|
||||
} SLIRP_PACKED;
|
||||
#endif
|
||||
struct qlink {
|
||||
void *next, *prev;
|
||||
};
|
||||
|
||||
/*
|
||||
* Overlay for ip header used by other protocols (tcp, udp).
|
||||
*/
|
||||
struct ipovly {
|
||||
struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */
|
||||
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 */
|
||||
} SLIRP_PACKED;
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
struct qlink frag_link; /* to ip headers of fragments */
|
||||
struct qlink ip_link; /* to other reass headers */
|
||||
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 */
|
||||
struct in_addr ipq_src,ipq_dst;
|
||||
};
|
||||
|
||||
/*
|
||||
* Ip header, when holding a fragment.
|
||||
*
|
||||
* Note: ipf_link must be at same offset as frag_link above
|
||||
*/
|
||||
struct ipasfrag {
|
||||
struct qlink ipf_link;
|
||||
struct ip ipf_ip;
|
||||
};
|
||||
|
||||
G_STATIC_ASSERT(offsetof(struct ipq, frag_link) ==
|
||||
offsetof(struct ipasfrag, ipf_link));
|
||||
|
||||
#define ipf_off ipf_ip.ip_off
|
||||
#define ipf_tos ipf_ip.ip_tos
|
||||
#define ipf_len ipf_ip.ip_len
|
||||
#define ipf_next ipf_link.next
|
||||
#define ipf_prev ipf_link.prev
|
||||
|
||||
#endif
|
||||
-160
@@ -1,160 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2013
|
||||
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
|
||||
*/
|
||||
|
||||
#ifndef SLIRP_IP6_H
|
||||
#define SLIRP_IP6_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ALLNODES_MULTICAST { .s6_addr = \
|
||||
{ 0xff, 0x02, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x01 } }
|
||||
|
||||
#define SOLICITED_NODE_PREFIX { .s6_addr = \
|
||||
{ 0xff, 0x02, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x01,\
|
||||
0xff, 0x00, 0x00, 0x00 } }
|
||||
|
||||
#define LINKLOCAL_ADDR { .s6_addr = \
|
||||
{ 0xfe, 0x80, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x02 } }
|
||||
|
||||
#define ZERO_ADDR { .s6_addr = \
|
||||
{ 0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00,\
|
||||
0x00, 0x00, 0x00, 0x00 } }
|
||||
|
||||
static inline bool in6_equal(const struct in6_addr *a, const struct in6_addr *b)
|
||||
{
|
||||
return memcmp(a, b, sizeof(*a)) == 0;
|
||||
}
|
||||
|
||||
static inline bool in6_equal_net(const struct in6_addr *a,
|
||||
const struct in6_addr *b,
|
||||
int prefix_len)
|
||||
{
|
||||
if (memcmp(a, b, prefix_len / 8) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prefix_len % 8 == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return a->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8))
|
||||
== b->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8));
|
||||
}
|
||||
|
||||
static inline bool in6_equal_mach(const struct in6_addr *a,
|
||||
const struct in6_addr *b,
|
||||
int prefix_len)
|
||||
{
|
||||
if (memcmp(&(a->s6_addr[DIV_ROUND_UP(prefix_len, 8)]),
|
||||
&(b->s6_addr[DIV_ROUND_UP(prefix_len, 8)]),
|
||||
16 - DIV_ROUND_UP(prefix_len, 8)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prefix_len % 8 == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return (a->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1))
|
||||
== (b->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1));
|
||||
}
|
||||
|
||||
|
||||
#define in6_equal_router(a)\
|
||||
((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\
|
||||
&& in6_equal_mach(a, &slirp->vhost_addr6, slirp->vprefix_len))\
|
||||
|| (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
|
||||
&& in6_equal_mach(a, &slirp->vhost_addr6, 64)))
|
||||
|
||||
#define in6_equal_dns(a)\
|
||||
((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\
|
||||
&& in6_equal_mach(a, &slirp->vnameserver_addr6, slirp->vprefix_len))\
|
||||
|| (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
|
||||
&& in6_equal_mach(a, &slirp->vnameserver_addr6, 64)))
|
||||
|
||||
#define in6_equal_host(a)\
|
||||
(in6_equal_router(a) || in6_equal_dns(a))
|
||||
|
||||
#define in6_solicitednode_multicast(a)\
|
||||
(in6_equal_net(a, &(struct in6_addr)SOLICITED_NODE_PREFIX, 104))
|
||||
|
||||
#define in6_zero(a)\
|
||||
(in6_equal(a, &(struct in6_addr)ZERO_ADDR))
|
||||
|
||||
/* Compute emulated host MAC address from its ipv6 address */
|
||||
static inline void in6_compute_ethaddr(struct in6_addr ip,
|
||||
uint8_t eth[ETH_ALEN])
|
||||
{
|
||||
eth[0] = 0x52;
|
||||
eth[1] = 0x56;
|
||||
memcpy(ð[2], &ip.s6_addr[16 - (ETH_ALEN - 2)], ETH_ALEN - 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Definitions for internet protocol version 6.
|
||||
* Per RFC 2460, December 1998.
|
||||
*/
|
||||
#define IP6VERSION 6
|
||||
#define IP6_HOP_LIMIT 255
|
||||
|
||||
/*
|
||||
* Structure of an internet header, naked of options.
|
||||
*/
|
||||
struct ip6 {
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
uint32_t
|
||||
ip_v:4, /* version */
|
||||
ip_tc_hi:4, /* traffic class */
|
||||
ip_tc_lo:4,
|
||||
ip_fl_hi:4, /* flow label */
|
||||
ip_fl_lo:16;
|
||||
#else
|
||||
uint32_t
|
||||
ip_tc_hi:4,
|
||||
ip_v:4,
|
||||
ip_fl_hi:4,
|
||||
ip_tc_lo:4,
|
||||
ip_fl_lo:16;
|
||||
#endif
|
||||
uint16_t ip_pl; /* payload length */
|
||||
uint8_t ip_nh; /* next header */
|
||||
uint8_t ip_hl; /* hop limit */
|
||||
struct in6_addr ip_src, ip_dst; /* source and dest address */
|
||||
};
|
||||
|
||||
/*
|
||||
* IPv6 pseudo-header used by upper-layer protocols
|
||||
*/
|
||||
struct ip6_pseudohdr {
|
||||
struct in6_addr ih_src; /* source internet address */
|
||||
struct in6_addr ih_dst; /* destination internet address */
|
||||
uint32_t ih_pl; /* upper-layer packet length */
|
||||
uint16_t ih_zero_hi; /* zero */
|
||||
uint8_t ih_zero_lo; /* zero */
|
||||
uint8_t ih_nh; /* next header */
|
||||
};
|
||||
|
||||
/*
|
||||
* We don't want to mark these ip6 structs as packed as they are naturally
|
||||
* correctly aligned; instead assert that there is no stray padding.
|
||||
* If we marked the struct as packed then we would be unable to take
|
||||
* the address of any of the fields in it.
|
||||
*/
|
||||
G_STATIC_ASSERT(sizeof(struct ip6) == 40);
|
||||
G_STATIC_ASSERT(sizeof(struct ip6_pseudohdr) == 40);
|
||||
|
||||
#endif
|
||||
@@ -1,438 +0,0 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (c) 2013
|
||||
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
|
||||
*/
|
||||
|
||||
#include "slirp.h"
|
||||
#include "ip6_icmp.h"
|
||||
|
||||
#define NDP_Interval g_rand_int_range(slirp->grand, \
|
||||
NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval)
|
||||
|
||||
static void ra_timer_handler(void *opaque)
|
||||
{
|
||||
Slirp *slirp = opaque;
|
||||
|
||||
slirp->cb->timer_mod(slirp->ra_timer,
|
||||
slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + NDP_Interval,
|
||||
slirp->opaque);
|
||||
ndp_send_ra(slirp);
|
||||
}
|
||||
|
||||
void icmp6_init(Slirp *slirp)
|
||||
{
|
||||
if (!slirp->in6_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
slirp->ra_timer = slirp->cb->timer_new(ra_timer_handler, slirp, slirp->opaque);
|
||||
slirp->cb->timer_mod(slirp->ra_timer,
|
||||
slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + NDP_Interval,
|
||||
slirp->opaque);
|
||||
}
|
||||
|
||||
void icmp6_cleanup(Slirp *slirp)
|
||||
{
|
||||
if (!slirp->in6_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
slirp->cb->timer_free(slirp->ra_timer, slirp->opaque);
|
||||
}
|
||||
|
||||
static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
|
||||
struct icmp6 *icmp)
|
||||
{
|
||||
struct mbuf *t = m_get(slirp);
|
||||
t->m_len = sizeof(struct ip6) + ntohs(ip->ip_pl);
|
||||
memcpy(t->m_data, m->m_data, t->m_len);
|
||||
|
||||
/* IPv6 Packet */
|
||||
struct ip6 *rip = mtod(t, struct ip6 *);
|
||||
rip->ip_dst = ip->ip_src;
|
||||
rip->ip_src = ip->ip_dst;
|
||||
|
||||
/* ICMPv6 packet */
|
||||
t->m_data += sizeof(struct ip6);
|
||||
struct icmp6 *ricmp = mtod(t, struct icmp6 *);
|
||||
ricmp->icmp6_type = ICMP6_ECHO_REPLY;
|
||||
ricmp->icmp6_cksum = 0;
|
||||
|
||||
/* Checksum */
|
||||
t->m_data -= sizeof(struct ip6);
|
||||
ricmp->icmp6_cksum = ip6_cksum(t);
|
||||
|
||||
ip6_output(NULL, t, 0);
|
||||
}
|
||||
|
||||
void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
|
||||
{
|
||||
Slirp *slirp = m->slirp;
|
||||
struct mbuf *t;
|
||||
struct ip6 *ip = mtod(m, struct ip6 *);
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
|
||||
DEBUG_CALL("icmp6_send_error");
|
||||
DEBUG_ARG("type = %d, code = %d", type, code);
|
||||
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip->ip_src) ||
|
||||
in6_zero(&ip->ip_src)) {
|
||||
/* TODO icmp error? */
|
||||
return;
|
||||
}
|
||||
|
||||
t = m_get(slirp);
|
||||
|
||||
/* IPv6 packet */
|
||||
struct ip6 *rip = mtod(t, struct ip6 *);
|
||||
rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
|
||||
rip->ip_dst = ip->ip_src;
|
||||
inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
|
||||
DEBUG_ARG("target = %s", addrstr);
|
||||
|
||||
rip->ip_nh = IPPROTO_ICMPV6;
|
||||
const int error_data_len = MIN(m->m_len,
|
||||
IF_MTU - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN));
|
||||
rip->ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len);
|
||||
t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
|
||||
|
||||
/* ICMPv6 packet */
|
||||
t->m_data += sizeof(struct ip6);
|
||||
struct icmp6 *ricmp = mtod(t, struct icmp6 *);
|
||||
ricmp->icmp6_type = type;
|
||||
ricmp->icmp6_code = code;
|
||||
ricmp->icmp6_cksum = 0;
|
||||
|
||||
switch (type) {
|
||||
case ICMP6_UNREACH:
|
||||
case ICMP6_TIMXCEED:
|
||||
ricmp->icmp6_err.unused = 0;
|
||||
break;
|
||||
case ICMP6_TOOBIG:
|
||||
ricmp->icmp6_err.mtu = htonl(IF_MTU);
|
||||
break;
|
||||
case ICMP6_PARAMPROB:
|
||||
/* TODO: Handle this case */
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
t->m_data += ICMP6_ERROR_MINLEN;
|
||||
memcpy(t->m_data, m->m_data, error_data_len);
|
||||
|
||||
/* Checksum */
|
||||
t->m_data -= ICMP6_ERROR_MINLEN;
|
||||
t->m_data -= sizeof(struct ip6);
|
||||
ricmp->icmp6_cksum = ip6_cksum(t);
|
||||
|
||||
ip6_output(NULL, t, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send NDP Router Advertisement
|
||||
*/
|
||||
void ndp_send_ra(Slirp *slirp)
|
||||
{
|
||||
DEBUG_CALL("ndp_send_ra");
|
||||
|
||||
/* Build IPv6 packet */
|
||||
struct mbuf *t = m_get(slirp);
|
||||
struct ip6 *rip = mtod(t, struct ip6 *);
|
||||
size_t pl_size = 0;
|
||||
struct in6_addr addr;
|
||||
uint32_t scope_id;
|
||||
|
||||
rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
|
||||
rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST;
|
||||
rip->ip_nh = IPPROTO_ICMPV6;
|
||||
|
||||
/* Build ICMPv6 packet */
|
||||
t->m_data += sizeof(struct ip6);
|
||||
struct icmp6 *ricmp = mtod(t, struct icmp6 *);
|
||||
ricmp->icmp6_type = ICMP6_NDP_RA;
|
||||
ricmp->icmp6_code = 0;
|
||||
ricmp->icmp6_cksum = 0;
|
||||
|
||||
/* NDP */
|
||||
ricmp->icmp6_nra.chl = NDP_AdvCurHopLimit;
|
||||
ricmp->icmp6_nra.M = NDP_AdvManagedFlag;
|
||||
ricmp->icmp6_nra.O = NDP_AdvOtherConfigFlag;
|
||||
ricmp->icmp6_nra.reserved = 0;
|
||||
ricmp->icmp6_nra.lifetime = htons(NDP_AdvDefaultLifetime);
|
||||
ricmp->icmp6_nra.reach_time = htonl(NDP_AdvReachableTime);
|
||||
ricmp->icmp6_nra.retrans_time = htonl(NDP_AdvRetransTime);
|
||||
t->m_data += ICMP6_NDP_RA_MINLEN;
|
||||
pl_size += ICMP6_NDP_RA_MINLEN;
|
||||
|
||||
/* Source link-layer address (NDP option) */
|
||||
struct ndpopt *opt = mtod(t, struct ndpopt *);
|
||||
opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE;
|
||||
opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8;
|
||||
in6_compute_ethaddr(rip->ip_src, opt->ndpopt_linklayer);
|
||||
t->m_data += NDPOPT_LINKLAYER_LEN;
|
||||
pl_size += NDPOPT_LINKLAYER_LEN;
|
||||
|
||||
/* Prefix information (NDP option) */
|
||||
struct ndpopt *opt2 = mtod(t, struct ndpopt *);
|
||||
opt2->ndpopt_type = NDPOPT_PREFIX_INFO;
|
||||
opt2->ndpopt_len = NDPOPT_PREFIXINFO_LEN / 8;
|
||||
opt2->ndpopt_prefixinfo.prefix_length = slirp->vprefix_len;
|
||||
opt2->ndpopt_prefixinfo.L = 1;
|
||||
opt2->ndpopt_prefixinfo.A = 1;
|
||||
opt2->ndpopt_prefixinfo.reserved1 = 0;
|
||||
opt2->ndpopt_prefixinfo.valid_lt = htonl(NDP_AdvValidLifetime);
|
||||
opt2->ndpopt_prefixinfo.pref_lt = htonl(NDP_AdvPrefLifetime);
|
||||
opt2->ndpopt_prefixinfo.reserved2 = 0;
|
||||
opt2->ndpopt_prefixinfo.prefix = slirp->vprefix_addr6;
|
||||
t->m_data += NDPOPT_PREFIXINFO_LEN;
|
||||
pl_size += NDPOPT_PREFIXINFO_LEN;
|
||||
|
||||
/* Prefix information (NDP option) */
|
||||
if (get_dns6_addr(&addr, &scope_id) >= 0) {
|
||||
/* Host system does have an IPv6 DNS server, announce our proxy. */
|
||||
struct ndpopt *opt3 = mtod(t, struct ndpopt *);
|
||||
opt3->ndpopt_type = NDPOPT_RDNSS;
|
||||
opt3->ndpopt_len = NDPOPT_RDNSS_LEN / 8;
|
||||
opt3->ndpopt_rdnss.reserved = 0;
|
||||
opt3->ndpopt_rdnss.lifetime = htonl(2 * NDP_MaxRtrAdvInterval);
|
||||
opt3->ndpopt_rdnss.addr = slirp->vnameserver_addr6;
|
||||
t->m_data += NDPOPT_RDNSS_LEN;
|
||||
pl_size += NDPOPT_RDNSS_LEN;
|
||||
}
|
||||
|
||||
rip->ip_pl = htons(pl_size);
|
||||
t->m_data -= sizeof(struct ip6) + pl_size;
|
||||
t->m_len = sizeof(struct ip6) + pl_size;
|
||||
|
||||
/* ICMPv6 Checksum */
|
||||
ricmp->icmp6_cksum = ip6_cksum(t);
|
||||
|
||||
ip6_output(NULL, t, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send NDP Neighbor Solitication
|
||||
*/
|
||||
void ndp_send_ns(Slirp *slirp, struct in6_addr addr)
|
||||
{
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
|
||||
inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN);
|
||||
|
||||
DEBUG_CALL("ndp_send_ns");
|
||||
DEBUG_ARG("target = %s", addrstr);
|
||||
|
||||
/* Build IPv6 packet */
|
||||
struct mbuf *t = m_get(slirp);
|
||||
struct ip6 *rip = mtod(t, struct ip6 *);
|
||||
rip->ip_src = slirp->vhost_addr6;
|
||||
rip->ip_dst = (struct in6_addr)SOLICITED_NODE_PREFIX;
|
||||
memcpy(&rip->ip_dst.s6_addr[13], &addr.s6_addr[13], 3);
|
||||
rip->ip_nh = IPPROTO_ICMPV6;
|
||||
rip->ip_pl = htons(ICMP6_NDP_NS_MINLEN + NDPOPT_LINKLAYER_LEN);
|
||||
t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
|
||||
|
||||
/* Build ICMPv6 packet */
|
||||
t->m_data += sizeof(struct ip6);
|
||||
struct icmp6 *ricmp = mtod(t, struct icmp6 *);
|
||||
ricmp->icmp6_type = ICMP6_NDP_NS;
|
||||
ricmp->icmp6_code = 0;
|
||||
ricmp->icmp6_cksum = 0;
|
||||
|
||||
/* NDP */
|
||||
ricmp->icmp6_nns.reserved = 0;
|
||||
ricmp->icmp6_nns.target = addr;
|
||||
|
||||
/* Build NDP option */
|
||||
t->m_data += ICMP6_NDP_NS_MINLEN;
|
||||
struct ndpopt *opt = mtod(t, struct ndpopt *);
|
||||
opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE;
|
||||
opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8;
|
||||
in6_compute_ethaddr(slirp->vhost_addr6, opt->ndpopt_linklayer);
|
||||
|
||||
/* ICMPv6 Checksum */
|
||||
t->m_data -= ICMP6_NDP_NA_MINLEN;
|
||||
t->m_data -= sizeof(struct ip6);
|
||||
ricmp->icmp6_cksum = ip6_cksum(t);
|
||||
|
||||
ip6_output(NULL, t, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send NDP Neighbor Advertisement
|
||||
*/
|
||||
static void ndp_send_na(Slirp *slirp, struct ip6 *ip, struct icmp6 *icmp)
|
||||
{
|
||||
/* Build IPv6 packet */
|
||||
struct mbuf *t = m_get(slirp);
|
||||
struct ip6 *rip = mtod(t, struct ip6 *);
|
||||
rip->ip_src = icmp->icmp6_nns.target;
|
||||
if (in6_zero(&ip->ip_src)) {
|
||||
rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST;
|
||||
} else {
|
||||
rip->ip_dst = ip->ip_src;
|
||||
}
|
||||
rip->ip_nh = IPPROTO_ICMPV6;
|
||||
rip->ip_pl = htons(ICMP6_NDP_NA_MINLEN
|
||||
+ NDPOPT_LINKLAYER_LEN);
|
||||
t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
|
||||
|
||||
/* Build ICMPv6 packet */
|
||||
t->m_data += sizeof(struct ip6);
|
||||
struct icmp6 *ricmp = mtod(t, struct icmp6 *);
|
||||
ricmp->icmp6_type = ICMP6_NDP_NA;
|
||||
ricmp->icmp6_code = 0;
|
||||
ricmp->icmp6_cksum = 0;
|
||||
|
||||
/* NDP */
|
||||
ricmp->icmp6_nna.R = NDP_IsRouter;
|
||||
ricmp->icmp6_nna.S = !IN6_IS_ADDR_MULTICAST(&rip->ip_dst);
|
||||
ricmp->icmp6_nna.O = 1;
|
||||
ricmp->icmp6_nna.reserved_hi = 0;
|
||||
ricmp->icmp6_nna.reserved_lo = 0;
|
||||
ricmp->icmp6_nna.target = icmp->icmp6_nns.target;
|
||||
|
||||
/* Build NDP option */
|
||||
t->m_data += ICMP6_NDP_NA_MINLEN;
|
||||
struct ndpopt *opt = mtod(t, struct ndpopt *);
|
||||
opt->ndpopt_type = NDPOPT_LINKLAYER_TARGET;
|
||||
opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8;
|
||||
in6_compute_ethaddr(ricmp->icmp6_nna.target,
|
||||
opt->ndpopt_linklayer);
|
||||
|
||||
/* ICMPv6 Checksum */
|
||||
t->m_data -= ICMP6_NDP_NA_MINLEN;
|
||||
t->m_data -= sizeof(struct ip6);
|
||||
ricmp->icmp6_cksum = ip6_cksum(t);
|
||||
|
||||
ip6_output(NULL, t, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a NDP message
|
||||
*/
|
||||
static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
|
||||
struct icmp6 *icmp)
|
||||
{
|
||||
m->m_len += ETH_HLEN;
|
||||
m->m_data -= ETH_HLEN;
|
||||
struct ethhdr *eth = mtod(m, struct ethhdr *);
|
||||
m->m_len -= ETH_HLEN;
|
||||
m->m_data += ETH_HLEN;
|
||||
|
||||
switch (icmp->icmp6_type) {
|
||||
case ICMP6_NDP_RS:
|
||||
DEBUG_CALL(" type = Router Solicitation");
|
||||
if (ip->ip_hl == 255
|
||||
&& icmp->icmp6_code == 0
|
||||
&& ntohs(ip->ip_pl) >= ICMP6_NDP_RS_MINLEN) {
|
||||
/* Gratuitous NDP */
|
||||
ndp_table_add(slirp, ip->ip_src, eth->h_source);
|
||||
|
||||
ndp_send_ra(slirp);
|
||||
}
|
||||
break;
|
||||
|
||||
case ICMP6_NDP_RA:
|
||||
DEBUG_CALL(" type = Router Advertisement");
|
||||
slirp->cb->guest_error("Warning: guest sent NDP RA, but shouldn't",
|
||||
slirp->opaque);
|
||||
break;
|
||||
|
||||
case ICMP6_NDP_NS:
|
||||
DEBUG_CALL(" type = Neighbor Solicitation");
|
||||
if (ip->ip_hl == 255
|
||||
&& icmp->icmp6_code == 0
|
||||
&& !IN6_IS_ADDR_MULTICAST(&icmp->icmp6_nns.target)
|
||||
&& ntohs(ip->ip_pl) >= ICMP6_NDP_NS_MINLEN
|
||||
&& (!in6_zero(&ip->ip_src)
|
||||
|| in6_solicitednode_multicast(&ip->ip_dst))) {
|
||||
if (in6_equal_host(&icmp->icmp6_nns.target)) {
|
||||
/* Gratuitous NDP */
|
||||
ndp_table_add(slirp, ip->ip_src, eth->h_source);
|
||||
ndp_send_na(slirp, ip, icmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ICMP6_NDP_NA:
|
||||
DEBUG_CALL(" type = Neighbor Advertisement");
|
||||
if (ip->ip_hl == 255
|
||||
&& icmp->icmp6_code == 0
|
||||
&& ntohs(ip->ip_pl) >= ICMP6_NDP_NA_MINLEN
|
||||
&& !IN6_IS_ADDR_MULTICAST(&icmp->icmp6_nna.target)
|
||||
&& (!IN6_IS_ADDR_MULTICAST(&ip->ip_dst)
|
||||
|| icmp->icmp6_nna.S == 0)) {
|
||||
ndp_table_add(slirp, ip->ip_src, eth->h_source);
|
||||
}
|
||||
break;
|
||||
|
||||
case ICMP6_NDP_REDIRECT:
|
||||
DEBUG_CALL(" type = Redirect");
|
||||
slirp->cb->guest_error(
|
||||
"Warning: guest sent NDP REDIRECT, but shouldn't", slirp->opaque);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a received ICMPv6 message.
|
||||
*/
|
||||
void icmp6_input(struct mbuf *m)
|
||||
{
|
||||
struct icmp6 *icmp;
|
||||
struct ip6 *ip = mtod(m, struct ip6 *);
|
||||
Slirp *slirp = m->slirp;
|
||||
int hlen = sizeof(struct ip6);
|
||||
|
||||
DEBUG_CALL("icmp6_input");
|
||||
DEBUG_ARG("m = %p", m);
|
||||
DEBUG_ARG("m_len = %d", m->m_len);
|
||||
|
||||
if (ntohs(ip->ip_pl) < ICMP6_MINLEN) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ip6_cksum(m)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
m->m_len -= hlen;
|
||||
m->m_data += hlen;
|
||||
icmp = mtod(m, struct icmp6 *);
|
||||
m->m_len += hlen;
|
||||
m->m_data -= hlen;
|
||||
|
||||
DEBUG_ARG("icmp6_type = %d", icmp->icmp6_type);
|
||||
switch (icmp->icmp6_type) {
|
||||
case ICMP6_ECHO_REQUEST:
|
||||
if (in6_equal_host(&ip->ip_dst)) {
|
||||
icmp6_send_echoreply(m, slirp, ip, icmp);
|
||||
} else {
|
||||
/* TODO */
|
||||
g_critical("external icmpv6 not supported yet");
|
||||
}
|
||||
break;
|
||||
|
||||
case ICMP6_NDP_RS:
|
||||
case ICMP6_NDP_RA:
|
||||
case ICMP6_NDP_NS:
|
||||
case ICMP6_NDP_NA:
|
||||
case ICMP6_NDP_REDIRECT:
|
||||
ndp_input(m, slirp, ip, icmp);
|
||||
break;
|
||||
|
||||
case ICMP6_UNREACH:
|
||||
case ICMP6_TOOBIG:
|
||||
case ICMP6_TIMXCEED:
|
||||
case ICMP6_PARAMPROB:
|
||||
/* XXX? report error? close socket? */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
m_free(m);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user