Revision f0cbd3ec

b/slirp/bootp.c
1
/*
2
 * QEMU BOOTP/DHCP server
3
 * 
4
 * Copyright (c) 2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <slirp.h>
25

  
26
/* XXX: only DHCP is supported */
27

  
28
#define NB_ADDR 16
29

  
30
#define START_ADDR 15
31

  
32
#define LEASE_TIME (24 * 3600)
33

  
34
typedef struct {
35
    uint8_t allocated;
36
} BOOTPClient;
37

  
38
BOOTPClient bootp_clients[NB_ADDR];
39

  
40
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
41

  
42
#ifdef DEBUG
43
#define dprintf(fmt, args...) \
44
if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); }
45
#else
46
#define dprintf(fmt, args...)
47
#endif
48

  
49
static BOOTPClient *get_new_addr(struct in_addr *paddr)
50
{
51
    BOOTPClient *bc;
52
    int i;
53

  
54
    for(i = 0; i < NB_ADDR; i++) {
55
        if (!bootp_clients[i].allocated)
56
            goto found;
57
    }
58
    return NULL;
59
 found:
60
    bc = &bootp_clients[i];
61
    bc->allocated = 1;
62
    paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
63
    return bc;
64
}
65

  
66
static void dhcp_decode(const uint8_t *buf, int size,
67
                        int *pmsg_type)
68
{
69
    const uint8_t *p, *p_end;
70
    int len, tag;
71

  
72
    *pmsg_type = 0;    
73

  
74
    p = buf;
75
    p_end = buf + size;
76
    if (size < 5)
77
        return;
78
    if (memcmp(p, rfc1533_cookie, 4) != 0)
79
        return;
80
    p += 4;
81
    while (p < p_end) {
82
        tag = p[0];
83
        if (tag == RFC1533_PAD) {
84
            p++; 
85
        } else if (tag == RFC1533_END) {
86
            break;
87
        } else {
88
            p++;
89
            if (p >= p_end)
90
                break;
91
            len = *p++;
92
            dprintf("dhcp: tag=0x%02x len=%d\n", tag, len);
93

  
94
            switch(tag) {
95
            case RFC2132_MSG_TYPE:
96
                if (len >= 1)
97
                    *pmsg_type = p[0];
98
                break;
99
            default:
100
                break;
101
            }
102
            p += len;
103
        }
104
    }
105
}
106

  
107
static void bootp_reply(struct bootp_t *bp)
108
{
109
    BOOTPClient *bc;
110
    struct mbuf *m;
111
    struct bootp_t *rbp;
112
    struct sockaddr_in saddr, daddr;
113
    struct in_addr dns_addr;
114
    int dhcp_msg_type, val;
115
    uint8_t *q;
116

  
117
    /* extract exact DHCP msg type */
118
    dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
119
    dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
120
    
121
    if (dhcp_msg_type != DHCPDISCOVER && 
122
        dhcp_msg_type != DHCPREQUEST)
123
        return;
124
    /* XXX: this is a hack to get the client mac address */
125
    memcpy(client_ethaddr, bp->bp_hwaddr, 6);
126
    
127
    if ((m = m_get()) == NULL)
128
        return;
129
    m->m_data += if_maxlinkhdr;
130
    rbp = (struct bootp_t *)m->m_data;
131
    m->m_data += sizeof(struct udpiphdr);
132
    memset(rbp, 0, sizeof(struct bootp_t));
133

  
134
    bc = get_new_addr(&daddr.sin_addr);
135
    if (!bc) {
136
        dprintf("no address left\n");
137
        return;
138
    }
139
    dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
140

  
141
    saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
142
    saddr.sin_port = htons(BOOTP_SERVER);
143

  
144
    daddr.sin_port = htons(BOOTP_CLIENT);
145

  
146
    rbp->bp_op = BOOTP_REPLY;
147
    rbp->bp_xid = bp->bp_xid;
148
    rbp->bp_htype = 1;
149
    rbp->bp_hlen = 6;
150
    memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);
151

  
152
    rbp->bp_yiaddr = daddr.sin_addr; /* IP address */
153

  
154
    q = rbp->bp_vend;
155
    memcpy(q, rfc1533_cookie, 4);
156
    q += 4;
157

  
158
    if (dhcp_msg_type == DHCPDISCOVER) {
159
        *q++ = RFC2132_MSG_TYPE;
160
        *q++ = 1;
161
        *q++ = DHCPOFFER;
162
    } else if (dhcp_msg_type == DHCPREQUEST) {
163
        *q++ = RFC2132_MSG_TYPE;
164
        *q++ = 1;
165
        *q++ = DHCPACK;
166
    }
167
        
168
    if (dhcp_msg_type == DHCPDISCOVER ||
169
        dhcp_msg_type == DHCPREQUEST) {
170
        *q++ = RFC2132_SRV_ID;
171
        *q++ = 4;
172
        memcpy(q, &saddr.sin_addr, 4);
173
        q += 4;
174

  
175
        *q++ = RFC1533_NETMASK;
176
        *q++ = 4;
177
        *q++ = 0xff;
178
        *q++ = 0xff;
179
        *q++ = 0xff;
180
        *q++ = 0x00;
181
        
182
        *q++ = RFC1533_GATEWAY;
183
        *q++ = 4;
184
        memcpy(q, &saddr.sin_addr, 4);
185
        q += 4;
186
        
187
        *q++ = RFC1533_DNS;
188
        *q++ = 4;
189
        dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
190
        memcpy(q, &dns_addr, 4);
191
        q += 4;
192

  
193
        *q++ = RFC2132_LEASE_TIME;
194
        *q++ = 4;
195
        val = htonl(LEASE_TIME);
196
        memcpy(q, &val, 4);
197
        q += 4;
198
    }
199
    *q++ = RFC1533_END;
200
    
201
    m->m_len = sizeof(struct bootp_t);
202
    udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
