slirp: change tabs to spaces

This commit is contained in:
Mark Pizzolato 2018-05-08 13:04:39 -07:00
parent 6ccbfc7381
commit 0c0a9958b1
30 changed files with 4411 additions and 4411 deletions

View file

@ -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;

View file

@ -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);
} }

View file

@ -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
} }

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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);
} }
} }

View file

@ -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 *);

File diff suppressed because it is too large Load diff

View file

@ -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 *);

View file

@ -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
/* /*

File diff suppressed because it is too large Load diff

View file

@ -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++;
} }

File diff suppressed because it is too large Load diff

View file

@ -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);
} }

View file

@ -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[];

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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;
} }

View file

@ -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

View file

@ -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;