mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@733 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
+212
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
/* XXX: only DHCP is supported */
|
||||
|
||||
#define NB_ADDR 16
|
||||
|
||||
#define START_ADDR 15
|
||||
|
||||
#define LEASE_TIME (24 * 3600)
|
||||
|
||||
typedef struct {
|
||||
uint8_t allocated;
|
||||
} BOOTPClient;
|
||||
|
||||
BOOTPClient bootp_clients[NB_ADDR];
|
||||
|
||||
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintf(fmt, args...) \
|
||||
if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); }
|
||||
#else
|
||||
#define dprintf(fmt, args...)
|
||||
#endif
|
||||
|
||||
static BOOTPClient *get_new_addr(struct in_addr *paddr)
|
||||
{
|
||||
BOOTPClient *bc;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < NB_ADDR; i++) {
|
||||
if (!bootp_clients[i].allocated)
|
||||
goto found;
|
||||
}
|
||||
return NULL;
|
||||
found:
|
||||
bc = &bootp_clients[i];
|
||||
bc->allocated = 1;
|
||||
paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
|
||||
return bc;
|
||||
}
|
||||
|
||||
static void dhcp_decode(const uint8_t *buf, int size,
|
||||
int *pmsg_type)
|
||||
{
|
||||
const uint8_t *p, *p_end;
|
||||
int len, tag;
|
||||
|
||||
*pmsg_type = 0;
|
||||
|
||||
p = buf;
|
||||
p_end = buf + size;
|
||||
if (size < 5)
|
||||
return;
|
||||
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++;
|
||||
dprintf("dhcp: tag=0x%02x len=%d\n", tag, len);
|
||||
|
||||
switch(tag) {
|
||||
case RFC2132_MSG_TYPE:
|
||||
if (len >= 1)
|
||||
*pmsg_type = p[0];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
p += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bootp_reply(struct bootp_t *bp)
|
||||
{
|
||||
BOOTPClient *bc;
|
||||
struct mbuf *m;
|
||||
struct bootp_t *rbp;
|
||||
struct sockaddr_in saddr, daddr;
|
||||
struct in_addr dns_addr;
|
||||
int dhcp_msg_type, val;
|
||||
uint8_t *q;
|
||||
|
||||
/* extract exact DHCP msg type */
|
||||
dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
|
||||
dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
|
||||
|
||||
if (dhcp_msg_type != DHCPDISCOVER &&
|
||||
dhcp_msg_type != DHCPREQUEST)
|
||||
return;
|
||||
/* XXX: this is a hack to get the client mac address */
|
||||
memcpy(client_ethaddr, bp->bp_hwaddr, 6);
|
||||
|
||||
if ((m = m_get()) == NULL)
|
||||
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));
|
||||
|
||||
bc = get_new_addr(&daddr.sin_addr);
|
||||
if (!bc) {
|
||||
dprintf("no address left\n");
|
||||
return;
|
||||
}
|
||||
dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
|
||||
|
||||
saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
|
||||
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, 6);
|
||||
|
||||
rbp->bp_yiaddr = daddr.sin_addr; /* IP address */
|
||||
|
||||
q = rbp->bp_vend;
|
||||
memcpy(q, rfc1533_cookie, 4);
|
||||
q += 4;
|
||||
|
||||
if (dhcp_msg_type == DHCPDISCOVER) {
|
||||
*q++ = RFC2132_MSG_TYPE;
|
||||
*q++ = 1;
|
||||
*q++ = DHCPOFFER;
|
||||
} else if (dhcp_msg_type == DHCPREQUEST) {
|
||||
*q++ = RFC2132_MSG_TYPE;
|
||||
*q++ = 1;
|
||||
*q++ = DHCPACK;
|
||||
}
|
||||
|
||||
if (dhcp_msg_type == DHCPDISCOVER ||
|
||||
dhcp_msg_type == DHCPREQUEST) {
|
||||
*q++ = RFC2132_SRV_ID;
|
||||
*q++ = 4;
|
||||
memcpy(q, &saddr.sin_addr, 4);
|
||||
q += 4;
|
||||
|
||||
*q++ = RFC1533_NETMASK;
|
||||
*q++ = 4;
|
||||
*q++ = 0xff;
|
||||
*q++ = 0xff;
|
||||
*q++ = 0xff;
|
||||
*q++ = 0x00;
|
||||
|
||||
*q++ = RFC1533_GATEWAY;
|
||||
*q++ = 4;
|
||||
memcpy(q, &saddr.sin_addr, 4);
|
||||
q += 4;
|
||||
|
||||
*q++ = RFC1533_DNS;
|
||||
*q++ = 4;
|
||||
dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
|
||||
memcpy(q, &dns_addr, 4);
|
||||
q += 4;
|
||||
|
||||
*q++ = RFC2132_LEASE_TIME;
|
||||
*q++ = 4;
|
||||
val = htonl(LEASE_TIME);
|
||||
memcpy(q, &val, 4);
|
||||
q += 4;
|
||||
}
|
||||
*q++ = RFC1533_END;
|
||||
|
||||
m->m_len = sizeof(struct bootp_t);
|
||||
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
||||
}
|
||||
|
||||
void bootp_input(struct mbuf *m)
|
||||
{
|
||||
struct bootp_t *bp = (struct bootp_t *)m->m_data;
|
||||
|
||||
if (bp->bp_op == BOOTP_REQUEST) {
|
||||
bootp_reply(bp);
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/* 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 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
|
||||
|
||||
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;
|
||||
unsigned long bp_xid;
|
||||
unsigned short bp_secs;
|
||||
unsigned short 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];
|
||||
};
|
||||
|
||||
void bootp_input(struct mbuf *m);
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. 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]; ADDCARRY(sum);}
|
||||
|
||||
int cksum(struct mbuf *m, int len)
|
||||
{
|
||||
register u_int16_t *w;
|
||||
register int sum = 0;
|
||||
register int mlen = 0;
|
||||
int byte_swapped = 0;
|
||||
|
||||
union {
|
||||
u_int8_t c[2];
|
||||
u_int16_t s;
|
||||
} s_util;
|
||||
union {
|
||||
u_int16_t s[2];
|
||||
u_int32_t l;
|
||||
} l_util;
|
||||
|
||||
if (m->m_len == 0)
|
||||
goto cont;
|
||||
w = mtod(m, u_int16_t *);
|
||||
|
||||
mlen = m->m_len;
|
||||
|
||||
if (len < mlen)
|
||||
mlen = len;
|
||||
len -= mlen;
|
||||
/*
|
||||
* Force to even boundary.
|
||||
*/
|
||||
if ((1 & (long) w) && (mlen > 0)) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
s_util.c[0] = *(u_int8_t *)w;
|
||||
w = (u_int16_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] = *(u_int8_t *)w;
|
||||
sum += s_util.s;
|
||||
mlen = 0;
|
||||
} else
|
||||
|
||||
mlen = -1;
|
||||
} else if (mlen == -1)
|
||||
s_util.c[0] = *(u_int8_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 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);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#define CTL_CMD 0
|
||||
#define CTL_EXEC 1
|
||||
#define CTL_ALIAS 2
|
||||
#define CTL_DNS 3
|
||||
|
||||
#define CTL_SPECIAL "10.0.2.0"
|
||||
#define CTL_LOCAL "10.0.2.15"
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
* Portions copyright (c) 2000 Kelly Price.
|
||||
*
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
#include <slirp.h>
|
||||
|
||||
FILE *dfd = NULL;
|
||||
#ifdef DEBUG
|
||||
int dostats = 1;
|
||||
#else
|
||||
int dostats = 0;
|
||||
#endif
|
||||
int slirp_debug = 0;
|
||||
|
||||
extern char *strerror _P((int));
|
||||
|
||||
/* Carry over one item from main.c so that the tty's restored.
|
||||
* Only done when the tty being used is /dev/tty --RedWolf */
|
||||
extern struct termios slirp_tty_settings;
|
||||
extern int slirp_tty_restore;
|
||||
|
||||
|
||||
void
|
||||
debug_init(file, dbg)
|
||||
char *file;
|
||||
int dbg;
|
||||
{
|
||||
/* Close the old debugging file */
|
||||
if (dfd)
|
||||
fclose(dfd);
|
||||
|
||||
dfd = fopen(file,"w");
|
||||
if (dfd != NULL) {
|
||||
#if 0
|
||||
fprintf(dfd,"Slirp %s - Debugging Started.\n", SLIRP_VERSION);
|
||||
#endif
|
||||
fprintf(dfd,"Debugging Started level %i.\r\n",dbg);
|
||||
fflush(dfd);
|
||||
slirp_debug = dbg;
|
||||
} else {
|
||||
lprint("Error: Debugging file \"%s\" could not be opened: %s\r\n",
|
||||
file, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump a packet in the same format as tcpdump -x
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
void
|
||||
dump_packet(dat, n)
|
||||
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
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Statistic routines
|
||||
*
|
||||
* These will print statistics to the screen, the debug file (dfd), or
|
||||
* a buffer, depending on "type", so that the stats can be sent over
|
||||
* the link as well.
|
||||
*/
|
||||
|
||||
void
|
||||
ttystats(ttyp)
|
||||
struct ttys *ttyp;
|
||||
{
|
||||
struct slirp_ifstats *is = &ttyp->ifstats;
|
||||
char buff[512];
|
||||
|
||||
lprint(" \r\n");
|
||||
|
||||
if (if_comp & IF_COMPRESS)
|
||||
strcpy(buff, "on");
|
||||
else if (if_comp & IF_NOCOMPRESS)
|
||||
strcpy(buff, "off");
|
||||
else
|
||||
strcpy(buff, "off (for now)");
|
||||
lprint("Unit %d:\r\n", ttyp->unit);
|
||||
lprint(" using %s encapsulation (VJ compression is %s)\r\n", (
|
||||
#ifdef USE_PPP
|
||||
ttyp->proto==PROTO_PPP?"PPP":
|
||||
#endif
|
||||
"SLIP"), buff);
|
||||
lprint(" %d baudrate\r\n", ttyp->baud);
|
||||
lprint(" interface is %s\r\n", ttyp->up?"up":"down");
|
||||
lprint(" using fd %d, guardian pid is %d\r\n", ttyp->fd, ttyp->pid);
|
||||
#ifndef FULL_BOLT
|
||||
lprint(" towrite is %d bytes\r\n", ttyp->towrite);
|
||||
#endif
|
||||
if (ttyp->zeros)
|
||||
lprint(" %d zeros have been typed\r\n", ttyp->zeros);
|
||||
else if (ttyp->ones)
|
||||
lprint(" %d ones have been typed\r\n", ttyp->ones);
|
||||
lprint("Interface stats:\r\n");
|
||||
lprint(" %6d output packets sent (%d bytes)\r\n", is->out_pkts, is->out_bytes);
|
||||
lprint(" %6d output packets dropped (%d bytes)\r\n", is->out_errpkts, is->out_errbytes);
|
||||
lprint(" %6d input packets received (%d bytes)\r\n", is->in_pkts, is->in_bytes);
|
||||
lprint(" %6d input packets dropped (%d bytes)\r\n", is->in_errpkts, is->in_errbytes);
|
||||
lprint(" %6d bad input packets\r\n", is->in_mbad);
|
||||
}
|
||||
|
||||
void
|
||||
allttystats()
|
||||
{
|
||||
struct ttys *ttyp;
|
||||
|
||||
for (ttyp = ttys; ttyp; ttyp = ttyp->next)
|
||||
ttystats(ttyp);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ipstats()
|
||||
{
|
||||
lprint(" \r\n");
|
||||
|
||||
lprint("IP stats:\r\n");
|
||||
lprint(" %6d total packets received (%d were unaligned)\r\n",
|
||||
ipstat.ips_total, ipstat.ips_unaligned);
|
||||
lprint(" %6d with incorrect version\r\n", ipstat.ips_badvers);
|
||||
lprint(" %6d with bad header checksum\r\n", ipstat.ips_badsum);
|
||||
lprint(" %6d with length too short (len < sizeof(iphdr))\r\n", ipstat.ips_tooshort);
|
||||
lprint(" %6d with length too small (len < ip->len)\r\n", ipstat.ips_toosmall);
|
||||
lprint(" %6d with bad header length\r\n", ipstat.ips_badhlen);
|
||||
lprint(" %6d with bad packet length\r\n", ipstat.ips_badlen);
|
||||
lprint(" %6d fragments received\r\n", ipstat.ips_fragments);
|
||||
lprint(" %6d fragments dropped\r\n", ipstat.ips_fragdropped);
|
||||
lprint(" %6d fragments timed out\r\n", ipstat.ips_fragtimeout);
|
||||
lprint(" %6d packets reassembled ok\r\n", ipstat.ips_reassembled);
|
||||
lprint(" %6d outgoing packets fragmented\r\n", ipstat.ips_fragmented);
|
||||
lprint(" %6d total outgoing fragments\r\n", ipstat.ips_ofragments);
|
||||
lprint(" %6d with bad protocol field\r\n", ipstat.ips_noproto);
|
||||
lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
vjstats()
|
||||
{
|
||||
lprint(" \r\n");
|
||||
|
||||
lprint("VJ compression stats:\r\n");
|
||||
|
||||
lprint(" %6d outbound packets (%d compressed)\r\n",
|
||||
comp_s.sls_packets, comp_s.sls_compressed);
|
||||
lprint(" %6d searches for connection stats (%d misses)\r\n",
|
||||
comp_s.sls_searches, comp_s.sls_misses);
|
||||
lprint(" %6d inbound uncompressed packets\r\n", comp_s.sls_uncompressedin);
|
||||
lprint(" %6d inbound compressed packets\r\n", comp_s.sls_compressedin);
|
||||
lprint(" %6d inbound unknown type packets\r\n", comp_s.sls_errorin);
|
||||
lprint(" %6d inbound packets tossed due to error\r\n", comp_s.sls_tossed);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
tcpstats()
|
||||
{
|
||||
lprint(" \r\n");
|
||||
|
||||
lprint("TCP stats:\r\n");
|
||||
|
||||
lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal);
|
||||
lprint(" %6d data packets (%d bytes)\r\n",
|
||||
tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
|
||||
lprint(" %6d data packets retransmitted (%d bytes)\r\n",
|
||||
tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte);
|
||||
lprint(" %6d ack-only packets (%d delayed)\r\n",
|
||||
tcpstat.tcps_sndacks, tcpstat.tcps_delack);
|
||||
lprint(" %6d URG only packets\r\n", tcpstat.tcps_sndurg);
|
||||
lprint(" %6d window probe packets\r\n", tcpstat.tcps_sndprobe);
|
||||
lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup);
|
||||
lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl);
|
||||
lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin);
|
||||
|
||||
lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal);
|
||||
lprint(" %6d acks (for %d bytes)\r\n",
|
||||
tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
|
||||
lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack);
|
||||
lprint(" %6d acks for unsent data\r\n", tcpstat.tcps_rcvacktoomuch);
|
||||
lprint(" %6d packets received in sequence (%d bytes)\r\n",
|
||||
tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
|
||||
lprint(" %6d completely duplicate packets (%d bytes)\r\n",
|
||||
tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
|
||||
|
||||
lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n",
|
||||
tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
|
||||
lprint(" %6d out-of-order packets (%d bytes)\r\n",
|
||||
tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte);
|
||||
lprint(" %6d packets of data after window (%d bytes)\r\n",
|
||||
tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin);
|
||||
lprint(" %6d window probes\r\n", tcpstat.tcps_rcvwinprobe);
|
||||
lprint(" %6d window update packets\r\n", tcpstat.tcps_rcvwinupd);
|
||||
lprint(" %6d packets received after close\r\n", tcpstat.tcps_rcvafterclose);
|
||||
lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum);
|
||||
lprint(" %6d discarded for bad header offset fields\r\n",
|
||||
tcpstat.tcps_rcvbadoff);
|
||||
|
||||
lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt);
|
||||
lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts);
|
||||
lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects);
|
||||
lprint(" %6d connections closed (including %d drop)\r\n",
|
||||
tcpstat.tcps_closed, tcpstat.tcps_drops);
|
||||
lprint(" %6d embryonic connections dropped\r\n", tcpstat.tcps_conndrops);
|
||||
lprint(" %6d segments we tried to get rtt (%d succeeded)\r\n",
|
||||
tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated);
|
||||
lprint(" %6d retransmit timeouts\r\n", tcpstat.tcps_rexmttimeo);
|
||||
lprint(" %6d connections dropped by rxmt timeout\r\n",
|
||||
tcpstat.tcps_timeoutdrop);
|
||||
lprint(" %6d persist timeouts\r\n", tcpstat.tcps_persisttimeo);
|
||||
lprint(" %6d keepalive timeouts\r\n", tcpstat.tcps_keeptimeo);
|
||||
lprint(" %6d keepalive probes sent\r\n", tcpstat.tcps_keepprobe);
|
||||
lprint(" %6d connections dropped by keepalive\r\n", tcpstat.tcps_keepdrops);
|
||||
lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack);
|
||||
lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat);
|
||||
lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
|
||||
|
||||
|
||||
/* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */
|
||||
/* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
udpstats()
|
||||
{
|
||||
lprint(" \r\n");
|
||||
|
||||
lprint("UDP stats:\r\n");
|
||||
lprint(" %6d datagrams received\r\n", udpstat.udps_ipackets);
|
||||
lprint(" %6d with packets shorter than header\r\n", udpstat.udps_hdrops);
|
||||
lprint(" %6d with bad checksums\r\n", udpstat.udps_badsum);
|
||||
lprint(" %6d with data length larger than packet\r\n", udpstat.udps_badlen);
|
||||
lprint(" %6d UDP socket cache misses\r\n", udpstat.udpps_pcbcachemiss);
|
||||
lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets);
|
||||
}
|
||||
|
||||
void
|
||||
icmpstats()
|
||||
{
|
||||
lprint(" \r\n");
|
||||
lprint("ICMP stats:\r\n");
|
||||
lprint(" %6d ICMP packets received\r\n", icmpstat.icps_received);
|
||||
lprint(" %6d were too short\r\n", icmpstat.icps_tooshort);
|
||||
lprint(" %6d with bad checksums\r\n", icmpstat.icps_checksum);
|
||||
lprint(" %6d with type not supported\r\n", icmpstat.icps_notsupp);
|
||||
lprint(" %6d with bad type feilds\r\n", icmpstat.icps_badtype);
|
||||
lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
|
||||
}
|
||||
|
||||
void
|
||||
mbufstats()
|
||||
{
|
||||
struct mbuf *m;
|
||||
int i;
|
||||
|
||||
lprint(" \r\n");
|
||||
|
||||
lprint("Mbuf stats:\r\n");
|
||||
|
||||
lprint(" %6d mbufs allocated (%d max)\r\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\r\n", i);
|
||||
|
||||
i = 0;
|
||||
for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
|
||||
i++;
|
||||
lprint(" %6d mbufs on used list\r\n", i);
|
||||
lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
|
||||
}
|
||||
|
||||
void
|
||||
sockstats()
|
||||
{
|
||||
char buff[256];
|
||||
int n;
|
||||
struct socket *so;
|
||||
|
||||
lprint(" \r\n");
|
||||
|
||||
lprint(
|
||||
"Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\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\r\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);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
slirp_exit(exit_status)
|
||||
int exit_status;
|
||||
{
|
||||
struct ttys *ttyp;
|
||||
|
||||
DEBUG_CALL("slirp_exit");
|
||||
DEBUG_ARG("exit_status = %d", exit_status);
|
||||
|
||||
if (dostats) {
|
||||
lprint_print = (int (*) _P((void *, const char *, va_list)))vfprintf;
|
||||
if (!dfd)
|
||||
debug_init("slirp_stats", 0xf);
|
||||
lprint_arg = (char **)&dfd;
|
||||
|
||||
ipstats();
|
||||
tcpstats();
|
||||
udpstats();
|
||||
icmpstats();
|
||||
mbufstats();
|
||||
sockstats();
|
||||
allttystats();
|
||||
vjstats();
|
||||
}
|
||||
|
||||
for (ttyp = ttys; ttyp; ttyp = ttyp->next)
|
||||
tty_detached(ttyp, 1);
|
||||
|
||||
if (slirp_forked) {
|
||||
/* Menendez time */
|
||||
if (kill(getppid(), SIGQUIT) < 0)
|
||||
lprint("Couldn't kill parent process %ld!\n",
|
||||
(long) getppid());
|
||||
}
|
||||
|
||||
/* Restore the terminal if we gotta */
|
||||
if(slirp_tty_restore)
|
||||
tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */
|
||||
exit(exit_status);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
#define PRN_STDERR 1
|
||||
#define PRN_SPRINTF 2
|
||||
|
||||
extern FILE *dfd;
|
||||
extern FILE *lfd;
|
||||
extern int dostats;
|
||||
extern int slirp_debug;
|
||||
|
||||
#define DBG_CALL 0x1
|
||||
#define DBG_MISC 0x2
|
||||
#define DBG_ERROR 0x4
|
||||
#define DEBUG_DEFAULT DBG_CALL|DBG_MISC|DBG_ERROR
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { fprintf(dfd, "%s...\n", x); fflush(dfd); }
|
||||
#define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { fputc(' ', dfd); fprintf(dfd, x, y); fputc('\n', dfd); fflush(dfd); }
|
||||
#define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { fprintf x ; fflush(dfd); }
|
||||
#define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { fprintf x ; fflush(dfd); }
|
||||
#define DEBUG_ERROR(x) if (slirp_debug & 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
|
||||
|
||||
void debug_init _P((char *, int));
|
||||
//void ttystats _P((struct ttys *));
|
||||
void allttystats _P((void));
|
||||
void ipstats _P((void));
|
||||
void vjstats _P((void));
|
||||
void tcpstats _P((void));
|
||||
void udpstats _P((void));
|
||||
void icmpstats _P((void));
|
||||
void mbufstats _P((void));
|
||||
void sockstats _P((void));
|
||||
void slirp_exit _P((int));
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. 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
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
#include <slirp.h>
|
||||
|
||||
int if_mtu, if_mru;
|
||||
int if_comp;
|
||||
int if_maxlinkhdr;
|
||||
int if_queued = 0; /* Number of packets queued so far */
|
||||
int if_thresh = 10; /* Number of packets queued before we start sending
|
||||
* (to prevent allocing too many mbufs) */
|
||||
|
||||
struct mbuf if_fastq; /* fast queue (for interactive data) */
|
||||
struct mbuf if_batchq; /* queue for non-interactive data */
|
||||
struct mbuf *next_m; /* Pointer to next mbuf to output */
|
||||
|
||||
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
|
||||
|
||||
void
|
||||
ifs_insque(ifm, ifmhead)
|
||||
struct mbuf *ifm, *ifmhead;
|
||||
{
|
||||
ifm->ifs_next = ifmhead->ifs_next;
|
||||
ifmhead->ifs_next = ifm;
|
||||
ifm->ifs_prev = ifmhead;
|
||||
ifm->ifs_next->ifs_prev = ifm;
|
||||
}
|
||||
|
||||
void
|
||||
ifs_remque(ifm)
|
||||
struct mbuf *ifm;
|
||||
{
|
||||
ifm->ifs_prev->ifs_next = ifm->ifs_next;
|
||||
ifm->ifs_next->ifs_prev = ifm->ifs_prev;
|
||||
}
|
||||
|
||||
void
|
||||
if_init()
|
||||
{
|
||||
#if 0
|
||||
/*
|
||||
* Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
|
||||
* and 8 bytes for PPP, but need to have it on an 8byte boundary
|
||||
*/
|
||||
#ifdef USE_PPP
|
||||
if_maxlinkhdr = 48;
|
||||
#else
|
||||
if_maxlinkhdr = 40;
|
||||
#endif
|
||||
#else
|
||||
/* 14 for ethernet + 40 */
|
||||
if_maxlinkhdr = 14 + 40;
|
||||
#endif
|
||||
if_mtu = 1500;
|
||||
if_mru = 1500;
|
||||
if_comp = IF_AUTOCOMP;
|
||||
if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
|
||||
if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
|
||||
// sl_compress_init(&comp_s);
|
||||
next_m = &if_batchq;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This shouldn't be needed since the modem is blocking and
|
||||
* we don't expect any signals, but what the hell..
|
||||
*/
|
||||
inline int
|
||||
writen(fd, bptr, n)
|
||||
int fd;
|
||||
char *bptr;
|
||||
int n;
|
||||
{
|
||||
int ret;
|
||||
int total;
|
||||
|
||||
/* This should succeed most of the time */
|
||||
ret = write(fd, bptr, n);
|
||||
if (ret == n || ret <= 0)
|
||||
return ret;
|
||||
|
||||
/* Didn't write everything, go into the loop */
|
||||
total = ret;
|
||||
while (n > total) {
|
||||
ret = write(fd, bptr+total, n-total);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
total += ret;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/*
|
||||
* if_input - read() the tty, do "top level" processing (ie: check for any escapes),
|
||||
* and pass onto (*ttyp->if_input)
|
||||
*
|
||||
* XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
|
||||
*/
|
||||
#define INBUFF_SIZE 2048 /* XXX */
|
||||
void
|
||||
if_input(ttyp)
|
||||
struct ttys *ttyp;
|
||||
{
|
||||
u_char if_inbuff[INBUFF_SIZE];
|
||||
int if_n;
|
||||
|
||||
DEBUG_CALL("if_input");
|
||||
DEBUG_ARG("ttyp = %lx", (long)ttyp);
|
||||
|
||||
if_n = read(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE);
|
||||
|
||||
DEBUG_MISC((dfd, " read %d bytes\n", if_n));
|
||||
|
||||
if (if_n <= 0) {
|
||||
if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
|
||||
if (ttyp->up)
|
||||
link_up--;
|
||||
tty_detached(ttyp, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (if_n == 1) {
|
||||
if (*if_inbuff == '0') {
|
||||
ttyp->ones = 0;
|
||||
if (++ttyp->zeros >= 5)
|
||||
slirp_exit(0);
|
||||
return;
|
||||
}
|
||||
if (*if_inbuff == '1') {
|
||||
ttyp->zeros = 0;
|
||||
if (++ttyp->ones >= 5)
|
||||
tty_detached(ttyp, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ttyp->ones = ttyp->zeros = 0;
|
||||
|
||||
(*ttyp->if_input)(ttyp, if_inbuff, if_n);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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(so, ifm)
|
||||
struct socket *so;
|
||||
struct mbuf *ifm;
|
||||
{
|
||||
struct mbuf *ifq;
|
||||
int on_fastq = 1;
|
||||
|
||||
DEBUG_CALL("if_output");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
DEBUG_ARG("ifm = %lx", (long)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?
|
||||
*/
|
||||
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 mbufs
|
||||
*/
|
||||
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 mbuf *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(ifm->m_data, ifm->m_len);
|
||||
|
||||
if (if_queued)
|
||||
goto again;
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
#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 */
|
||||
|
||||
/* Needed for FreeBSD */
|
||||
#undef if_mtu
|
||||
extern int if_mtu;
|
||||
extern int if_mru; /* MTU and MRU */
|
||||
extern int if_comp; /* Flags for compression */
|
||||
extern int if_maxlinkhdr;
|
||||
extern int if_queued; /* Number of packets queued so far */
|
||||
extern int if_thresh; /* Number of packets queued before we start sending
|
||||
* (to prevent allocing too many mbufs) */
|
||||
|
||||
extern struct mbuf if_fastq; /* fast queue (for interactive data) */
|
||||
extern struct mbuf if_batchq; /* queue for non-interactive data */
|
||||
extern struct mbuf *next_m;
|
||||
|
||||
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
|
||||
|
||||
/* 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: number of bytes that didn't need to be sent over the link
|
||||
* because of compression */
|
||||
|
||||
u_int in_mbad; /* Bad incoming packets */
|
||||
};
|
||||
|
||||
#endif
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. 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_
|
||||
|
||||
#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((u_int16_t)(d)))
|
||||
# endif
|
||||
# ifndef HTONL
|
||||
# define HTONL(d) ((d) = htonl((d)))
|
||||
# endif
|
||||
# ifndef HTONS
|
||||
# define HTONS(d) ((d) = htons((u_int16_t)(d)))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef u_int32_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.
|
||||
*
|
||||
* We declare ip_len and ip_off to be short, rather than u_short
|
||||
* pragmatically since otherwise unsigned comparisons can result
|
||||
* against negative integers quite easily, and fail in subtle ways.
|
||||
*/
|
||||
struct ip {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
u_int ip_v:4, /* version */
|
||||
ip_hl:4; /* header length */
|
||||
#else
|
||||
u_int ip_hl:4, /* header length */
|
||||
ip_v:4; /* version */
|
||||
#endif
|
||||
u_int8_t ip_tos; /* type of service */
|
||||
int16_t ip_len; /* total length */
|
||||
u_int16_t ip_id; /* identification */
|
||||
int16_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 */
|
||||
u_int8_t ip_ttl; /* time to live */
|
||||
u_int8_t ip_p; /* protocol */
|
||||
u_int16_t ip_sum; /* checksum */
|
||||
struct in_addr ip_src,ip_dst; /* source and dest address */
|
||||
};
|
||||
|
||||
#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 {
|
||||
u_int8_t ipt_code; /* IPOPT_TS */
|
||||
u_int8_t ipt_len; /* size of structure (variable) */
|
||||
u_int8_t ipt_ptr; /* index of current entry */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
u_int ipt_oflw:4, /* overflow counter */
|
||||
ipt_flg:4; /* flags, see below */
|
||||
#else
|
||||
u_int 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;
|
||||
};
|
||||
|
||||
/* 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 caddr_t caddr32_t;
|
||||
#else
|
||||
typedef u_int32_t caddr32_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
/*
|
||||
* Overlay for ip header used by other protocols (tcp, udp).
|
||||
*/
|
||||
struct ipovly {
|
||||
caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
|
||||
u_int8_t ih_x1; /* (unused) */
|
||||
u_int8_t ih_pr; /* protocol */
|
||||
int16_t ih_len; /* protocol length */
|
||||
struct in_addr ih_src; /* source internet address */
|
||||
struct in_addr ih_dst; /* destination internet address */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
ipqp_32 next,prev; /* to other reass headers */
|
||||
u_int8_t ipq_ttl; /* time for reass q to live */
|
||||
u_int8_t ipq_p; /* protocol of this fragment */
|
||||
u_int16_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
|
||||
u_int ip_v:4,
|
||||
ip_hl:4;
|
||||
#else
|
||||
u_int ip_hl:4,
|
||||
ip_v:4;
|
||||
#endif
|
||||
/* BUG : u_int changed to u_int8_t.
|
||||
* sizeof(u_int)==4 on linux 2.0
|
||||
*/
|
||||
u_int8_t ipf_mff; /* XXX overlays ip_tos: use low bit
|
||||
* to avoid destroying tos (PPPDTRuu);
|
||||
* copied from (ip_off&IP_MF) */
|
||||
int16_t ip_len;
|
||||
u_int16_t ip_id;
|
||||
int16_t ip_off;
|
||||
u_int8_t ip_ttl;
|
||||
u_int8_t ip_p;
|
||||
u_int16_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 {
|
||||
u_long ips_total; /* total packets received */
|
||||
u_long ips_badsum; /* checksum bad */
|
||||
u_long ips_tooshort; /* packet too short */
|
||||
u_long ips_toosmall; /* not enough data */
|
||||
u_long ips_badhlen; /* ip header length < data size */
|
||||
u_long ips_badlen; /* ip length < ip header length */
|
||||
u_long ips_fragments; /* fragments received */
|
||||
u_long ips_fragdropped; /* frags dropped (dups, out of space) */
|
||||
u_long ips_fragtimeout; /* fragments timed out */
|
||||
u_long ips_forward; /* packets forwarded */
|
||||
u_long ips_cantforward; /* packets rcvd for unreachable dest */
|
||||
u_long ips_redirectsent; /* packets forwarded on same net */
|
||||
u_long ips_noproto; /* unknown or unsupported protocol */
|
||||
u_long ips_delivered; /* datagrams delivered to upper level*/
|
||||
u_long ips_localout; /* total ip packets generated here */
|
||||
u_long ips_odropped; /* lost packets due to nobufs, etc. */
|
||||
u_long ips_reassembled; /* total packets reassembled ok */
|
||||
u_long ips_fragmented; /* datagrams successfully fragmented */
|
||||
u_long ips_ofragments; /* output fragments created */
|
||||
u_long ips_cantfrag; /* don't fragment flag was set, etc. */
|
||||
u_long ips_badoptions; /* error in option processing */
|
||||
u_long ips_noroute; /* packets discarded due to no route */
|
||||
u_long ips_badvers; /* ip version != 4 */
|
||||
u_long ips_rawout; /* total raw ip packets generated */
|
||||
u_long ips_unaligned; /* times the ip packet was not aligned */
|
||||
};
|
||||
|
||||
extern struct ipstat ipstat;
|
||||
extern struct ipq ipq; /* ip reass. queue */
|
||||
extern u_int16_t ip_id; /* ip packet ctr, for ids */
|
||||
extern int ip_defttl; /* default IP ttl */
|
||||
|
||||
#endif
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. 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
|
||||
*/
|
||||
|
||||
#include "slirp.h"
|
||||
#include "ip_icmp.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
|
||||
};
|
||||
|
||||
/*
|
||||
* Process a received ICMP message.
|
||||
*/
|
||||
void
|
||||
icmp_input(m, hlen)
|
||||
struct mbuf *m;
|
||||
int hlen;
|
||||
{
|
||||
register struct icmp *icp;
|
||||
register struct ip *ip=mtod(m, struct ip *);
|
||||
int icmplen=ip->ip_len;
|
||||
/* int code; */
|
||||
|
||||
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 mbuf, 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;
|
||||
|
||||
/* icmpstat.icps_inhist[icp->icmp_type]++; */
|
||||
/* code = icp->icmp_code; */
|
||||
|
||||
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 == our_addr.s_addr ||
|
||||
(ip->ip_dst.s_addr == (special_addr.s_addr|htonl(CTL_ALIAS))) ) {
|
||||
icmp_reflect(m);
|
||||
} else {
|
||||
struct socket *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_DNS:
|
||||
addr.sin_addr = dns_addr;
|
||||
break;
|
||||
case CTL_ALIAS:
|
||||
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);
|
||||
}
|
||||
} /* if ip->ip_dst.s_addr == our_addr.s_addr */
|
||||
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);
|
||||
} /* swith */
|
||||
|
||||
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.
|
||||
* mbuf *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(msrc, type, code, minsize, message)
|
||||
struct mbuf *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 mbuf *m;
|
||||
|
||||
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;
|
||||
ip = mtod(msrc, struct ip *);
|
||||
#if DEBUG
|
||||
{ char bufa[20], bufb[20];
|
||||
strcpy(bufa, inet_ntoa(ip->ip_src));
|
||||
strcpy(bufb, inet_ntoa(ip->ip_dst));
|
||||
DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
|
||||
}
|
||||
#endif
|
||||
if(ip->ip_off & IP_OFFMASK) goto end_error; /* Only reply to fragment 0 */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* make a copy */
|
||||
if(!(m=m_get())) goto end_error; /* get mbuf */
|
||||
{ int new_m_size;
|
||||
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; /* copy msrc to m */
|
||||
|
||||
/* 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);
|
||||
|
||||
#if DEBUG
|
||||
if(message) { /* DEBUG : append message to ICMP packet */
|
||||
int message_len;
|
||||
char *cpnt;
|
||||
message_len=strlen(message);
|
||||
if(message_len>ICMP_MAXDATALEN) message_len=ICMP_MAXDATALEN;
|
||||
cpnt=(char *)m->m_data+m->m_len;
|
||||
memcpy(cpnt, message, message_len);
|
||||
m->m_len+=message_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
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 = 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 = our_addr;
|
||||
|
||||
(void ) ip_output((struct socket *)NULL, m);
|
||||
|
||||
icmpstat.icps_reflect++;
|
||||
|
||||
end_error:
|
||||
return;
|
||||
}
|
||||
#undef ICMP_MAXDATALEN
|
||||
|
||||
/*
|
||||
* Reflect the ip packet back to the source
|
||||
*/
|
||||
void
|
||||
icmp_reflect(m)
|
||||
struct mbuf *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;
|
||||
|
||||
/*
|
||||
* 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
|
||||
* mbuf's data back, and adjust the IP length.
|
||||
*/
|
||||
memmove((caddr_t)(ip + 1), (caddr_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 */
|
||||
struct in_addr icmp_dst;
|
||||
icmp_dst = ip->ip_dst;
|
||||
ip->ip_dst = ip->ip_src;
|
||||
ip->ip_src = icmp_dst;
|
||||
}
|
||||
|
||||
(void ) ip_output((struct socket *)NULL, m);
|
||||
|
||||
icmpstat.icps_reflect++;
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. 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 _NETINET_IP_ICMP_H_
|
||||
#define _NETINET_IP_ICMP_H_
|
||||
|
||||
/*
|
||||
* Interface Control Message Protocol Definitions.
|
||||
* Per RFC 792, September 1981.
|
||||
*/
|
||||
|
||||
typedef u_int32_t n_time;
|
||||
|
||||
/*
|
||||
* Structure of an icmp header.
|
||||
*/
|
||||
struct icmp {
|
||||
u_char icmp_type; /* type of message, see below */
|
||||
u_char icmp_code; /* type sub code */
|
||||
u_short icmp_cksum; /* ones complement cksum of struct */
|
||||
union {
|
||||
u_char ih_pptr; /* ICMP_PARAMPROB */
|
||||
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
|
||||
struct ih_idseq {
|
||||
u_short icd_id;
|
||||
u_short icd_seq;
|
||||
} ih_idseq;
|
||||
int ih_void;
|
||||
|
||||
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
|
||||
struct ih_pmtu {
|
||||
u_short ipm_void;
|
||||
u_short 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;
|
||||
u_long 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
|
||||
};
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
void icmp_input _P((struct mbuf *, int));
|
||||
void icmp_error _P((struct mbuf *, u_char, u_char, int, char *));
|
||||
void icmp_reflect _P((struct mbuf *));
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <slirp.h>
|
||||
|
||||
u_int16_t ip_id;
|
||||
|
||||
/*
|
||||
* IP output. The packet in mbuf chain m contains a skeletal IP
|
||||
* header (with len, off, ttl, proto, tos, src, dst).
|
||||
* The mbuf chain containing the packet will be freed.
|
||||
* The mbuf opt, if present, will not be freed.
|
||||
*/
|
||||
int
|
||||
ip_output(so, m0)
|
||||
struct socket *so;
|
||||
struct mbuf *m0;
|
||||
{
|
||||
register struct ip *ip;
|
||||
register struct mbuf *m = m0;
|
||||
register int hlen = sizeof(struct ip );
|
||||
int len, off, error = 0;
|
||||
|
||||
DEBUG_CALL("ip_output");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
DEBUG_ARG("m0 = %lx", (long)m0);
|
||||
|
||||
/* We do no options */
|
||||
/* if (opt) {
|
||||
* m = ip_insertoptions(m, opt, &len);
|
||||
* hlen = len;
|
||||
* }
|
||||
*/
|
||||
ip = mtod(m, struct ip *);
|
||||
/*
|
||||
* Fill in IP header.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
/* XXX Hmmm... */
|
||||
/* if (if_queued > if_thresh && towrite <= 0) {
|
||||
* error = ENOBUFS;
|
||||
* goto bad;
|
||||
* }
|
||||
*/
|
||||
|
||||
/*
|
||||
* If small enough for interface, can just send directly.
|
||||
*/
|
||||
if ((u_int16_t)ip->ip_len <= if_mtu) {
|
||||
ip->ip_len = htons((u_int16_t)ip->ip_len);
|
||||
ip->ip_off = htons((u_int16_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;
|
||||
}
|
||||
|
||||
{
|
||||
int mhlen, firstlen = len;
|
||||
struct mbuf **mnext = &m->m_nextpkt;
|
||||
|
||||
/*
|
||||
* 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 < (u_int16_t)ip->ip_len; off += len) {
|
||||
register struct ip *mhip;
|
||||
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 (hlen > sizeof (struct ip)) {
|
||||
* mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
|
||||
* mhip->ip_hl = mhlen >> 2;
|
||||
* }
|
||||
*/
|
||||
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 >= (u_int16_t)ip->ip_len)
|
||||
len = (u_int16_t)ip->ip_len - off;
|
||||
else
|
||||
mhip->ip_off |= IP_MF;
|
||||
mhip->ip_len = htons((u_int16_t)(len + mhlen));
|
||||
|
||||
if (m_copy(m, m0, off, len) < 0) {
|
||||
error = -1;
|
||||
goto sendorfree;
|
||||
}
|
||||
|
||||
mhip->ip_off = htons((u_int16_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 - (u_int16_t)ip->ip_len);
|
||||
ip->ip_len = htons((u_int16_t)m->m_len);
|
||||
ip->ip_off = htons((u_int16_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;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef _LIBSLIRP_H
|
||||
#define _LIBSLIRP_H
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
void slirp_init(void);
|
||||
|
||||
void slirp_select_fill(int *pnfds,
|
||||
fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
||||
|
||||
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
||||
|
||||
void slirp_input(const uint8_t *pkt, int pkt_len);
|
||||
|
||||
/* you must provide the following functions: */
|
||||
int slirp_can_output(void);
|
||||
void slirp_output(const uint8_t *pkt, int pkt_len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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
|
||||
#define min(x,y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
extern struct timeval tt;
|
||||
extern int link_up;
|
||||
extern int slirp_socket;
|
||||
extern int slirp_socket_unit;
|
||||
extern int slirp_socket_port;
|
||||
extern u_int32_t slirp_socket_addr;
|
||||
extern char *slirp_socket_passwd;
|
||||
extern int ctty_closed;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
extern char *slirp_tty;
|
||||
extern char *exec_shell;
|
||||
extern u_int curtime;
|
||||
extern fd_set *global_readfds, *global_writefds, *global_xfds;
|
||||
extern struct in_addr ctl_addr;
|
||||
extern struct in_addr special_addr;
|
||||
extern struct in_addr our_addr;
|
||||
extern struct in_addr loopback_addr;
|
||||
extern struct in_addr dns_addr;
|
||||
extern char *username;
|
||||
extern char *socket_path;
|
||||
extern int towrite_max;
|
||||
extern int ppp_exit;
|
||||
extern int so_options;
|
||||
extern int tcp_keepintvl;
|
||||
extern uint8_t client_ethaddr[6];
|
||||
|
||||
#define PROTO_SLIP 0x1
|
||||
#ifdef USE_PPP
|
||||
#define PROTO_PPP 0x2
|
||||
#endif
|
||||
|
||||
void if_encap(const uint8_t *ip_data, int ip_data_len);
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski
|
||||
*
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <slirp.h>
|
||||
|
||||
struct mbuf *mbutl;
|
||||
char *mclrefcnt;
|
||||
int mbuf_alloced = 0;
|
||||
struct mbuf m_freelist, m_usedlist;
|
||||
int mbuf_thresh = 30;
|
||||
int mbuf_max = 0;
|
||||
int msize;
|
||||
|
||||
void
|
||||
m_init()
|
||||
{
|
||||
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()
|
||||
{
|
||||
/*
|
||||
* 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 mbuf *
|
||||
m_get()
|
||||
{
|
||||
register struct mbuf *m;
|
||||
int flags = 0;
|
||||
|
||||
DEBUG_CALL("m_get");
|
||||
|
||||
if (m_freelist.m_next == &m_freelist) {
|
||||
m = (struct mbuf *)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;
|
||||
}
|
||||
|
||||
void
|
||||
m_free(m)
|
||||
struct mbuf *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(m, n)
|
||||
register struct mbuf *m, *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(m, size)
|
||||
struct mbuf *m;
|
||||
int size;
|
||||
{
|
||||
/* some compiles throw up on gotos. This one we can fake. */
|
||||
if(m->m_size>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 mbuf *)NULL;
|
||||
*/
|
||||
/* m->m_data = m->m_ext + datasize; */
|
||||
} else {
|
||||
int datasize;
|
||||
char *dat;
|
||||
datasize = m->m_data - m->m_dat;
|
||||
dat = (char *)malloc(size);
|
||||
/* if (dat == NULL)
|
||||
* return (struct mbuf *)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(m, len)
|
||||
struct mbuf *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(n, m, off, len)
|
||||
struct mbuf *n, *m;
|
||||
int off, 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 mbuf *
|
||||
dtom(dat)
|
||||
void *dat;
|
||||
{
|
||||
struct mbuf *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 mbuf *)0;
|
||||
}
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. 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 _MBUF_H_
|
||||
#define _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 mbuf *)((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 mbuf *mh_next; /* Linked list of mbufs */
|
||||
struct mbuf *mh_prev;
|
||||
struct mbuf *mh_nextpkt; /* Next packet in queue/record */
|
||||
struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */
|
||||
int mh_flags; /* Misc flags */
|
||||
|
||||
int mh_size; /* Size of data */
|
||||
struct socket *mh_so;
|
||||
|
||||
caddr_t mh_data; /* Location of data */
|
||||
int 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 mbuf {
|
||||
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 mbuf m_freelist, m_usedlist;
|
||||
extern int mbuf_max;
|
||||
|
||||
void m_init _P((void));
|
||||
void msize_init _P((void));
|
||||
struct mbuf * m_get _P((void));
|
||||
void m_free _P((struct mbuf *));
|
||||
void m_cat _P((register struct mbuf *, register struct mbuf *));
|
||||
void m_inc _P((struct mbuf *, int));
|
||||
void m_adj _P((struct mbuf *, int));
|
||||
int m_copy _P((struct mbuf *, struct mbuf *, int, int));
|
||||
struct mbuf * dtom _P((void *));
|
||||
|
||||
#endif
|
||||
+925
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
#ifndef _MISC_H_
|
||||
#define _MISC_H_
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
extern struct ex_list *exec_list;
|
||||
extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait;
|
||||
|
||||
extern int (*lprint_print) _P((void *, const char *, va_list));
|
||||
extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
|
||||
extern struct sbuf *lprint_sb;
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup _P((const char *));
|
||||
#endif
|
||||
|
||||
void do_wait _P((int));
|
||||
|
||||
#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 {
|
||||
u_int16_t lport;
|
||||
u_int16_t fport;
|
||||
u_int8_t tos;
|
||||
u_int8_t emu;
|
||||
};
|
||||
|
||||
struct emu_t {
|
||||
u_int16_t lport;
|
||||
u_int16_t fport;
|
||||
u_int8_t tos;
|
||||
u_int8_t emu;
|
||||
struct emu_t *next;
|
||||
};
|
||||
|
||||
extern struct emu_t *tcpemu;
|
||||
|
||||
extern int x_port, x_server, x_display;
|
||||
|
||||
int show_x _P((char *, struct socket *));
|
||||
void redir_x _P((u_int32_t, int, int, int));
|
||||
void getouraddr _P((void));
|
||||
inline void slirp_insque _P((void *, void *));
|
||||
inline void slirp_remque _P((void *));
|
||||
int add_exec _P((struct ex_list **, int, char *, int, int));
|
||||
int openpty _P((int *, int *));
|
||||
int fork_exec _P((struct socket *, char *, int));
|
||||
void snooze_hup _P((int));
|
||||
void snooze _P((void));
|
||||
void relay _P((int));
|
||||
void add_emu _P((char *));
|
||||
void u_sleep _P((int));
|
||||
void fd_nonblock _P((int));
|
||||
void fd_block _P((int));
|
||||
int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *));
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user