203
}
204

  
205
void bootp_input(struct mbuf *m)
206
{
207
    struct bootp_t *bp = (struct bootp_t *)m->m_data;
208

  
209
    if (bp->bp_op == BOOTP_REQUEST) {
210
        bootp_reply(bp);
211
    }
212
}
b/slirp/bootp.h
1
/* bootp/dhcp defines */
2

  
3
#define BOOTP_SERVER	67
4
#define BOOTP_CLIENT	68
5

  
6
#define BOOTP_REQUEST	1
7
#define BOOTP_REPLY	2
8

  
9
#define RFC1533_COOKIE		99, 130, 83, 99
10
#define RFC1533_PAD		0
11
#define RFC1533_NETMASK		1
12
#define RFC1533_TIMEOFFSET	2
13
#define RFC1533_GATEWAY		3
14
#define RFC1533_TIMESERVER	4
15
#define RFC1533_IEN116NS	5
16
#define RFC1533_DNS		6
17
#define RFC1533_LOGSERVER	7
18
#define RFC1533_COOKIESERVER	8
19
#define RFC1533_LPRSERVER	9
20
#define RFC1533_IMPRESSSERVER	10
21
#define RFC1533_RESOURCESERVER	11
22
#define RFC1533_HOSTNAME	12
23
#define RFC1533_BOOTFILESIZE	13
24
#define RFC1533_MERITDUMPFILE	14
25
#define RFC1533_DOMAINNAME	15
26
#define RFC1533_SWAPSERVER	16
27
#define RFC1533_ROOTPATH	17
28
#define RFC1533_EXTENSIONPATH	18
29
#define RFC1533_IPFORWARDING	19
30
#define RFC1533_IPSOURCEROUTING	20
31
#define RFC1533_IPPOLICYFILTER	21
32
#define RFC1533_IPMAXREASSEMBLY	22
33
#define RFC1533_IPTTL		23
34
#define RFC1533_IPMTU		24
35
#define RFC1533_IPMTUPLATEAU	25
36
#define RFC1533_INTMTU		26
37
#define RFC1533_INTLOCALSUBNETS	27
38
#define RFC1533_INTBROADCAST	28
39
#define RFC1533_INTICMPDISCOVER	29
40
#define RFC1533_INTICMPRESPOND	30
41
#define RFC1533_INTROUTEDISCOVER 31
42
#define RFC1533_INTROUTESOLICIT	32
43
#define RFC1533_INTSTATICROUTES	33
44
#define RFC1533_LLTRAILERENCAP	34
45
#define RFC1533_LLARPCACHETMO	35
46
#define RFC1533_LLETHERNETENCAP	36
47
#define RFC1533_TCPTTL		37
48
#define RFC1533_TCPKEEPALIVETMO	38
49
#define RFC1533_TCPKEEPALIVEGB	39
50
#define RFC1533_NISDOMAIN	40
51
#define RFC1533_NISSERVER	41
52
#define RFC1533_NTPSERVER	42
53
#define RFC1533_VENDOR		43
54
#define RFC1533_NBNS		44
55
#define RFC1533_NBDD		45
56
#define RFC1533_NBNT		46
57
#define RFC1533_NBSCOPE		47
58
#define RFC1533_XFS		48
59
#define RFC1533_XDM		49
60

  
61
#define RFC2132_REQ_ADDR	50
62
#define RFC2132_LEASE_TIME      51
63
#define RFC2132_MSG_TYPE	53
64
#define RFC2132_SRV_ID		54
65
#define RFC2132_PARAM_LIST	55
66
#define RFC2132_MAX_SIZE	57
67
#define RFC2132_RENEWAL_TIME    58
68
#define RFC2132_REBIND_TIME     59
69

  
70
#define DHCPDISCOVER		1
71
#define DHCPOFFER		2
72
#define DHCPREQUEST		3
73
#define DHCPACK			5
74

  
75
#define RFC1533_VENDOR_MAJOR	0
76
#define RFC1533_VENDOR_MINOR	0
77

  
78
#define RFC1533_VENDOR_MAGIC	128
79
#define RFC1533_VENDOR_ADDPARM	129
80
#define	RFC1533_VENDOR_ETHDEV	130
81
#define RFC1533_VENDOR_HOWTO    132
82
#define RFC1533_VENDOR_MNUOPTS	160
83
#define RFC1533_VENDOR_SELECTION 176
84
#define RFC1533_VENDOR_MOTD	184
85
#define RFC1533_VENDOR_NUMOFMOTD 8
86
#define RFC1533_VENDOR_IMG	192
87
#define RFC1533_VENDOR_NUMOFIMG	16
88

  
89
#define RFC1533_END		255
90
#define BOOTP_VENDOR_LEN	64
91
#define DHCP_OPT_LEN		312
92

  
93
struct bootp_t {
94
    struct ip ip;
95
    struct udphdr udp;
96
    uint8_t bp_op;
97
    uint8_t bp_htype;
98
    uint8_t bp_hlen;
99
    uint8_t bp_hops;
100
    unsigned long bp_xid;
101
    unsigned short bp_secs;
102
    unsigned short unused;
103
    struct in_addr bp_ciaddr;
104
    struct in_addr bp_yiaddr;
105
    struct in_addr bp_siaddr;
106
    struct in_addr bp_giaddr;
107
    uint8_t bp_hwaddr[16];
108
    uint8_t bp_sname[64];
109
    uint8_t bp_file[128];
110
    uint8_t bp_vend[DHCP_OPT_LEN];
111
};
112

  
113
void bootp_input(struct mbuf *m);
b/slirp/cksum.c
1
/*
2
 * Copyright (c) 1988, 1992, 1993
3
 *	The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *	This product includes software developed by the University of
16
 *	California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 *
33
 *	@(#)in_cksum.c	8.1 (Berkeley) 6/10/93
34
 * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp
35
 */
36

  
37
#include <slirp.h>
38

  
39
/*
40
 * Checksum routine for Internet Protocol family headers (Portable Version).
41
 *
42
 * This routine is very heavily used in the network
43
 * code and should be modified for each CPU to be as fast as possible.
44
 * 
45
 * XXX Since we will never span more than 1 mbuf, we can optimise this
46
 */
