slirp: change tabs to spaces
This commit is contained in:
parent
6ccbfc7381
commit
0c0a9958b1
30 changed files with 4411 additions and 4411 deletions
154
slirp/bootp.h
154
slirp/bootp.h
|
@ -2,97 +2,97 @@
|
||||||
#ifndef SLIRP_BOOTP_H
|
#ifndef SLIRP_BOOTP_H
|
||||||
#define SLIRP_BOOTP_H 1
|
#define SLIRP_BOOTP_H 1
|
||||||
|
|
||||||
#define BOOTP_SERVER 67
|
#define BOOTP_SERVER 67
|
||||||
#define BOOTP_CLIENT 68
|
#define BOOTP_CLIENT 68
|
||||||
|
|
||||||
#define BOOTP_REQUEST 1
|
#define BOOTP_REQUEST 1
|
||||||
#define BOOTP_REPLY 2
|
#define BOOTP_REPLY 2
|
||||||
|
|
||||||
#define RFC1533_COOKIE 99, 130, 83, 99
|
#define RFC1533_COOKIE 99, 130, 83, 99
|
||||||
#define RFC1533_PAD 0
|
#define RFC1533_PAD 0
|
||||||
#define RFC1533_NETMASK 1
|
#define RFC1533_NETMASK 1
|
||||||
#define RFC1533_TIMEOFFSET 2
|
#define RFC1533_TIMEOFFSET 2
|
||||||
#define RFC1533_GATEWAY 3
|
#define RFC1533_GATEWAY 3
|
||||||
#define RFC1533_TIMESERVER 4
|
#define RFC1533_TIMESERVER 4
|
||||||
#define RFC1533_IEN116NS 5
|
#define RFC1533_IEN116NS 5
|
||||||
#define RFC1533_DNS 6
|
#define RFC1533_DNS 6
|
||||||
#define RFC1533_LOGSERVER 7
|
#define RFC1533_LOGSERVER 7
|
||||||
#define RFC1533_COOKIESERVER 8
|
#define RFC1533_COOKIESERVER 8
|
||||||
#define RFC1533_LPRSERVER 9
|
#define RFC1533_LPRSERVER 9
|
||||||
#define RFC1533_IMPRESSSERVER 10
|
#define RFC1533_IMPRESSSERVER 10
|
||||||
#define RFC1533_RESOURCESERVER 11
|
#define RFC1533_RESOURCESERVER 11
|
||||||
#define RFC1533_HOSTNAME 12
|
#define RFC1533_HOSTNAME 12
|
||||||
#define RFC1533_BOOTFILESIZE 13
|
#define RFC1533_BOOTFILESIZE 13
|
||||||
#define RFC1533_MERITDUMPFILE 14
|
#define RFC1533_MERITDUMPFILE 14
|
||||||
#define RFC1533_DOMAINNAME 15
|
#define RFC1533_DOMAINNAME 15
|
||||||
#define RFC1533_SWAPSERVER 16
|
#define RFC1533_SWAPSERVER 16
|
||||||
#define RFC1533_ROOTPATH 17
|
#define RFC1533_ROOTPATH 17
|
||||||
#define RFC1533_EXTENSIONPATH 18
|
#define RFC1533_EXTENSIONPATH 18
|
||||||
#define RFC1533_IPFORWARDING 19
|
#define RFC1533_IPFORWARDING 19
|
||||||
#define RFC1533_IPSOURCEROUTING 20
|
#define RFC1533_IPSOURCEROUTING 20
|
||||||
#define RFC1533_IPPOLICYFILTER 21
|
#define RFC1533_IPPOLICYFILTER 21
|
||||||
#define RFC1533_IPMAXREASSEMBLY 22
|
#define RFC1533_IPMAXREASSEMBLY 22
|
||||||
#define RFC1533_IPTTL 23
|
#define RFC1533_IPTTL 23
|
||||||
#define RFC1533_IPMTU 24
|
#define RFC1533_IPMTU 24
|
||||||
#define RFC1533_IPMTUPLATEAU 25
|
#define RFC1533_IPMTUPLATEAU 25
|
||||||
#define RFC1533_INTMTU 26
|
#define RFC1533_INTMTU 26
|
||||||
#define RFC1533_INTLOCALSUBNETS 27
|
#define RFC1533_INTLOCALSUBNETS 27
|
||||||
#define RFC1533_INTBROADCAST 28
|
#define RFC1533_INTBROADCAST 28
|
||||||
#define RFC1533_INTICMPDISCOVER 29
|
#define RFC1533_INTICMPDISCOVER 29
|
||||||
#define RFC1533_INTICMPRESPOND 30
|
#define RFC1533_INTICMPRESPOND 30
|
||||||
#define RFC1533_INTROUTEDISCOVER 31
|
#define RFC1533_INTROUTEDISCOVER 31
|
||||||
#define RFC1533_INTROUTESOLICIT 32
|
#define RFC1533_INTROUTESOLICIT 32
|
||||||
#define RFC1533_INTSTATICROUTES 33
|
#define RFC1533_INTSTATICROUTES 33
|
||||||
#define RFC1533_LLTRAILERENCAP 34
|
#define RFC1533_LLTRAILERENCAP 34
|
||||||
#define RFC1533_LLARPCACHETMO 35
|
#define RFC1533_LLARPCACHETMO 35
|
||||||
#define RFC1533_LLETHERNETENCAP 36
|
#define RFC1533_LLETHERNETENCAP 36
|
||||||
#define RFC1533_TCPTTL 37
|
#define RFC1533_TCPTTL 37
|
||||||
#define RFC1533_TCPKEEPALIVETMO 38
|
#define RFC1533_TCPKEEPALIVETMO 38
|
||||||
#define RFC1533_TCPKEEPALIVEGB 39
|
#define RFC1533_TCPKEEPALIVEGB 39
|
||||||
#define RFC1533_NISDOMAIN 40
|
#define RFC1533_NISDOMAIN 40
|
||||||
#define RFC1533_NISSERVER 41
|
#define RFC1533_NISSERVER 41
|
||||||
#define RFC1533_NTPSERVER 42
|
#define RFC1533_NTPSERVER 42
|
||||||
#define RFC1533_VENDOR 43
|
#define RFC1533_VENDOR 43
|
||||||
#define RFC1533_NBNS 44
|
#define RFC1533_NBNS 44
|
||||||
#define RFC1533_NBDD 45
|
#define RFC1533_NBDD 45
|
||||||
#define RFC1533_NBNT 46
|
#define RFC1533_NBNT 46
|
||||||
#define RFC1533_NBSCOPE 47
|
#define RFC1533_NBSCOPE 47
|
||||||
#define RFC1533_XFS 48
|
#define RFC1533_XFS 48
|
||||||
#define RFC1533_XDM 49
|
#define RFC1533_XDM 49
|
||||||
|
|
||||||
#define RFC2132_REQ_ADDR 50
|
#define RFC2132_REQ_ADDR 50
|
||||||
#define RFC2132_LEASE_TIME 51
|
#define RFC2132_LEASE_TIME 51
|
||||||
#define RFC2132_MSG_TYPE 53
|
#define RFC2132_MSG_TYPE 53
|
||||||
#define RFC2132_SRV_ID 54
|
#define RFC2132_SRV_ID 54
|
||||||
#define RFC2132_PARAM_LIST 55
|
#define RFC2132_PARAM_LIST 55
|
||||||
#define RFC2132_MESSAGE 56
|
#define RFC2132_MESSAGE 56
|
||||||
#define RFC2132_MAX_SIZE 57
|
#define RFC2132_MAX_SIZE 57
|
||||||
#define RFC2132_RENEWAL_TIME 58
|
#define RFC2132_RENEWAL_TIME 58
|
||||||
#define RFC2132_REBIND_TIME 59
|
#define RFC2132_REBIND_TIME 59
|
||||||
|
|
||||||
#define DHCPDISCOVER 1
|
#define DHCPDISCOVER 1
|
||||||
#define DHCPOFFER 2
|
#define DHCPOFFER 2
|
||||||
#define DHCPREQUEST 3
|
#define DHCPREQUEST 3
|
||||||
#define DHCPACK 5
|
#define DHCPACK 5
|
||||||
#define DHCPNAK 6
|
#define DHCPNAK 6
|
||||||
|
|
||||||
#define RFC1533_VENDOR_MAJOR 0
|
#define RFC1533_VENDOR_MAJOR 0
|
||||||
#define RFC1533_VENDOR_MINOR 0
|
#define RFC1533_VENDOR_MINOR 0
|
||||||
|
|
||||||
#define RFC1533_VENDOR_MAGIC 128
|
#define RFC1533_VENDOR_MAGIC 128
|
||||||
#define RFC1533_VENDOR_ADDPARM 129
|
#define RFC1533_VENDOR_ADDPARM 129
|
||||||
#define RFC1533_VENDOR_ETHDEV 130
|
#define RFC1533_VENDOR_ETHDEV 130
|
||||||
#define RFC1533_VENDOR_HOWTO 132
|
#define RFC1533_VENDOR_HOWTO 132
|
||||||
#define RFC1533_VENDOR_MNUOPTS 160
|
#define RFC1533_VENDOR_MNUOPTS 160
|
||||||
#define RFC1533_VENDOR_SELECTION 176
|
#define RFC1533_VENDOR_SELECTION 176
|
||||||
#define RFC1533_VENDOR_MOTD 184
|
#define RFC1533_VENDOR_MOTD 184
|
||||||
#define RFC1533_VENDOR_NUMOFMOTD 8
|
#define RFC1533_VENDOR_NUMOFMOTD 8
|
||||||
#define RFC1533_VENDOR_IMG 192
|
#define RFC1533_VENDOR_IMG 192
|
||||||
#define RFC1533_VENDOR_NUMOFIMG 16
|
#define RFC1533_VENDOR_NUMOFIMG 16
|
||||||
|
|
||||||
#define RFC1533_END 255
|
#define RFC1533_END 255
|
||||||
#define BOOTP_VENDOR_LEN 64
|
#define BOOTP_VENDOR_LEN 64
|
||||||
#define DHCP_OPT_LEN 312
|
#define DHCP_OPT_LEN 312
|
||||||
|
|
||||||
struct bootp_t {
|
struct bootp_t {
|
||||||
struct ip ip;
|
struct ip ip;
|
||||||
|
|
158
slirp/cksum.c
158
slirp/cksum.c
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1988, 1992, 1993
|
* Copyright (c) 1988, 1992, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
|
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
|
||||||
* in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp
|
* in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -47,93 +47,93 @@
|
||||||
|
|
||||||
int cksum(struct mbuf *m, int len)
|
int cksum(struct mbuf *m, int len)
|
||||||
{
|
{
|
||||||
register uint16_t *w;
|
register uint16_t *w;
|
||||||
register int sum = 0;
|
register int sum = 0;
|
||||||
register int mlen = 0;
|
register int mlen = 0;
|
||||||
int byte_swapped = 0;
|
int byte_swapped = 0;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
uint8_t c[2];
|
uint8_t c[2];
|
||||||
uint16_t s;
|
uint16_t s;
|
||||||
} s_util;
|
} s_util;
|
||||||
union {
|
union {
|
||||||
uint16_t s[2];
|
uint16_t s[2];
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
} l_util;
|
} l_util;
|
||||||
|
|
||||||
if (m->m_len == 0)
|
if (m->m_len == 0)
|
||||||
goto cont;
|
goto cont;
|
||||||
w = mtod(m, uint16_t *);
|
w = mtod(m, uint16_t *);
|
||||||
|
|
||||||
mlen = m->m_len;
|
mlen = m->m_len;
|
||||||
|
|
||||||
if (len < mlen)
|
if (len < mlen)
|
||||||
mlen = len;
|
mlen = len;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
len -= mlen;
|
len -= mlen;
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Force to even boundary.
|
* Force to even boundary.
|
||||||
*/
|
*/
|
||||||
if ((1 & (uintptr_t)w) && (mlen > 0)) {
|
if ((1 & (uintptr_t)w) && (mlen > 0)) {
|
||||||
REDUCE;
|
REDUCE;
|
||||||
sum <<= 8;
|
sum <<= 8;
|
||||||
s_util.c[0] = *(uint8_t *)w;
|
s_util.c[0] = *(uint8_t *)w;
|
||||||
w = (uint16_t *)((int8_t *)w + 1);
|
w = (uint16_t *)((int8_t *)w + 1);
|
||||||
mlen--;
|
mlen--;
|
||||||
byte_swapped = 1;
|
byte_swapped = 1;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Unroll the loop to make overhead from
|
* Unroll the loop to make overhead from
|
||||||
* branches &c small.
|
* branches &c small.
|
||||||
*/
|
*/
|
||||||
while ((mlen -= 32) >= 0) {
|
while ((mlen -= 32) >= 0) {
|
||||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
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[4]; sum += w[5]; sum += w[6]; sum += w[7];
|
||||||
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
|
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
|
||||||
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
|
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
|
||||||
w += 16;
|
w += 16;
|
||||||
}
|
}
|
||||||
mlen += 32;
|
mlen += 32;
|
||||||
while ((mlen -= 8) >= 0) {
|
while ((mlen -= 8) >= 0) {
|
||||||
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
|
||||||
w += 4;
|
w += 4;
|
||||||
}
|
}
|
||||||
mlen += 8;
|
mlen += 8;
|
||||||
if (mlen == 0 && byte_swapped == 0)
|
if (mlen == 0 && byte_swapped == 0)
|
||||||
goto cont;
|
goto cont;
|
||||||
REDUCE;
|
REDUCE;
|
||||||
while ((mlen -= 2) >= 0) {
|
while ((mlen -= 2) >= 0) {
|
||||||
sum += *w++;
|
sum += *w++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (byte_swapped) {
|
if (byte_swapped) {
|
||||||
REDUCE;
|
REDUCE;
|
||||||
sum <<= 8;
|
sum <<= 8;
|
||||||
if (mlen == -1) {
|
if (mlen == -1) {
|
||||||
s_util.c[1] = *(uint8_t *)w;
|
s_util.c[1] = *(uint8_t *)w;
|
||||||
sum += s_util.s;
|
sum += s_util.s;
|
||||||
mlen = 0;
|
mlen = 0;
|
||||||
} else
|
} else
|
||||||
|
|
||||||
mlen = -1;
|
mlen = -1;
|
||||||
} else if (mlen == -1)
|
} else if (mlen == -1)
|
||||||
s_util.c[0] = *(uint8_t *)w;
|
s_util.c[0] = *(uint8_t *)w;
|
||||||
|
|
||||||
cont:
|
cont:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (len) {
|
if (len) {
|
||||||
DEBUG_ERROR("cksum: out of data\n");
|
DEBUG_ERROR("cksum: out of data\n");
|
||||||
DEBUG_ERROR(" len = %d\n", len);
|
DEBUG_ERROR(" len = %d\n", len);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (mlen == -1) {
|
if (mlen == -1) {
|
||||||
/* The last mbuf has odd # of bytes. Follow the
|
/* The last mbuf has odd # of bytes. Follow the
|
||||||
standard (the odd byte may be shifted left by 8 bits
|
standard (the odd byte may be shifted left by 8 bits
|
||||||
or not as determined by endian-ness of the machine) */
|
or not as determined by endian-ness of the machine) */
|
||||||
s_util.c[1] = 0;
|
s_util.c[1] = 0;
|
||||||
sum += s_util.s;
|
sum += s_util.s;
|
||||||
}
|
}
|
||||||
REDUCE;
|
REDUCE;
|
||||||
return (~sum & 0xffff);
|
return (~sum & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
156
slirp/if.c
156
slirp/if.c
|
@ -11,17 +11,17 @@
|
||||||
static void
|
static void
|
||||||
ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)
|
ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)
|
||||||
{
|
{
|
||||||
ifm->ifs_next = ifmhead->ifs_next;
|
ifm->ifs_next = ifmhead->ifs_next;
|
||||||
ifmhead->ifs_next = ifm;
|
ifmhead->ifs_next = ifm;
|
||||||
ifm->ifs_prev = ifmhead;
|
ifm->ifs_prev = ifmhead;
|
||||||
ifm->ifs_next->ifs_prev = ifm;
|
ifm->ifs_next->ifs_prev = ifm;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ifs_remque(struct mbuf *ifm)
|
ifs_remque(struct mbuf *ifm)
|
||||||
{
|
{
|
||||||
ifm->ifs_prev->ifs_next = ifm->ifs_next;
|
ifm->ifs_prev->ifs_next = ifm->ifs_next;
|
||||||
ifm->ifs_next->ifs_prev = ifm->ifs_prev;
|
ifm->ifs_next->ifs_prev = ifm->ifs_prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -48,95 +48,95 @@ if_init(Slirp *slirp)
|
||||||
void
|
void
|
||||||
if_output(struct socket *so, struct mbuf *ifm)
|
if_output(struct socket *so, struct mbuf *ifm)
|
||||||
{
|
{
|
||||||
Slirp *slirp = ifm->slirp;
|
Slirp *slirp = ifm->slirp;
|
||||||
struct mbuf *ifq;
|
struct mbuf *ifq;
|
||||||
int on_fastq = 1;
|
int on_fastq = 1;
|
||||||
|
|
||||||
DEBUG_CALL("if_output");
|
DEBUG_CALL("if_output");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("ifm = %lx", (long)ifm);
|
DEBUG_ARG("ifm = %lx", (long)ifm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First remove the mbuf from m_usedlist,
|
* First remove the mbuf from m_usedlist,
|
||||||
* since we're gonna use m_next and m_prev ourselves
|
* since we're gonna use m_next and m_prev ourselves
|
||||||
* XXX Shouldn't need this, gotta change dtom() etc.
|
* XXX Shouldn't need this, gotta change dtom() etc.
|
||||||
*/
|
*/
|
||||||
if (ifm->m_flags & M_USEDLIST) {
|
if (ifm->m_flags & M_USEDLIST) {
|
||||||
remque(ifm);
|
remque(ifm);
|
||||||
ifm->m_flags &= ~M_USEDLIST;
|
ifm->m_flags &= ~M_USEDLIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if there's already a batchq list for this session.
|
* See if there's already a batchq list for this session.
|
||||||
* This can include an interactive session, which should go on fastq,
|
* This can include an interactive session, which should go on fastq,
|
||||||
* but gets too greedy... hence it'll be downgraded from fastq to batchq.
|
* 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)
|
* We mustn't put this packet back on the fastq (or we'll send it out of order)
|
||||||
* XXX add cache here?
|
* XXX add cache here?
|
||||||
*/
|
*/
|
||||||
for (ifq = slirp->if_batchq.ifq_prev; ifq && ifq != &slirp->if_batchq;
|
for (ifq = slirp->if_batchq.ifq_prev; ifq && ifq != &slirp->if_batchq;
|
||||||
ifq = ifq->ifq_prev) {
|
ifq = ifq->ifq_prev) {
|
||||||
if (so == ifq->ifq_so) {
|
if (so == ifq->ifq_so) {
|
||||||
/* A match! */
|
/* A match! */
|
||||||
ifm->ifq_so = so;
|
ifm->ifq_so = so;
|
||||||
ifs_insque(ifm, ifq->ifs_prev);
|
ifs_insque(ifm, ifq->ifs_prev);
|
||||||
goto diddit;
|
goto diddit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No match, check which queue to put it on */
|
/* No match, check which queue to put it on */
|
||||||
if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
|
if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
|
||||||
ifq = slirp->if_fastq.ifq_prev;
|
ifq = slirp->if_fastq.ifq_prev;
|
||||||
on_fastq = 1;
|
on_fastq = 1;
|
||||||
/*
|
/*
|
||||||
* Check if this packet is a part of the last
|
* Check if this packet is a part of the last
|
||||||
* packet's session
|
* packet's session
|
||||||
*/
|
*/
|
||||||
if (ifq->ifq_so == so) {
|
if (ifq->ifq_so == so) {
|
||||||
ifm->ifq_so = so;
|
ifm->ifq_so = so;
|
||||||
ifs_insque(ifm, ifq->ifs_prev);
|
ifs_insque(ifm, ifq->ifs_prev);
|
||||||
goto diddit;
|
goto diddit;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ifq = slirp->if_batchq.ifq_prev;
|
ifq = slirp->if_batchq.ifq_prev;
|
||||||
/* Set next_m if the queue was empty so far */
|
/* Set next_m if the queue was empty so far */
|
||||||
if (slirp->next_m == &slirp->if_batchq) {
|
if (slirp->next_m == &slirp->if_batchq) {
|
||||||
slirp->next_m = ifm;
|
slirp->next_m = ifm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new doubly linked list for this session */
|
/* Create a new doubly linked list for this session */
|
||||||
ifm->ifq_so = so;
|
ifm->ifq_so = so;
|
||||||
ifs_init(ifm);
|
ifs_init(ifm);
|
||||||
insque(ifm, ifq);
|
insque(ifm, ifq);
|
||||||
|
|
||||||
diddit:
|
diddit:
|
||||||
if (so) {
|
if (so) {
|
||||||
/* Update *_queued */
|
/* Update *_queued */
|
||||||
so->so_queued++;
|
so->so_queued++;
|
||||||
so->so_nqueued++;
|
so->so_nqueued++;
|
||||||
/*
|
/*
|
||||||
* Check if the interactive session should be downgraded to
|
* Check if the interactive session should be downgraded to
|
||||||
* the batchq. A session is downgraded if it has queued 6
|
* the batchq. A session is downgraded if it has queued 6
|
||||||
* packets without pausing, and at least 3 of those packets
|
* packets without pausing, and at least 3 of those packets
|
||||||
* have been sent over the link
|
* have been sent over the link
|
||||||
* (XXX These are arbitrary numbers, probably not optimal..)
|
* (XXX These are arbitrary numbers, probably not optimal..)
|
||||||
*/
|
*/
|
||||||
if (on_fastq && ((so->so_nqueued >= 6) &&
|
if (on_fastq && ((so->so_nqueued >= 6) &&
|
||||||
(so->so_nqueued - so->so_queued) >= 3)) {
|
(so->so_nqueued - so->so_queued) >= 3)) {
|
||||||
|
|
||||||
/* Remove from current queue... */
|
/* Remove from current queue... */
|
||||||
remque(ifm->ifs_next);
|
remque(ifm->ifs_next);
|
||||||
|
|
||||||
/* ...And insert in the new. That'll teach ya! */
|
/* ...And insert in the new. That'll teach ya! */
|
||||||
insque(ifm->ifs_next, &slirp->if_batchq);
|
insque(ifm->ifs_next, &slirp->if_batchq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FULL_BOLT
|
#ifndef FULL_BOLT
|
||||||
/*
|
/*
|
||||||
* This prevents us from malloc()ing too many mbufs
|
* This prevents us from malloc()ing too many mbufs
|
||||||
*/
|
*/
|
||||||
if_start(ifm->slirp);
|
if_start(ifm->slirp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
slirp/if.h
10
slirp/if.h
|
@ -8,14 +8,14 @@
|
||||||
#ifndef _IF_H_
|
#ifndef _IF_H_
|
||||||
#define _IF_H_
|
#define _IF_H_
|
||||||
|
|
||||||
#define IF_COMPRESS 0x01 /* We want compression */
|
#define IF_COMPRESS 0x01 /* We want compression */
|
||||||
#define IF_NOCOMPRESS 0x02 /* Do not do compression */
|
#define IF_NOCOMPRESS 0x02 /* Do not do compression */
|
||||||
#define IF_AUTOCOMP 0x04 /* Autodetect (default) */
|
#define IF_AUTOCOMP 0x04 /* Autodetect (default) */
|
||||||
#define IF_NOCIDCOMP 0x08 /* CID compression */
|
#define IF_NOCIDCOMP 0x08 /* CID compression */
|
||||||
|
|
||||||
#define IF_MTU 1500
|
#define IF_MTU 1500
|
||||||
#define IF_MRU 1500
|
#define IF_MRU 1500
|
||||||
#define IF_COMP IF_AUTOCOMP /* Flags for compression */
|
#define IF_COMP IF_AUTOCOMP /* Flags for compression */
|
||||||
|
|
||||||
/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
|
/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
|
||||||
#define IF_MAXLINKHDR (2 + 14 + 40)
|
#define IF_MAXLINKHDR (2 + 14 + 40)
|
||||||
|
|
186
slirp/ip.h
186
slirp/ip.h
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993
|
* Copyright (c) 1982, 1986, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)ip.h 8.1 (Berkeley) 6/10/93
|
* @(#)ip.h 8.1 (Berkeley) 6/10/93
|
||||||
* ip.h,v 1.3 1994/08/21 05:27:30 paul Exp
|
* ip.h,v 1.3 1994/08/21 05:27:30 paul Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ typedef uint32_t n_long; /* long as received from the net */
|
||||||
* Definitions for internet protocol version 4.
|
* Definitions for internet protocol version 4.
|
||||||
* Per RFC 791, September 1981.
|
* Per RFC 791, September 1981.
|
||||||
*/
|
*/
|
||||||
#define IPVERSION 4
|
#define IPVERSION 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure of an internet header, naked of options.
|
* Structure of an internet header, naked of options.
|
||||||
|
@ -86,126 +86,126 @@ typedef uint32_t n_long; /* long as received from the net */
|
||||||
PACKED_BEGIN
|
PACKED_BEGIN
|
||||||
struct ip {
|
struct ip {
|
||||||
#ifdef HOST_WORDS_BIGENDIAN
|
#ifdef HOST_WORDS_BIGENDIAN
|
||||||
uint8_t ip_v:4, /* version */
|
uint8_t ip_v:4, /* version */
|
||||||
ip_hl:4; /* header length */
|
ip_hl:4; /* header length */
|
||||||
#else
|
#else
|
||||||
uint8_t ip_hl:4, /* header length */
|
uint8_t ip_hl:4, /* header length */
|
||||||
ip_v:4; /* version */
|
ip_v:4; /* version */
|
||||||
#endif
|
#endif
|
||||||
uint8_t ip_tos; /* type of service */
|
uint8_t ip_tos; /* type of service */
|
||||||
uint16_t ip_len; /* total length */
|
uint16_t ip_len; /* total length */
|
||||||
uint16_t ip_id; /* identification */
|
uint16_t ip_id; /* identification */
|
||||||
uint16_t ip_off; /* fragment offset field */
|
uint16_t ip_off; /* fragment offset field */
|
||||||
#define IP_DF 0x4000 /* don't fragment flag */
|
#define IP_DF 0x4000 /* don't fragment flag */
|
||||||
#define IP_MF 0x2000 /* more fragments flag */
|
#define IP_MF 0x2000 /* more fragments flag */
|
||||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||||
uint8_t ip_ttl; /* time to live */
|
uint8_t ip_ttl; /* time to live */
|
||||||
uint8_t ip_p; /* protocol */
|
uint8_t ip_p; /* protocol */
|
||||||
uint16_t ip_sum; /* checksum */
|
uint16_t ip_sum; /* checksum */
|
||||||
struct in_addr ip_src,ip_dst; /* source and dest address */
|
struct in_addr ip_src,ip_dst; /* source and dest address */
|
||||||
} PACKED_END;
|
} PACKED_END;
|
||||||
|
|
||||||
#define IP_MAXPACKET 65535 /* maximum packet size */
|
#define IP_MAXPACKET 65535 /* maximum packet size */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Definitions for IP type of service (ip_tos)
|
* Definitions for IP type of service (ip_tos)
|
||||||
*/
|
*/
|
||||||
#define IPTOS_LOWDELAY 0x10
|
#define IPTOS_LOWDELAY 0x10
|
||||||
#define IPTOS_THROUGHPUT 0x08
|
#define IPTOS_THROUGHPUT 0x08
|
||||||
#define IPTOS_RELIABILITY 0x04
|
#define IPTOS_RELIABILITY 0x04
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Definitions for options.
|
* Definitions for options.
|
||||||
*/
|
*/
|
||||||
#define IPOPT_COPIED(o) ((o)&0x80)
|
#define IPOPT_COPIED(o) ((o)&0x80)
|
||||||
#define IPOPT_CLASS(o) ((o)&0x60)
|
#define IPOPT_CLASS(o) ((o)&0x60)
|
||||||
#define IPOPT_NUMBER(o) ((o)&0x1f)
|
#define IPOPT_NUMBER(o) ((o)&0x1f)
|
||||||
|
|
||||||
#define IPOPT_CONTROL 0x00
|
#define IPOPT_CONTROL 0x00
|
||||||
#define IPOPT_RESERVED1 0x20
|
#define IPOPT_RESERVED1 0x20
|
||||||
#define IPOPT_DEBMEAS 0x40
|
#define IPOPT_DEBMEAS 0x40
|
||||||
#define IPOPT_RESERVED2 0x60
|
#define IPOPT_RESERVED2 0x60
|
||||||
|
|
||||||
#define IPOPT_EOL 0 /* end of option list */
|
#define IPOPT_EOL 0 /* end of option list */
|
||||||
#define IPOPT_NOP 1 /* no operation */
|
#define IPOPT_NOP 1 /* no operation */
|
||||||
|
|
||||||
#define IPOPT_RR 7 /* record packet route */
|
#define IPOPT_RR 7 /* record packet route */
|
||||||
#define IPOPT_TS 68 /* timestamp */
|
#define IPOPT_TS 68 /* timestamp */
|
||||||
#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
|
#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
|
||||||
#define IPOPT_LSRR 131 /* loose source route */
|
#define IPOPT_LSRR 131 /* loose source route */
|
||||||
#define IPOPT_SATID 136 /* satnet id */
|
#define IPOPT_SATID 136 /* satnet id */
|
||||||
#define IPOPT_SSRR 137 /* strict source route */
|
#define IPOPT_SSRR 137 /* strict source route */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Offsets to fields in options other than EOL and NOP.
|
* Offsets to fields in options other than EOL and NOP.
|
||||||
*/
|
*/
|
||||||
#define IPOPT_OPTVAL 0 /* option ID */
|
#define IPOPT_OPTVAL 0 /* option ID */
|
||||||
#define IPOPT_OLEN 1 /* option length */
|
#define IPOPT_OLEN 1 /* option length */
|
||||||
#define IPOPT_OFFSET 2 /* offset within option */
|
#define IPOPT_OFFSET 2 /* offset within option */
|
||||||
#define IPOPT_MINOFF 4 /* min value of above */
|
#define IPOPT_MINOFF 4 /* min value of above */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Time stamp option structure.
|
* Time stamp option structure.
|
||||||
*/
|
*/
|
||||||
PACKED_BEGIN
|
PACKED_BEGIN
|
||||||
struct ip_timestamp {
|
struct ip_timestamp {
|
||||||
uint8_t ipt_code; /* IPOPT_TS */
|
uint8_t ipt_code; /* IPOPT_TS */
|
||||||
uint8_t ipt_len; /* size of structure (variable) */
|
uint8_t ipt_len; /* size of structure (variable) */
|
||||||
uint8_t ipt_ptr; /* index of current entry */
|
uint8_t ipt_ptr; /* index of current entry */
|
||||||
#ifdef HOST_WORDS_BIGENDIAN
|
#ifdef HOST_WORDS_BIGENDIAN
|
||||||
uint8_t ipt_oflw:4, /* overflow counter */
|
uint8_t ipt_oflw:4, /* overflow counter */
|
||||||
ipt_flg:4; /* flags, see below */
|
ipt_flg:4; /* flags, see below */
|
||||||
#else
|
#else
|
||||||
uint8_t ipt_flg:4, /* flags, see below */
|
uint8_t ipt_flg:4, /* flags, see below */
|
||||||
ipt_oflw:4; /* overflow counter */
|
ipt_oflw:4; /* overflow counter */
|
||||||
#endif
|
#endif
|
||||||
union ipt_timestamp {
|
union ipt_timestamp {
|
||||||
n_long ipt_time[1];
|
n_long ipt_time[1];
|
||||||
struct ipt_ta {
|
struct ipt_ta {
|
||||||
struct in_addr ipt_addr;
|
struct in_addr ipt_addr;
|
||||||
n_long ipt_time;
|
n_long ipt_time;
|
||||||
} ipt_ta[1];
|
} ipt_ta[1];
|
||||||
} ipt_timestamp;
|
} ipt_timestamp;
|
||||||
} PACKED_END;
|
} PACKED_END;
|
||||||
|
|
||||||
/* flag bits for ipt_flg */
|
/* flag bits for ipt_flg */
|
||||||
#define IPOPT_TS_TSONLY 0 /* timestamps only */
|
#define IPOPT_TS_TSONLY 0 /* timestamps only */
|
||||||
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
|
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
|
||||||
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
|
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
|
||||||
|
|
||||||
/* bits for security (not byte swapped) */
|
/* bits for security (not byte swapped) */
|
||||||
#define IPOPT_SECUR_UNCLASS 0x0000
|
#define IPOPT_SECUR_UNCLASS 0x0000
|
||||||
#define IPOPT_SECUR_CONFID 0xf135
|
#define IPOPT_SECUR_CONFID 0xf135
|
||||||
#define IPOPT_SECUR_EFTO 0x789a
|
#define IPOPT_SECUR_EFTO 0x789a
|
||||||
#define IPOPT_SECUR_MMMM 0xbc4d
|
#define IPOPT_SECUR_MMMM 0xbc4d
|
||||||
#define IPOPT_SECUR_RESTR 0xaf13
|
#define IPOPT_SECUR_RESTR 0xaf13
|
||||||
#define IPOPT_SECUR_SECRET 0xd788
|
#define IPOPT_SECUR_SECRET 0xd788
|
||||||
#define IPOPT_SECUR_TOPSECRET 0x6bc5
|
#define IPOPT_SECUR_TOPSECRET 0x6bc5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internet implementation parameters.
|
* Internet implementation parameters.
|
||||||
*/
|
*/
|
||||||
#define MAXTTL 255 /* maximum time to live (seconds) */
|
#define MAXTTL 255 /* maximum time to live (seconds) */
|
||||||
#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
|
#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
|
||||||
#define IPFRAGTTL 60 /* time to live for frags, slowhz */
|
#define IPFRAGTTL 60 /* time to live for frags, slowhz */
|
||||||
#define IPTTLDEC 1 /* subtracted when forwarding */
|
#define IPTTLDEC 1 /* subtracted when forwarding */
|
||||||
|
|
||||||
#define IP_MSS 576 /* default maximum segment size */
|
#define IP_MSS 576 /* default maximum segment size */
|
||||||
|
|
||||||
PACKED_BEGIN
|
PACKED_BEGIN
|
||||||
#if SIZEOF_CHAR_P == 4
|
#if SIZEOF_CHAR_P == 4
|
||||||
struct mbuf_ptr {
|
struct mbuf_ptr {
|
||||||
struct mbuf *mptr;
|
struct mbuf *mptr;
|
||||||
uint32_t dummy;
|
uint32_t dummy;
|
||||||
} PACKED_END;
|
} PACKED_END;
|
||||||
#else
|
#else
|
||||||
struct mbuf_ptr {
|
struct mbuf_ptr {
|
||||||
struct mbuf *mptr;
|
struct mbuf *mptr;
|
||||||
} PACKED_END;
|
} PACKED_END;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct qlink {
|
struct qlink {
|
||||||
void *next, *prev;
|
void *next, *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -213,12 +213,12 @@ struct qlink {
|
||||||
*/
|
*/
|
||||||
PACKED_BEGIN
|
PACKED_BEGIN
|
||||||
struct ipovly {
|
struct ipovly {
|
||||||
struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */
|
struct mbuf_ptr ih_mbuf; /* backpointer to mbuf */
|
||||||
uint8_t ih_x1; /* (unused) */
|
uint8_t ih_x1; /* (unused) */
|
||||||
uint8_t ih_pr; /* protocol */
|
uint8_t ih_pr; /* protocol */
|
||||||
uint16_t ih_len; /* protocol length */
|
uint16_t ih_len; /* protocol length */
|
||||||
struct in_addr ih_src; /* source internet address */
|
struct in_addr ih_src; /* source internet address */
|
||||||
struct in_addr ih_dst; /* destination internet address */
|
struct in_addr ih_dst; /* destination internet address */
|
||||||
} PACKED_END;
|
} PACKED_END;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -230,12 +230,12 @@ struct ipovly {
|
||||||
*/
|
*/
|
||||||
PACKED_BEGIN
|
PACKED_BEGIN
|
||||||
struct ipq {
|
struct ipq {
|
||||||
struct qlink frag_link; /* to ip headers of fragments */
|
struct qlink frag_link; /* to ip headers of fragments */
|
||||||
struct qlink ip_link; /* to other reass headers */
|
struct qlink ip_link; /* to other reass headers */
|
||||||
uint8_t ipq_ttl; /* time for reass q to live */
|
uint8_t ipq_ttl; /* time for reass q to live */
|
||||||
uint8_t ipq_p; /* protocol of this fragment */
|
uint8_t ipq_p; /* protocol of this fragment */
|
||||||
uint16_t ipq_id; /* sequence id for reassembly */
|
uint16_t ipq_id; /* sequence id for reassembly */
|
||||||
struct in_addr ipq_src,ipq_dst;
|
struct in_addr ipq_src,ipq_dst;
|
||||||
} PACKED_END;
|
} PACKED_END;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -244,9 +244,9 @@ struct ipq {
|
||||||
* Note: ipf_link must be at same offset as frag_link above
|
* Note: ipf_link must be at same offset as frag_link above
|
||||||
*/
|
*/
|
||||||
PACKED_BEGIN
|
PACKED_BEGIN
|
||||||
struct ipasfrag {
|
struct ipasfrag {
|
||||||
struct qlink ipf_link;
|
struct qlink ipf_link;
|
||||||
struct ip ipf_ip;
|
struct ip ipf_ip;
|
||||||
} PACKED_END;
|
} PACKED_END;
|
||||||
|
|
||||||
#define ipf_off ipf_ip.ip_off
|
#define ipf_off ipf_ip.ip_off
|
||||||
|
@ -261,12 +261,12 @@ struct ipasfrag {
|
||||||
* The actual length of the options (including ipopt_dst)
|
* The actual length of the options (including ipopt_dst)
|
||||||
* is in m_len.
|
* is in m_len.
|
||||||
*/
|
*/
|
||||||
#define MAX_IPOPTLEN 40
|
#define MAX_IPOPTLEN 40
|
||||||
|
|
||||||
PACKED_BEGIN
|
PACKED_BEGIN
|
||||||
struct ipoption {
|
struct ipoption {
|
||||||
struct in_addr ipopt_dst; /* first-hop dst if source routed */
|
struct in_addr ipopt_dst; /* first-hop dst if source routed */
|
||||||
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
|
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
|
||||||
} PACKED_END;
|
} PACKED_END;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1988, 1993
|
* Copyright (c) 1982, 1986, 1988, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
|
* @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
|
||||||
* ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp
|
* ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -40,13 +40,13 @@ static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp
|
||||||
/* list of actions for icmp_error() on RX of an icmp message */
|
/* list of actions for icmp_error() on RX of an icmp message */
|
||||||
static const int icmp_flush[19] = {
|
static const int icmp_flush[19] = {
|
||||||
/* ECHO REPLY (0) */ 0,
|
/* ECHO REPLY (0) */ 0,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
/* DEST UNREACH (3) */ 1,
|
/* DEST UNREACH (3) */ 1,
|
||||||
/* SOURCE QUENCH (4)*/ 1,
|
/* SOURCE QUENCH (4)*/ 1,
|
||||||
/* REDIRECT (5) */ 1,
|
/* REDIRECT (5) */ 1,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
/* ECHO (8) */ 0,
|
/* ECHO (8) */ 0,
|
||||||
/* ROUTERADVERT (9) */ 1,
|
/* ROUTERADVERT (9) */ 1,
|
||||||
/* ROUTERSOLICIT (10) */ 1,
|
/* ROUTERSOLICIT (10) */ 1,
|
||||||
|
@ -150,7 +150,7 @@ icmp_input(struct mbuf *m, int hlen)
|
||||||
DEBUG_ARG("icmp_type = %d", icp->icmp_type);
|
DEBUG_ARG("icmp_type = %d", icp->icmp_type);
|
||||||
switch (icp->icmp_type) {
|
switch (icp->icmp_type) {
|
||||||
case ICMP_ECHO:
|
case ICMP_ECHO:
|
||||||
ip->ip_len += hlen; /* since ip_input subtracts this */
|
ip->ip_len += hlen; /* since ip_input subtracts this */
|
||||||
if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
|
if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
|
||||||
icmp_reflect(m);
|
icmp_reflect(m);
|
||||||
} else if (slirp->restricted) {
|
} else if (slirp->restricted) {
|
||||||
|
@ -163,11 +163,11 @@ icmp_input(struct mbuf *m, int hlen)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(udp_attach(so) == -1) {
|
if(udp_attach(so) == -1) {
|
||||||
DEBUG_MISC("icmp_input udp_attach errno = %d-%s\n",
|
DEBUG_MISC("icmp_input udp_attach errno = %d-%s\n",
|
||||||
errno,strerror(errno));
|
errno,strerror(errno));
|
||||||
sofree(so);
|
sofree(so);
|
||||||
m_free(m);
|
m_free(m);
|
||||||
goto end_error;
|
goto end_error;
|
||||||
}
|
}
|
||||||
so->so_m = m;
|
so->so_m = m;
|
||||||
so->so_faddr = ip->ip_dst;
|
so->so_faddr = ip->ip_dst;
|
||||||
|
@ -182,23 +182,23 @@ icmp_input(struct mbuf *m, int hlen)
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
|
if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
|
||||||
slirp->vnetwork_addr.s_addr) {
|
slirp->vnetwork_addr.s_addr) {
|
||||||
/* It's an alias */
|
/* It's an alias */
|
||||||
if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
|
if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
|
||||||
if (get_dns_addr(&addr.sin_addr) < 0)
|
if (get_dns_addr(&addr.sin_addr) < 0)
|
||||||
addr.sin_addr = loopback_addr;
|
addr.sin_addr = loopback_addr;
|
||||||
} else {
|
} else {
|
||||||
addr.sin_addr = loopback_addr;
|
addr.sin_addr = loopback_addr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addr.sin_addr = so->so_faddr;
|
addr.sin_addr = so->so_faddr;
|
||||||
}
|
}
|
||||||
addr.sin_port = so->so_fport;
|
addr.sin_port = so->so_fport;
|
||||||
if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
|
if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
|
||||||
(struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
(struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||||
DEBUG_MISC("icmp_input udp sendto tx errno = %d-%s\n",
|
DEBUG_MISC("icmp_input udp sendto tx errno = %d-%s\n",
|
||||||
errno,strerror(errno));
|
errno,strerror(errno));
|
||||||
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
||||||
udp_detach(so);
|
udp_detach(so);
|
||||||
}
|
}
|
||||||
} /* if ip->ip_dst.s_addr == alias_addr.s_addr */
|
} /* if ip->ip_dst.s_addr == alias_addr.s_addr */
|
||||||
break;
|
break;
|
||||||
|
@ -224,13 +224,13 @@ end_error:
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send an ICMP message in response to a situation
|
* 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).
|
* 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 change this header information.
|
||||||
* MUST NOT reply to a multicast/broadcast IP address.
|
* MUST NOT reply to a multicast/broadcast IP address.
|
||||||
* MUST NOT reply to a multicast/broadcast MAC address.
|
* MUST NOT reply to a multicast/broadcast MAC address.
|
||||||
* MUST reply to only the first fragment.
|
* MUST reply to only the first fragment.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Send ICMP_UNREACH back to the source regarding msrc.
|
* Send ICMP_UNREACH back to the source regarding msrc.
|
||||||
|
@ -279,8 +279,8 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
|
||||||
if(ip->ip_p == IPPROTO_ICMP) {
|
if(ip->ip_p == IPPROTO_ICMP) {
|
||||||
icp = (struct icmp *)((char *)ip + shlen);
|
icp = (struct icmp *)((char *)ip + shlen);
|
||||||
/*
|
/*
|
||||||
* Assume any unknown ICMP type is an error. This isn't
|
* Assume any unknown ICMP type is an error. This isn't
|
||||||
* specified by the RFC, but think about it..
|
* specified by the RFC, but think about it..
|
||||||
*/
|
*/
|
||||||
if(icp->icmp_type>18 || icmp_flush[icp->icmp_type]) goto end_error;
|
if(icp->icmp_type>18 || icmp_flush[icp->icmp_type]) goto end_error;
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,7 @@ icmp_reflect(struct mbuf *m)
|
||||||
* mbuf's data back, and adjust the IP length.
|
* mbuf's data back, and adjust the IP length.
|
||||||
*/
|
*/
|
||||||
memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen,
|
memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen,
|
||||||
(unsigned )(m->m_len - hlen));
|
(unsigned )(m->m_len - hlen));
|
||||||
hlen -= optlen;
|
hlen -= optlen;
|
||||||
ip->ip_hl = hlen >> 2;
|
ip->ip_hl = hlen >> 2;
|
||||||
ip->ip_len -= optlen;
|
ip->ip_len -= optlen;
|
||||||
|
|
186
slirp/ip_icmp.h
186
slirp/ip_icmp.h
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993
|
* Copyright (c) 1982, 1986, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
|
* @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
|
||||||
* ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp
|
* ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -44,50 +44,50 @@ typedef uint32_t n_time;
|
||||||
* Structure of an icmp header.
|
* Structure of an icmp header.
|
||||||
*/
|
*/
|
||||||
struct icmp {
|
struct icmp {
|
||||||
u_char icmp_type; /* type of message, see below */
|
u_char icmp_type; /* type of message, see below */
|
||||||
u_char icmp_code; /* type sub code */
|
u_char icmp_code; /* type sub code */
|
||||||
u_short icmp_cksum; /* ones complement cksum of struct */
|
u_short icmp_cksum; /* ones complement cksum of struct */
|
||||||
union {
|
union {
|
||||||
u_char ih_pptr; /* ICMP_PARAMPROB */
|
u_char ih_pptr; /* ICMP_PARAMPROB */
|
||||||
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
|
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
|
||||||
struct ih_idseq {
|
struct ih_idseq {
|
||||||
u_short icd_id;
|
u_short icd_id;
|
||||||
u_short icd_seq;
|
u_short icd_seq;
|
||||||
} ih_idseq;
|
} ih_idseq;
|
||||||
int ih_void;
|
int ih_void;
|
||||||
|
|
||||||
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
|
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
|
||||||
struct ih_pmtu {
|
struct ih_pmtu {
|
||||||
u_short ipm_void;
|
u_short ipm_void;
|
||||||
u_short ipm_nextmtu;
|
u_short ipm_nextmtu;
|
||||||
} ih_pmtu;
|
} ih_pmtu;
|
||||||
} icmp_hun;
|
} icmp_hun;
|
||||||
#define icmp_pptr icmp_hun.ih_pptr
|
#define icmp_pptr icmp_hun.ih_pptr
|
||||||
#define icmp_gwaddr icmp_hun.ih_gwaddr
|
#define icmp_gwaddr icmp_hun.ih_gwaddr
|
||||||
#define icmp_id icmp_hun.ih_idseq.icd_id
|
#define icmp_id icmp_hun.ih_idseq.icd_id
|
||||||
#define icmp_seq icmp_hun.ih_idseq.icd_seq
|
#define icmp_seq icmp_hun.ih_idseq.icd_seq
|
||||||
#define icmp_void icmp_hun.ih_void
|
#define icmp_void icmp_hun.ih_void
|
||||||
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
|
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
|
||||||
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
|
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
|
||||||
union {
|
union {
|
||||||
struct id_ts {
|
struct id_ts {
|
||||||
n_time its_otime;
|
n_time its_otime;
|
||||||
n_time its_rtime;
|
n_time its_rtime;
|
||||||
n_time its_ttime;
|
n_time its_ttime;
|
||||||
} id_ts;
|
} id_ts;
|
||||||
struct id_ip {
|
struct id_ip {
|
||||||
struct ip idi_ip;
|
struct ip idi_ip;
|
||||||
/* options and then 64 bits of data */
|
/* options and then 64 bits of data */
|
||||||
} id_ip;
|
} id_ip;
|
||||||
uint32_t id_mask;
|
uint32_t id_mask;
|
||||||
char id_data[1];
|
char id_data[1];
|
||||||
} icmp_dun;
|
} icmp_dun;
|
||||||
#define icmp_otime icmp_dun.id_ts.its_otime
|
#define icmp_otime icmp_dun.id_ts.its_otime
|
||||||
#define icmp_rtime icmp_dun.id_ts.its_rtime
|
#define icmp_rtime icmp_dun.id_ts.its_rtime
|
||||||
#define icmp_ttime icmp_dun.id_ts.its_ttime
|
#define icmp_ttime icmp_dun.id_ts.its_ttime
|
||||||
#define icmp_ip icmp_dun.id_ip.idi_ip
|
#define icmp_ip icmp_dun.id_ip.idi_ip
|
||||||
#define icmp_mask icmp_dun.id_mask
|
#define icmp_mask icmp_dun.id_mask
|
||||||
#define icmp_data icmp_dun.id_data
|
#define icmp_data icmp_dun.id_data
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -98,60 +98,60 @@ struct icmp {
|
||||||
* data have been returned, since we need to check the returned
|
* data have been returned, since we need to check the returned
|
||||||
* ip header length.
|
* ip header length.
|
||||||
*/
|
*/
|
||||||
#define ICMP_MINLEN 8 /* abs minimum */
|
#define ICMP_MINLEN 8 /* abs minimum */
|
||||||
#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
|
#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
|
||||||
#define ICMP_MASKLEN 12 /* address mask */
|
#define ICMP_MASKLEN 12 /* address mask */
|
||||||
#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
|
#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
|
||||||
#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
|
#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
|
||||||
/* N.B.: must separately check that ip_hl >= 5 */
|
/* N.B.: must separately check that ip_hl >= 5 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Definition of type and code field values.
|
* Definition of type and code field values.
|
||||||
*/
|
*/
|
||||||
#define ICMP_ECHOREPLY 0 /* echo reply */
|
#define ICMP_ECHOREPLY 0 /* echo reply */
|
||||||
#define ICMP_UNREACH 3 /* dest unreachable, codes: */
|
#define ICMP_UNREACH 3 /* dest unreachable, codes: */
|
||||||
#define ICMP_UNREACH_NET 0 /* bad net */
|
#define ICMP_UNREACH_NET 0 /* bad net */
|
||||||
#define ICMP_UNREACH_HOST 1 /* bad host */
|
#define ICMP_UNREACH_HOST 1 /* bad host */
|
||||||
#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
|
#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
|
||||||
#define ICMP_UNREACH_PORT 3 /* bad port */
|
#define ICMP_UNREACH_PORT 3 /* bad port */
|
||||||
#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
|
#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
|
||||||
#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
|
#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
|
||||||
#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
|
#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
|
||||||
#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
|
#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
|
||||||
#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
|
#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
|
||||||
#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */
|
#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */
|
||||||
#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
|
#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
|
||||||
#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
|
#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
|
||||||
#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
|
#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
|
||||||
#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
|
#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
|
||||||
#define ICMP_REDIRECT 5 /* shorter route, codes: */
|
#define ICMP_REDIRECT 5 /* shorter route, codes: */
|
||||||
#define ICMP_REDIRECT_NET 0 /* for network */
|
#define ICMP_REDIRECT_NET 0 /* for network */
|
||||||
#define ICMP_REDIRECT_HOST 1 /* for host */
|
#define ICMP_REDIRECT_HOST 1 /* for host */
|
||||||
#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
|
#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
|
||||||
#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
|
#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
|
||||||
#define ICMP_ECHO 8 /* echo service */
|
#define ICMP_ECHO 8 /* echo service */
|
||||||
#define ICMP_ROUTERADVERT 9 /* router advertisement */
|
#define ICMP_ROUTERADVERT 9 /* router advertisement */
|
||||||
#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
|
#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
|
||||||
#define ICMP_TIMXCEED 11 /* time exceeded, code: */
|
#define ICMP_TIMXCEED 11 /* time exceeded, code: */
|
||||||
#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
|
#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
|
||||||
#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
|
#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
|
||||||
#define ICMP_PARAMPROB 12 /* ip header bad */
|
#define ICMP_PARAMPROB 12 /* ip header bad */
|
||||||
#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
|
#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
|
||||||
#define ICMP_TSTAMP 13 /* timestamp request */
|
#define ICMP_TSTAMP 13 /* timestamp request */
|
||||||
#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
|
#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
|
||||||
#define ICMP_IREQ 15 /* information request */
|
#define ICMP_IREQ 15 /* information request */
|
||||||
#define ICMP_IREQREPLY 16 /* information reply */
|
#define ICMP_IREQREPLY 16 /* information reply */
|
||||||
#define ICMP_MASKREQ 17 /* address mask request */
|
#define ICMP_MASKREQ 17 /* address mask request */
|
||||||
#define ICMP_MASKREPLY 18 /* address mask reply */
|
#define ICMP_MASKREPLY 18 /* address mask reply */
|
||||||
|
|
||||||
#define ICMP_MAXTYPE 18
|
#define ICMP_MAXTYPE 18
|
||||||
|
|
||||||
#define ICMP_INFOTYPE(type) \
|
#define ICMP_INFOTYPE(type) \
|
||||||
((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
|
((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
|
||||||
(type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
|
(type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
|
||||||
(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
|
(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
|
||||||
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
|
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
|
||||||
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
|
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
|
||||||
|
|
||||||
void icmp_init(Slirp *slirp);
|
void icmp_init(Slirp *slirp);
|
||||||
void icmp_cleanup(Slirp *slirp);
|
void icmp_cleanup(Slirp *slirp);
|
||||||
|
|
862
slirp/ip_input.c
862
slirp/ip_input.c
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1988, 1993
|
* Copyright (c) 1982, 1986, 1988, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
|
* @(#)ip_input.c 8.2 (Berkeley) 1/4/94
|
||||||
* ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp
|
* ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -75,144 +75,144 @@ void ip_cleanup(Slirp *slirp)
|
||||||
void
|
void
|
||||||
ip_input(struct mbuf *m)
|
ip_input(struct mbuf *m)
|
||||||
{
|
{
|
||||||
Slirp *slirp = m->slirp;
|
Slirp *slirp = m->slirp;
|
||||||
register struct ip *ip;
|
register struct ip *ip;
|
||||||
int hlen;
|
int hlen;
|
||||||
|
|
||||||
DEBUG_CALL("ip_input");
|
DEBUG_CALL("ip_input");
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
DEBUG_ARG("m_len = %d", m->m_len);
|
DEBUG_ARG("m_len = %d", m->m_len);
|
||||||
|
|
||||||
if (m->m_len < sizeof (struct ip)) {
|
if (m->m_len < sizeof (struct ip)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = mtod(m, struct ip *);
|
ip = mtod(m, struct ip *);
|
||||||
|
|
||||||
if (ip->ip_v != IPVERSION) {
|
if (ip->ip_v != IPVERSION) {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
hlen = ip->ip_hl << 2;
|
hlen = ip->ip_hl << 2;
|
||||||
if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
|
if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
|
||||||
goto bad; /* or packet too short */
|
goto bad; /* or packet too short */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* keep ip header intact for ICMP reply
|
/* keep ip header intact for ICMP reply
|
||||||
* ip->ip_sum = cksum(m, hlen);
|
* ip->ip_sum = cksum(m, hlen);
|
||||||
* if (ip->ip_sum) {
|
* if (ip->ip_sum) {
|
||||||
*/
|
*/
|
||||||
if(cksum(m,hlen)) {
|
if(cksum(m,hlen)) {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert fields to host representation.
|
* Convert fields to host representation.
|
||||||
*/
|
*/
|
||||||
NTOHS(ip->ip_len);
|
NTOHS(ip->ip_len);
|
||||||
if (ip->ip_len < hlen) {
|
if (ip->ip_len < hlen) {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
NTOHS(ip->ip_id);
|
NTOHS(ip->ip_id);
|
||||||
NTOHS(ip->ip_off);
|
NTOHS(ip->ip_off);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the amount of data in the buffers
|
* Check that the amount of data in the buffers
|
||||||
* is as at least much as the IP header would have us expect.
|
* is as at least much as the IP header would have us expect.
|
||||||
* Trim mbufs if longer than we expect.
|
* Trim mbufs if longer than we expect.
|
||||||
* Drop packet if shorter than we expect.
|
* Drop packet if shorter than we expect.
|
||||||
*/
|
*/
|
||||||
if (m->m_len < ip->ip_len) {
|
if (m->m_len < ip->ip_len) {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should drop packet if mbuf too long? hmmm... */
|
/* Should drop packet if mbuf too long? hmmm... */
|
||||||
if (m->m_len > ip->ip_len)
|
if (m->m_len > ip->ip_len)
|
||||||
m_adj(m, ip->ip_len - m->m_len);
|
m_adj(m, ip->ip_len - m->m_len);
|
||||||
|
|
||||||
/* check ip_ttl for a correct ICMP reply */
|
/* check ip_ttl for a correct ICMP reply */
|
||||||
if(ip->ip_ttl==0) {
|
if(ip->ip_ttl==0) {
|
||||||
icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
|
icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If offset or IP_MF are set, must reassemble.
|
* If offset or IP_MF are set, must reassemble.
|
||||||
* Otherwise, nothing need be done.
|
* Otherwise, nothing need be done.
|
||||||
* (We could look in the reassembly queue to see
|
* (We could look in the reassembly queue to see
|
||||||
* if the packet was previously fragmented,
|
* if the packet was previously fragmented,
|
||||||
* but it's not worth the time; just let them time out.)
|
* but it's not worth the time; just let them time out.)
|
||||||
*
|
*
|
||||||
* XXX This should fail, don't fragment yet
|
* XXX This should fail, don't fragment yet
|
||||||
*/
|
*/
|
||||||
if (ip->ip_off &~ IP_DF) {
|
if (ip->ip_off &~ IP_DF) {
|
||||||
register struct ipq *fp;
|
register struct ipq *fp;
|
||||||
struct qlink *l;
|
struct qlink *l;
|
||||||
/*
|
/*
|
||||||
* Look for queue of fragments
|
* Look for queue of fragments
|
||||||
* of this datagram.
|
* of this datagram.
|
||||||
*/
|
*/
|
||||||
for (l = (struct qlink *)slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link;
|
for (l = (struct qlink *)slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link;
|
||||||
l = (struct qlink *)l->next) {
|
l = (struct qlink *)l->next) {
|
||||||
fp = container_of(l, struct ipq, ip_link);
|
fp = container_of(l, struct ipq, ip_link);
|
||||||
if (ip->ip_id == fp->ipq_id &&
|
if (ip->ip_id == fp->ipq_id &&
|
||||||
ip->ip_src.s_addr == fp->ipq_src.s_addr &&
|
ip->ip_src.s_addr == fp->ipq_src.s_addr &&
|
||||||
ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
|
ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
|
||||||
ip->ip_p == fp->ipq_p)
|
ip->ip_p == fp->ipq_p)
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
fp = NULL;
|
fp = NULL;
|
||||||
found:
|
found:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust ip_len to not reflect header,
|
* Adjust ip_len to not reflect header,
|
||||||
* set ip_mff if more fragments are expected,
|
* set ip_mff if more fragments are expected,
|
||||||
* convert offset of this to bytes.
|
* convert offset of this to bytes.
|
||||||
*/
|
*/
|
||||||
ip->ip_len -= hlen;
|
ip->ip_len -= hlen;
|
||||||
if (ip->ip_off & IP_MF)
|
if (ip->ip_off & IP_MF)
|
||||||
ip->ip_tos |= 1;
|
ip->ip_tos |= 1;
|
||||||
else
|
else
|
||||||
ip->ip_tos &= ~1;
|
ip->ip_tos &= ~1;
|
||||||
|
|
||||||
ip->ip_off <<= 3;
|
ip->ip_off <<= 3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If datagram marked as having more fragments
|
* If datagram marked as having more fragments
|
||||||
* or if this is not the first fragment,
|
* or if this is not the first fragment,
|
||||||
* attempt reassembly; if it succeeds, proceed.
|
* attempt reassembly; if it succeeds, proceed.
|
||||||
*/
|
*/
|
||||||
if (ip->ip_tos & 1 || ip->ip_off) {
|
if (ip->ip_tos & 1 || ip->ip_off) {
|
||||||
ip = ip_reass(slirp, ip, fp);
|
ip = ip_reass(slirp, ip, fp);
|
||||||
if (ip == NULL)
|
if (ip == NULL)
|
||||||
return;
|
return;
|
||||||
m = dtom(slirp, ip);
|
m = dtom(slirp, ip);
|
||||||
} else
|
} else
|
||||||
if (fp)
|
if (fp)
|
||||||
ip_freef(slirp, fp);
|
ip_freef(slirp, fp);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
ip->ip_len -= hlen;
|
ip->ip_len -= hlen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Switch out to protocol's input routine.
|
* Switch out to protocol's input routine.
|
||||||
*/
|
*/
|
||||||
switch (ip->ip_p) {
|
switch (ip->ip_p) {
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
tcp_input(m, hlen, (struct socket *)NULL);
|
tcp_input(m, hlen, (struct socket *)NULL);
|
||||||
break;
|
break;
|
||||||
case IPPROTO_UDP:
|
case IPPROTO_UDP:
|
||||||
udp_input(m, hlen);
|
udp_input(m, hlen);
|
||||||
break;
|
break;
|
||||||
case IPPROTO_ICMP:
|
case IPPROTO_ICMP:
|
||||||
icmp_input(m, hlen);
|
icmp_input(m, hlen);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_free(m);
|
m_free(m);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
bad:
|
bad:
|
||||||
m_free(m);
|
m_free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))
|
#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))
|
||||||
|
@ -226,151 +226,151 @@ bad:
|
||||||
static struct ip *
|
static struct ip *
|
||||||
ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
|
ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
|
||||||
{
|
{
|
||||||
register struct mbuf *m = dtom(slirp, ip);
|
register struct mbuf *m = dtom(slirp, ip);
|
||||||
register struct ipasfrag *q;
|
register struct ipasfrag *q;
|
||||||
int hlen = ip->ip_hl << 2;
|
int hlen = ip->ip_hl << 2;
|
||||||
int i, next;
|
int i, next;
|
||||||
|
|
||||||
DEBUG_CALL("ip_reass");
|
DEBUG_CALL("ip_reass");
|
||||||
DEBUG_ARG("ip = %lx", (long)ip);
|
DEBUG_ARG("ip = %lx", (long)ip);
|
||||||
DEBUG_ARG("fp = %lx", (long)fp);
|
DEBUG_ARG("fp = %lx", (long)fp);
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Presence of header sizes in mbufs
|
* Presence of header sizes in mbufs
|
||||||
* would confuse code below.
|
* would confuse code below.
|
||||||
* Fragment m_data is concatenated.
|
* Fragment m_data is concatenated.
|
||||||
*/
|
*/
|
||||||
m->m_data += hlen;
|
m->m_data += hlen;
|
||||||
m->m_len -= hlen;
|
m->m_len -= hlen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If first fragment to arrive, create a reassembly queue.
|
* If first fragment to arrive, create a reassembly queue.
|
||||||
*/
|
*/
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
struct mbuf *t = m_get(slirp);
|
struct mbuf *t = m_get(slirp);
|
||||||
|
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
goto dropfrag;
|
goto dropfrag;
|
||||||
}
|
}
|
||||||
fp = mtod(t, struct ipq *);
|
fp = mtod(t, struct ipq *);
|
||||||
insque(&fp->ip_link, &slirp->ipq.ip_link);
|
insque(&fp->ip_link, &slirp->ipq.ip_link);
|
||||||
fp->ipq_ttl = IPFRAGTTL;
|
fp->ipq_ttl = IPFRAGTTL;
|
||||||
fp->ipq_p = ip->ip_p;
|
fp->ipq_p = ip->ip_p;
|
||||||
fp->ipq_id = ip->ip_id;
|
fp->ipq_id = ip->ip_id;
|
||||||
fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;
|
fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;
|
||||||
fp->ipq_src = ip->ip_src;
|
fp->ipq_src = ip->ip_src;
|
||||||
fp->ipq_dst = ip->ip_dst;
|
fp->ipq_dst = ip->ip_dst;
|
||||||
q = (struct ipasfrag *)fp;
|
q = (struct ipasfrag *)fp;
|
||||||
goto insert;
|
goto insert;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a segment which begins after this one does.
|
* Find a segment which begins after this one does.
|
||||||
*/
|
*/
|
||||||
for (q = (struct ipasfrag *)fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
|
for (q = (struct ipasfrag *)fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
|
||||||
q = (struct ipasfrag *)q->ipf_next)
|
q = (struct ipasfrag *)q->ipf_next)
|
||||||
if (q->ipf_off > ip->ip_off)
|
if (q->ipf_off > ip->ip_off)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is a preceding segment, it may provide some of
|
* If there is a preceding segment, it may provide some of
|
||||||
* our data already. If so, drop the data from the incoming
|
* our data already. If so, drop the data from the incoming
|
||||||
* segment. If it provides all of our data, drop us.
|
* segment. If it provides all of our data, drop us.
|
||||||
*/
|
*/
|
||||||
if (q->ipf_prev != &fp->frag_link) {
|
if (q->ipf_prev != &fp->frag_link) {
|
||||||
struct ipasfrag *pq = (struct ipasfrag *)q->ipf_prev;
|
struct ipasfrag *pq = (struct ipasfrag *)q->ipf_prev;
|
||||||
i = pq->ipf_off + pq->ipf_len - ip->ip_off;
|
i = pq->ipf_off + pq->ipf_len - ip->ip_off;
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
if (i >= ip->ip_len)
|
if (i >= ip->ip_len)
|
||||||
goto dropfrag;
|
goto dropfrag;
|
||||||
m_adj(dtom(slirp, ip), i);
|
m_adj(dtom(slirp, ip), i);
|
||||||
ip->ip_off += i;
|
ip->ip_off += i;
|
||||||
ip->ip_len -= i;
|
ip->ip_len -= i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* While we overlap succeeding segments trim them or,
|
* While we overlap succeeding segments trim them or,
|
||||||
* if they are completely covered, dequeue them.
|
* if they are completely covered, dequeue them.
|
||||||
*/
|
*/
|
||||||
while (q != (struct ipasfrag*)&fp->frag_link &&
|
while (q != (struct ipasfrag*)&fp->frag_link &&
|
||||||
ip->ip_off + ip->ip_len > q->ipf_off) {
|
ip->ip_off + ip->ip_len > q->ipf_off) {
|
||||||
i = (ip->ip_off + ip->ip_len) - q->ipf_off;
|
i = (ip->ip_off + ip->ip_len) - q->ipf_off;
|
||||||
if (i < q->ipf_len) {
|
if (i < q->ipf_len) {
|
||||||
q->ipf_len -= i;
|
q->ipf_len -= i;
|
||||||
q->ipf_off += i;
|
q->ipf_off += i;
|
||||||
m_adj(dtom(slirp, q), i);
|
m_adj(dtom(slirp, q), i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
q = (struct ipasfrag *)q->ipf_next;
|
q = (struct ipasfrag *)q->ipf_next;
|
||||||
m_free(dtom(slirp, q->ipf_prev));
|
m_free(dtom(slirp, q->ipf_prev));
|
||||||
ip_deq((struct ipasfrag*)q->ipf_prev);
|
ip_deq((struct ipasfrag*)q->ipf_prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
insert:
|
insert:
|
||||||
/*
|
/*
|
||||||
* Stick new segment in its place;
|
* Stick new segment in its place;
|
||||||
* check for complete reassembly.
|
* check for complete reassembly.
|
||||||
*/
|
*/
|
||||||
ip_enq(iptofrag(ip), (struct ipasfrag*)q->ipf_prev);
|
ip_enq(iptofrag(ip), (struct ipasfrag*)q->ipf_prev);
|
||||||
next = 0;
|
next = 0;
|
||||||
for (q = (struct ipasfrag*)fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;
|
for (q = (struct ipasfrag*)fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;
|
||||||
q = (struct ipasfrag*)q->ipf_next) {
|
q = (struct ipasfrag*)q->ipf_next) {
|
||||||
if (q->ipf_off != next)
|
if (q->ipf_off != next)
|
||||||
return NULL;
|
return NULL;
|
||||||
next += q->ipf_len;
|
next += q->ipf_len;
|
||||||
}
|
}
|
||||||
if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)
|
if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reassembly is complete; concatenate fragments.
|
* Reassembly is complete; concatenate fragments.
|
||||||
*/
|
*/
|
||||||
q = (struct ipasfrag*)fp->frag_link.next;
|
q = (struct ipasfrag*)fp->frag_link.next;
|
||||||
m = dtom(slirp, q);
|
m = dtom(slirp, q);
|
||||||
|
|
||||||
q = (struct ipasfrag *) q->ipf_next;
|
q = (struct ipasfrag *) q->ipf_next;
|
||||||
while (q != (struct ipasfrag*)&fp->frag_link) {
|
while (q != (struct ipasfrag*)&fp->frag_link) {
|
||||||
struct mbuf *t = dtom(slirp, q);
|
struct mbuf *t = dtom(slirp, q);
|
||||||
q = (struct ipasfrag *) q->ipf_next;
|
q = (struct ipasfrag *) q->ipf_next;
|
||||||
m_cat(m, t);
|
m_cat(m, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create header for new ip packet by
|
* Create header for new ip packet by
|
||||||
* modifying header of first packet;
|
* modifying header of first packet;
|
||||||
* dequeue and discard fragment reassembly header.
|
* dequeue and discard fragment reassembly header.
|
||||||
* Make header visible.
|
* Make header visible.
|
||||||
*/
|
*/
|
||||||
q = (struct ipasfrag*)fp->frag_link.next;
|
q = (struct ipasfrag*)fp->frag_link.next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the fragments concatenated to an mbuf that's
|
* If the fragments concatenated to an mbuf that's
|
||||||
* bigger than the total size of the fragment, then and
|
* bigger than the total size of the fragment, then and
|
||||||
* m_ext buffer was alloced. But fp->ipq_next points to
|
* m_ext buffer was alloced. But fp->ipq_next points to
|
||||||
* the old buffer (in the mbuf), so we must point ip
|
* the old buffer (in the mbuf), so we must point ip
|
||||||
* into the new buffer.
|
* into the new buffer.
|
||||||
*/
|
*/
|
||||||
if (m->m_flags & M_EXT) {
|
if (m->m_flags & M_EXT) {
|
||||||
int delta = (char *)q - m->m_dat;
|
int delta = (char *)q - m->m_dat;
|
||||||
q = (struct ipasfrag *)(m->m_ext + delta);
|
q = (struct ipasfrag *)(m->m_ext + delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = fragtoip(q);
|
ip = fragtoip(q);
|
||||||
ip->ip_len = next;
|
ip->ip_len = next;
|
||||||
ip->ip_tos &= ~1;
|
ip->ip_tos &= ~1;
|
||||||
ip->ip_src = fp->ipq_src;
|
ip->ip_src = fp->ipq_src;
|
||||||
ip->ip_dst = fp->ipq_dst;
|
ip->ip_dst = fp->ipq_dst;
|
||||||
remque(&fp->ip_link);
|
remque(&fp->ip_link);
|
||||||
(void) m_free(dtom(slirp, fp));
|
(void) m_free(dtom(slirp, fp));
|
||||||
m->m_len += (ip->ip_hl << 2);
|
m->m_len += (ip->ip_hl << 2);
|
||||||
m->m_data -= (ip->ip_hl << 2);
|
m->m_data -= (ip->ip_hl << 2);
|
||||||
|
|
||||||
return ip;
|
return ip;
|
||||||
|
|
||||||
dropfrag:
|
dropfrag:
|
||||||
m_free(m);
|
m_free(m);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,15 +381,15 @@ dropfrag:
|
||||||
static void
|
static void
|
||||||
ip_freef(Slirp *slirp, struct ipq *fp)
|
ip_freef(Slirp *slirp, struct ipq *fp)
|
||||||
{
|
{
|
||||||
register struct ipasfrag *q, *p;
|
register struct ipasfrag *q, *p;
|
||||||
|
|
||||||
for (q = (struct ipasfrag*)fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
|
for (q = (struct ipasfrag*)fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
|
||||||
p = (struct ipasfrag*)q->ipf_next;
|
p = (struct ipasfrag*)q->ipf_next;
|
||||||
ip_deq(q);
|
ip_deq(q);
|
||||||
m_free(dtom(slirp, q));
|
m_free(dtom(slirp, q));
|
||||||
}
|
}
|
||||||
remque(&fp->ip_link);
|
remque(&fp->ip_link);
|
||||||
(void) m_free(dtom(slirp, fp));
|
(void) m_free(dtom(slirp, fp));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -399,12 +399,12 @@ ip_freef(Slirp *slirp, struct ipq *fp)
|
||||||
static void
|
static void
|
||||||
ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
|
ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
|
||||||
{
|
{
|
||||||
DEBUG_CALL("ip_enq");
|
DEBUG_CALL("ip_enq");
|
||||||
DEBUG_ARG("prev = %lx", (long)prev);
|
DEBUG_ARG("prev = %lx", (long)prev);
|
||||||
p->ipf_prev = prev;
|
p->ipf_prev = prev;
|
||||||
p->ipf_next = prev->ipf_next;
|
p->ipf_next = prev->ipf_next;
|
||||||
((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;
|
((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;
|
||||||
prev->ipf_next = p;
|
prev->ipf_next = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -413,8 +413,8 @@ ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
|
||||||
static void
|
static void
|
||||||
ip_deq(register struct ipasfrag *p)
|
ip_deq(register struct ipasfrag *p)
|
||||||
{
|
{
|
||||||
((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
|
((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
|
||||||
((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
|
((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -427,19 +427,19 @@ ip_slowtimo(Slirp *slirp)
|
||||||
{
|
{
|
||||||
struct qlink *l;
|
struct qlink *l;
|
||||||
|
|
||||||
DEBUG_CALL("ip_slowtimo");
|
DEBUG_CALL("ip_slowtimo");
|
||||||
|
|
||||||
l = (struct qlink*)slirp->ipq.ip_link.next;
|
l = (struct qlink*)slirp->ipq.ip_link.next;
|
||||||
|
|
||||||
if (l == NULL)
|
if (l == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (l != &slirp->ipq.ip_link) {
|
while (l != &slirp->ipq.ip_link) {
|
||||||
struct ipq *fp = container_of(l, struct ipq, ip_link);
|
struct ipq *fp = container_of(l, struct ipq, ip_link);
|
||||||
l = (struct qlink*)l->next;
|
l = (struct qlink*)l->next;
|
||||||
if (--fp->ipq_ttl == 0) {
|
if (--fp->ipq_ttl == 0) {
|
||||||
ip_freef(slirp, fp);
|
ip_freef(slirp, fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,190 +455,190 @@ ip_slowtimo(Slirp *slirp)
|
||||||
|
|
||||||
int
|
int
|
||||||
ip_dooptions(m)
|
ip_dooptions(m)
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
{
|
{
|
||||||
register struct ip *ip = mtod(m, struct ip *);
|
register struct ip *ip = mtod(m, struct ip *);
|
||||||
register u_char *cp;
|
register u_char *cp;
|
||||||
register struct ip_timestamp *ipt;
|
register struct ip_timestamp *ipt;
|
||||||
register struct in_ifaddr *ia;
|
register struct in_ifaddr *ia;
|
||||||
int opt, optlen, cnt, off, code, type, forward = 0;
|
int opt, optlen, cnt, off, code, type, forward = 0;
|
||||||
struct in_addr *sin, dst;
|
struct in_addr *sin, dst;
|
||||||
typedef uint32_t n_time;
|
typedef uint32_t n_time;
|
||||||
n_time ntime;
|
n_time ntime;
|
||||||
|
|
||||||
dst = ip->ip_dst;
|
dst = ip->ip_dst;
|
||||||
cp = (u_char *)(ip + 1);
|
cp = (u_char *)(ip + 1);
|
||||||
cnt = (ip->ip_hl << 2) - sizeof (struct ip);
|
cnt = (ip->ip_hl << 2) - sizeof (struct ip);
|
||||||
for (; cnt > 0; cnt -= optlen, cp += optlen) {
|
for (; cnt > 0; cnt -= optlen, cp += optlen) {
|
||||||
opt = cp[IPOPT_OPTVAL];
|
opt = cp[IPOPT_OPTVAL];
|
||||||
if (opt == IPOPT_EOL)
|
if (opt == IPOPT_EOL)
|
||||||
break;
|
break;
|
||||||
if (opt == IPOPT_NOP)
|
if (opt == IPOPT_NOP)
|
||||||
optlen = 1;
|
optlen = 1;
|
||||||
else {
|
else {
|
||||||
optlen = cp[IPOPT_OLEN];
|
optlen = cp[IPOPT_OLEN];
|
||||||
if (optlen <= 0 || optlen > cnt) {
|
if (optlen <= 0 || optlen > cnt) {
|
||||||
code = &cp[IPOPT_OLEN] - (u_char *)ip;
|
code = &cp[IPOPT_OLEN] - (u_char *)ip;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Source routing with record.
|
* Source routing with record.
|
||||||
* Find interface with current destination address.
|
* Find interface with current destination address.
|
||||||
* If none on this machine then drop if strictly routed,
|
* If none on this machine then drop if strictly routed,
|
||||||
* or do nothing if loosely routed.
|
* or do nothing if loosely routed.
|
||||||
* Record interface address and bring up next address
|
* Record interface address and bring up next address
|
||||||
* component. If strictly routed make sure next
|
* component. If strictly routed make sure next
|
||||||
* address is on directly accessible net.
|
* address is on directly accessible net.
|
||||||
*/
|
*/
|
||||||
case IPOPT_LSRR:
|
case IPOPT_LSRR:
|
||||||
case IPOPT_SSRR:
|
case IPOPT_SSRR:
|
||||||
if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
|
if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
|
||||||
code = &cp[IPOPT_OFFSET] - (u_char *)ip;
|
code = &cp[IPOPT_OFFSET] - (u_char *)ip;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
ipaddr.sin_addr = ip->ip_dst;
|
ipaddr.sin_addr = ip->ip_dst;
|
||||||
ia = (struct in_ifaddr *)
|
ia = (struct in_ifaddr *)
|
||||||
ifa_ifwithaddr((struct sockaddr *)&ipaddr);
|
ifa_ifwithaddr((struct sockaddr *)&ipaddr);
|
||||||
if (ia == 0) {
|
if (ia == 0) {
|
||||||
if (opt == IPOPT_SSRR) {
|
if (opt == IPOPT_SSRR) {
|
||||||
type = ICMP_UNREACH;
|
type = ICMP_UNREACH;
|
||||||
code = ICMP_UNREACH_SRCFAIL;
|
code = ICMP_UNREACH_SRCFAIL;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Loose routing, and not at next destination
|
* Loose routing, and not at next destination
|
||||||
* yet; nothing to do except forward.
|
* yet; nothing to do except forward.
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
off--; /* 0 origin */
|
off--; /* 0 origin */
|
||||||
if (off > optlen - sizeof(struct in_addr)) {
|
if (off > optlen - sizeof(struct in_addr)) {
|
||||||
/*
|
/*
|
||||||
* End of source route. Should be for us.
|
* End of source route. Should be for us.
|
||||||
*/
|
*/
|
||||||
save_rte(cp, ip->ip_src);
|
save_rte(cp, ip->ip_src);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* locate outgoing interface
|
* locate outgoing interface
|
||||||
*/
|
*/
|
||||||
bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
|
bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
|
||||||
sizeof(ipaddr.sin_addr));
|
sizeof(ipaddr.sin_addr));
|
||||||
if (opt == IPOPT_SSRR) {
|
if (opt == IPOPT_SSRR) {
|
||||||
#define INA struct in_ifaddr *
|
#define INA struct in_ifaddr *
|
||||||
#define SA struct sockaddr *
|
#define SA struct sockaddr *
|
||||||
if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
|
if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
|
||||||
ia = (INA)ifa_ifwithnet((SA)&ipaddr);
|
ia = (INA)ifa_ifwithnet((SA)&ipaddr);
|
||||||
} else
|
} else
|
||||||
ia = ip_rtaddr(ipaddr.sin_addr);
|
ia = ip_rtaddr(ipaddr.sin_addr);
|
||||||
if (ia == 0) {
|
if (ia == 0) {
|
||||||
type = ICMP_UNREACH;
|
type = ICMP_UNREACH;
|
||||||
code = ICMP_UNREACH_SRCFAIL;
|
code = ICMP_UNREACH_SRCFAIL;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
ip->ip_dst = ipaddr.sin_addr;
|
ip->ip_dst = ipaddr.sin_addr;
|
||||||
bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
|
bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
|
||||||
(caddr_t)(cp + off), sizeof(struct in_addr));
|
(caddr_t)(cp + off), sizeof(struct in_addr));
|
||||||
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
|
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
|
||||||
/*
|
/*
|
||||||
* Let ip_intr's mcast routing check handle mcast pkts
|
* Let ip_intr's mcast routing check handle mcast pkts
|
||||||
*/
|
*/
|
||||||
forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
|
forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPOPT_RR:
|
case IPOPT_RR:
|
||||||
if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
|
if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
|
||||||
code = &cp[IPOPT_OFFSET] - (u_char *)ip;
|
code = &cp[IPOPT_OFFSET] - (u_char *)ip;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If no space remains, ignore.
|
* If no space remains, ignore.
|
||||||
*/
|
*/
|
||||||
off--; /* 0 origin */
|
off--; /* 0 origin */
|
||||||
if (off > optlen - sizeof(struct in_addr))
|
if (off > optlen - sizeof(struct in_addr))
|
||||||
break;
|
break;
|
||||||
bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
|
bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
|
||||||
sizeof(ipaddr.sin_addr));
|
sizeof(ipaddr.sin_addr));
|
||||||
/*
|
/*
|
||||||
* locate outgoing interface; if we're the destination,
|
* locate outgoing interface; if we're the destination,
|
||||||
* use the incoming interface (should be same).
|
* use the incoming interface (should be same).
|
||||||
*/
|
*/
|
||||||
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
|
if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
|
||||||
(ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
|
(ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
|
||||||
type = ICMP_UNREACH;
|
type = ICMP_UNREACH;
|
||||||
code = ICMP_UNREACH_HOST;
|
code = ICMP_UNREACH_HOST;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
|
bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
|
||||||
(caddr_t)(cp + off), sizeof(struct in_addr));
|
(caddr_t)(cp + off), sizeof(struct in_addr));
|
||||||
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
|
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPOPT_TS:
|
case IPOPT_TS:
|
||||||
code = cp - (u_char *)ip;
|
code = cp - (u_char *)ip;
|
||||||
ipt = (struct ip_timestamp *)cp;
|
ipt = (struct ip_timestamp *)cp;
|
||||||
if (ipt->ipt_len < 5)
|
if (ipt->ipt_len < 5)
|
||||||
goto bad;
|
goto bad;
|
||||||
if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
|
if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
|
||||||
if (++ipt->ipt_oflw == 0)
|
if (++ipt->ipt_oflw == 0)
|
||||||
goto bad;
|
goto bad;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
|
sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
|
||||||
switch (ipt->ipt_flg) {
|
switch (ipt->ipt_flg) {
|
||||||
|
|
||||||
case IPOPT_TS_TSONLY:
|
case IPOPT_TS_TSONLY:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPOPT_TS_TSANDADDR:
|
case IPOPT_TS_TSANDADDR:
|
||||||
if (ipt->ipt_ptr + sizeof(n_time) +
|
if (ipt->ipt_ptr + sizeof(n_time) +
|
||||||
sizeof(struct in_addr) > ipt->ipt_len)
|
sizeof(struct in_addr) > ipt->ipt_len)
|
||||||
goto bad;
|
goto bad;
|
||||||
ipaddr.sin_addr = dst;
|
ipaddr.sin_addr = dst;
|
||||||
ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,
|
ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,
|
||||||
m->m_pkthdr.rcvif);
|
m->m_pkthdr.rcvif);
|
||||||
if (ia == 0)
|
if (ia == 0)
|
||||||
continue;
|
continue;
|
||||||
bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
|
bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
|
||||||
(caddr_t)sin, sizeof(struct in_addr));
|
(caddr_t)sin, sizeof(struct in_addr));
|
||||||
ipt->ipt_ptr += sizeof(struct in_addr);
|
ipt->ipt_ptr += sizeof(struct in_addr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPOPT_TS_PRESPEC:
|
case IPOPT_TS_PRESPEC:
|
||||||
if (ipt->ipt_ptr + sizeof(n_time) +
|
if (ipt->ipt_ptr + sizeof(n_time) +
|
||||||
sizeof(struct in_addr) > ipt->ipt_len)
|
sizeof(struct in_addr) > ipt->ipt_len)
|
||||||
goto bad;
|
goto bad;
|
||||||
bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
|
bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
|
||||||
sizeof(struct in_addr));
|
sizeof(struct in_addr));
|
||||||
if (ifa_ifwithaddr((SA)&ipaddr) == 0)
|
if (ifa_ifwithaddr((SA)&ipaddr) == 0)
|
||||||
continue;
|
continue;
|
||||||
ipt->ipt_ptr += sizeof(struct in_addr);
|
ipt->ipt_ptr += sizeof(struct in_addr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
ntime = iptime();
|
ntime = iptime();
|
||||||
bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
|
bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
|
||||||
sizeof(n_time));
|
sizeof(n_time));
|
||||||
ipt->ipt_ptr += sizeof(n_time);
|
ipt->ipt_ptr += sizeof(n_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (forward) {
|
if (forward) {
|
||||||
ip_forward(m, 1);
|
ip_forward(m, 1);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
bad:
|
bad:
|
||||||
icmp_error(m, type, code, 0, 0);
|
icmp_error(m, type, code, 0, 0);
|
||||||
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* notdef */
|
#endif /* notdef */
|
||||||
|
@ -653,16 +653,16 @@ bad:
|
||||||
void
|
void
|
||||||
ip_stripoptions(register struct mbuf *m, struct mbuf *mopt)
|
ip_stripoptions(register struct mbuf *m, struct mbuf *mopt)
|
||||||
{
|
{
|
||||||
register int i;
|
register int i;
|
||||||
struct ip *ip = mtod(m, struct ip *);
|
struct ip *ip = mtod(m, struct ip *);
|
||||||
register caddr_t opts;
|
register caddr_t opts;
|
||||||
int olen;
|
int olen;
|
||||||
|
|
||||||
olen = (ip->ip_hl<<2) - sizeof (struct ip);
|
olen = (ip->ip_hl<<2) - sizeof (struct ip);
|
||||||
opts = (caddr_t)(ip + 1);
|
opts = (caddr_t)(ip + 1);
|
||||||
i = m->m_len - (sizeof (struct ip) + olen);
|
i = m->m_len - (sizeof (struct ip) + olen);
|
||||||
memcpy(opts, opts + olen, (unsigned)i);
|
memcpy(opts, opts + olen, (unsigned)i);
|
||||||
m->m_len -= olen;
|
m->m_len -= olen;
|
||||||
|
|
||||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1988, 1990, 1993
|
* Copyright (c) 1982, 1986, 1988, 1990, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94
|
* @(#)ip_output.c 8.3 (Berkeley) 1/21/94
|
||||||
* ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp
|
* ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -53,120 +53,120 @@
|
||||||
int
|
int
|
||||||
ip_output(struct socket *so, struct mbuf *m0)
|
ip_output(struct socket *so, struct mbuf *m0)
|
||||||
{
|
{
|
||||||
Slirp *slirp = m0->slirp;
|
Slirp *slirp = m0->slirp;
|
||||||
register struct ip *ip;
|
register struct ip *ip;
|
||||||
register struct mbuf *m = m0;
|
register struct mbuf *m = m0;
|
||||||
register int hlen = sizeof(struct ip );
|
register int hlen = sizeof(struct ip );
|
||||||
int len, off, error = 0;
|
int len, off, error = 0;
|
||||||
|
|
||||||
DEBUG_CALL("ip_output");
|
DEBUG_CALL("ip_output");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("m0 = %lx", (long)m0);
|
DEBUG_ARG("m0 = %lx", (long)m0);
|
||||||
|
|
||||||
ip = mtod(m, struct ip *);
|
ip = mtod(m, struct ip *);
|
||||||
/*
|
/*
|
||||||
* Fill in IP header.
|
* Fill in IP header.
|
||||||
*/
|
*/
|
||||||
ip->ip_v = IPVERSION;
|
ip->ip_v = IPVERSION;
|
||||||
ip->ip_off &= IP_DF;
|
ip->ip_off &= IP_DF;
|
||||||
ip->ip_id = htons(slirp->ip_id++);
|
ip->ip_id = htons(slirp->ip_id++);
|
||||||
ip->ip_hl = hlen >> 2;
|
ip->ip_hl = hlen >> 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If small enough for interface, can just send directly.
|
* If small enough for interface, can just send directly.
|
||||||
*/
|
*/
|
||||||
if ((uint16_t)ip->ip_len <= IF_MTU) {
|
if ((uint16_t)ip->ip_len <= IF_MTU) {
|
||||||
ip->ip_len = htons((uint16_t)ip->ip_len);
|
ip->ip_len = htons((uint16_t)ip->ip_len);
|
||||||
ip->ip_off = htons((uint16_t)ip->ip_off);
|
ip->ip_off = htons((uint16_t)ip->ip_off);
|
||||||
ip->ip_sum = 0;
|
ip->ip_sum = 0;
|
||||||
ip->ip_sum = cksum(m, hlen);
|
ip->ip_sum = cksum(m, hlen);
|
||||||
|
|
||||||
if_output(so, m);
|
if_output(so, m);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Too large for interface; fragment if possible.
|
* Too large for interface; fragment if possible.
|
||||||
* Must be able to put at least 8 bytes per fragment.
|
* Must be able to put at least 8 bytes per fragment.
|
||||||
*/
|
*/
|
||||||
if (ip->ip_off & IP_DF) {
|
if (ip->ip_off & IP_DF) {
|
||||||
error = -1;
|
error = -1;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */
|
len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */
|
||||||
if (len < 8) {
|
if (len < 8) {
|
||||||
error = -1;
|
error = -1;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int mhlen, firstlen = len;
|
int mhlen, firstlen = len;
|
||||||
struct mbuf **mnext = &m->m_nextpkt;
|
struct mbuf **mnext = &m->m_nextpkt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop through length of segment after first fragment,
|
* Loop through length of segment after first fragment,
|
||||||
* make new header and copy data of each part and link onto chain.
|
* make new header and copy data of each part and link onto chain.
|
||||||
*/
|
*/
|
||||||
m0 = m;
|
m0 = m;
|
||||||
mhlen = sizeof (struct ip);
|
mhlen = sizeof (struct ip);
|
||||||
for (off = hlen + len; off < (uint16_t)ip->ip_len; off += len) {
|
for (off = hlen + len; off < (uint16_t)ip->ip_len; off += len) {
|
||||||
register struct ip *mhip;
|
register struct ip *mhip;
|
||||||
m = m_get(slirp);
|
m = m_get(slirp);
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
error = -1;
|
error = -1;
|
||||||
goto sendorfree;
|
goto sendorfree;
|
||||||
}
|
}
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += IF_MAXLINKHDR;
|
||||||
mhip = mtod(m, struct ip *);
|
mhip = mtod(m, struct ip *);
|
||||||
*mhip = *ip;
|
*mhip = *ip;
|
||||||
|
|
||||||
m->m_len = mhlen;
|
m->m_len = mhlen;
|
||||||
mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
|
mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
|
||||||
if (ip->ip_off & IP_MF)
|
if (ip->ip_off & IP_MF)
|
||||||
mhip->ip_off |= IP_MF;
|
mhip->ip_off |= IP_MF;
|
||||||
if (off + len >= (uint16_t)ip->ip_len)
|
if (off + len >= (uint16_t)ip->ip_len)
|
||||||
len = (uint16_t)ip->ip_len - off;
|
len = (uint16_t)ip->ip_len - off;
|
||||||
else
|
else
|
||||||
mhip->ip_off |= IP_MF;
|
mhip->ip_off |= IP_MF;
|
||||||
mhip->ip_len = htons((uint16_t)(len + mhlen));
|
mhip->ip_len = htons((uint16_t)(len + mhlen));
|
||||||
|
|
||||||
if (m_copy(m, m0, off, len) < 0) {
|
if (m_copy(m, m0, off, len) < 0) {
|
||||||
error = -1;
|
error = -1;
|
||||||
goto sendorfree;
|
goto sendorfree;
|
||||||
}
|
}
|
||||||
|
|
||||||
mhip->ip_off = htons((uint16_t)mhip->ip_off);
|
mhip->ip_off = htons((uint16_t)mhip->ip_off);
|
||||||
mhip->ip_sum = 0;
|
mhip->ip_sum = 0;
|
||||||
mhip->ip_sum = cksum(m, mhlen);
|
mhip->ip_sum = cksum(m, mhlen);
|
||||||
*mnext = m;
|
*mnext = m;
|
||||||
mnext = &m->m_nextpkt;
|
mnext = &m->m_nextpkt;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Update first fragment by trimming what's been copied out
|
* Update first fragment by trimming what's been copied out
|
||||||
* and updating header, then send each fragment (in order).
|
* and updating header, then send each fragment (in order).
|
||||||
*/
|
*/
|
||||||
m = m0;
|
m = m0;
|
||||||
m_adj(m, hlen + firstlen - (uint16_t)ip->ip_len);
|
m_adj(m, hlen + firstlen - (uint16_t)ip->ip_len);
|
||||||
ip->ip_len = htons((uint16_t)m->m_len);
|
ip->ip_len = htons((uint16_t)m->m_len);
|
||||||
ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF));
|
ip->ip_off = htons((uint16_t)(ip->ip_off | IP_MF));
|
||||||
ip->ip_sum = 0;
|
ip->ip_sum = 0;
|
||||||
ip->ip_sum = cksum(m, hlen);
|
ip->ip_sum = cksum(m, hlen);
|
||||||
sendorfree:
|
sendorfree:
|
||||||
for (m = m0; m; m = m0) {
|
for (m = m0; m; m = m0) {
|
||||||
m0 = m->m_nextpkt;
|
m0 = m->m_nextpkt;
|
||||||
m->m_nextpkt = NULL;
|
m->m_nextpkt = NULL;
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
if_output(so, m);
|
if_output(so, m);
|
||||||
else
|
else
|
||||||
m_free(m);
|
m_free(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
m_free(m0);
|
m_free(m0);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
182
slirp/mbuf.c
182
slirp/mbuf.c
|
@ -64,38 +64,38 @@ void m_cleanup(Slirp *slirp)
|
||||||
struct mbuf *
|
struct mbuf *
|
||||||
m_get(Slirp *slirp)
|
m_get(Slirp *slirp)
|
||||||
{
|
{
|
||||||
register struct mbuf *m;
|
register struct mbuf *m;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
DEBUG_CALL("m_get");
|
DEBUG_CALL("m_get");
|
||||||
|
|
||||||
if (slirp->m_freelist.m_next == &slirp->m_freelist) {
|
if (slirp->m_freelist.m_next == &slirp->m_freelist) {
|
||||||
m = (struct mbuf *)malloc(SLIRP_MSIZE);
|
m = (struct mbuf *)malloc(SLIRP_MSIZE);
|
||||||
if (m == NULL) goto end_error;
|
if (m == NULL) goto end_error;
|
||||||
slirp->mbuf_alloced++;
|
slirp->mbuf_alloced++;
|
||||||
if (slirp->mbuf_alloced > MBUF_THRESH)
|
if (slirp->mbuf_alloced > MBUF_THRESH)
|
||||||
flags = M_DOFREE;
|
flags = M_DOFREE;
|
||||||
m->slirp = slirp;
|
m->slirp = slirp;
|
||||||
} else {
|
} else {
|
||||||
m = slirp->m_freelist.m_next;
|
m = slirp->m_freelist.m_next;
|
||||||
remque(m);
|
remque(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert it in the used list */
|
/* Insert it in the used list */
|
||||||
insque(m,&slirp->m_usedlist);
|
insque(m,&slirp->m_usedlist);
|
||||||
m->m_flags = (flags | M_USEDLIST);
|
m->m_flags = (flags | M_USEDLIST);
|
||||||
|
|
||||||
/* Initialise it */
|
/* Initialise it */
|
||||||
m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
|
m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
|
||||||
m->m_data = m->m_dat;
|
m->m_data = m->m_dat;
|
||||||
m->m_len = 0;
|
m->m_len = 0;
|
||||||
m->m_nextpkt = NULL;
|
m->m_nextpkt = NULL;
|
||||||
m->m_prevpkt = NULL;
|
m->m_prevpkt = NULL;
|
||||||
m->arp_requested = false;
|
m->arp_requested = false;
|
||||||
m->expiration_date = (uint64_t)-1;
|
m->expiration_date = (uint64_t)-1;
|
||||||
end_error:
|
end_error:
|
||||||
DEBUG_ARG("m = %lx", (long )m);
|
DEBUG_ARG("m = %lx", (long )m);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -106,24 +106,24 @@ m_free(struct mbuf *m)
|
||||||
DEBUG_ARG("m = %lx", (long )m);
|
DEBUG_ARG("m = %lx", (long )m);
|
||||||
|
|
||||||
if(m) {
|
if(m) {
|
||||||
/* Remove from m_usedlist */
|
/* Remove from m_usedlist */
|
||||||
if (m->m_flags & M_USEDLIST)
|
if (m->m_flags & M_USEDLIST)
|
||||||
remque(m);
|
remque(m);
|
||||||
|
|
||||||
/* If it's M_EXT, free() it */
|
/* If it's M_EXT, free() it */
|
||||||
if (m->m_flags & M_EXT)
|
if (m->m_flags & M_EXT)
|
||||||
free(m->m_ext);
|
free(m->m_ext);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Either free() it or put it on the free list
|
* Either free() it or put it on the free list
|
||||||
*/
|
*/
|
||||||
if (m->m_flags & M_DOFREE) {
|
if (m->m_flags & M_DOFREE) {
|
||||||
m->slirp->mbuf_alloced--;
|
m->slirp->mbuf_alloced--;
|
||||||
free(m);
|
free(m);
|
||||||
} else if ((m->m_flags & M_FREELIST) == 0) {
|
} else if ((m->m_flags & M_FREELIST) == 0) {
|
||||||
insque(m,&m->slirp->m_freelist);
|
insque(m,&m->slirp->m_freelist);
|
||||||
m->m_flags = M_FREELIST; /* Clobber other flags */
|
m->m_flags = M_FREELIST; /* Clobber other flags */
|
||||||
}
|
}
|
||||||
} /* if(m) */
|
} /* if(m) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,16 +135,16 @@ m_free(struct mbuf *m)
|
||||||
void
|
void
|
||||||
m_cat(struct mbuf *m, struct mbuf *n)
|
m_cat(struct mbuf *m, struct mbuf *n)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If there's no room, realloc
|
* If there's no room, realloc
|
||||||
*/
|
*/
|
||||||
if (M_FREEROOM(m) < n->m_len)
|
if (M_FREEROOM(m) < n->m_len)
|
||||||
m_inc(m,m->m_size+MINCSIZE);
|
m_inc(m,m->m_size+MINCSIZE);
|
||||||
|
|
||||||
memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
|
memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
|
||||||
m->m_len += n->m_len;
|
m->m_len += n->m_len;
|
||||||
|
|
||||||
m_free(n);
|
m_free(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,24 +152,24 @@ m_cat(struct mbuf *m, struct mbuf *n)
|
||||||
void
|
void
|
||||||
m_inc(struct mbuf *m, int size)
|
m_inc(struct mbuf *m, int size)
|
||||||
{
|
{
|
||||||
int datasize;
|
int datasize;
|
||||||
|
|
||||||
/* some compiles throw up on gotos. This one we can fake. */
|
/* some compiles throw up on gotos. This one we can fake. */
|
||||||
if(m->m_size>size) return;
|
if(m->m_size>size) return;
|
||||||
|
|
||||||
if (m->m_flags & M_EXT) {
|
if (m->m_flags & M_EXT) {
|
||||||
datasize = m->m_data - m->m_ext;
|
datasize = m->m_data - m->m_ext;
|
||||||
m->m_ext = (char *)realloc(m->m_ext,size);
|
m->m_ext = (char *)realloc(m->m_ext,size);
|
||||||
m->m_data = m->m_ext + datasize;
|
m->m_data = m->m_ext + datasize;
|
||||||
} else {
|
} else {
|
||||||
char *dat;
|
char *dat;
|
||||||
datasize = m->m_data - m->m_dat;
|
datasize = m->m_data - m->m_dat;
|
||||||
dat = (char *)malloc(size);
|
dat = (char *)malloc(size);
|
||||||
memcpy(dat, m->m_dat, m->m_size);
|
memcpy(dat, m->m_dat, m->m_size);
|
||||||
|
|
||||||
m->m_ext = dat;
|
m->m_ext = dat;
|
||||||
m->m_data = m->m_ext + datasize;
|
m->m_data = m->m_ext + datasize;
|
||||||
m->m_flags |= M_EXT;
|
m->m_flags |= M_EXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->m_size = size;
|
m->m_size = size;
|
||||||
|
@ -181,17 +181,17 @@ m_inc(struct mbuf *m, int size)
|
||||||
void
|
void
|
||||||
m_adj(struct mbuf *m, int len)
|
m_adj(struct mbuf *m, int len)
|
||||||
{
|
{
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
return;
|
return;
|
||||||
if (len >= 0) {
|
if (len >= 0) {
|
||||||
/* Trim from head */
|
/* Trim from head */
|
||||||
m->m_data += len;
|
m->m_data += len;
|
||||||
m->m_len -= len;
|
m->m_len -= len;
|
||||||
} else {
|
} else {
|
||||||
/* Trim from tail */
|
/* Trim from tail */
|
||||||
len = -len;
|
len = -len;
|
||||||
m->m_len -= len;
|
m->m_len -= len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -201,12 +201,12 @@ m_adj(struct mbuf *m, int len)
|
||||||
int
|
int
|
||||||
m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
|
m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
|
||||||
{
|
{
|
||||||
if (len > M_FREEROOM(n))
|
if (len > M_FREEROOM(n))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
memcpy((n->m_data + n->m_len), (m->m_data + off), len);
|
memcpy((n->m_data + n->m_len), (m->m_data + off), len);
|
||||||
n->m_len += len;
|
n->m_len += len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,24 +218,24 @@ m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
|
||||||
struct mbuf *
|
struct mbuf *
|
||||||
dtom(Slirp *slirp, void *dat)
|
dtom(Slirp *slirp, void *dat)
|
||||||
{
|
{
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
|
|
||||||
DEBUG_CALL("dtom");
|
DEBUG_CALL("dtom");
|
||||||
DEBUG_ARG("dat = %lx", (long )dat);
|
DEBUG_ARG("dat = %lx", (long )dat);
|
||||||
|
|
||||||
/* bug corrected for M_EXT buffers */
|
/* bug corrected for M_EXT buffers */
|
||||||
for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
|
for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
|
||||||
m = m->m_next) {
|
m = m->m_next) {
|
||||||
if (m->m_flags & M_EXT) {
|
if (m->m_flags & M_EXT) {
|
||||||
if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
|
if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
|
||||||
return m;
|
return m;
|
||||||
} else {
|
} else {
|
||||||
if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
|
if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_ERROR("dtom failed");
|
DEBUG_ERROR("dtom failed");
|
||||||
|
|
||||||
return (struct mbuf *)0;
|
return (struct mbuf *)0;
|
||||||
}
|
}
|
||||||
|
|
64
slirp/mbuf.h
64
slirp/mbuf.h
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1988, 1993
|
* Copyright (c) 1982, 1986, 1988, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,20 +26,20 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)mbuf.h 8.3 (Berkeley) 1/21/94
|
* @(#)mbuf.h 8.3 (Berkeley) 1/21/94
|
||||||
* mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp
|
* mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _MBUF_H_
|
#ifndef _MBUF_H_
|
||||||
#define _MBUF_H_
|
#define _MBUF_H_
|
||||||
|
|
||||||
#define MINCSIZE 4096 /* Amount to increase mbuf if too small */
|
#define MINCSIZE 4096 /* Amount to increase mbuf if too small */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros for type conversion
|
* Macros for type conversion
|
||||||
* mtod(m,t) - convert mbuf pointer to data pointer of correct type
|
* mtod(m,t) - convert mbuf pointer to data pointer of correct type
|
||||||
*/
|
*/
|
||||||
#define mtod(m,t) ((t)(m)->m_data)
|
#define mtod(m,t) ((t)(m)->m_data)
|
||||||
|
|
||||||
/* XXX About mbufs for slirp:
|
/* XXX About mbufs for slirp:
|
||||||
* Only one mbuf is ever used in a chain, for each "cell" of data.
|
* Only one mbuf is ever used in a chain, for each "cell" of data.
|
||||||
|
@ -53,9 +53,9 @@
|
||||||
* How much room is in the mbuf, from m_data to the end of the 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)? \
|
#define M_ROOM(m) ((m->m_flags & M_EXT)? \
|
||||||
(((m)->m_ext + (m)->m_size) - (m)->m_data) \
|
(((m)->m_ext + (m)->m_size) - (m)->m_data) \
|
||||||
: \
|
: \
|
||||||
(((m)->m_dat + (m)->m_size) - (m)->m_data))
|
(((m)->m_dat + (m)->m_size) - (m)->m_data))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* How much free room there is
|
* How much free room there is
|
||||||
|
@ -64,28 +64,28 @@
|
||||||
#define M_TRAILINGSPACE M_FREEROOM
|
#define M_TRAILINGSPACE M_FREEROOM
|
||||||
|
|
||||||
struct mbuf {
|
struct mbuf {
|
||||||
/* XXX should union some of these! */
|
/* XXX should union some of these! */
|
||||||
/* header at beginning of each mbuf: */
|
/* header at beginning of each mbuf: */
|
||||||
struct mbuf *m_next; /* Linked list of mbufs */
|
struct mbuf *m_next; /* Linked list of mbufs */
|
||||||
struct mbuf *m_prev;
|
struct mbuf *m_prev;
|
||||||
struct mbuf *m_nextpkt; /* Next packet in queue/record */
|
struct mbuf *m_nextpkt; /* Next packet in queue/record */
|
||||||
struct mbuf *m_prevpkt; /* Flags aren't used in the output queue */
|
struct mbuf *m_prevpkt; /* Flags aren't used in the output queue */
|
||||||
int m_flags; /* Misc flags */
|
int m_flags; /* Misc flags */
|
||||||
|
|
||||||
int m_size; /* Size of data */
|
int m_size; /* Size of data */
|
||||||
struct socket *m_so;
|
struct socket *m_so;
|
||||||
|
|
||||||
caddr_t m_data; /* Location of data */
|
caddr_t m_data; /* Location of data */
|
||||||
int m_len; /* Amount of data in this mbuf */
|
int m_len; /* Amount of data in this mbuf */
|
||||||
|
|
||||||
Slirp *slirp;
|
Slirp *slirp;
|
||||||
bool arp_requested;
|
bool arp_requested;
|
||||||
uint64_t expiration_date;
|
uint64_t expiration_date;
|
||||||
/* start of dynamic buffer area, must be last element */
|
/* start of dynamic buffer area, must be last element */
|
||||||
union {
|
union {
|
||||||
char m_dat[1]; /* ANSI don't like 0 sized arrays */
|
char m_dat[1]; /* ANSI don't like 0 sized arrays */
|
||||||
char *m_ext;
|
char *m_ext;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ifq_prev m_prev
|
#define ifq_prev m_prev
|
||||||
|
@ -94,11 +94,11 @@ struct mbuf {
|
||||||
#define ifs_next m_nextpkt
|
#define ifs_next m_nextpkt
|
||||||
#define ifq_so m_so
|
#define ifq_so m_so
|
||||||
|
|
||||||
#define M_EXT 0x01 /* m_ext points to more (malloced) data */
|
#define M_EXT 0x01 /* m_ext points to more (malloced) data */
|
||||||
#define M_FREELIST 0x02 /* mbuf is on free list */
|
#define M_FREELIST 0x02 /* mbuf is on free list */
|
||||||
#define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */
|
#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()
|
#define M_DOFREE 0x08 /* when m_free is called on the mbuf, free()
|
||||||
* it rather than putting it on the free list */
|
* it rather than putting it on the free list */
|
||||||
|
|
||||||
void m_init(Slirp *);
|
void m_init(Slirp *);
|
||||||
void m_cleanup(Slirp *slirp);
|
void m_cleanup(Slirp *slirp);
|
||||||
|
|
196
slirp/misc.c
196
slirp/misc.c
|
@ -20,20 +20,20 @@ int slirp_debug =
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct quehead {
|
struct quehead {
|
||||||
struct quehead *qh_link;
|
struct quehead *qh_link;
|
||||||
struct quehead *qh_rlink;
|
struct quehead *qh_rlink;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
insque(void *a, void *b)
|
insque(void *a, void *b)
|
||||||
{
|
{
|
||||||
register struct quehead *element = (struct quehead *) a;
|
register struct quehead *element = (struct quehead *) a;
|
||||||
register struct quehead *head = (struct quehead *) b;
|
register struct quehead *head = (struct quehead *) b;
|
||||||
element->qh_link = head->qh_link;
|
element->qh_link = head->qh_link;
|
||||||
head->qh_link = (struct quehead *)element;
|
head->qh_link = (struct quehead *)element;
|
||||||
element->qh_rlink = (struct quehead *)head;
|
element->qh_rlink = (struct quehead *)head;
|
||||||
((struct quehead *)(element->qh_link))->qh_rlink
|
((struct quehead *)(element->qh_link))->qh_rlink
|
||||||
= (struct quehead *)element;
|
= (struct quehead *)element;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -48,23 +48,23 @@ remque(void *a)
|
||||||
int add_exec(struct ex_list **ex_ptr, int do_pty, const char *exec,
|
int add_exec(struct ex_list **ex_ptr, int do_pty, const char *exec,
|
||||||
struct in_addr addr, int port)
|
struct in_addr addr, int port)
|
||||||
{
|
{
|
||||||
struct ex_list *tmp_ptr;
|
struct ex_list *tmp_ptr;
|
||||||
|
|
||||||
/* First, check if the port is "bound" */
|
/* First, check if the port is "bound" */
|
||||||
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
|
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
|
||||||
if (port == tmp_ptr->ex_fport &&
|
if (port == tmp_ptr->ex_fport &&
|
||||||
addr.s_addr == tmp_ptr->ex_addr.s_addr)
|
addr.s_addr == tmp_ptr->ex_addr.s_addr)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_ptr = *ex_ptr;
|
tmp_ptr = *ex_ptr;
|
||||||
*ex_ptr = (struct ex_list *)g_new(struct ex_list, 1);
|
*ex_ptr = (struct ex_list *)g_new(struct ex_list, 1);
|
||||||
(*ex_ptr)->ex_fport = port;
|
(*ex_ptr)->ex_fport = port;
|
||||||
(*ex_ptr)->ex_addr = addr;
|
(*ex_ptr)->ex_addr = addr;
|
||||||
(*ex_ptr)->ex_pty = do_pty;
|
(*ex_ptr)->ex_pty = do_pty;
|
||||||
(*ex_ptr)->ex_exec = (do_pty == 3) ? exec : g_strdup(exec);
|
(*ex_ptr)->ex_exec = (do_pty == 3) ? exec : g_strdup(exec);
|
||||||
(*ex_ptr)->ex_next = tmp_ptr;
|
(*ex_ptr)->ex_next = tmp_ptr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_STRERROR
|
#ifndef HAVE_STRERROR
|
||||||
|
@ -78,12 +78,12 @@ extern char *sys_errlist[];
|
||||||
|
|
||||||
char *
|
char *
|
||||||
strerror(error)
|
strerror(error)
|
||||||
int error;
|
int error;
|
||||||
{
|
{
|
||||||
if (error < sys_nerr)
|
if (error < sys_nerr)
|
||||||
return sys_errlist[error];
|
return sys_errlist[error];
|
||||||
else
|
else
|
||||||
return "Unknown error.";
|
return "Unknown error.";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -114,50 +114,50 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
int
|
int
|
||||||
fork_exec(struct socket *so, const char *ex, int do_pty)
|
fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
int opt;
|
int opt;
|
||||||
const char *argv[256];
|
const char *argv[256];
|
||||||
/* don't want to clobber the original */
|
/* don't want to clobber the original */
|
||||||
char *bptr;
|
char *bptr;
|
||||||
const char *curarg;
|
const char *curarg;
|
||||||
int c, i, ret;
|
int c, i, ret;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
DEBUG_CALL("fork_exec");
|
DEBUG_CALL("fork_exec");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("ex = %lx", (long)ex);
|
DEBUG_ARG("ex = %lx", (long)ex);
|
||||||
DEBUG_ARG("do_pty = %lx", (long)do_pty);
|
DEBUG_ARG("do_pty = %lx", (long)do_pty);
|
||||||
|
|
||||||
if (do_pty == 2) {
|
if (do_pty == 2) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = 0;
|
addr.sin_port = 0;
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
|
if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
|
||||||
bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
|
bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
|
||||||
listen(s, 1) < 0) {
|
listen(s, 1) < 0) {
|
||||||
error_report("Error: inet socket: %s", strerror(errno));
|
error_report("Error: inet socket: %s", strerror(errno));
|
||||||
closesocket(s);
|
closesocket(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
switch(pid) {
|
switch(pid) {
|
||||||
case -1:
|
case -1:
|
||||||
error_report("Error: fork failed: %s", strerror(errno));
|
error_report("Error: fork failed: %s", strerror(errno));
|
||||||
close(s);
|
close(s);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
setsid();
|
setsid();
|
||||||
|
|
||||||
/* Set the DISPLAY */
|
/* Set the DISPLAY */
|
||||||
getsockname(s, (struct sockaddr *)&addr, &addrlen);
|
getsockname(s, (struct sockaddr *)&addr, &addrlen);
|
||||||
close(s);
|
close(s);
|
||||||
/*
|
/*
|
||||||
|
@ -170,41 +170,41 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
ret = connect(s, (struct sockaddr *)&addr, addrlen);
|
ret = connect(s, (struct sockaddr *)&addr, addrlen);
|
||||||
} while (ret < 0 && errno == EINTR);
|
} while (ret < 0 && errno == EINTR);
|
||||||
|
|
||||||
dup2(s, 0);
|
dup2(s, 0);
|
||||||
dup2(s, 1);
|
dup2(s, 1);
|
||||||
dup2(s, 2);
|
dup2(s, 2);
|
||||||
for (s = getdtablesize() - 1; s >= 3; s--)
|
for (s = getdtablesize() - 1; s >= 3; s--)
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
bptr = g_strdup(ex); /* No need to free() this */
|
bptr = g_strdup(ex); /* No need to free() this */
|
||||||
if (do_pty == 1) {
|
if (do_pty == 1) {
|
||||||
/* Setup "slirp.telnetd -x" */
|
/* Setup "slirp.telnetd -x" */
|
||||||
argv[i++] = "slirp.telnetd";
|
argv[i++] = "slirp.telnetd";
|
||||||
argv[i++] = "-x";
|
argv[i++] = "-x";
|
||||||
argv[i++] = bptr;
|
argv[i++] = bptr;
|
||||||
} else
|
} else
|
||||||
do {
|
do {
|
||||||
/* Change the string into argv[] */
|
/* Change the string into argv[] */
|
||||||
curarg = bptr;
|
curarg = bptr;
|
||||||
while (*bptr != ' ' && *bptr != (char)0)
|
while (*bptr != ' ' && *bptr != (char)0)
|
||||||
bptr++;
|
bptr++;
|
||||||
c = *bptr;
|
c = *bptr;
|
||||||
*bptr++ = (char)0;
|
*bptr++ = (char)0;
|
||||||
argv[i++] = g_strdup(curarg);
|
argv[i++] = g_strdup(curarg);
|
||||||
} while (c);
|
} while (c);
|
||||||
|
|
||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
execvp(argv[0], (char * const *)argv);
|
execvp(argv[0], (char * const *)argv);
|
||||||
|
|
||||||
/* Ooops, failed, let's tell the user why */
|
/* Ooops, failed, let's tell the user why */
|
||||||
fprintf(stderr, "Error: execvp of %s failed: %s\n",
|
fprintf(stderr, "Error: execvp of %s failed: %s\n",
|
||||||
argv[0], strerror(errno));
|
argv[0], strerror(errno));
|
||||||
close(0); close(1); close(2); /* XXX */
|
close(0); close(1); close(2); /* XXX */
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
qemu_add_child_watch(pid);
|
qemu_add_child_watch(pid);
|
||||||
/*
|
/*
|
||||||
* XXX this could block us...
|
* XXX this could block us...
|
||||||
* XXX Should set a timer here, and if accept() doesn't
|
* XXX Should set a timer here, and if accept() doesn't
|
||||||
|
@ -219,16 +219,16 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
socket_set_fast_reuse(so->s);
|
socket_set_fast_reuse(so->s);
|
||||||
opt = 1;
|
opt = 1;
|
||||||
qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
|
qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
|
||||||
qemu_set_nonblock(so->s);
|
qemu_set_nonblock(so->s);
|
||||||
|
|
||||||
/* Append the telnet options now */
|
/* Append the telnet options now */
|
||||||
if (so->so_m != NULL && do_pty == 1) {
|
if (so->so_m != NULL && do_pty == 1) {
|
||||||
sbappend(so, so->so_m);
|
sbappend(so, so->so_m);
|
||||||
so->so_m = NULL;
|
so->so_m = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
12
slirp/misc.h
12
slirp/misc.h
|
@ -11,11 +11,11 @@
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
struct ex_list {
|
struct ex_list {
|
||||||
int ex_pty; /* Do we want a pty? */
|
int ex_pty; /* Do we want a pty? */
|
||||||
struct in_addr ex_addr; /* Server address */
|
struct in_addr ex_addr; /* Server address */
|
||||||
int ex_fport; /* Port to telnet to */
|
int ex_fport; /* Port to telnet to */
|
||||||
const char *ex_exec; /* Command line of what to exec */
|
const char *ex_exec; /* Command line of what to exec */
|
||||||
struct ex_list *ex_next;
|
struct ex_list *ex_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EMU_NONE 0x0
|
#define EMU_NONE 0x0
|
||||||
|
@ -30,7 +30,7 @@ struct ex_list {
|
||||||
#define EMU_IDENT 0x7
|
#define EMU_IDENT 0x7
|
||||||
#define EMU_RSH 0x8
|
#define EMU_RSH 0x8
|
||||||
|
|
||||||
#define EMU_NOCONNECT 0x10 /* Don't connect */
|
#define EMU_NOCONNECT 0x10 /* Don't connect */
|
||||||
|
|
||||||
struct tos_t {
|
struct tos_t {
|
||||||
uint16_t lport;
|
uint16_t lport;
|
||||||
|
|
230
slirp/sbuf.c
230
slirp/sbuf.c
|
@ -13,7 +13,7 @@ static void sbappendsb(struct sbuf *sb, struct mbuf *m);
|
||||||
void
|
void
|
||||||
sbfree(struct sbuf *sb)
|
sbfree(struct sbuf *sb)
|
||||||
{
|
{
|
||||||
free(sb->sb_data);
|
free(sb->sb_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -21,16 +21,16 @@ sbdrop(struct sbuf *sb, int num)
|
||||||
{
|
{
|
||||||
u_int limit = sb->sb_datalen / 2;
|
u_int limit = sb->sb_datalen / 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can only drop how much we have
|
* We can only drop how much we have
|
||||||
* This should never succeed
|
* This should never succeed
|
||||||
*/
|
*/
|
||||||
if((u_int)num > sb->sb_cc)
|
if((u_int)num > sb->sb_cc)
|
||||||
num = sb->sb_cc;
|
num = sb->sb_cc;
|
||||||
sb->sb_cc -= num;
|
sb->sb_cc -= num;
|
||||||
sb->sb_rptr += num;
|
sb->sb_rptr += num;
|
||||||
if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
|
if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
|
||||||
sb->sb_rptr -= sb->sb_datalen;
|
sb->sb_rptr -= sb->sb_datalen;
|
||||||
|
|
||||||
if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {
|
if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {
|
||||||
qemu_notify_event();
|
qemu_notify_event();
|
||||||
|
@ -40,24 +40,24 @@ sbdrop(struct sbuf *sb, int num)
|
||||||
void
|
void
|
||||||
sbreserve(struct sbuf *sb, int size)
|
sbreserve(struct sbuf *sb, int size)
|
||||||
{
|
{
|
||||||
if (sb->sb_data) {
|
if (sb->sb_data) {
|
||||||
/* Already alloced, realloc if necessary */
|
/* Already alloced, realloc if necessary */
|
||||||
if (sb->sb_datalen != size) {
|
if (sb->sb_datalen != size) {
|
||||||
sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
|
sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
|
||||||
sb->sb_cc = 0;
|
sb->sb_cc = 0;
|
||||||
if (sb->sb_wptr)
|
if (sb->sb_wptr)
|
||||||
sb->sb_datalen = size;
|
sb->sb_datalen = size;
|
||||||
else
|
else
|
||||||
sb->sb_datalen = 0;
|
sb->sb_datalen = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
|
sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
|
||||||
sb->sb_cc = 0;
|
sb->sb_cc = 0;
|
||||||
if (sb->sb_wptr)
|
if (sb->sb_wptr)
|
||||||
sb->sb_datalen = size;
|
sb->sb_datalen = size;
|
||||||
else
|
else
|
||||||
sb->sb_datalen = 0;
|
sb->sb_datalen = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -69,57 +69,57 @@ sbreserve(struct sbuf *sb, int size)
|
||||||
void
|
void
|
||||||
sbappend(struct socket *so, struct mbuf *m)
|
sbappend(struct socket *so, struct mbuf *m)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
DEBUG_CALL("sbappend");
|
DEBUG_CALL("sbappend");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
DEBUG_ARG("m->m_len = %d", m->m_len);
|
DEBUG_ARG("m->m_len = %d", m->m_len);
|
||||||
|
|
||||||
/* Shouldn't happen, but... e.g. foreign host closes connection */
|
/* Shouldn't happen, but... e.g. foreign host closes connection */
|
||||||
if (m->m_len <= 0) {
|
if (m->m_len <= 0) {
|
||||||
m_free(m);
|
m_free(m);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is urgent data, call sosendoob
|
* If there is urgent data, call sosendoob
|
||||||
* if not all was sent, sowrite will take care of the rest
|
* if not all was sent, sowrite will take care of the rest
|
||||||
* (The rest of this function is just an optimisation)
|
* (The rest of this function is just an optimisation)
|
||||||
*/
|
*/
|
||||||
if (so->so_urgc) {
|
if (so->so_urgc) {
|
||||||
sbappendsb(&so->so_rcv, m);
|
sbappendsb(&so->so_rcv, m);
|
||||||
m_free(m);
|
m_free(m);
|
||||||
sosendoob(so);
|
sosendoob(so);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We only write if there's nothing in the buffer,
|
* We only write if there's nothing in the buffer,
|
||||||
* ottherwise it'll arrive out of order, and hence corrupt
|
* ottherwise it'll arrive out of order, and hence corrupt
|
||||||
*/
|
*/
|
||||||
if (!so->so_rcv.sb_cc)
|
if (!so->so_rcv.sb_cc)
|
||||||
ret = slirp_send(so, m->m_data, m->m_len, 0);
|
ret = slirp_send(so, m->m_data, m->m_len, 0);
|
||||||
|
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
/*
|
/*
|
||||||
* Nothing was written
|
* Nothing was written
|
||||||
* It's possible that the socket has closed, but
|
* It's possible that the socket has closed, but
|
||||||
* we don't need to check because if it has closed,
|
* we don't need to check because if it has closed,
|
||||||
* it will be detected in the normal way by soread()
|
* it will be detected in the normal way by soread()
|
||||||
*/
|
*/
|
||||||
sbappendsb(&so->so_rcv, m);
|
sbappendsb(&so->so_rcv, m);
|
||||||
} else if (ret != m->m_len) {
|
} else if (ret != m->m_len) {
|
||||||
/*
|
/*
|
||||||
* Something was written, but not everything..
|
* Something was written, but not everything..
|
||||||
* sbappendsb the rest
|
* sbappendsb the rest
|
||||||
*/
|
*/
|
||||||
m->m_len -= ret;
|
m->m_len -= ret;
|
||||||
m->m_data += ret;
|
m->m_data += ret;
|
||||||
sbappendsb(&so->so_rcv, m);
|
sbappendsb(&so->so_rcv, m);
|
||||||
} /* else */
|
} /* else */
|
||||||
/* Whatever happened, we free the mbuf */
|
/* Whatever happened, we free the mbuf */
|
||||||
m_free(m);
|
m_free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -129,33 +129,33 @@ sbappend(struct socket *so, struct mbuf *m)
|
||||||
static void
|
static void
|
||||||
sbappendsb(struct sbuf *sb, struct mbuf *m)
|
sbappendsb(struct sbuf *sb, struct mbuf *m)
|
||||||
{
|
{
|
||||||
int len, n, nn;
|
int len, n, nn;
|
||||||
|
|
||||||
len = m->m_len;
|
len = m->m_len;
|
||||||
|
|
||||||
if (sb->sb_wptr < sb->sb_rptr) {
|
if (sb->sb_wptr < sb->sb_rptr) {
|
||||||
n = sb->sb_rptr - sb->sb_wptr;
|
n = sb->sb_rptr - sb->sb_wptr;
|
||||||
if (n > len) n = len;
|
if (n > len) n = len;
|
||||||
memcpy(sb->sb_wptr, m->m_data, n);
|
memcpy(sb->sb_wptr, m->m_data, n);
|
||||||
} else {
|
} else {
|
||||||
/* Do the right edge first */
|
/* Do the right edge first */
|
||||||
n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
|
n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
|
||||||
if (n > len) n = len;
|
if (n > len) n = len;
|
||||||
memcpy(sb->sb_wptr, m->m_data, n);
|
memcpy(sb->sb_wptr, m->m_data, n);
|
||||||
len -= n;
|
len -= n;
|
||||||
if (len) {
|
if (len) {
|
||||||
/* Now the left edge */
|
/* Now the left edge */
|
||||||
nn = sb->sb_rptr - sb->sb_data;
|
nn = sb->sb_rptr - sb->sb_data;
|
||||||
if (nn > len) nn = len;
|
if (nn > len) nn = len;
|
||||||
memcpy(sb->sb_data,m->m_data+n,nn);
|
memcpy(sb->sb_data,m->m_data+n,nn);
|
||||||
n += nn;
|
n += nn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sb->sb_cc += n;
|
sb->sb_cc += n;
|
||||||
sb->sb_wptr += n;
|
sb->sb_wptr += n;
|
||||||
if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
|
if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
|
||||||
sb->sb_wptr -= sb->sb_datalen;
|
sb->sb_wptr -= sb->sb_datalen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -166,22 +166,22 @@ sbappendsb(struct sbuf *sb, struct mbuf *m)
|
||||||
void
|
void
|
||||||
sbcopy(struct sbuf *sb, int off, int len, char *to)
|
sbcopy(struct sbuf *sb, int off, int len, char *to)
|
||||||
{
|
{
|
||||||
char *from;
|
char *from;
|
||||||
|
|
||||||
from = sb->sb_rptr + off;
|
from = sb->sb_rptr + off;
|
||||||
if (from >= sb->sb_data + sb->sb_datalen)
|
if (from >= sb->sb_data + sb->sb_datalen)
|
||||||
from -= sb->sb_datalen;
|
from -= sb->sb_datalen;
|
||||||
|
|
||||||
if (from < sb->sb_wptr) {
|
if (from < sb->sb_wptr) {
|
||||||
if ((u_int)len > sb->sb_cc) len = sb->sb_cc;
|
if ((u_int)len > sb->sb_cc) len = sb->sb_cc;
|
||||||
memcpy(to,from,len);
|
memcpy(to,from,len);
|
||||||
} else {
|
} else {
|
||||||
/* re-use off */
|
/* re-use off */
|
||||||
off = (sb->sb_data + sb->sb_datalen) - from;
|
off = (sb->sb_data + sb->sb_datalen) - from;
|
||||||
if (off > len) off = len;
|
if (off > len) off = len;
|
||||||
memcpy(to,from,off);
|
memcpy(to,from,off);
|
||||||
len -= off;
|
len -= off;
|
||||||
if (len)
|
if (len)
|
||||||
memcpy(to+off,sb->sb_data,len);
|
memcpy(to+off,sb->sb_data,len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
slirp/sbuf.h
14
slirp/sbuf.h
|
@ -12,13 +12,13 @@
|
||||||
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
|
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
|
||||||
|
|
||||||
struct sbuf {
|
struct sbuf {
|
||||||
u_int sb_cc; /* actual chars in buffer */
|
u_int sb_cc; /* actual chars in buffer */
|
||||||
u_int sb_datalen; /* Length of data */
|
u_int sb_datalen; /* Length of data */
|
||||||
char *sb_wptr; /* write pointer. points to where the next
|
char *sb_wptr; /* write pointer. points to where the next
|
||||||
* bytes should be written in the sbuf */
|
* bytes should be written in the sbuf */
|
||||||
char *sb_rptr; /* read pointer. points to where the next
|
char *sb_rptr; /* read pointer. points to where the next
|
||||||
* byte should be read from the sbuf */
|
* byte should be read from the sbuf */
|
||||||
char *sb_data; /* Actual data */
|
char *sb_data; /* Actual data */
|
||||||
};
|
};
|
||||||
|
|
||||||
void sbfree(struct sbuf *);
|
void sbfree(struct sbuf *);
|
||||||
|
|
840
slirp/socket.c
840
slirp/socket.c
File diff suppressed because it is too large
Load diff
|
@ -22,37 +22,37 @@ struct socket {
|
||||||
|
|
||||||
int pollfds_idx; /* GPollFD GArray index */
|
int pollfds_idx; /* GPollFD GArray index */
|
||||||
|
|
||||||
Slirp *slirp; /* managing slirp instance */
|
Slirp *slirp; /* managing slirp instance */
|
||||||
|
|
||||||
/* XXX union these with not-yet-used sbuf params */
|
/* XXX union these with not-yet-used sbuf params */
|
||||||
struct mbuf *so_m; /* Pointer to the original SYN packet,
|
struct mbuf *so_m; /* Pointer to the original SYN packet,
|
||||||
* for non-blocking connect()'s, and
|
* for non-blocking connect()'s, and
|
||||||
* PING reply's */
|
* PING reply's */
|
||||||
struct tcpiphdr *so_ti; /* Pointer to the original ti within
|
struct tcpiphdr *so_ti; /* Pointer to the original ti within
|
||||||
* so_mconn, for non-blocking connections */
|
* so_mconn, for non-blocking connections */
|
||||||
int so_urgc;
|
int so_urgc;
|
||||||
struct in_addr so_faddr; /* foreign host table entry */
|
struct in_addr so_faddr; /* foreign host table entry */
|
||||||
struct in_addr so_laddr; /* local host table entry */
|
struct in_addr so_laddr; /* local host table entry */
|
||||||
uint16_t so_fport; /* foreign port */
|
uint16_t so_fport; /* foreign port */
|
||||||
uint16_t so_lport; /* local port */
|
uint16_t so_lport; /* local port */
|
||||||
|
|
||||||
uint8_t so_iptos; /* Type of service */
|
uint8_t so_iptos; /* Type of service */
|
||||||
uint8_t so_emu; /* Is the socket emulated? */
|
uint8_t so_emu; /* Is the socket emulated? */
|
||||||
|
|
||||||
u_char so_type; /* Type of socket, UDP or TCP */
|
u_char so_type; /* Type of socket, UDP or TCP */
|
||||||
int so_state; /* internal state flags SS_*, below */
|
int so_state; /* internal state flags SS_*, below */
|
||||||
|
|
||||||
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
|
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
|
||||||
u_int so_expire; /* When the socket will expire */
|
u_int so_expire; /* When the socket will expire */
|
||||||
|
|
||||||
int so_queued; /* Number of packets queued from this socket */
|
int so_queued; /* Number of packets queued from this socket */
|
||||||
int so_nqueued; /* Number of packets queued in a row
|
int so_nqueued; /* Number of packets queued in a row
|
||||||
* Used to determine when to "downgrade" a session
|
* Used to determine when to "downgrade" a session
|
||||||
* from fastq to batchq */
|
* from fastq to batchq */
|
||||||
|
|
||||||
struct sbuf so_rcv; /* Receive buffer */
|
struct sbuf so_rcv; /* Receive buffer */
|
||||||
struct sbuf so_snd; /* Send buffer */
|
struct sbuf so_snd; /* Send buffer */
|
||||||
void * extra; /* Extra pointer */
|
void * extra; /* Extra pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,21 +60,21 @@ struct socket {
|
||||||
* Socket state bits. (peer means the host on the Internet,
|
* Socket state bits. (peer means the host on the Internet,
|
||||||
* local host means the host on the other end of the modem)
|
* local host means the host on the other end of the modem)
|
||||||
*/
|
*/
|
||||||
#define SS_NOFDREF 0x001 /* No fd reference */
|
#define SS_NOFDREF 0x001 /* No fd reference */
|
||||||
|
|
||||||
#define SS_ISFCONNECTING 0x002 /* Socket is connecting to peer (non-blocking connect()'s) */
|
#define SS_ISFCONNECTING 0x002 /* Socket is connecting to peer (non-blocking connect()'s) */
|
||||||
#define SS_ISFCONNECTED 0x004 /* Socket is connected to peer */
|
#define SS_ISFCONNECTED 0x004 /* Socket is connected to peer */
|
||||||
#define SS_FCANTRCVMORE 0x008 /* Socket can't receive more from peer (for half-closes) */
|
#define SS_FCANTRCVMORE 0x008 /* Socket can't receive more from peer (for half-closes) */
|
||||||
#define SS_FCANTSENDMORE 0x010 /* Socket can't send more to peer (for half-closes) */
|
#define SS_FCANTSENDMORE 0x010 /* Socket can't send more to peer (for half-closes) */
|
||||||
#define SS_FWDRAIN 0x040 /* We received a FIN, drain data and set SS_FCANTSENDMORE */
|
#define SS_FWDRAIN 0x040 /* We received a FIN, drain data and set SS_FCANTSENDMORE */
|
||||||
|
|
||||||
#define SS_CTL 0x080
|
#define SS_CTL 0x080
|
||||||
#define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */
|
#define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */
|
||||||
#define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */
|
#define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */
|
||||||
|
|
||||||
#define SS_PERSISTENT_MASK 0xf000 /* Unremovable state bits */
|
#define SS_PERSISTENT_MASK 0xf000 /* Unremovable state bits */
|
||||||
#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */
|
#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */
|
||||||
#define SS_INCOMING 0x2000 /* Connection was initiated by a host on the internet */
|
#define SS_INCOMING 0x2000 /* Connection was initiated by a host on the internet */
|
||||||
|
|
||||||
struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);
|
struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);
|
||||||
struct socket * socreate(Slirp *);
|
struct socket * socreate(Slirp *);
|
||||||
|
|
76
slirp/tcp.h
76
slirp/tcp.h
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993
|
* Copyright (c) 1982, 1986, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,14 +26,14 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)tcp.h 8.1 (Berkeley) 6/10/93
|
* @(#)tcp.h 8.1 (Berkeley) 6/10/93
|
||||||
* tcp.h,v 1.3 1994/08/21 05:27:34 paul Exp
|
* tcp.h,v 1.3 1994/08/21 05:27:34 paul Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TCP_H_
|
#ifndef _TCP_H_
|
||||||
#define _TCP_H_
|
#define _TCP_H_
|
||||||
|
|
||||||
typedef uint32_t tcp_seq;
|
typedef uint32_t tcp_seq;
|
||||||
|
|
||||||
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
|
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
|
||||||
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
|
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
|
||||||
|
@ -47,53 +47,53 @@ typedef uint32_t tcp_seq;
|
||||||
*/
|
*/
|
||||||
#define tcphdr slirp_tcphdr
|
#define tcphdr slirp_tcphdr
|
||||||
struct tcphdr {
|
struct tcphdr {
|
||||||
uint16_t th_sport; /* source port */
|
uint16_t th_sport; /* source port */
|
||||||
uint16_t th_dport; /* destination port */
|
uint16_t th_dport; /* destination port */
|
||||||
tcp_seq th_seq; /* sequence number */
|
tcp_seq th_seq; /* sequence number */
|
||||||
tcp_seq th_ack; /* acknowledgement number */
|
tcp_seq th_ack; /* acknowledgement number */
|
||||||
#ifdef HOST_WORDS_BIGENDIAN
|
#ifdef HOST_WORDS_BIGENDIAN
|
||||||
uint8_t th_off:4, /* data offset */
|
uint8_t th_off:4, /* data offset */
|
||||||
th_x2:4; /* (unused) */
|
th_x2:4; /* (unused) */
|
||||||
#else
|
#else
|
||||||
uint8_t th_x2:4, /* (unused) */
|
uint8_t th_x2:4, /* (unused) */
|
||||||
th_off:4; /* data offset */
|
th_off:4; /* data offset */
|
||||||
#endif
|
#endif
|
||||||
uint8_t th_flags;
|
uint8_t th_flags;
|
||||||
uint16_t th_win; /* window */
|
uint16_t th_win; /* window */
|
||||||
uint16_t th_sum; /* checksum */
|
uint16_t th_sum; /* checksum */
|
||||||
uint16_t th_urp; /* urgent pointer */
|
uint16_t th_urp; /* urgent pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "tcp_var.h"
|
#include "tcp_var.h"
|
||||||
|
|
||||||
#ifndef TH_FIN
|
#ifndef TH_FIN
|
||||||
#define TH_FIN 0x01
|
#define TH_FIN 0x01
|
||||||
#define TH_SYN 0x02
|
#define TH_SYN 0x02
|
||||||
#define TH_RST 0x04
|
#define TH_RST 0x04
|
||||||
#define TH_PUSH 0x08
|
#define TH_PUSH 0x08
|
||||||
#define TH_ACK 0x10
|
#define TH_ACK 0x10
|
||||||
#define TH_URG 0x20
|
#define TH_URG 0x20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TCPOPT_EOL
|
#ifndef TCPOPT_EOL
|
||||||
#define TCPOPT_EOL 0
|
#define TCPOPT_EOL 0
|
||||||
#define TCPOPT_NOP 1
|
#define TCPOPT_NOP 1
|
||||||
#define TCPOPT_MAXSEG 2
|
#define TCPOPT_MAXSEG 2
|
||||||
#define TCPOPT_WINDOW 3
|
#define TCPOPT_WINDOW 3
|
||||||
#define TCPOPT_SACK_PERMITTED 4 /* Experimental */
|
#define TCPOPT_SACK_PERMITTED 4 /* Experimental */
|
||||||
#define TCPOPT_SACK 5 /* Experimental */
|
#define TCPOPT_SACK 5 /* Experimental */
|
||||||
#define TCPOPT_TIMESTAMP 8
|
#define TCPOPT_TIMESTAMP 8
|
||||||
|
|
||||||
#define TCPOPT_TSTAMP_HDR \
|
#define TCPOPT_TSTAMP_HDR \
|
||||||
(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
|
(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TCPOLEN_MAXSEG
|
#ifndef TCPOLEN_MAXSEG
|
||||||
#define TCPOLEN_MAXSEG 4
|
#define TCPOLEN_MAXSEG 4
|
||||||
#define TCPOLEN_WINDOW 3
|
#define TCPOLEN_WINDOW 3
|
||||||
#define TCPOLEN_SACK_PERMITTED 2
|
#define TCPOLEN_SACK_PERMITTED 2
|
||||||
#define TCPOLEN_TIMESTAMP 10
|
#define TCPOLEN_TIMESTAMP 10
|
||||||
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
|
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -105,13 +105,13 @@ struct tcphdr {
|
||||||
* We make this 1460 because we only care about Ethernet in the qemu context.
|
* We make this 1460 because we only care about Ethernet in the qemu context.
|
||||||
*/
|
*/
|
||||||
#undef TCP_MSS
|
#undef TCP_MSS
|
||||||
#define TCP_MSS 1460
|
#define TCP_MSS 1460
|
||||||
|
|
||||||
#undef TCP_MAXWIN
|
#undef TCP_MAXWIN
|
||||||
#define TCP_MAXWIN 65535u /* largest value for (unscaled) window */
|
#define TCP_MAXWIN 65535u /* largest value for (unscaled) window */
|
||||||
|
|
||||||
#undef TCP_MAX_WINSHIFT
|
#undef TCP_MAX_WINSHIFT
|
||||||
#define TCP_MAX_WINSHIFT 14 /* maximum window shift */
|
#define TCP_MAX_WINSHIFT 14 /* maximum window shift */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* User-settable options (used with setsockopt).
|
* User-settable options (used with setsockopt).
|
||||||
|
@ -121,7 +121,7 @@ struct tcphdr {
|
||||||
* so we undefine them.
|
* so we undefine them.
|
||||||
*/
|
*/
|
||||||
#undef TCP_NODELAY
|
#undef TCP_NODELAY
|
||||||
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
|
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
|
||||||
#undef TCP_MAXSEG
|
#undef TCP_MAXSEG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
2370
slirp/tcp_input.c
2370
slirp/tcp_input.c
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1988, 1990, 1993
|
* Copyright (c) 1982, 1986, 1988, 1990, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)tcp_output.c 8.3 (Berkeley) 12/30/93
|
* @(#)tcp_output.c 8.3 (Berkeley) 12/30/93
|
||||||
* tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg Exp
|
* tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -41,14 +41,14 @@
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
|
|
||||||
static const u_char tcp_outflags[TCP_NSTATES] = {
|
static const u_char tcp_outflags[TCP_NSTATES] = {
|
||||||
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
|
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
|
||||||
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
|
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
|
||||||
TH_FIN|TH_ACK, TH_ACK, TH_ACK,
|
TH_FIN|TH_ACK, TH_ACK, TH_ACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#undef MAX_TCPOPTLEN
|
#undef MAX_TCPOPTLEN
|
||||||
#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */
|
#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tcp output routine: figure out what should be sent and send it.
|
* Tcp output routine: figure out what should be sent and send it.
|
||||||
|
@ -56,425 +56,425 @@ static const u_char tcp_outflags[TCP_NSTATES] = {
|
||||||
int
|
int
|
||||||
tcp_output(struct tcpcb *tp)
|
tcp_output(struct tcpcb *tp)
|
||||||
{
|
{
|
||||||
register struct socket *so = tp->t_socket;
|
register struct socket *so = tp->t_socket;
|
||||||
register long len, win;
|
register long len, win;
|
||||||
int off, flags, error;
|
int off, flags, error;
|
||||||
register struct mbuf *m;
|
register struct mbuf *m;
|
||||||
register struct tcpiphdr *ti;
|
register struct tcpiphdr *ti;
|
||||||
u_char opt[MAX_TCPOPTLEN];
|
u_char opt[MAX_TCPOPTLEN];
|
||||||
unsigned optlen, hdrlen;
|
unsigned optlen, hdrlen;
|
||||||
int idle, sendalot;
|
int idle, sendalot;
|
||||||
|
|
||||||
DEBUG_CALL("tcp_output");
|
DEBUG_CALL("tcp_output");
|
||||||
DEBUG_ARG("tp = %lx", (long )tp);
|
DEBUG_ARG("tp = %lx", (long )tp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine length of data that should be transmitted,
|
* Determine length of data that should be transmitted,
|
||||||
* and flags that will be used.
|
* and flags that will be used.
|
||||||
* If there is some data or critical controls (SYN, RST)
|
* If there is some data or critical controls (SYN, RST)
|
||||||
* to send, then transmit; otherwise, investigate further.
|
* to send, then transmit; otherwise, investigate further.
|
||||||
*/
|
*/
|
||||||
idle = (tp->snd_max == tp->snd_una);
|
idle = (tp->snd_max == tp->snd_una);
|
||||||
if (idle && tp->t_idle >= tp->t_rxtcur)
|
if (idle && tp->t_idle >= tp->t_rxtcur)
|
||||||
/*
|
/*
|
||||||
* We have been idle for "a while" and no acks are
|
* We have been idle for "a while" and no acks are
|
||||||
* expected to clock out any data we send --
|
* expected to clock out any data we send --
|
||||||
* slow start to get ack "clock" running again.
|
* slow start to get ack "clock" running again.
|
||||||
*/
|
*/
|
||||||
tp->snd_cwnd = tp->t_maxseg;
|
tp->snd_cwnd = tp->t_maxseg;
|
||||||
again:
|
again:
|
||||||
sendalot = 0;
|
sendalot = 0;
|
||||||
off = tp->snd_nxt - tp->snd_una;
|
off = tp->snd_nxt - tp->snd_una;
|
||||||
win = min(tp->snd_wnd, tp->snd_cwnd);
|
win = min(tp->snd_wnd, tp->snd_cwnd);
|
||||||
|
|
||||||
flags = tcp_outflags[tp->t_state];
|
flags = tcp_outflags[tp->t_state];
|
||||||
|
|
||||||
DEBUG_MISC(" --- tcp_output flags = 0x%x\n",flags);
|
DEBUG_MISC(" --- tcp_output flags = 0x%x\n",flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If in persist timeout with window of 0, send 1 byte.
|
* If in persist timeout with window of 0, send 1 byte.
|
||||||
* Otherwise, if window is small but nonzero
|
* Otherwise, if window is small but nonzero
|
||||||
* and timer expired, we will send what we can
|
* and timer expired, we will send what we can
|
||||||
* and go to transmit state.
|
* and go to transmit state.
|
||||||
*/
|
*/
|
||||||
if (tp->t_force) {
|
if (tp->t_force) {
|
||||||
if (win == 0) {
|
if (win == 0) {
|
||||||
/*
|
/*
|
||||||
* If we still have some data to send, then
|
* If we still have some data to send, then
|
||||||
* clear the FIN bit. Usually this would
|
* clear the FIN bit. Usually this would
|
||||||
* happen below when it realizes that we
|
* happen below when it realizes that we
|
||||||
* aren't sending all the data. However,
|
* aren't sending all the data. However,
|
||||||
* if we have exactly 1 byte of unset data,
|
* if we have exactly 1 byte of unset data,
|
||||||
* then it won't clear the FIN bit below,
|
* then it won't clear the FIN bit below,
|
||||||
* and if we are in persist state, we wind
|
* and if we are in persist state, we wind
|
||||||
* up sending the packet without recording
|
* up sending the packet without recording
|
||||||
* that we sent the FIN bit.
|
* that we sent the FIN bit.
|
||||||
*
|
*
|
||||||
* We can't just blindly clear the FIN bit,
|
* We can't just blindly clear the FIN bit,
|
||||||
* because if we don't have any more data
|
* because if we don't have any more data
|
||||||
* to send then the probe will be the FIN
|
* to send then the probe will be the FIN
|
||||||
* itself.
|
* itself.
|
||||||
*/
|
*/
|
||||||
if (off < (int)so->so_snd.sb_cc)
|
if (off < (int)so->so_snd.sb_cc)
|
||||||
flags &= ~TH_FIN;
|
flags &= ~TH_FIN;
|
||||||
win = 1;
|
win = 1;
|
||||||
} else {
|
} else {
|
||||||
tp->t_timer[TCPT_PERSIST] = 0;
|
tp->t_timer[TCPT_PERSIST] = 0;
|
||||||
tp->t_rxtshift = 0;
|
tp->t_rxtshift = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
len = min((long)so->so_snd.sb_cc, win) - off;
|
len = min((long)so->so_snd.sb_cc, win) - off;
|
||||||
|
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
/*
|
/*
|
||||||
* If FIN has been sent but not acked,
|
* If FIN has been sent but not acked,
|
||||||
* but we haven't been called to retransmit,
|
* but we haven't been called to retransmit,
|
||||||
* len will be -1. Otherwise, window shrank
|
* len will be -1. Otherwise, window shrank
|
||||||
* after we sent into it. If window shrank to 0,
|
* after we sent into it. If window shrank to 0,
|
||||||
* cancel pending retransmit and pull snd_nxt
|
* cancel pending retransmit and pull snd_nxt
|
||||||
* back to (closed) window. We will enter persist
|
* back to (closed) window. We will enter persist
|
||||||
* state below. If the window didn't close completely,
|
* state below. If the window didn't close completely,
|
||||||
* just wait for an ACK.
|
* just wait for an ACK.
|
||||||
*/
|
*/
|
||||||
len = 0;
|
len = 0;
|
||||||
if (win == 0) {
|
if (win == 0) {
|
||||||
tp->t_timer[TCPT_REXMT] = 0;
|
tp->t_timer[TCPT_REXMT] = 0;
|
||||||
tp->snd_nxt = tp->snd_una;
|
tp->snd_nxt = tp->snd_una;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > tp->t_maxseg) {
|
if (len > tp->t_maxseg) {
|
||||||
len = tp->t_maxseg;
|
len = tp->t_maxseg;
|
||||||
sendalot = 1;
|
sendalot = 1;
|
||||||
}
|
}
|
||||||
if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
|
if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
|
||||||
flags &= ~TH_FIN;
|
flags &= ~TH_FIN;
|
||||||
|
|
||||||
win = sbspace(&so->so_rcv);
|
win = sbspace(&so->so_rcv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sender silly window avoidance. If connection is idle
|
* Sender silly window avoidance. If connection is idle
|
||||||
* and can send all data, a maximum segment,
|
* and can send all data, a maximum segment,
|
||||||
* at least a maximum default-size segment do it,
|
* at least a maximum default-size segment do it,
|
||||||
* or are forced, do it; otherwise don't bother.
|
* or are forced, do it; otherwise don't bother.
|
||||||
* If peer's buffer is tiny, then send
|
* If peer's buffer is tiny, then send
|
||||||
* when window is at least half open.
|
* when window is at least half open.
|
||||||
* If retransmitting (possibly after persist timer forced us
|
* If retransmitting (possibly after persist timer forced us
|
||||||
* to send into a small window), then must resend.
|
* to send into a small window), then must resend.
|
||||||
*/
|
*/
|
||||||
if (len) {
|
if (len) {
|
||||||
if (len == tp->t_maxseg)
|
if (len == tp->t_maxseg)
|
||||||
goto send;
|
goto send;
|
||||||
if ((1 || idle || (tp->t_flags & TF_NODELAY)) &&
|
if ((1 || idle || (tp->t_flags & TF_NODELAY)) &&
|
||||||
((len + off) >= (long)so->so_snd.sb_cc))
|
((len + off) >= (long)so->so_snd.sb_cc))
|
||||||
goto send;
|
goto send;
|
||||||
if (tp->t_force)
|
if (tp->t_force)
|
||||||
goto send;
|
goto send;
|
||||||
if ((len >= (long)(tp->max_sndwnd / 2)) && (tp->max_sndwnd > 0))
|
if ((len >= (long)(tp->max_sndwnd / 2)) && (tp->max_sndwnd > 0))
|
||||||
goto send;
|
goto send;
|
||||||
if (SEQ_LT(tp->snd_nxt, tp->snd_max))
|
if (SEQ_LT(tp->snd_nxt, tp->snd_max))
|
||||||
goto send;
|
goto send;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare available window to amount of window
|
* Compare available window to amount of window
|
||||||
* known to peer (as advertised window less
|
* known to peer (as advertised window less
|
||||||
* next expected input). If the difference is at least two
|
* next expected input). If the difference is at least two
|
||||||
* max size segments, or at least 50% of the maximum possible
|
* max size segments, or at least 50% of the maximum possible
|
||||||
* window, then want to send a window update to peer.
|
* window, then want to send a window update to peer.
|
||||||
*/
|
*/
|
||||||
if (win > 0) {
|
if (win > 0) {
|
||||||
/*
|
/*
|
||||||
* "adv" is the amount we can increase the window,
|
* "adv" is the amount we can increase the window,
|
||||||
* taking into account that we are limited by
|
* taking into account that we are limited by
|
||||||
* TCP_MAXWIN << tp->rcv_scale.
|
* TCP_MAXWIN << tp->rcv_scale.
|
||||||
*/
|
*/
|
||||||
long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
|
long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
|
||||||
(tp->rcv_adv - tp->rcv_nxt);
|
(tp->rcv_adv - tp->rcv_nxt);
|
||||||
|
|
||||||
if (adv >= (long) (2 * tp->t_maxseg))
|
if (adv >= (long) (2 * tp->t_maxseg))
|
||||||
goto send;
|
goto send;
|
||||||
if (2 * adv >= (long) so->so_rcv.sb_datalen)
|
if (2 * adv >= (long) so->so_rcv.sb_datalen)
|
||||||
goto send;
|
goto send;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send if we owe peer an ACK.
|
* Send if we owe peer an ACK.
|
||||||
*/
|
*/
|
||||||
if (tp->t_flags & TF_ACKNOW)
|
if (tp->t_flags & TF_ACKNOW)
|
||||||
goto send;
|
goto send;
|
||||||
if (flags & (TH_SYN|TH_RST))
|
if (flags & (TH_SYN|TH_RST))
|
||||||
goto send;
|
goto send;
|
||||||
if (SEQ_GT(tp->snd_up, tp->snd_una))
|
if (SEQ_GT(tp->snd_up, tp->snd_una))
|
||||||
goto send;
|
goto send;
|
||||||
/*
|
/*
|
||||||
* If our state indicates that FIN should be sent
|
* If our state indicates that FIN should be sent
|
||||||
* and we have not yet done so, or we're retransmitting the FIN,
|
* and we have not yet done so, or we're retransmitting the FIN,
|
||||||
* then we need to send.
|
* then we need to send.
|
||||||
*/
|
*/
|
||||||
if (flags & TH_FIN &&
|
if (flags & TH_FIN &&
|
||||||
((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
|
((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
|
||||||
goto send;
|
goto send;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCP window updates are not reliable, rather a polling protocol
|
* TCP window updates are not reliable, rather a polling protocol
|
||||||
* using ``persist'' packets is used to insure receipt of window
|
* using ``persist'' packets is used to insure receipt of window
|
||||||
* updates. The three ``states'' for the output side are:
|
* updates. The three ``states'' for the output side are:
|
||||||
* idle not doing retransmits or persists
|
* idle not doing retransmits or persists
|
||||||
* persisting to move a small or zero window
|
* persisting to move a small or zero window
|
||||||
* (re)transmitting and thereby not persisting
|
* (re)transmitting and thereby not persisting
|
||||||
*
|
*
|
||||||
* tp->t_timer[TCPT_PERSIST]
|
* tp->t_timer[TCPT_PERSIST]
|
||||||
* is set when we are in persist state.
|
* is set when we are in persist state.
|
||||||
* tp->t_force
|
* tp->t_force
|
||||||
* is set when we are called to send a persist packet.
|
* is set when we are called to send a persist packet.
|
||||||
* tp->t_timer[TCPT_REXMT]
|
* tp->t_timer[TCPT_REXMT]
|
||||||
* is set when we are retransmitting
|
* is set when we are retransmitting
|
||||||
* The output side is idle when both timers are zero.
|
* The output side is idle when both timers are zero.
|
||||||
*
|
*
|
||||||
* If send window is too small, there is data to transmit, and no
|
* If send window is too small, there is data to transmit, and no
|
||||||
* retransmit or persist is pending, then go to persist state.
|
* retransmit or persist is pending, then go to persist state.
|
||||||
* If nothing happens soon, send when timer expires:
|
* If nothing happens soon, send when timer expires:
|
||||||
* if window is nonzero, transmit what we can,
|
* if window is nonzero, transmit what we can,
|
||||||
* otherwise force out a byte.
|
* otherwise force out a byte.
|
||||||
*/
|
*/
|
||||||
if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&
|
if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&
|
||||||
tp->t_timer[TCPT_PERSIST] == 0) {
|
tp->t_timer[TCPT_PERSIST] == 0) {
|
||||||
tp->t_rxtshift = 0;
|
tp->t_rxtshift = 0;
|
||||||
tcp_setpersist(tp);
|
tcp_setpersist(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No reason to send a segment, just return.
|
* No reason to send a segment, just return.
|
||||||
*/
|
*/
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
send:
|
send:
|
||||||
/*
|
/*
|
||||||
* Before ESTABLISHED, force sending of initial options
|
* Before ESTABLISHED, force sending of initial options
|
||||||
* unless TCP set not to do any options.
|
* unless TCP set not to do any options.
|
||||||
* NOTE: we assume that the IP/TCP header plus TCP options
|
* NOTE: we assume that the IP/TCP header plus TCP options
|
||||||
* always fit in a single mbuf, leaving room for a maximum
|
* always fit in a single mbuf, leaving room for a maximum
|
||||||
* link header, i.e.
|
* link header, i.e.
|
||||||
* max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
|
* max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
|
||||||
*/
|
*/
|
||||||
optlen = 0;
|
optlen = 0;
|
||||||
hdrlen = sizeof (struct tcpiphdr);
|
hdrlen = sizeof (struct tcpiphdr);
|
||||||
if (flags & TH_SYN) {
|
if (flags & TH_SYN) {
|
||||||
tp->snd_nxt = tp->iss;
|
tp->snd_nxt = tp->iss;
|
||||||
if ((tp->t_flags & TF_NOOPT) == 0) {
|
if ((tp->t_flags & TF_NOOPT) == 0) {
|
||||||
uint16_t mss;
|
uint16_t mss;
|
||||||
|
|
||||||
opt[0] = TCPOPT_MAXSEG;
|
opt[0] = TCPOPT_MAXSEG;
|
||||||
opt[1] = 4;
|
opt[1] = 4;
|
||||||
mss = htons((uint16_t) tcp_mss(tp, 0));
|
mss = htons((uint16_t) tcp_mss(tp, 0));
|
||||||
memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
|
memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
|
||||||
optlen = 4;
|
optlen = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hdrlen += optlen;
|
hdrlen += optlen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust data length if insertion of options will
|
* Adjust data length if insertion of options will
|
||||||
* bump the packet length beyond the t_maxseg length.
|
* bump the packet length beyond the t_maxseg length.
|
||||||
*/
|
*/
|
||||||
if (len > (long)(tp->t_maxseg - optlen)) {
|
if (len > (long)(tp->t_maxseg - optlen)) {
|
||||||
len = tp->t_maxseg - optlen;
|
len = tp->t_maxseg - optlen;
|
||||||
sendalot = 1;
|
sendalot = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Grab a header mbuf, attaching a copy of data to
|
* Grab a header mbuf, attaching a copy of data to
|
||||||
* be transmitted, and initialize the header from
|
* be transmitted, and initialize the header from
|
||||||
* the template for sends on this connection.
|
* the template for sends on this connection.
|
||||||
*/
|
*/
|
||||||
if (len) {
|
if (len) {
|
||||||
m = m_get(so->slirp);
|
m = m_get(so->slirp);
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
error = 1;
|
error = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += IF_MAXLINKHDR;
|
||||||
m->m_len = hdrlen;
|
m->m_len = hdrlen;
|
||||||
|
|
||||||
sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
|
sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
|
||||||
m->m_len += len;
|
m->m_len += len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're sending everything we've got, set PUSH.
|
* If we're sending everything we've got, set PUSH.
|
||||||
* (This will keep happy those implementations which only
|
* (This will keep happy those implementations which only
|
||||||
* give data to the user when a buffer fills or
|
* give data to the user when a buffer fills or
|
||||||
* a PUSH comes in.)
|
* a PUSH comes in.)
|
||||||
*/
|
*/
|
||||||
if (off + len == so->so_snd.sb_cc)
|
if (off + len == so->so_snd.sb_cc)
|
||||||
flags |= TH_PUSH;
|
flags |= TH_PUSH;
|
||||||
} else {
|
} else {
|
||||||
m = m_get(so->slirp);
|
m = m_get(so->slirp);
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
error = 1;
|
error = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += IF_MAXLINKHDR;
|
||||||
m->m_len = hdrlen;
|
m->m_len = hdrlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
ti = mtod(m, struct tcpiphdr *);
|
ti = mtod(m, struct tcpiphdr *);
|
||||||
|
|
||||||
memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
|
memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill in fields, remembering maximum advertised
|
* Fill in fields, remembering maximum advertised
|
||||||
* window for use in delaying messages about window sizes.
|
* window for use in delaying messages about window sizes.
|
||||||
* If resending a FIN, be sure not to use a new sequence number.
|
* If resending a FIN, be sure not to use a new sequence number.
|
||||||
*/
|
*/
|
||||||
if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
|
if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
|
||||||
tp->snd_nxt == tp->snd_max)
|
tp->snd_nxt == tp->snd_max)
|
||||||
tp->snd_nxt--;
|
tp->snd_nxt--;
|
||||||
/*
|
/*
|
||||||
* If we are doing retransmissions, then snd_nxt will
|
* If we are doing retransmissions, then snd_nxt will
|
||||||
* not reflect the first unsent octet. For ACK only
|
* not reflect the first unsent octet. For ACK only
|
||||||
* packets, we do not want the sequence number of the
|
* packets, we do not want the sequence number of the
|
||||||
* retransmitted packet, we want the sequence number
|
* retransmitted packet, we want the sequence number
|
||||||
* of the next unsent octet. So, if there is no data
|
* of the next unsent octet. So, if there is no data
|
||||||
* (and no SYN or FIN), use snd_max instead of snd_nxt
|
* (and no SYN or FIN), use snd_max instead of snd_nxt
|
||||||
* when filling in ti_seq. But if we are in persist
|
* when filling in ti_seq. But if we are in persist
|
||||||
* state, snd_max might reflect one byte beyond the
|
* state, snd_max might reflect one byte beyond the
|
||||||
* right edge of the window, so use snd_nxt in that
|
* right edge of the window, so use snd_nxt in that
|
||||||
* case, since we know we aren't doing a retransmission.
|
* case, since we know we aren't doing a retransmission.
|
||||||
* (retransmit and persist are mutually exclusive...)
|
* (retransmit and persist are mutually exclusive...)
|
||||||
*/
|
*/
|
||||||
if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
|
if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
|
||||||
ti->ti_seq = htonl(tp->snd_nxt);
|
ti->ti_seq = htonl(tp->snd_nxt);
|
||||||
else
|
else
|
||||||
ti->ti_seq = htonl(tp->snd_max);
|
ti->ti_seq = htonl(tp->snd_max);
|
||||||
ti->ti_ack = htonl(tp->rcv_nxt);
|
ti->ti_ack = htonl(tp->rcv_nxt);
|
||||||
if (optlen) {
|
if (optlen) {
|
||||||
memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);
|
memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);
|
||||||
ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
|
ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
|
||||||
}
|
}
|
||||||
ti->ti_flags = flags;
|
ti->ti_flags = flags;
|
||||||
/*
|
/*
|
||||||
* Calculate receive window. Don't shrink window,
|
* Calculate receive window. Don't shrink window,
|
||||||
* but avoid silly window syndrome.
|
* but avoid silly window syndrome.
|
||||||
*/
|
*/
|
||||||
if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
|
if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
|
||||||
win = 0;
|
win = 0;
|
||||||
if (win > (long)TCP_MAXWIN << tp->rcv_scale)
|
if (win > (long)TCP_MAXWIN << tp->rcv_scale)
|
||||||
win = (long)TCP_MAXWIN << tp->rcv_scale;
|
win = (long)TCP_MAXWIN << tp->rcv_scale;
|
||||||
if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
|
if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
|
||||||
win = (long)(tp->rcv_adv - tp->rcv_nxt);
|
win = (long)(tp->rcv_adv - tp->rcv_nxt);
|
||||||
ti->ti_win = htons((uint16_t) (win>>tp->rcv_scale));
|
ti->ti_win = htons((uint16_t) (win>>tp->rcv_scale));
|
||||||
|
|
||||||
if (SEQ_GT(tp->snd_up, tp->snd_una)) {
|
if (SEQ_GT(tp->snd_up, tp->snd_una)) {
|
||||||
ti->ti_urp = htons((uint16_t)(tp->snd_up - ntohl(ti->ti_seq)));
|
ti->ti_urp = htons((uint16_t)(tp->snd_up - ntohl(ti->ti_seq)));
|
||||||
ti->ti_flags |= TH_URG;
|
ti->ti_flags |= TH_URG;
|
||||||
} else
|
} else
|
||||||
/*
|
/*
|
||||||
* If no urgent pointer to send, then we pull
|
* If no urgent pointer to send, then we pull
|
||||||
* the urgent pointer to the left edge of the send window
|
* the urgent pointer to the left edge of the send window
|
||||||
* so that it doesn't drift into the send window on sequence
|
* so that it doesn't drift into the send window on sequence
|
||||||
* number wraparound.
|
* number wraparound.
|
||||||
*/
|
*/
|
||||||
tp->snd_up = tp->snd_una; /* drag it along */
|
tp->snd_up = tp->snd_una; /* drag it along */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put TCP length in extended header, and then
|
* Put TCP length in extended header, and then
|
||||||
* checksum extended header and data.
|
* checksum extended header and data.
|
||||||
*/
|
*/
|
||||||
if (len + optlen)
|
if (len + optlen)
|
||||||
ti->ti_len = htons((uint16_t)(sizeof (struct tcphdr) +
|
ti->ti_len = htons((uint16_t)(sizeof (struct tcphdr) +
|
||||||
optlen + len));
|
optlen + len));
|
||||||
ti->ti_sum = cksum(m, (int)(hdrlen + len));
|
ti->ti_sum = cksum(m, (int)(hdrlen + len));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In transmit state, time the transmission and arrange for
|
* In transmit state, time the transmission and arrange for
|
||||||
* the retransmit. In persist state, just set snd_max.
|
* the retransmit. In persist state, just set snd_max.
|
||||||
*/
|
*/
|
||||||
if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
|
if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
|
||||||
tcp_seq startseq = tp->snd_nxt;
|
tcp_seq startseq = tp->snd_nxt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Advance snd_nxt over sequence space of this segment.
|
* Advance snd_nxt over sequence space of this segment.
|
||||||
*/
|
*/
|
||||||
if (flags & (TH_SYN|TH_FIN)) {
|
if (flags & (TH_SYN|TH_FIN)) {
|
||||||
if (flags & TH_SYN)
|
if (flags & TH_SYN)
|
||||||
tp->snd_nxt++;
|
tp->snd_nxt++;
|
||||||
if (flags & TH_FIN) {
|
if (flags & TH_FIN) {
|
||||||
tp->snd_nxt++;
|
tp->snd_nxt++;
|
||||||
tp->t_flags |= TF_SENTFIN;
|
tp->t_flags |= TF_SENTFIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tp->snd_nxt += len;
|
tp->snd_nxt += len;
|
||||||
if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
|
if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
|
||||||
tp->snd_max = tp->snd_nxt;
|
tp->snd_max = tp->snd_nxt;
|
||||||
/*
|
/*
|
||||||
* Time this transmission if not a retransmission and
|
* Time this transmission if not a retransmission and
|
||||||
* not currently timing anything.
|
* not currently timing anything.
|
||||||
*/
|
*/
|
||||||
if (tp->t_rtt == 0) {
|
if (tp->t_rtt == 0) {
|
||||||
tp->t_rtt = 1;
|
tp->t_rtt = 1;
|
||||||
tp->t_rtseq = startseq;
|
tp->t_rtseq = startseq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set retransmit timer if not currently set,
|
* Set retransmit timer if not currently set,
|
||||||
* and not doing an ack or a keep-alive probe.
|
* and not doing an ack or a keep-alive probe.
|
||||||
* Initial value for retransmit timer is smoothed
|
* Initial value for retransmit timer is smoothed
|
||||||
* round-trip time + 2 * round-trip time variance.
|
* round-trip time + 2 * round-trip time variance.
|
||||||
* Initialize shift counter which is used for backoff
|
* Initialize shift counter which is used for backoff
|
||||||
* of retransmit time.
|
* of retransmit time.
|
||||||
*/
|
*/
|
||||||
if (tp->t_timer[TCPT_REXMT] == 0 &&
|
if (tp->t_timer[TCPT_REXMT] == 0 &&
|
||||||
tp->snd_nxt != tp->snd_una) {
|
tp->snd_nxt != tp->snd_una) {
|
||||||
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
|
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
|
||||||
if (tp->t_timer[TCPT_PERSIST]) {
|
if (tp->t_timer[TCPT_PERSIST]) {
|
||||||
tp->t_timer[TCPT_PERSIST] = 0;
|
tp->t_timer[TCPT_PERSIST] = 0;
|
||||||
tp->t_rxtshift = 0;
|
tp->t_rxtshift = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
|
if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
|
||||||
tp->snd_max = tp->snd_nxt + len;
|
tp->snd_max = tp->snd_nxt + len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill in IP length and desired time to live and
|
* Fill in IP length and desired time to live and
|
||||||
* send to IP level. There should be a better way
|
* send to IP level. There should be a better way
|
||||||
* to handle ttl and tos; we could keep them in
|
* to handle ttl and tos; we could keep them in
|
||||||
* the template, but need a way to checksum without them.
|
* the template, but need a way to checksum without them.
|
||||||
*/
|
*/
|
||||||
m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
|
m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
((struct ip *)ti)->ip_len = m->m_len;
|
((struct ip *)ti)->ip_len = m->m_len;
|
||||||
|
|
||||||
((struct ip *)ti)->ip_ttl = IPDEFTTL;
|
((struct ip *)ti)->ip_ttl = IPDEFTTL;
|
||||||
((struct ip *)ti)->ip_tos = so->so_iptos;
|
((struct ip *)ti)->ip_tos = so->so_iptos;
|
||||||
|
|
||||||
error = ip_output(so, m);
|
error = ip_output(so, m);
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
out:
|
out:
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data sent (as far as we can tell).
|
* Data sent (as far as we can tell).
|
||||||
* If this advertises a larger window than any other segment,
|
* If this advertises a larger window than any other segment,
|
||||||
* then remember the size of the advertised window.
|
* then remember the size of the advertised window.
|
||||||
* Any pending ACK has now been sent.
|
* Any pending ACK has now been sent.
|
||||||
*/
|
*/
|
||||||
if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
|
if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
|
||||||
tp->rcv_adv = tp->rcv_nxt + win;
|
tp->rcv_adv = tp->rcv_nxt + win;
|
||||||
tp->last_ack_sent = tp->rcv_nxt;
|
tp->last_ack_sent = tp->rcv_nxt;
|
||||||
tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
|
tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
|
||||||
if (sendalot)
|
if (sendalot)
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -482,12 +482,12 @@ tcp_setpersist(struct tcpcb *tp)
|
||||||
{
|
{
|
||||||
int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
|
int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start/restart persistence timer.
|
* Start/restart persistence timer.
|
||||||
*/
|
*/
|
||||||
TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
|
TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
|
||||||
t * tcp_backoff[tp->t_rxtshift],
|
t * tcp_backoff[tp->t_rxtshift],
|
||||||
TCPTV_PERSMIN, TCPTV_PERSMAX);
|
TCPTV_PERSMIN, TCPTV_PERSMAX);
|
||||||
if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
|
if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
|
||||||
tp->t_rxtshift++;
|
tp->t_rxtshift++;
|
||||||
}
|
}
|
||||||
|
|
918
slirp/tcp_subr.c
918
slirp/tcp_subr.c
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1988, 1990, 1993
|
* Copyright (c) 1982, 1986, 1988, 1990, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)tcp_timer.c 8.1 (Berkeley) 6/10/93
|
* @(#)tcp_timer.c 8.1 (Berkeley) 6/10/93
|
||||||
* tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp
|
* tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -40,20 +40,20 @@ static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
|
||||||
void
|
void
|
||||||
tcp_fasttimo(Slirp *slirp)
|
tcp_fasttimo(Slirp *slirp)
|
||||||
{
|
{
|
||||||
register struct socket *so;
|
register struct socket *so;
|
||||||
register struct tcpcb *tp;
|
register struct tcpcb *tp;
|
||||||
|
|
||||||
DEBUG_CALL("tcp_fasttimo");
|
DEBUG_CALL("tcp_fasttimo");
|
||||||
|
|
||||||
so = slirp->tcb.so_next;
|
so = slirp->tcb.so_next;
|
||||||
if (so)
|
if (so)
|
||||||
for (; so != &slirp->tcb; so = so->so_next)
|
for (; so != &slirp->tcb; so = so->so_next)
|
||||||
if ((tp = (struct tcpcb *)so->so_tcpcb) &&
|
if ((tp = (struct tcpcb *)so->so_tcpcb) &&
|
||||||
(tp->t_flags & TF_DELACK)) {
|
(tp->t_flags & TF_DELACK)) {
|
||||||
tp->t_flags &= ~TF_DELACK;
|
tp->t_flags &= ~TF_DELACK;
|
||||||
tp->t_flags |= TF_ACKNOW;
|
tp->t_flags |= TF_ACKNOW;
|
||||||
(void) tcp_output(tp);
|
(void) tcp_output(tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -64,40 +64,40 @@ tcp_fasttimo(Slirp *slirp)
|
||||||
void
|
void
|
||||||
tcp_slowtimo(Slirp *slirp)
|
tcp_slowtimo(Slirp *slirp)
|
||||||
{
|
{
|
||||||
register struct socket *ip, *ipnxt;
|
register struct socket *ip, *ipnxt;
|
||||||
register struct tcpcb *tp;
|
register struct tcpcb *tp;
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
DEBUG_CALL("tcp_slowtimo");
|
DEBUG_CALL("tcp_slowtimo");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Search through tcb's and update active timers.
|
* Search through tcb's and update active timers.
|
||||||
*/
|
*/
|
||||||
ip = slirp->tcb.so_next;
|
ip = slirp->tcb.so_next;
|
||||||
if (ip == NULL) {
|
if (ip == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (; ip != &slirp->tcb; ip = ipnxt) {
|
for (; ip != &slirp->tcb; ip = ipnxt) {
|
||||||
ipnxt = ip->so_next;
|
ipnxt = ip->so_next;
|
||||||
tp = sototcpcb(ip);
|
tp = sototcpcb(ip);
|
||||||
if (tp == NULL) {
|
if (tp == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (i = 0; i < TCPT_NTIMERS; i++) {
|
for (i = 0; i < TCPT_NTIMERS; i++) {
|
||||||
if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
|
if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
|
||||||
tcp_timers(tp,i);
|
tcp_timers(tp,i);
|
||||||
if (ipnxt->so_prev != ip)
|
if (ipnxt->so_prev != ip)
|
||||||
goto tpgone;
|
goto tpgone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tp->t_idle++;
|
tp->t_idle++;
|
||||||
if (tp->t_rtt)
|
if (tp->t_rtt)
|
||||||
tp->t_rtt++;
|
tp->t_rtt++;
|
||||||
tpgone:
|
tpgone:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
slirp->tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
|
slirp->tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
|
||||||
slirp->tcp_now++; /* for timestamps */
|
slirp->tcp_now++; /* for timestamps */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,10 +106,10 @@ tpgone:
|
||||||
void
|
void
|
||||||
tcp_canceltimers(struct tcpcb *tp)
|
tcp_canceltimers(struct tcpcb *tp)
|
||||||
{
|
{
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
for (i = 0; i < TCPT_NTIMERS; i++)
|
for (i = 0; i < TCPT_NTIMERS; i++)
|
||||||
tp->t_timer[i] = 0;
|
tp->t_timer[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
|
const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
|
||||||
|
@ -121,172 +121,172 @@ const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
|
||||||
static struct tcpcb *
|
static struct tcpcb *
|
||||||
tcp_timers(register struct tcpcb *tp, int timer)
|
tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
{
|
{
|
||||||
register int rexmt;
|
register int rexmt;
|
||||||
|
|
||||||
DEBUG_CALL("tcp_timers");
|
DEBUG_CALL("tcp_timers");
|
||||||
|
|
||||||
switch (timer) {
|
switch (timer) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2 MSL timeout in shutdown went off. If we're closed but
|
* 2 MSL timeout in shutdown went off. If we're closed but
|
||||||
* still waiting for peer to close and connection has been idle
|
* still waiting for peer to close and connection has been idle
|
||||||
* too long, or if 2MSL time is up from TIME_WAIT, delete connection
|
* too long, or if 2MSL time is up from TIME_WAIT, delete connection
|
||||||
* control block. Otherwise, check again in a bit.
|
* control block. Otherwise, check again in a bit.
|
||||||
*/
|
*/
|
||||||
case TCPT_2MSL:
|
case TCPT_2MSL:
|
||||||
if (tp->t_state != TCPS_TIME_WAIT &&
|
if (tp->t_state != TCPS_TIME_WAIT &&
|
||||||
tp->t_idle <= TCP_MAXIDLE)
|
tp->t_idle <= TCP_MAXIDLE)
|
||||||
tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
|
tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
|
||||||
else
|
else
|
||||||
tp = tcp_close(tp);
|
tp = tcp_close(tp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retransmission timer went off. Message has not
|
* Retransmission timer went off. Message has not
|
||||||
* been acked within retransmit interval. Back off
|
* been acked within retransmit interval. Back off
|
||||||
* to a longer retransmit interval and retransmit one segment.
|
* to a longer retransmit interval and retransmit one segment.
|
||||||
*/
|
*/
|
||||||
case TCPT_REXMT:
|
case TCPT_REXMT:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXXXX If a packet has timed out, then remove all the queued
|
* XXXXX If a packet has timed out, then remove all the queued
|
||||||
* packets for that session.
|
* packets for that session.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
|
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
|
||||||
/*
|
/*
|
||||||
* This is a hack to suit our terminal server here at the uni of canberra
|
* This is a hack to suit our terminal server here at the uni of canberra
|
||||||
* since they have trouble with zeroes... It usually lets them through
|
* since they have trouble with zeroes... It usually lets them through
|
||||||
* unharmed, but under some conditions, it'll eat the zeros. If we
|
* unharmed, but under some conditions, it'll eat the zeros. If we
|
||||||
* keep retransmitting it, it'll keep eating the zeroes, so we keep
|
* keep retransmitting it, it'll keep eating the zeroes, so we keep
|
||||||
* retransmitting, and eventually the connection dies...
|
* retransmitting, and eventually the connection dies...
|
||||||
* (this only happens on incoming data)
|
* (this only happens on incoming data)
|
||||||
*
|
*
|
||||||
* So, if we were gonna drop the connection from too many retransmits,
|
* So, if we were gonna drop the connection from too many retransmits,
|
||||||
* don't... instead halve the t_maxseg, which might break up the NULLs and
|
* don't... instead halve the t_maxseg, which might break up the NULLs and
|
||||||
* let them through
|
* let them through
|
||||||
*
|
*
|
||||||
* *sigh*
|
* *sigh*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tp->t_maxseg >>= 1;
|
tp->t_maxseg >>= 1;
|
||||||
if (tp->t_maxseg < 32) {
|
if (tp->t_maxseg < 32) {
|
||||||
/*
|
/*
|
||||||
* We tried our best, now the connection must die!
|
* We tried our best, now the connection must die!
|
||||||
*/
|
*/
|
||||||
tp->t_rxtshift = TCP_MAXRXTSHIFT;
|
tp->t_rxtshift = TCP_MAXRXTSHIFT;
|
||||||
tp = tcp_drop(tp, tp->t_softerror);
|
tp = tcp_drop(tp, tp->t_softerror);
|
||||||
/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
|
/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
|
||||||
return (tp); /* XXX */
|
return (tp); /* XXX */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set rxtshift to 6, which is still at the maximum
|
* Set rxtshift to 6, which is still at the maximum
|
||||||
* backoff time
|
* backoff time
|
||||||
*/
|
*/
|
||||||
tp->t_rxtshift = 6;
|
tp->t_rxtshift = 6;
|
||||||
}
|
}
|
||||||
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
|
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
|
||||||
TCPT_RANGESET(tp->t_rxtcur, rexmt,
|
TCPT_RANGESET(tp->t_rxtcur, rexmt,
|
||||||
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
|
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
|
||||||
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
|
tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
|
||||||
/*
|
/*
|
||||||
* If losing, let the lower level know and try for
|
* If losing, let the lower level know and try for
|
||||||
* a better route. Also, if we backed off this far,
|
* a better route. Also, if we backed off this far,
|
||||||
* our srtt estimate is probably bogus. Clobber it
|
* our srtt estimate is probably bogus. Clobber it
|
||||||
* so we'll take the next rtt measurement as our srtt;
|
* so we'll take the next rtt measurement as our srtt;
|
||||||
* move the current srtt into rttvar to keep the current
|
* move the current srtt into rttvar to keep the current
|
||||||
* retransmit times until then.
|
* retransmit times until then.
|
||||||
*/
|
*/
|
||||||
if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
|
if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
|
||||||
tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
|
tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
|
||||||
tp->t_srtt = 0;
|
tp->t_srtt = 0;
|
||||||
}
|
}
|
||||||
tp->snd_nxt = tp->snd_una;
|
tp->snd_nxt = tp->snd_una;
|
||||||
/*
|
/*
|
||||||
* If timing a segment in this window, stop the timer.
|
* If timing a segment in this window, stop the timer.
|
||||||
*/
|
*/
|
||||||
tp->t_rtt = 0;
|
tp->t_rtt = 0;
|
||||||
/*
|
/*
|
||||||
* Close the congestion window down to one segment
|
* Close the congestion window down to one segment
|
||||||
* (we'll open it by one segment for each ack we get).
|
* (we'll open it by one segment for each ack we get).
|
||||||
* Since we probably have a window's worth of unacked
|
* Since we probably have a window's worth of unacked
|
||||||
* data accumulated, this "slow start" keeps us from
|
* data accumulated, this "slow start" keeps us from
|
||||||
* dumping all that data as back-to-back packets (which
|
* dumping all that data as back-to-back packets (which
|
||||||
* might overwhelm an intermediate gateway).
|
* might overwhelm an intermediate gateway).
|
||||||
*
|
*
|
||||||
* There are two phases to the opening: Initially we
|
* There are two phases to the opening: Initially we
|
||||||
* open by one mss on each ack. This makes the window
|
* open by one mss on each ack. This makes the window
|
||||||
* size increase exponentially with time. If the
|
* size increase exponentially with time. If the
|
||||||
* window is larger than the path can handle, this
|
* window is larger than the path can handle, this
|
||||||
* exponential growth results in dropped packet(s)
|
* exponential growth results in dropped packet(s)
|
||||||
* almost immediately. To get more time between
|
* almost immediately. To get more time between
|
||||||
* drops but still "push" the network to take advantage
|
* drops but still "push" the network to take advantage
|
||||||
* of improving conditions, we switch from exponential
|
* of improving conditions, we switch from exponential
|
||||||
* to linear window opening at some threshold size.
|
* to linear window opening at some threshold size.
|
||||||
* For a threshold, we use half the current window
|
* For a threshold, we use half the current window
|
||||||
* size, truncated to a multiple of the mss.
|
* size, truncated to a multiple of the mss.
|
||||||
*
|
*
|
||||||
* (the minimum cwnd that will give us exponential
|
* (the minimum cwnd that will give us exponential
|
||||||
* growth is 2 mss. We don't allow the threshold
|
* growth is 2 mss. We don't allow the threshold
|
||||||
* to go below this.)
|
* to go below this.)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
|
u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
|
||||||
if (win < 2)
|
if (win < 2)
|
||||||
win = 2;
|
win = 2;
|
||||||
tp->snd_cwnd = tp->t_maxseg;
|
tp->snd_cwnd = tp->t_maxseg;
|
||||||
tp->snd_ssthresh = win * tp->t_maxseg;
|
tp->snd_ssthresh = win * tp->t_maxseg;
|
||||||
tp->t_dupacks = 0;
|
tp->t_dupacks = 0;
|
||||||
}
|
}
|
||||||
(void) tcp_output(tp);
|
(void) tcp_output(tp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Persistence timer into zero window.
|
* Persistence timer into zero window.
|
||||||
* Force a byte to be output, if possible.
|
* Force a byte to be output, if possible.
|
||||||
*/
|
*/
|
||||||
case TCPT_PERSIST:
|
case TCPT_PERSIST:
|
||||||
tcp_setpersist(tp);
|
tcp_setpersist(tp);
|
||||||
tp->t_force = 1;
|
tp->t_force = 1;
|
||||||
(void) tcp_output(tp);
|
(void) tcp_output(tp);
|
||||||
tp->t_force = 0;
|
tp->t_force = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep-alive timer went off; send something
|
* Keep-alive timer went off; send something
|
||||||
* or drop connection if idle for too long.
|
* or drop connection if idle for too long.
|
||||||
*/
|
*/
|
||||||
case TCPT_KEEP:
|
case TCPT_KEEP:
|
||||||
if (tp->t_state < TCPS_ESTABLISHED)
|
if (tp->t_state < TCPS_ESTABLISHED)
|
||||||
goto dropit;
|
goto dropit;
|
||||||
|
|
||||||
if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
|
if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
|
||||||
if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
|
if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
|
||||||
goto dropit;
|
goto dropit;
|
||||||
/*
|
/*
|
||||||
* Send a packet designed to force a response
|
* Send a packet designed to force a response
|
||||||
* if the peer is up and reachable:
|
* if the peer is up and reachable:
|
||||||
* either an ACK if the connection is still alive,
|
* either an ACK if the connection is still alive,
|
||||||
* or an RST if the peer has closed the connection
|
* or an RST if the peer has closed the connection
|
||||||
* due to timeout or reboot.
|
* due to timeout or reboot.
|
||||||
* Using sequence number tp->snd_una-1
|
* Using sequence number tp->snd_una-1
|
||||||
* causes the transmitted zero-length segment
|
* causes the transmitted zero-length segment
|
||||||
* to lie outside the receive window;
|
* to lie outside the receive window;
|
||||||
* by the protocol spec, this requires the
|
* by the protocol spec, this requires the
|
||||||
* correspondent TCP to respond.
|
* correspondent TCP to respond.
|
||||||
*/
|
*/
|
||||||
tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
|
tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
|
||||||
tp->rcv_nxt, tp->snd_una - 1, 0);
|
tp->rcv_nxt, tp->snd_una - 1, 0);
|
||||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
|
tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
|
||||||
} else
|
} else
|
||||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
|
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
dropit:
|
dropit:
|
||||||
tp = tcp_drop(tp, 0);
|
tp = tcp_drop(tp, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (tp);
|
return (tp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993
|
* Copyright (c) 1982, 1986, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93
|
* @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93
|
||||||
* tcp_timer.h,v 1.4 1994/08/21 05:27:38 paul Exp
|
* tcp_timer.h,v 1.4 1994/08/21 05:27:38 paul Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -37,12 +37,12 @@
|
||||||
* Definitions of the TCP timers. These timers are counted
|
* Definitions of the TCP timers. These timers are counted
|
||||||
* down PR_SLOWHZ times a second.
|
* down PR_SLOWHZ times a second.
|
||||||
*/
|
*/
|
||||||
#define TCPT_NTIMERS 4
|
#define TCPT_NTIMERS 4
|
||||||
|
|
||||||
#define TCPT_REXMT 0 /* retransmit */
|
#define TCPT_REXMT 0 /* retransmit */
|
||||||
#define TCPT_PERSIST 1 /* retransmit persistence */
|
#define TCPT_PERSIST 1 /* retransmit persistence */
|
||||||
#define TCPT_KEEP 2 /* keep alive */
|
#define TCPT_KEEP 2 /* keep alive */
|
||||||
#define TCPT_2MSL 3 /* 2*msl quiet time timer */
|
#define TCPT_2MSL 3 /* 2*msl quiet time timer */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The TCPT_REXMT timer is used to force retransmissions.
|
* The TCPT_REXMT timer is used to force retransmissions.
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
* is established, if the connection is idle for TCPTV_KEEP_IDLE time
|
* is established, if the connection is idle for TCPTV_KEEP_IDLE time
|
||||||
* (and keepalives have been enabled on the socket), we begin to probe
|
* (and keepalives have been enabled on the socket), we begin to probe
|
||||||
* the connection. We force the peer to send us a segment by sending:
|
* the connection. We force the peer to send us a segment by sending:
|
||||||
* <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
|
* <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
|
||||||
* This segment is (deliberately) outside the window, and should elicit
|
* This segment is (deliberately) outside the window, and should elicit
|
||||||
* an ack segment in response from the peer. If, despite the TCPT_KEEP
|
* an ack segment in response from the peer. If, despite the TCPT_KEEP
|
||||||
* initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
|
* initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
|
||||||
|
@ -85,22 +85,22 @@
|
||||||
*/
|
*/
|
||||||
#define TCPTV_MSL ( 5*PR_SLOWHZ) /* max seg lifetime (hah!) */
|
#define TCPTV_MSL ( 5*PR_SLOWHZ) /* max seg lifetime (hah!) */
|
||||||
|
|
||||||
#define TCPTV_SRTTBASE 0 /* base roundtrip time;
|
#define TCPTV_SRTTBASE 0 /* base roundtrip time;
|
||||||
if 0, no idea yet */
|
if 0, no idea yet */
|
||||||
#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */
|
#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */
|
||||||
|
|
||||||
#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistence */
|
#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistence */
|
||||||
#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
|
#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
|
||||||
|
|
||||||
#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */
|
#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */
|
||||||
#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */
|
#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */
|
||||||
#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */
|
#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */
|
||||||
#define TCPTV_KEEPCNT 8 /* max probes before drop */
|
#define TCPTV_KEEPCNT 8 /* max probes before drop */
|
||||||
|
|
||||||
#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */
|
#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */
|
||||||
#define TCPTV_REXMTMAX ( 12*PR_SLOWHZ) /* max allowable REXMT value */
|
#define TCPTV_REXMTMAX ( 12*PR_SLOWHZ) /* max allowable REXMT value */
|
||||||
|
|
||||||
#define TCP_LINGERTIME 120 /* linger at most 2 minutes */
|
#define TCP_LINGERTIME 120 /* linger at most 2 minutes */
|
||||||
|
|
||||||
#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */
|
#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */
|
||||||
|
|
||||||
|
@ -108,12 +108,12 @@
|
||||||
/*
|
/*
|
||||||
* Force a time value to be in a certain range.
|
* Force a time value to be in a certain range.
|
||||||
*/
|
*/
|
||||||
#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \
|
#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \
|
||||||
(tv) = (value); \
|
(tv) = (value); \
|
||||||
if ((tv) < (tvmin)) \
|
if ((tv) < (tvmin)) \
|
||||||
(tv) = (tvmin); \
|
(tv) = (tvmin); \
|
||||||
else if ((tv) > (tvmax)) \
|
else if ((tv) > (tvmax)) \
|
||||||
(tv) = (tvmax); \
|
(tv) = (tvmax); \
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const int tcp_backoff[];
|
extern const int tcp_backoff[];
|
||||||
|
|
140
slirp/tcp_var.h
140
slirp/tcp_var.h
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993, 1994
|
* Copyright (c) 1982, 1986, 1993, 1994
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)tcp_var.h 8.3 (Berkeley) 4/10/94
|
* @(#)tcp_var.h 8.3 (Berkeley) 4/10/94
|
||||||
* tcp_var.h,v 1.3 1994/08/21 05:27:39 paul Exp
|
* tcp_var.h,v 1.3 1994/08/21 05:27:39 paul Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -40,93 +40,93 @@
|
||||||
* Tcp control block, one per tcp; fields:
|
* Tcp control block, one per tcp; fields:
|
||||||
*/
|
*/
|
||||||
struct tcpcb {
|
struct tcpcb {
|
||||||
struct tcpiphdr *seg_next; /* sequencing queue */
|
struct tcpiphdr *seg_next; /* sequencing queue */
|
||||||
struct tcpiphdr *seg_prev;
|
struct tcpiphdr *seg_prev;
|
||||||
short t_state; /* state of this connection */
|
short t_state; /* state of this connection */
|
||||||
short t_timer[TCPT_NTIMERS]; /* tcp timers */
|
short t_timer[TCPT_NTIMERS]; /* tcp timers */
|
||||||
short t_rxtshift; /* log(2) of rexmt exp. backoff */
|
short t_rxtshift; /* log(2) of rexmt exp. backoff */
|
||||||
short t_rxtcur; /* current retransmit value */
|
short t_rxtcur; /* current retransmit value */
|
||||||
short t_dupacks; /* consecutive dup acks recd */
|
short t_dupacks; /* consecutive dup acks recd */
|
||||||
u_short t_maxseg; /* maximum segment size */
|
u_short t_maxseg; /* maximum segment size */
|
||||||
char t_force; /* 1 if forcing out a byte */
|
char t_force; /* 1 if forcing out a byte */
|
||||||
u_short t_flags;
|
u_short t_flags;
|
||||||
#define TF_ACKNOW 0x0001 /* ack peer immediately */
|
#define TF_ACKNOW 0x0001 /* ack peer immediately */
|
||||||
#define TF_DELACK 0x0002 /* ack, but try to delay it */
|
#define TF_DELACK 0x0002 /* ack, but try to delay it */
|
||||||
#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */
|
#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */
|
||||||
#define TF_NOOPT 0x0008 /* don't use tcp options */
|
#define TF_NOOPT 0x0008 /* don't use tcp options */
|
||||||
#define TF_SENTFIN 0x0010 /* have sent FIN */
|
#define TF_SENTFIN 0x0010 /* have sent FIN */
|
||||||
#define TF_REQ_SCALE 0x0020 /* have/will request window scaling */
|
#define TF_REQ_SCALE 0x0020 /* have/will request window scaling */
|
||||||
#define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */
|
#define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */
|
||||||
#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */
|
#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */
|
||||||
#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */
|
#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */
|
||||||
#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */
|
#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */
|
||||||
|
|
||||||
struct tcpiphdr t_template; /* static skeletal packet for xmit */
|
struct tcpiphdr t_template; /* static skeletal packet for xmit */
|
||||||
|
|
||||||
struct socket *t_socket; /* back pointer to socket */
|
struct socket *t_socket; /* back pointer to socket */
|
||||||
/*
|
/*
|
||||||
* The following fields are used as in the protocol specification.
|
* The following fields are used as in the protocol specification.
|
||||||
* See RFC783, Dec. 1981, page 21.
|
* See RFC783, Dec. 1981, page 21.
|
||||||
*/
|
*/
|
||||||
/* send sequence variables */
|
/* send sequence variables */
|
||||||
tcp_seq snd_una; /* send unacknowledged */
|
tcp_seq snd_una; /* send unacknowledged */
|
||||||
tcp_seq snd_nxt; /* send next */
|
tcp_seq snd_nxt; /* send next */
|
||||||
tcp_seq snd_up; /* send urgent pointer */
|
tcp_seq snd_up; /* send urgent pointer */
|
||||||
tcp_seq snd_wl1; /* window update seg seq number */
|
tcp_seq snd_wl1; /* window update seg seq number */
|
||||||
tcp_seq snd_wl2; /* window update seg ack number */
|
tcp_seq snd_wl2; /* window update seg ack number */
|
||||||
tcp_seq iss; /* initial send sequence number */
|
tcp_seq iss; /* initial send sequence number */
|
||||||
uint32_t snd_wnd; /* send window */
|
uint32_t snd_wnd; /* send window */
|
||||||
/* receive sequence variables */
|
/* receive sequence variables */
|
||||||
uint32_t rcv_wnd; /* receive window */
|
uint32_t rcv_wnd; /* receive window */
|
||||||
tcp_seq rcv_nxt; /* receive next */
|
tcp_seq rcv_nxt; /* receive next */
|
||||||
tcp_seq rcv_up; /* receive urgent pointer */
|
tcp_seq rcv_up; /* receive urgent pointer */
|
||||||
tcp_seq irs; /* initial receive sequence number */
|
tcp_seq irs; /* initial receive sequence number */
|
||||||
/*
|
/*
|
||||||
* Additional variables for this implementation.
|
* Additional variables for this implementation.
|
||||||
*/
|
*/
|
||||||
/* receive variables */
|
/* receive variables */
|
||||||
tcp_seq rcv_adv; /* advertised window */
|
tcp_seq rcv_adv; /* advertised window */
|
||||||
/* retransmit variables */
|
/* retransmit variables */
|
||||||
tcp_seq snd_max; /* highest sequence number sent;
|
tcp_seq snd_max; /* highest sequence number sent;
|
||||||
* used to recognize retransmits
|
* used to recognize retransmits
|
||||||
*/
|
*/
|
||||||
/* congestion control (for slow start, source quench, retransmit after loss) */
|
/* congestion control (for slow start, source quench, retransmit after loss) */
|
||||||
uint32_t snd_cwnd; /* congestion-controlled window */
|
uint32_t snd_cwnd; /* congestion-controlled window */
|
||||||
uint32_t snd_ssthresh; /* snd_cwnd size threshold for
|
uint32_t snd_ssthresh; /* snd_cwnd size threshold for
|
||||||
* for slow start exponential to
|
* for slow start exponential to
|
||||||
* linear switch
|
* linear switch
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* transmit timing stuff. See below for scale of srtt and rttvar.
|
* transmit timing stuff. See below for scale of srtt and rttvar.
|
||||||
* "Variance" is actually smoothed difference.
|
* "Variance" is actually smoothed difference.
|
||||||
*/
|
*/
|
||||||
short t_idle; /* inactivity time */
|
short t_idle; /* inactivity time */
|
||||||
short t_rtt; /* round trip time */
|
short t_rtt; /* round trip time */
|
||||||
tcp_seq t_rtseq; /* sequence number being timed */
|
tcp_seq t_rtseq; /* sequence number being timed */
|
||||||
short t_srtt; /* smoothed round-trip time */
|
short t_srtt; /* smoothed round-trip time */
|
||||||
short t_rttvar; /* variance in round-trip time */
|
short t_rttvar; /* variance in round-trip time */
|
||||||
u_short t_rttmin; /* minimum rtt allowed */
|
u_short t_rttmin; /* minimum rtt allowed */
|
||||||
uint32_t max_sndwnd; /* largest window peer has offered */
|
uint32_t max_sndwnd; /* largest window peer has offered */
|
||||||
|
|
||||||
/* out-of-band data */
|
/* out-of-band data */
|
||||||
char t_oobflags; /* have some */
|
char t_oobflags; /* have some */
|
||||||
char t_iobc; /* input character */
|
char t_iobc; /* input character */
|
||||||
#define TCPOOB_HAVEDATA 0x01
|
#define TCPOOB_HAVEDATA 0x01
|
||||||
#define TCPOOB_HADDATA 0x02
|
#define TCPOOB_HADDATA 0x02
|
||||||
short t_softerror; /* possible error not yet reported */
|
short t_softerror; /* possible error not yet reported */
|
||||||
|
|
||||||
/* RFC 1323 variables */
|
/* RFC 1323 variables */
|
||||||
u_char snd_scale; /* window scaling for send window */
|
u_char snd_scale; /* window scaling for send window */
|
||||||
u_char rcv_scale; /* window scaling for recv window */
|
u_char rcv_scale; /* window scaling for recv window */
|
||||||
u_char request_r_scale; /* pending window scaling */
|
u_char request_r_scale; /* pending window scaling */
|
||||||
u_char requested_s_scale;
|
u_char requested_s_scale;
|
||||||
uint32_t ts_recent; /* timestamp echo data */
|
uint32_t ts_recent; /* timestamp echo data */
|
||||||
uint32_t ts_recent_age; /* when last updated */
|
uint32_t ts_recent_age; /* when last updated */
|
||||||
tcp_seq last_ack_sent;
|
tcp_seq last_ack_sent;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define sototcpcb(so) ((so)->so_tcpcb)
|
#define sototcpcb(so) ((so)->so_tcpcb)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The smoothed round-trip time and estimated variance
|
* The smoothed round-trip time and estimated variance
|
||||||
|
@ -137,10 +137,10 @@ struct tcpcb {
|
||||||
* and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the
|
* and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the
|
||||||
* binary point, and is smoothed with an ALPHA of 0.75.
|
* binary point, and is smoothed with an ALPHA of 0.75.
|
||||||
*/
|
*/
|
||||||
#define TCP_RTT_SCALE 8 /* multiplier for srtt; 3 bits frac. */
|
#define TCP_RTT_SCALE 8 /* multiplier for srtt; 3 bits frac. */
|
||||||
#define TCP_RTT_SHIFT 3 /* shift for srtt; 3 bits frac. */
|
#define TCP_RTT_SHIFT 3 /* shift for srtt; 3 bits frac. */
|
||||||
#define TCP_RTTVAR_SCALE 4 /* multiplier for rttvar; 2 bits */
|
#define TCP_RTTVAR_SCALE 4 /* multiplier for rttvar; 2 bits */
|
||||||
#define TCP_RTTVAR_SHIFT 2 /* multiplier for rttvar; 2 bits */
|
#define TCP_RTTVAR_SHIFT 2 /* multiplier for rttvar; 2 bits */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The initial retransmission should happen at rtt + 4 * rttvar.
|
* The initial retransmission should happen at rtt + 4 * rttvar.
|
||||||
|
@ -155,7 +155,7 @@ struct tcpcb {
|
||||||
* This macro assumes that the value of TCP_RTTVAR_SCALE
|
* This macro assumes that the value of TCP_RTTVAR_SCALE
|
||||||
* is the same as the multiplier for rttvar.
|
* is the same as the multiplier for rttvar.
|
||||||
*/
|
*/
|
||||||
#define TCP_REXMTVAL(tp) \
|
#define TCP_REXMTVAL(tp) \
|
||||||
(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
|
(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993
|
* Copyright (c) 1982, 1986, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)tcpip.h 8.1 (Berkeley) 6/10/93
|
* @(#)tcpip.h 8.1 (Berkeley) 6/10/93
|
||||||
* tcpip.h,v 1.3 1994/08/21 05:27:40 paul Exp
|
* tcpip.h,v 1.3 1994/08/21 05:27:40 paul Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -37,25 +37,25 @@
|
||||||
* Tcp+ip header, after ip options removed.
|
* Tcp+ip header, after ip options removed.
|
||||||
*/
|
*/
|
||||||
struct tcpiphdr {
|
struct tcpiphdr {
|
||||||
struct ipovly ti_i; /* overlaid ip structure */
|
struct ipovly ti_i; /* overlaid ip structure */
|
||||||
struct tcphdr ti_t; /* tcp header */
|
struct tcphdr ti_t; /* tcp header */
|
||||||
};
|
};
|
||||||
#define ti_mbuf ti_i.ih_mbuf.mptr
|
#define ti_mbuf ti_i.ih_mbuf.mptr
|
||||||
#define ti_x1 ti_i.ih_x1
|
#define ti_x1 ti_i.ih_x1
|
||||||
#define ti_pr ti_i.ih_pr
|
#define ti_pr ti_i.ih_pr
|
||||||
#define ti_len ti_i.ih_len
|
#define ti_len ti_i.ih_len
|
||||||
#define ti_src ti_i.ih_src
|
#define ti_src ti_i.ih_src
|
||||||
#define ti_dst ti_i.ih_dst
|
#define ti_dst ti_i.ih_dst
|
||||||
#define ti_sport ti_t.th_sport
|
#define ti_sport ti_t.th_sport
|
||||||
#define ti_dport ti_t.th_dport
|
#define ti_dport ti_t.th_dport
|
||||||
#define ti_seq ti_t.th_seq
|
#define ti_seq ti_t.th_seq
|
||||||
#define ti_ack ti_t.th_ack
|
#define ti_ack ti_t.th_ack
|
||||||
#define ti_x2 ti_t.th_x2
|
#define ti_x2 ti_t.th_x2
|
||||||
#define ti_off ti_t.th_off
|
#define ti_off ti_t.th_off
|
||||||
#define ti_flags ti_t.th_flags
|
#define ti_flags ti_t.th_flags
|
||||||
#define ti_win ti_t.th_win
|
#define ti_win ti_t.th_win
|
||||||
#define ti_sum ti_t.th_sum
|
#define ti_sum ti_t.th_sum
|
||||||
#define ti_urp ti_t.th_urp
|
#define ti_urp ti_t.th_urp
|
||||||
|
|
||||||
#define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink)))
|
#define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink)))
|
||||||
#define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink)))
|
#define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink)))
|
||||||
|
@ -70,8 +70,8 @@ struct tcpiphdr {
|
||||||
* of the packet
|
* of the packet
|
||||||
*/
|
*/
|
||||||
struct tcpiphdr_2 {
|
struct tcpiphdr_2 {
|
||||||
struct tcpiphdr dummy;
|
struct tcpiphdr dummy;
|
||||||
char first_char;
|
char first_char;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
32
slirp/tftp.c
32
slirp/tftp.c
|
@ -87,9 +87,9 @@ static int tftp_session_find(Slirp *slirp, struct tftp_t *tp)
|
||||||
|
|
||||||
if (tftp_session_in_use(spt)) {
|
if (tftp_session_in_use(spt)) {
|
||||||
if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
|
if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
|
||||||
if (spt->client_port == tp->udp.uh_sport) {
|
if (spt->client_port == tp->udp.uh_sport) {
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ static int tftp_send_oack(struct tftp_session *spt,
|
||||||
m = m_get(spt->slirp);
|
m = m_get(spt->slirp);
|
||||||
|
|
||||||
if (!m)
|
if (!m)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
memset(m->m_data, 0, m->m_size);
|
memset(m->m_data, 0, m->m_size);
|
||||||
|
|
||||||
|
@ -348,25 +348,25 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
|
||||||
k += strlen(key) + 1;
|
k += strlen(key) + 1;
|
||||||
|
|
||||||
if (k >= pktlen) {
|
if (k >= pktlen) {
|
||||||
tftp_send_error(spt, 2, "Access violation", tp);
|
tftp_send_error(spt, 2, "Access violation", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = &tp->x.tp_buf[k];
|
value = &tp->x.tp_buf[k];
|
||||||
k += strlen(value) + 1;
|
k += strlen(value) + 1;
|
||||||
|
|
||||||
if (strcasecmp(key, "tsize") == 0) {
|
if (strcasecmp(key, "tsize") == 0) {
|
||||||
int tsize = atoi(value);
|
int tsize = atoi(value);
|
||||||
struct stat stat_p;
|
struct stat stat_p;
|
||||||
|
|
||||||
if (tsize == 0) {
|
if (tsize == 0) {
|
||||||
if (stat(spt->filename, &stat_p) == 0)
|
if (stat(spt->filename, &stat_p) == 0)
|
||||||
tsize = stat_p.st_size;
|
tsize = stat_p.st_size;
|
||||||
else {
|
else {
|
||||||
tftp_send_error(spt, 1, "File not found", tp);
|
tftp_send_error(spt, 1, "File not found", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
option_name[nb_options] = "tsize";
|
option_name[nb_options] = "tsize";
|
||||||
option_value[nb_options] = tsize;
|
option_value[nb_options] = tsize;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#define TFTP_SESSIONS_MAX 20
|
#define TFTP_SESSIONS_MAX 20
|
||||||
|
|
||||||
#define TFTP_SERVER 69
|
#define TFTP_SERVER 69
|
||||||
|
|
||||||
#define TFTP_RRQ 1
|
#define TFTP_RRQ 1
|
||||||
#define TFTP_WRQ 2
|
#define TFTP_WRQ 2
|
||||||
|
|
412
slirp/udp.c
412
slirp/udp.c
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1988, 1990, 1993
|
* Copyright (c) 1982, 1986, 1988, 1990, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
|
* @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
|
||||||
* udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
|
* udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -64,66 +64,66 @@ void udp_cleanup(Slirp *slirp)
|
||||||
void
|
void
|
||||||
udp_input(register struct mbuf *m, int iphlen)
|
udp_input(register struct mbuf *m, int iphlen)
|
||||||
{
|
{
|
||||||
Slirp *slirp = m->slirp;
|
Slirp *slirp = m->slirp;
|
||||||
register struct ip *ip;
|
register struct ip *ip;
|
||||||
register struct udphdr *uh;
|
register struct udphdr *uh;
|
||||||
int len;
|
int len;
|
||||||
struct ip save_ip;
|
struct ip save_ip;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
DEBUG_CALL("udp_input");
|
DEBUG_CALL("udp_input");
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
DEBUG_ARG("iphlen = %d", iphlen);
|
DEBUG_ARG("iphlen = %d", iphlen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strip IP options, if any; should skip this,
|
* Strip IP options, if any; should skip this,
|
||||||
* make available to user, and use on returned packets,
|
* make available to user, and use on returned packets,
|
||||||
* but we don't yet have a way to check the checksum
|
* but we don't yet have a way to check the checksum
|
||||||
* with options still present.
|
* with options still present.
|
||||||
*/
|
*/
|
||||||
if(iphlen > sizeof(struct ip)) {
|
if(iphlen > sizeof(struct ip)) {
|
||||||
ip_stripoptions(m, (struct mbuf *)0);
|
ip_stripoptions(m, (struct mbuf *)0);
|
||||||
iphlen = sizeof(struct ip);
|
iphlen = sizeof(struct ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get IP and UDP header together in first mbuf.
|
* Get IP and UDP header together in first mbuf.
|
||||||
*/
|
*/
|
||||||
ip = mtod(m, struct ip *);
|
ip = mtod(m, struct ip *);
|
||||||
uh = (struct udphdr *)((caddr_t)ip + iphlen);
|
uh = (struct udphdr *)((caddr_t)ip + iphlen);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make mbuf data length reflect UDP length.
|
* Make mbuf data length reflect UDP length.
|
||||||
* If not enough data to reflect UDP length, drop.
|
* If not enough data to reflect UDP length, drop.
|
||||||
*/
|
*/
|
||||||
len = ntohs((uint16_t)uh->uh_ulen);
|
len = ntohs((uint16_t)uh->uh_ulen);
|
||||||
|
|
||||||
if (ip->ip_len != len) {
|
if (ip->ip_len != len) {
|
||||||
if (len > ip->ip_len) {
|
if (len > ip->ip_len) {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
m_adj(m, len - ip->ip_len);
|
m_adj(m, len - ip->ip_len);
|
||||||
ip->ip_len = len;
|
ip->ip_len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save a copy of the IP header in case we want restore it
|
* Save a copy of the IP header in case we want restore it
|
||||||
* for sending an ICMP error message in response.
|
* for sending an ICMP error message in response.
|
||||||
*/
|
*/
|
||||||
save_ip = *ip;
|
save_ip = *ip;
|
||||||
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
|
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checksum extended UDP header and data.
|
* Checksum extended UDP header and data.
|
||||||
*/
|
*/
|
||||||
if (uh->uh_sum) {
|
if (uh->uh_sum) {
|
||||||
memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
|
memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
|
||||||
((struct ipovly *)ip)->ih_x1 = 0;
|
((struct ipovly *)ip)->ih_x1 = 0;
|
||||||
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
|
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
|
||||||
if(cksum(m, len + sizeof(struct ip))) {
|
if(cksum(m, len + sizeof(struct ip))) {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* handle DHCP/BOOTP
|
* handle DHCP/BOOTP
|
||||||
|
@ -148,140 +148,140 @@ udp_input(register struct mbuf *m, int iphlen)
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate pcb for datagram.
|
* Locate pcb for datagram.
|
||||||
*/
|
*/
|
||||||
so = slirp->udp_last_so;
|
so = slirp->udp_last_so;
|
||||||
if (so == &slirp->udb || so->so_lport != uh->uh_sport ||
|
if (so == &slirp->udb || so->so_lport != uh->uh_sport ||
|
||||||
so->so_laddr.s_addr != ip->ip_src.s_addr) {
|
so->so_laddr.s_addr != ip->ip_src.s_addr) {
|
||||||
struct socket *tmp;
|
struct socket *tmp;
|
||||||
|
|
||||||
for (tmp = slirp->udb.so_next; tmp != &slirp->udb;
|
for (tmp = slirp->udb.so_next; tmp != &slirp->udb;
|
||||||
tmp = tmp->so_next) {
|
tmp = tmp->so_next) {
|
||||||
if (tmp->so_lport == uh->uh_sport &&
|
if (tmp->so_lport == uh->uh_sport &&
|
||||||
tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
|
tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
|
||||||
so = tmp;
|
so = tmp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tmp == &slirp->udb) {
|
if (tmp == &slirp->udb) {
|
||||||
so = NULL;
|
so = NULL;
|
||||||
} else {
|
} else {
|
||||||
slirp->udp_last_so = so;
|
slirp->udp_last_so = so;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (so == NULL) {
|
if (so == NULL) {
|
||||||
/*
|
/*
|
||||||
* If there's no socket for this packet,
|
* If there's no socket for this packet,
|
||||||
* create one
|
* create one
|
||||||
*/
|
*/
|
||||||
so = socreate(slirp);
|
so = socreate(slirp);
|
||||||
if (!so) {
|
if (!so) {
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if(udp_attach(so) == -1) {
|
if(udp_attach(so) == -1) {
|
||||||
DEBUG_MISC(" udp_attach errno = %d-%s\n",
|
DEBUG_MISC(" udp_attach errno = %d-%s\n",
|
||||||
errno,strerror(errno));
|
errno,strerror(errno));
|
||||||
sofree(so);
|
sofree(so);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup fields
|
* Setup fields
|
||||||
*/
|
*/
|
||||||
so->so_laddr = ip->ip_src;
|
so->so_laddr = ip->ip_src;
|
||||||
so->so_lport = uh->uh_sport;
|
so->so_lport = uh->uh_sport;
|
||||||
|
|
||||||
if ((so->so_iptos = udp_tos(so)) == 0)
|
if ((so->so_iptos = udp_tos(so)) == 0)
|
||||||
so->so_iptos = ip->ip_tos;
|
so->so_iptos = ip->ip_tos;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXXXX Here, check if it's in udpexec_list,
|
* XXXXX Here, check if it's in udpexec_list,
|
||||||
* and if it is, do the fork_exec() etc.
|
* and if it is, do the fork_exec() etc.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
so->so_faddr = ip->ip_dst; /* XXX */
|
so->so_faddr = ip->ip_dst; /* XXX */
|
||||||
so->so_fport = uh->uh_dport; /* XXX */
|
so->so_fport = uh->uh_dport; /* XXX */
|
||||||
|
|
||||||
iphlen += sizeof(struct udphdr);
|
iphlen += sizeof(struct udphdr);
|
||||||
m->m_len -= iphlen;
|
m->m_len -= iphlen;
|
||||||
m->m_data += iphlen;
|
m->m_data += iphlen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we sendto() the packet.
|
* Now we sendto() the packet.
|
||||||
*/
|
*/
|
||||||
if(sosendto(so,m) == -1) {
|
if(sosendto(so,m) == -1) {
|
||||||
m->m_len += iphlen;
|
m->m_len += iphlen;
|
||||||
m->m_data -= iphlen;
|
m->m_data -= iphlen;
|
||||||
*ip=save_ip;
|
*ip=save_ip;
|
||||||
DEBUG_MISC("udp tx errno = %d-%s\n",errno,strerror(errno));
|
DEBUG_MISC("udp tx errno = %d-%s\n",errno,strerror(errno));
|
||||||
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
|
m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
|
||||||
|
|
||||||
/* restore the orig mbuf packet */
|
/* restore the orig mbuf packet */
|
||||||
m->m_len += iphlen;
|
m->m_len += iphlen;
|
||||||
m->m_data -= iphlen;
|
m->m_data -= iphlen;
|
||||||
*ip=save_ip;
|
*ip=save_ip;
|
||||||
so->so_m=m; /* ICMP backup */
|
so->so_m=m; /* ICMP backup */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
bad:
|
bad:
|
||||||
m_free(m);
|
m_free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
int udp_output2(struct socket *so, struct mbuf *m,
|
int udp_output2(struct socket *so, struct mbuf *m,
|
||||||
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
|
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
|
||||||
int iptos)
|
int iptos)
|
||||||
{
|
{
|
||||||
register struct udpiphdr *ui;
|
register struct udpiphdr *ui;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
DEBUG_CALL("udp_output");
|
DEBUG_CALL("udp_output");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
|
DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
|
||||||
DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
|
DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust for header
|
* Adjust for header
|
||||||
*/
|
*/
|
||||||
m->m_data -= sizeof(struct udpiphdr);
|
m->m_data -= sizeof(struct udpiphdr);
|
||||||
m->m_len += sizeof(struct udpiphdr);
|
m->m_len += sizeof(struct udpiphdr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill in mbuf with extended UDP header
|
* Fill in mbuf with extended UDP header
|
||||||
* and addresses and length put into network format.
|
* and addresses and length put into network format.
|
||||||
*/
|
*/
|
||||||
ui = mtod(m, struct udpiphdr *);
|
ui = mtod(m, struct udpiphdr *);
|
||||||
memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
|
memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
|
||||||
ui->ui_x1 = 0;
|
ui->ui_x1 = 0;
|
||||||
ui->ui_pr = IPPROTO_UDP;
|
ui->ui_pr = IPPROTO_UDP;
|
||||||
ui->ui_len = htons(m->m_len - sizeof(struct ip));
|
ui->ui_len = htons(m->m_len - sizeof(struct ip));
|
||||||
/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
|
/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
|
||||||
ui->ui_src = saddr->sin_addr;
|
ui->ui_src = saddr->sin_addr;
|
||||||
ui->ui_dst = daddr->sin_addr;
|
ui->ui_dst = daddr->sin_addr;
|
||||||
ui->ui_sport = saddr->sin_port;
|
ui->ui_sport = saddr->sin_port;
|
||||||
ui->ui_dport = daddr->sin_port;
|
ui->ui_dport = daddr->sin_port;
|
||||||
ui->ui_ulen = ui->ui_len;
|
ui->ui_ulen = ui->ui_len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stuff checksum and output datagram.
|
* Stuff checksum and output datagram.
|
||||||
*/
|
*/
|
||||||
ui->ui_sum = 0;
|
ui->ui_sum = 0;
|
||||||
if ((ui->ui_sum = cksum(m, m->m_len)) == 0)
|
if ((ui->ui_sum = cksum(m, m->m_len)) == 0)
|
||||||
ui->ui_sum = 0xffff;
|
ui->ui_sum = 0xffff;
|
||||||
((struct ip *)ui)->ip_len = m->m_len;
|
((struct ip *)ui)->ip_len = m->m_len;
|
||||||
|
|
||||||
((struct ip *)ui)->ip_ttl = IPDEFTTL;
|
((struct ip *)ui)->ip_ttl = IPDEFTTL;
|
||||||
((struct ip *)ui)->ip_tos = iptos;
|
((struct ip *)ui)->ip_tos = iptos;
|
||||||
|
|
||||||
error = ip_output(so, m);
|
error = ip_output(so, m);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
int udp_output(struct socket *so, struct mbuf *m,
|
int udp_output(struct socket *so, struct mbuf *m,
|
||||||
|
@ -322,73 +322,73 @@ udp_attach(struct socket *so)
|
||||||
void
|
void
|
||||||
udp_detach(struct socket *so)
|
udp_detach(struct socket *so)
|
||||||
{
|
{
|
||||||
closesocket(so->s);
|
closesocket(so->s);
|
||||||
sofree(so);
|
sofree(so);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct tos_t udptos[] = {
|
static const struct tos_t udptos[] = {
|
||||||
{0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
|
{0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
udp_tos(struct socket *so)
|
udp_tos(struct socket *so)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while(udptos[i].tos) {
|
while(udptos[i].tos) {
|
||||||
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
|
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
|
||||||
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
|
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
|
||||||
so->so_emu = udptos[i].emu;
|
so->so_emu = udptos[i].emu;
|
||||||
return udptos[i].tos;
|
return udptos[i].tos;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct socket *
|
struct socket *
|
||||||
udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
|
udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
|
||||||
u_int lport, int flags)
|
u_int lport, int flags)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
so = socreate(slirp);
|
so = socreate(slirp);
|
||||||
if (!so) {
|
if (!so) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
|
so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
|
||||||
so->so_expire = curtime + SO_EXPIRE;
|
so->so_expire = curtime + SO_EXPIRE;
|
||||||
insque(so, &slirp->udb);
|
insque(so, &slirp->udb);
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_addr.s_addr = haddr;
|
addr.sin_addr.s_addr = haddr;
|
||||||
addr.sin_port = hport;
|
addr.sin_port = hport;
|
||||||
|
|
||||||
if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
|
if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
|
||||||
udp_detach(so);
|
udp_detach(so);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
socket_set_fast_reuse(so->s);
|
socket_set_fast_reuse(so->s);
|
||||||
|
|
||||||
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
|
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
|
||||||
so->so_fport = addr.sin_port;
|
so->so_fport = addr.sin_port;
|
||||||
if (addr.sin_addr.s_addr == 0 ||
|
if (addr.sin_addr.s_addr == 0 ||
|
||||||
addr.sin_addr.s_addr == loopback_addr.s_addr) {
|
addr.sin_addr.s_addr == loopback_addr.s_addr) {
|
||||||
so->so_faddr = slirp->vhost_addr;
|
so->so_faddr = slirp->vhost_addr;
|
||||||
} else {
|
} else {
|
||||||
so->so_faddr = addr.sin_addr;
|
so->so_faddr = addr.sin_addr;
|
||||||
}
|
}
|
||||||
so->so_lport = lport;
|
so->so_lport = lport;
|
||||||
so->so_laddr.s_addr = laddr;
|
so->so_laddr.s_addr = laddr;
|
||||||
if (flags != SS_FACCEPTONCE)
|
if (flags != SS_FACCEPTONCE)
|
||||||
so->so_expire = 0;
|
so->so_expire = 0;
|
||||||
|
|
||||||
so->so_state &= SS_PERSISTENT_MASK;
|
so->so_state &= SS_PERSISTENT_MASK;
|
||||||
so->so_state |= SS_ISFCONNECTED | flags;
|
so->so_state |= SS_ISFCONNECTED | flags;
|
||||||
|
|
||||||
return so;
|
return so;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1982, 1986, 1993
|
* Copyright (c) 1982, 1986, 1993
|
||||||
* The Regents of the University of California. All rights reserved.
|
* The Regents of the University of California. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* @(#)udp.h 8.1 (Berkeley) 6/10/93
|
* @(#)udp.h 8.1 (Berkeley) 6/10/93
|
||||||
* udp.h,v 1.3 1994/08/21 05:27:41 paul Exp
|
* udp.h,v 1.3 1994/08/21 05:27:41 paul Exp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ struct udphdr {
|
||||||
* UDP kernel structures and variables.
|
* UDP kernel structures and variables.
|
||||||
*/
|
*/
|
||||||
struct udpiphdr {
|
struct udpiphdr {
|
||||||
struct ipovly ui_i; /* overlaid ip structure */
|
struct ipovly ui_i; /* overlaid ip structure */
|
||||||
struct udphdr ui_u; /* udp header */
|
struct udphdr ui_u; /* udp header */
|
||||||
};
|
};
|
||||||
#define ui_mbuf ui_i.ih_mbuf.mptr
|
#define ui_mbuf ui_i.ih_mbuf.mptr
|
||||||
#define ui_x1 ui_i.ih_x1
|
#define ui_x1 ui_i.ih_x1
|
||||||
|
|
|
@ -19,10 +19,10 @@ typedef struct GPollFD {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
SOCKET fd;
|
SOCKET fd;
|
||||||
#else
|
#else
|
||||||
gint fd;
|
gint fd;
|
||||||
#endif
|
#endif
|
||||||
gushort events;
|
gushort events;
|
||||||
gushort revents;
|
gushort revents;
|
||||||
} GPollFD;
|
} GPollFD;
|
||||||
typedef struct _GArray {
|
typedef struct _GArray {
|
||||||
gchar *data;
|
gchar *data;
|
||||||
|
|
Loading…
Add table
Reference in a new issue