47

  
48
#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
49
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
50

  
51
int cksum(struct mbuf *m, int len)
52
{
53
	register u_int16_t *w;
54
	register int sum = 0;
55
	register int mlen = 0;
56
	int byte_swapped = 0;
57

  
58
	union {
59
		u_int8_t	c[2];
60
		u_int16_t	s;
61
	} s_util;
62
	union {
63
		u_int16_t s[2];
64
		u_int32_t l;
65
	} l_util;
66
	
67
	if (m->m_len == 0)
68
	   goto cont;
69
	w = mtod(m, u_int16_t *);
70
	
71
	mlen = m->m_len;
72
	
73
	if (len < mlen)
74
	   mlen = len;
75
	len -= mlen;
76
	/*
77
	 * Force to even boundary.
78
	 */
79
	if ((1 & (long) w) && (mlen > 0)) {
80
		REDUCE;
81
		sum <<= 8;
82
		s_util.c[0] = *(u_int8_t *)w;
83
		w = (u_int16_t *)((int8_t *)w + 1);
84
		mlen--;
85
		byte_swapped = 1;
86
	}
87
	/*
88
	 * Unroll the loop to make overhead from
89
	 * branches &c small.
90
	 */
91
	while ((mlen -= 32) >= 0) {
92
		sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
93
		sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
94
		sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
95
		sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
96
		w += 16;
97
	}
98
	mlen += 32;
99
	while ((mlen -= 8) >= 0) {
100
		sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
101
		w += 4;
102
	}
103
	mlen += 8;
104
	if (mlen == 0 && byte_swapped == 0)
105
	   goto cont;
106
	REDUCE;
107
	while ((mlen -= 2) >= 0) {
108
		sum += *w++;
109
	}
110
	
111
	if (byte_swapped) {
112
		REDUCE;
113
		sum <<= 8;
114
		byte_swapped = 0;
115
		if (mlen == -1) {
116
			s_util.c[1] = *(u_int8_t *)w;
117
			sum += s_util.s;
118
			mlen = 0;
119
		} else
120
		   
121
		   mlen = -1;
122
	} else if (mlen == -1)
123
	   s_util.c[0] = *(u_int8_t *)w;
124
	
125
cont:
126
#ifdef DEBUG
127
	if (len) {
128
		DEBUG_ERROR((dfd, "cksum: out of data\n"));
129
		DEBUG_ERROR((dfd, " len = %d\n", len));
130
	}
131
#endif
132
	if (mlen == -1) {
133
		/* The last mbuf has odd # of bytes. Follow the
134
		 standard (the odd byte may be shifted left by 8 bits
135
			   or not as determined by endian-ness of the machine) */
136
		s_util.c[1] = 0;
137
		sum += s_util.s;
138
	}
139
	REDUCE;
140
	return (~sum & 0xffff);
141
}
b/slirp/ctl.h
1
#define CTL_CMD		0
2
#define CTL_EXEC	1
3
#define CTL_ALIAS	2
4
#define CTL_DNS		3
5

  
6
#define CTL_SPECIAL	"10.0.2.0"
7
#define CTL_LOCAL	"10.0.2.15"
b/slirp/debug.c
1
/*
2
 * Copyright (c) 1995 Danny Gasparovski.
3
 * Portions copyright (c) 2000 Kelly Price.
4
 * 
5
 * Please read the file COPYRIGHT for the 
6
 * terms and conditions of the copyright.
7
 */
8

  
9
#include <slirp.h>
10

  
11
FILE *dfd = NULL;
12
#ifdef DEBUG
13
int dostats = 1;
14
#else
15
int dostats = 0;
16
#endif
17
int slirp_debug = 0;
18

  
19
extern char *strerror _P((int));
20

  
21
/* Carry over one item from main.c so that the tty's restored. 
22
 * Only done when the tty being used is /dev/tty --RedWolf */
23
extern struct termios slirp_tty_settings;
24
extern int slirp_tty_restore;
25

  
26

  
27
void
28
debug_init(file, dbg)
29
	char *file;
30
	int dbg;
31
{
32
	/* Close the old debugging file */
33
	if (dfd)
34
	   fclose(dfd);
35
	
36
	dfd = fopen(file,"w");
37
	if (dfd != NULL) {
38
#if 0
39
		fprintf(dfd,"Slirp %s - Debugging Started.\n", SLIRP_VERSION);
40
#endif
41
		fprintf(dfd,"Debugging Started level %i.\r\n",dbg);
42
		fflush(dfd);
43
		slirp_debug = dbg;
44
	} else {
45
		lprint("Error: Debugging file \"%s\" could not be opened: %s\r\n",
46
			file, strerror(errno));
47
	}
48
}
49

  
50
/*
51
 * Dump a packet in the same format as tcpdump -x
52
 */
53
#ifdef DEBUG
54
void
55
dump_packet(dat, n)
56
	void *dat;
57
	int n;
58
{
59
	u_char *pptr = (u_char *)dat;
60
	int j,k;
61
	
62
	n /= 16;
63
	n++;
64
	DEBUG_MISC((dfd, "PACKET DUMPED: \n"));
65
	for(j = 0; j < n; j++) {
66
		for(k = 0; k < 6; k++)
67
			DEBUG_MISC((dfd, "%02x ", *pptr++));
68
		DEBUG_MISC((dfd, "\n"));
69
		fflush(dfd);
70
	}
71
}
72
#endif
73

  
74
#if 0
75
/*
76
 * Statistic routines
77
 * 
78
 * These will print statistics to the screen, the debug file (dfd), or
79
 * a buffer, depending on "type", so that the stats can be sent over
80
 * the link as well.
81
 */
82

  
83
void
84
ttystats(ttyp)
85
	struct ttys *ttyp;
86
{
87
	struct slirp_ifstats *is = &ttyp->ifstats;
88
	char buff[512];
89
	
90
	lprint(" \r\n");
91
	
92
	if (if_comp & IF_COMPRESS)
93
	   strcpy(buff, "on");
94
	else if (if_comp & IF_NOCOMPRESS)
95
	   strcpy(buff, "off");
96
	else
97
	   strcpy(buff, "off (for now)");
98
	lprint("Unit %d:\r\n", ttyp->unit);
99
	lprint("  using %s encapsulation (VJ compression is %s)\r\n", (
100
#ifdef USE_PPP
101
	       ttyp->proto==PROTO_PPP?"PPP":
102
#endif
103
	       "SLIP"), buff);
104
	lprint("  %d baudrate\r\n", ttyp->baud);
105
	lprint("  interface is %s\r\n", ttyp->up?"up":"down");
106
	lprint("  using fd %d, guardian pid is %d\r\n", ttyp->fd, ttyp->pid);
107
#ifndef FULL_BOLT
108
	lprint("  towrite is %d bytes\r\n", ttyp->towrite);
109
#endif
110
	if (ttyp->zeros)
111
	   lprint("  %d zeros have been typed\r\n", ttyp->zeros);
112
	else if (ttyp->ones)
113
	   lprint("  %d ones have been typed\r\n", ttyp->ones);
114
	lprint("Interface stats:\r\n");
115
	lprint("  %6d output packets sent (%d bytes)\r\n", is->out_pkts, is->out_bytes);
116
	lprint("  %6d output packets dropped (%d bytes)\r\n", is->out_errpkts, is->out_errbytes);
117
	lprint("  %6d input packets received (%d bytes)\r\n", is->in_pkts, is->in_bytes);
118
	lprint("  %6d input packets dropped (%d bytes)\r\n", is->in_errpkts, is->in_errbytes);
119
	lprint("  %6d bad input packets\r\n", is->in_mbad);
120
}
121

  
122
void
123
allttystats()
124
{
125
	struct ttys *ttyp;
126
	
127
	for (ttyp = ttys; ttyp; ttyp = ttyp->next)
128
	   ttystats(ttyp);
129
}
130
#endif
131

  
132
void
133
ipstats()
134
{
135
	lprint(" \r\n");	
136

  
137
	lprint("IP stats:\r\n");
138
	lprint("  %6d total packets received (%d were unaligned)\r\n",
139
			ipstat.ips_total, ipstat.ips_unaligned);
140
	lprint("  %6d with incorrect version\r\n", ipstat.ips_badvers);
141
	lprint("  %6d with bad header checksum\r\n", ipstat.ips_badsum);
142
	lprint("  %6d with length too short (len < sizeof(iphdr))\r\n", ipstat.ips_tooshort);
143
	lprint("  %6d with length too small (len < ip->len)\r\n", ipstat.ips_toosmall);
144
	lprint("  %6d with bad header length\r\n", ipstat.ips_badhlen);
145
	lprint("  %6d with bad packet length\r\n", ipstat.ips_badlen);
146
	lprint("  %6d fragments received\r\n", ipstat.ips_fragments);
147
	lprint("  %6d fragments dropped\r\n", ipstat.ips_fragdropped);
148
	lprint("  %6d fragments timed out\r\n", ipstat.ips_fragtimeout);
149
	lprint("  %6d packets reassembled ok\r\n", ipstat.ips_reassembled);
150
	lprint("  %6d outgoing packets fragmented\r\n", ipstat.ips_fragmented);
151
	lprint("  %6d total outgoing fragments\r\n", ipstat.ips_ofragments);
152
	lprint("  %6d with bad protocol field\r\n", ipstat.ips_noproto);
153
	lprint("  %6d total packets delivered\r\n", ipstat.ips_delivered);
154
}
155

  
156
#if 0
157
void
158
vjstats()
159
{
160
	lprint(" \r\n");
161
	
162
	lprint("VJ compression stats:\r\n");
163
	
164
	lprint("  %6d outbound packets (%d compressed)\r\n",
165
	       comp_s.sls_packets, comp_s.sls_compressed);
166
	lprint("  %6d searches for connection stats (%d misses)\r\n",
167
	       comp_s.sls_searches, comp_s.sls_misses);
168
	lprint("  %6d inbound uncompressed packets\r\n", comp_s.sls_uncompressedin);
169
	lprint("  %6d inbound compressed packets\r\n", comp_s.sls_compressedin);
170
	lprint("  %6d inbound unknown type packets\r\n", comp_s.sls_errorin);
171
	lprint("  %6d inbound packets tossed due to error\r\n", comp_s.sls_tossed);
172
}
173
#endif
174

  
175
void
176
tcpstats()
177
{
178
	lprint(" \r\n");
179

  
180
	lprint("TCP stats:\r\n");
181
	
182
	lprint("  %6d packets sent\r\n", tcpstat.tcps_sndtotal);
183
	lprint("          %6d data packets (%d bytes)\r\n",
184
			tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
185
	lprint("          %6d data packets retransmitted (%d bytes)\r\n",
186
			tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte);
187
	lprint("          %6d ack-only packets (%d delayed)\r\n",
188
			tcpstat.tcps_sndacks, tcpstat.tcps_delack);
189
	lprint("          %6d URG only packets\r\n", tcpstat.tcps_sndurg);
190
	lprint("          %6d window probe packets\r\n", tcpstat.tcps_sndprobe);
191
	lprint("          %6d window update packets\r\n", tcpstat.tcps_sndwinup);
192
	lprint("          %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl);
193
	lprint("          %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin);
194
	
195
	lprint("  %6d packets received\r\n", tcpstat.tcps_rcvtotal);       
196
	lprint("          %6d acks (for %d bytes)\r\n",
197
			tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
198
	lprint("          %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack);
199
	lprint("          %6d acks for unsent data\r\n", tcpstat.tcps_rcvacktoomuch);
200
	lprint("          %6d packets received in sequence (%d bytes)\r\n",
201
			tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
202
        lprint("          %6d completely duplicate packets (%d bytes)\r\n",
203
			tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
204
	
205
	lprint("          %6d packets with some duplicate data (%d bytes duped)\r\n",
206
			tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
207
	lprint("          %6d out-of-order packets (%d bytes)\r\n",
208
			tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte);
209
	lprint("          %6d packets of data after window (%d bytes)\r\n",
210
			tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin);
211
	lprint("          %6d window probes\r\n", tcpstat.tcps_rcvwinprobe);
212
	lprint("          %6d window update packets\r\n", tcpstat.tcps_rcvwinupd);
213
	lprint("          %6d packets received after close\r\n", tcpstat.tcps_rcvafterclose);
214
	lprint("          %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum);
215
	lprint("          %6d discarded for bad header offset fields\r\n",
216
			tcpstat.tcps_rcvbadoff);
217
	
218
	lprint("  %6d connection requests\r\n", tcpstat.tcps_connattempt);
219
	lprint("  %6d connection accepts\r\n", tcpstat.tcps_accepts);
220
	lprint("  %6d connections established (including accepts)\r\n", tcpstat.tcps_connects);
221
	lprint("  %6d connections closed (including %d drop)\r\n",
222
			tcpstat.tcps_closed, tcpstat.tcps_drops);
223
	lprint("  %6d embryonic connections dropped\r\n", tcpstat.tcps_conndrops);
224
	lprint("  %6d segments we tried to get rtt (%d succeeded)\r\n",
225
			tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated);
226
	lprint("  %6d retransmit timeouts\r\n", tcpstat.tcps_rexmttimeo);
227
	lprint("          %6d connections dropped by rxmt timeout\r\n",
228
			tcpstat.tcps_timeoutdrop);
229
	lprint("  %6d persist timeouts\r\n", tcpstat.tcps_persisttimeo);
230
	lprint("  %6d keepalive timeouts\r\n", tcpstat.tcps_keeptimeo);
231
	lprint("          %6d keepalive probes sent\r\n", tcpstat.tcps_keepprobe);
232
	lprint("          %6d connections dropped by keepalive\r\n", tcpstat.tcps_keepdrops);
233
	lprint("  %6d correct ACK header predictions\r\n", tcpstat.tcps_predack);
234
	lprint("  %6d correct data packet header predictions\n", tcpstat.tcps_preddat);
235
	lprint("  %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
236
	
237
	
238
/*	lprint("    Packets received too short:		%d\r\n", tcpstat.tcps_rcvshort); */
239
/*	lprint("    Segments dropped due to PAWS:	%d\r\n", tcpstat.tcps_pawsdrop); */
240

  
241
}
242

  
243
void
244
udpstats()
245
{
246
        lprint(" \r\n");
247

  
248
	lprint("UDP stats:\r\n");
249
	lprint("  %6d datagrams received\r\n", udpstat.udps_ipackets);
250
	lprint("  %6d with packets shorter than header\r\n", udpstat.udps_hdrops);
251
	lprint("  %6d with bad checksums\r\n", udpstat.udps_badsum);
252
	lprint("  %6d with data length larger than packet\r\n", udpstat.udps_badlen);
253
	lprint("  %6d UDP socket cache misses\r\n", udpstat.udpps_pcbcachemiss);
254
	lprint("  %6d datagrams sent\r\n", udpstat.udps_opackets);
255
}
256

  
257
void
258
icmpstats()
259
{
260
	lprint(" \r\n");
261
	lprint("ICMP stats:\r\n");
262
	lprint("  %6d ICMP packets received\r\n", icmpstat.icps_received);
263
	lprint("  %6d were too short\r\n", icmpstat.icps_tooshort);
264
	lprint("  %6d with bad checksums\r\n", icmpstat.icps_checksum);
265
	lprint("  %6d with type not supported\r\n", icmpstat.icps_notsupp);
266
	lprint("  %6d with bad type feilds\r\n", icmpstat.icps_badtype);
267
	lprint("  %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
268
}
269

  
270
void
271
mbufstats()
272
{
273
	struct mbuf *m;
274
	int i;
275
	
276
        lprint(" \r\n");
277
	
278
	lprint("Mbuf stats:\r\n");
279

  
280
	lprint("  %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
281
	
282
	i = 0;
283
	for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
284
		i++;
285
	lprint("  %6d mbufs on free list\r\n",  i);
286
	
287
	i = 0;
288
	for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
289
		i++;
290
	lprint("  %6d mbufs on used list\r\n",  i);
291
        lprint("  %6d mbufs queued as packets\r\n\r\n", if_queued);
292
}
293

  
294
void
295
sockstats()
296
{
297
	char buff[256];
298
	int n;
299
	struct socket *so;
300

  
301
        lprint(" \r\n");
302
	
303
	lprint(
304
	   "Proto[state]     Sock     Local Address, Port  Remote Address, Port RecvQ SendQ\r\n");
305
			
306
	for (so = tcb.so_next; so != &tcb; so = so->so_next) {
307
		
308
		n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
309
		while (n < 17)
310
		   buff[n++] = ' ';
311
		buff[17] = 0;
312
		lprint("%s %3d   %15s %5d ",
313
				buff, so->s,
314
				inet_ntoa(so->so_laddr), ntohs(so->so_lport));
315
		lprint("%15s %5d %5d %5d\r\n",
316
				inet_ntoa(so->so_faddr), ntohs(so->so_fport),
317
				so->so_rcv.sb_cc, so->so_snd.sb_cc);
318
	}
319
		   
320
	for (so = udb.so_next; so != &udb; so = so->so_next) {
321
		
322
		n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
323
		while (n < 17)
324
		   buff[n++] = ' ';
325
		buff[17] = 0;
326
		lprint("%s %3d  %15s %5d  ",
327
				buff, so->s,
328
				inet_ntoa(so->so_laddr), ntohs(so->so_lport));
329
		lprint("%15s %5d %5d %5d\r\n",
330
				inet_ntoa(so->so_faddr), ntohs(so->so_fport),
331
				so->so_rcv.sb_cc, so->so_snd.sb_cc);
332
	}
333
}
334

  
335
#if 0
336
void
337
slirp_exit(exit_status)
338
	int exit_status;
339
{
340
	struct ttys *ttyp;
341
	
342
	DEBUG_CALL("slirp_exit");
343
	DEBUG_ARG("exit_status = %d", exit_status);
344

  
345
	if (dostats) {
346
		lprint_print = (int (*) _P((void *, const char *, va_list)))vfprintf;
347
		if (!dfd)
348
		   debug_init("slirp_stats", 0xf);
349
		lprint_arg = (char **)&dfd;
350
		
351
		ipstats();
352
		tcpstats();
353
		udpstats();
354
		icmpstats();
355
		mbufstats();
356
		sockstats();
357
		allttystats();
358
		vjstats();
359
	}
360
	
361
	for (ttyp = ttys; ttyp; ttyp = ttyp->next)
362
	   tty_detached(ttyp, 1);
363
	
364
	if (slirp_forked) {
365
		/* Menendez time */
366
		if (kill(getppid(), SIGQUIT) < 0)
367
			lprint("Couldn't kill parent process %ld!\n",
368
			    (long) getppid());
369
    	}
370
	
371
	/* Restore the terminal if we gotta */
372
	if(slirp_tty_restore)
373
	  tcsetattr(0,TCSANOW, &slirp_tty_settings);  /* NOW DAMMIT! */
374
	exit(exit_status);
375
}
376
#endif
b/slirp/debug.h
1
/*
2
 * Copyright (c) 1995 Danny Gasparovski.
3
 * 
4
 * Please read the file COPYRIGHT for the 
5
 * terms and conditions of the copyright.
6
 */
7

  
8
#define PRN_STDERR	1
9
#define PRN_SPRINTF	2
10

  
11
extern FILE *dfd;
12
extern FILE *lfd;
13
extern int dostats;
14
extern int slirp_debug;
15

  
16
#define DBG_CALL 0x1
17
#define DBG_MISC 0x2
18
#define DBG_ERROR 0x4
19
#define DEBUG_DEFAULT DBG_CALL|DBG_MISC|DBG_ERROR
20

  
21
#ifdef DEBUG
22
#define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { fprintf(dfd, "%s...\n", x); fflush(dfd); }
23
#define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { fputc(' ', dfd); fprintf(dfd, x, y); fputc('\n', dfd); fflush(dfd); }
24
#define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { fprintf x ; fflush(dfd); }
25
#define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { fprintf x ; fflush(dfd); }
26
#define DEBUG_ERROR(x) if (slirp_debug & DBG_ERROR) {fprintf x ; fflush(dfd); }
27

  
28

  
29
#else
30

  
31
#define DEBUG_CALL(x)
32
#define DEBUG_ARG(x, y)
33
#define DEBUG_ARGS(x)
34
#define DEBUG_MISC(x)
35
#define DEBUG_ERROR(x)
36

  
37
#endif
38

  
39
void debug_init _P((char *, int));
40
//void ttystats _P((struct ttys *));
41
void allttystats _P((void));
42
void ipstats _P((void));
43
void vjstats _P((void));
44
void tcpstats _P((void));
45
void udpstats _P((void));
46
void icmpstats _P((void));
47
void mbufstats _P((void));
48
void sockstats _P((void));
49
void slirp_exit _P((int));
50

  
b/slirp/icmp_var.h
1
/*
2
 * Copyright (c) 1982, 1986, 1993
3
 *	The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *	This product includes software developed by the University of
16
 *	California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 *
33
 *	@(#)icmp_var.h	8.1 (Berkeley) 6/10/93
34
 * icmp_var.h,v 1.4 1995/02/16 00:27:40 wollman Exp
35
 */
36

  
37
#ifndef _NETINET_ICMP_VAR_H_
38
#define _NETINET_ICMP_VAR_H_
39

  
40
/*
41
 * Variables related to this implementation
42
 * of the internet control message protocol.
43
 */
44
struct icmpstat {
45
/* statistics related to input messages processed */
46
	u_long  icps_received;		/* #ICMP packets received */
47
	u_long	icps_tooshort;		/* packet < ICMP_MINLEN */
48
	u_long	icps_checksum;		/* bad checksum */
49
	u_long	icps_notsupp;		/* #ICMP packets not supported */
50
	u_long  icps_badtype;		/* #with bad type feild */
51
	u_long	icps_reflect;		/* number of responses */
52
};
53

  
54
/*
55
 * Names for ICMP sysctl objects
56
 */
57
#define	ICMPCTL_MASKREPL	1	/* allow replies to netmask requests */
58
#define	ICMPCTL_STATS		2	/* statistics (read-only) */
59
#define ICMPCTL_MAXID		3
60

  
61
#define ICMPCTL_NAMES { \
62
	{ 0, 0 }, \
63
	{ "maskrepl", CTLTYPE_INT }, \
64
	{ "stats", CTLTYPE_STRUCT }, \
65
}
66

  
67
extern struct icmpstat icmpstat;
68

  
69
#endif
b/slirp/if.c
1
/*
2
 * Copyright (c) 1995 Danny Gasparovski.
3
 *
4
 * Please read the file COPYRIGHT for the
5
 * terms and conditions of the copyright.
6
 */
7

  
8
#include <slirp.h>
9

  
10
int if_mtu, if_mru;
11
int if_comp;
12
int if_maxlinkhdr;
13
int     if_queued = 0;                  /* Number of packets queued so far */
14
int     if_thresh = 10;                 /* Number of packets queued before we start sending
15
					 * (to prevent allocing too many mbufs) */
16

  
17
struct  mbuf if_fastq;                  /* fast queue (for interactive data) */
18
struct  mbuf if_batchq;                 /* queue for non-interactive data */
19
struct	mbuf *next_m;			/* Pointer to next mbuf to output */
20

  
21
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
22

  
23
void
24
ifs_insque(ifm, ifmhead)
25
	struct mbuf *ifm, *ifmhead;
26
{
27
	ifm->ifs_next = ifmhead->ifs_next;
28
	ifmhead->ifs_next = ifm;
29
	ifm->ifs_prev = ifmhead;
30
	ifm->ifs_next->ifs_prev = ifm;
31
}
32

  
33
void
34
ifs_remque(ifm)
35
	struct mbuf *ifm;
36
{
37
	ifm->ifs_prev->ifs_next = ifm->ifs_next;
38
	ifm->ifs_next->ifs_prev = ifm->ifs_prev;
39
}
40

  
41
void
42
if_init()
43
{
44
#if 0
45
	/*
46
	 * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
47
	 * and 8 bytes for PPP, but need to have it on an 8byte boundary
48
	 */
49
#ifdef USE_PPP
50
	if_maxlinkhdr = 48;
51
#else
52
	if_maxlinkhdr = 40;
53
#endif
54
#else
55
        /* 14 for ethernet + 40 */
56
        if_maxlinkhdr = 14 + 40;
57
#endif
58
	if_mtu = 1500;
59
	if_mru = 1500;
60
	if_comp = IF_AUTOCOMP;
61
	if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
62
	if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
63
        //	sl_compress_init(&comp_s);
64
	next_m = &if_batchq;
65
}
66

  
67
#if 0
68
/*
69
 * This shouldn't be needed since the modem is blocking and
70
 * we don't expect any signals, but what the hell..
71
 */
72
inline int
73
writen(fd, bptr, n)
74
	int fd;
75
	char *bptr;
76
	int n;
77
{
78
	int ret;
79
	int total;
80
	
81
	/* This should succeed most of the time */
82
	ret = write(fd, bptr, n);
83
	if (ret == n || ret <= 0)
84
	   return ret;
85
	
86
	/* Didn't write everything, go into the loop */
87
	total = ret;
88
	while (n > total) {
89
		ret = write(fd, bptr+total, n-total);
90
		if (ret <= 0)
91
		   return ret;
92
		total += ret;
93
	}
94
	return total;
95
}
96

  
97
/*
98
 * if_input - read() the tty, do "top level" processing (ie: check for any escapes),
99
 * and pass onto (*ttyp->if_input)
100
 * 
101
 * XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
102
 */
103
#define INBUFF_SIZE 2048 /* XXX */
104
void
105
if_input(ttyp)
106
	struct ttys *ttyp;
107
{
108
	u_char if_inbuff[INBUFF_SIZE];
109
	int if_n;
110
	
111
	DEBUG_CALL("if_input");
112
	DEBUG_ARG("ttyp = %lx", (long)ttyp);
113
	
114
	if_n = read(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE);
115
	
116
	DEBUG_MISC((dfd, " read %d bytes\n", if_n));
117
	
118
	if (if_n <= 0) {
119
		if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
120
			if (ttyp->up)
121
			   link_up--;
122
			tty_detached(ttyp, 0);
123
		}
124
		return;
125
	}
126
	if (if_n == 1) {
127
		if (*if_inbuff == '0') {
128
			ttyp->ones = 0;
129
			if (++ttyp->zeros >= 5)
130
			   slirp_exit(0);
131
			return;
132
		}
133
		if (*if_inbuff == '1') {
134
			ttyp->zeros = 0;
135
			if (++ttyp->ones >= 5)
136
			   tty_detached(ttyp, 0);
137
			return;
138
		}
139
	}
140
	ttyp->ones = ttyp->zeros = 0;
141
	
142
	(*ttyp->if_input)(ttyp, if_inbuff, if_n);
143
}
144
#endif	
145
	
146
/*
147
 * if_output: Queue packet into an output queue.
148
 * There are 2 output queue's, if_fastq and if_batchq. 
149
 * Each output queue is a doubly linked list of double linked lists
150
 * of mbufs, each list belonging to one "session" (socket).  This
151
 * way, we can output packets fairly by sending one packet from each
152
 * session, instead of all the packets from one session, then all packets
153
 * from the next session, etc.  Packets on the if_fastq get absolute 
154
 * priority, but if one session hogs the link, it gets "downgraded"
155
 * to the batchq until it runs out of packets, then it'll return
156
 * to the fastq (eg. if the user does an ls -alR in a telnet session,
157
 * it'll temporarily get downgraded to the batchq)
158
 */
159
void
160
if_output(so, ifm)
161
	struct socket *so;
162
	struct mbuf *ifm;
163
{
164
	struct mbuf *ifq;
165
	int on_fastq = 1;
166
	
167
	DEBUG_CALL("if_output");
168
	DEBUG_ARG("so = %lx", (long)so);
169
	DEBUG_ARG("ifm = %lx", (long)ifm);
170
	
171
	/*
172
	 * First remove the mbuf from m_usedlist,
173
	 * since we're gonna use m_next and m_prev ourselves
174
	 * XXX Shouldn't need this, gotta change dtom() etc.
175
	 */
176
	if (ifm->m_flags & M_USEDLIST) {
177
		remque(ifm);
178
		ifm->m_flags &= ~M_USEDLIST;
179
	}
180
	
181
	/*
182
	 * See if there's already a batchq list for this session.  
183
	 * This can include an interactive session, which should go on fastq,
184
	 * but gets too greedy... hence it'll be downgraded from fastq to batchq.
185
	 * We mustn't put this packet back on the fastq (or we'll send it out of order)
186
	 * XXX add cache here?
187
	 */
188
	for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) {
189
		if (so == ifq->ifq_so) {
190
			/* A match! */
191
			ifm->ifq_so = so;
192
			ifs_insque(ifm, ifq->ifs_prev);
193
			goto diddit;
194
		}
195
	}
196
	
197
	/* No match, check which queue to put it on */
198
	if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
199
		ifq = if_fastq.ifq_prev;
200
		on_fastq = 1;
201
		/*
202
		 * Check if this packet is a part of the last
203
		 * packet's session
204
		 */
205
		if (ifq->ifq_so == so) {
206
			ifm->ifq_so = so;
207
			ifs_insque(ifm, ifq->ifs_prev);
208
			goto diddit;
209
		}
210
	} else
211
		ifq = if_batchq.ifq_prev;
212
	
213
	/* Create a new doubly linked list for this session */
214
	ifm->ifq_so = so;
215
	ifs_init(ifm);
216
	insque(ifm, ifq);
217
	
218
diddit:
219
	++if_queued;
220
	
221
	if (so) {
222
		/* Update *_queued */
223
		so->so_queued++;
224
		so->so_nqueued++;
225
		/*
226
		 * Check if the interactive session should be downgraded to
227
		 * the batchq.  A session is downgraded if it has queued 6
228
		 * packets without pausing, and at least 3 of those packets
229
		 * have been sent over the link
230
		 * (XXX These are arbitrary numbers, probably not optimal..)
231
		 */
232
		if (on_fastq && ((so->so_nqueued >= 6) && 
233
				 (so->so_nqueued - so->so_queued) >= 3)) {
234
			
235
			/* Remove from current queue... */
236
			remque(ifm->ifs_next);
237
			
238
			/* ...And insert in the new.  That'll teach ya! */
239
			insque(ifm->ifs_next, &if_batchq);
240
		}
241
	}
242

  
243
#ifndef FULL_BOLT
244
	/*
245
	 * This prevents us from malloc()ing too many mbufs
246
	 */
247
	if (link_up) {
248
		/* if_start will check towrite */
249
		if_start();
250
	}
251
#endif
252
}
253

  
254
/*
255
 * Send a packet
256
 * We choose a packet based on it's position in the output queues;
257
 * If there are packets on the fastq, they are sent FIFO, before
258
 * everything else.  Otherwise we choose the first packet from the
259
 * batchq and send it.  the next packet chosen will be from the session
260
 * after this one, then the session after that one, and so on..  So,
261
 * for example, if there are 3 ftp session's fighting for bandwidth,
262
 * one packet will be sent from the first session, then one packet
263
 * from the second session, then one packet from the third, then back
264
 * to the first, etc. etc.
265
 */
266
void
267
if_start(void)
268
{
269
	struct mbuf *ifm, *ifqt;
270
	
271
	DEBUG_CALL("if_start");
272
	
273
	if (if_queued == 0)
274
	   return; /* Nothing to do */
275
	
276
 again:
277
        /* check if we can really output */
278
        if (!slirp_can_output())
279
            return;
280

  
281
	/*
282
	 * See which queue to get next packet from
283
	 * If there's something in the fastq, select it immediately
284
	 */
285
	if (if_fastq.ifq_next != &if_fastq) {
286
		ifm = if_fastq.ifq_next;
287
	} else {
288
		/* Nothing on fastq, see if next_m is valid */
289
		if (next_m != &if_batchq)
290
		   ifm = next_m;
291
		else
292
		   ifm = if_batchq.ifq_next;
293
		
294
		/* Set which packet to send on next iteration */
295
		next_m = ifm->ifq_next;
296
	}
297
	/* Remove it from the queue */
298
	ifqt = ifm->ifq_prev;
299
	remque(ifm);
300
	--if_queued;
301
	
302
	/* If there are more packets for this session, re-queue them */
303
	if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
304
		insque(ifm->ifs_next, ifqt);
305
		ifs_remque(ifm);
306
	}
307
	
308
	/* Update so_queued */
309
	if (ifm->ifq_so) {
310
		if (--ifm->ifq_so->so_queued == 0)
311
		   /* If there's no more queued, reset nqueued */
312
		   ifm->ifq_so->so_nqueued = 0;
313
	}
314
	
315
	/* Encapsulate the packet for sending */
316
        if_encap(ifm->m_data, ifm->m_len);
317

  
318
	if (if_queued)
319
	   goto again;
320
}
b/slirp/if.h
1
/*
2
 * Copyright (c) 1995 Danny Gasparovski.
3
 * 
4
 * Please read the file COPYRIGHT for the 
5
 * terms and conditions of the copyright.
6
 */
7

  
8
#ifndef _IF_H_
9
#define _IF_H_
10

  
11
#define IF_COMPRESS	0x01	/* We want compression */
12
#define IF_NOCOMPRESS	0x02	/* Do not do compression */
13
#define IF_AUTOCOMP	0x04	/* Autodetect (default) */
14
#define IF_NOCIDCOMP	0x08	/* CID compression */
15

  
16
/* Needed for FreeBSD */
17
#undef if_mtu
18
extern int	if_mtu;
19
extern int	if_mru;	/* MTU and MRU */
20
extern int	if_comp;	/* Flags for compression */
21
extern int	if_maxlinkhdr;
22
extern int	if_queued;	/* Number of packets queued so far */
23
extern int	if_thresh;	/* Number of packets queued before we start sending
24
				 * (to prevent allocing too many mbufs) */
25

  
26
extern	struct mbuf if_fastq;                  /* fast queue (for interactive data) */
27
extern	struct mbuf if_batchq;                 /* queue for non-interactive data */
28
extern	struct mbuf *next_m;
29

  
30
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
31

  
32
/* Interface statistics */
33
struct slirp_ifstats {
34
	u_int out_pkts;		/* Output packets */
35
	u_int out_bytes;		/* Output bytes */
36
	u_int out_errpkts;	/* Output Error Packets */
37
	u_int out_errbytes;	/* Output Error Bytes */
38
	u_int in_pkts;		/* Input packets */
39
	u_int in_bytes;		/* Input bytes */
40
	u_int in_errpkts;		/* Input Error Packets */
41
	u_int in_errbytes;	/* Input Error Bytes */
42
	
43
	u_int bytes_saved;	/* Number of bytes that compression "saved" */
44
				/* ie: number of bytes that didn't need to be sent over the link
45
				 * because of compression */
46
	
47
	u_int in_mbad;		/* Bad incoming packets */
48
};
49

  
50
#endif
b/slirp/ip.h
1
/*
2
 * Copyright (c) 1982, 1986, 1993
3
 *	The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *	This product includes software developed by the University of
16
 *	California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 *
33
 *	@(#)ip.h	8.1 (Berkeley) 6/10/93
34
 * ip.h,v 1.3 1994/08/21 05:27:30 paul Exp
35
 */
36

  
37
#ifndef _IP_H_
38
#define _IP_H_
39

  
40
#ifdef WORDS_BIGENDIAN
41
# ifndef NTOHL
42
#  define NTOHL(d)
43
# endif
44
# ifndef NTOHS
45
#  define NTOHS(d)
46
# endif
47
# ifndef HTONL
48
#  define HTONL(d)
49
# endif
50
# ifndef HTONS
51
#  define HTONS(d)
52
# endif
53
#else
54
# ifndef NTOHL
55
#  define NTOHL(d) ((d) = ntohl((d)))
56
# endif
57
# ifndef NTOHS
58
#  define NTOHS(d) ((d) = ntohs((u_int16_t)(d)))
59
# endif
60
# ifndef HTONL
61
#  define HTONL(d) ((d) = htonl((d)))
62
# endif
63
# ifndef HTONS
64
#  define HTONS(d) ((d) = htons((u_int16_t)(d)))
65
# endif
66
#endif
67

  
68
typedef u_int32_t n_long;                 /* long as received from the net */
69

  
70
/*
71
 * Definitions for internet protocol version 4.
72
 * Per RFC 791, September 1981.
73
 */
74
#define	IPVERSION	4
75

  
76
/*
77
 * Structure of an internet header, naked of options.
78
 *
79
 * We declare ip_len and ip_off to be short, rather than u_short
80
 * pragmatically since otherwise unsigned comparisons can result
81
 * against negative integers quite easily, and fail in subtle ways.
82
 */
83
struct ip {
84
#ifdef WORDS_BIGENDIAN
85
	u_int ip_v:4,			/* version */
86
		ip_hl:4;		/* header length */
87
#else
88
	u_int ip_hl:4,		/* header length */
89
		ip_v:4;			/* version */
90
#endif
91
	u_int8_t ip_tos;			/* type of service */
92
	int16_t	ip_len;			/* total length */
93
	u_int16_t	ip_id;			/* identification */
94
	int16_t	ip_off;			/* fragment offset field */
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff