Commit f0cbd3ec9f4a3de1a9ef94deda09704543889f44
1 parent
7c1f25b4
initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@733 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
22 changed files
with
4806 additions
and
0 deletions
Too many changes to show.
To preserve performance only 22 of 37 files are displayed.
slirp/bootp.c
0 → 100644
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 | +} | ... | ... |
slirp/bootp.h
0 → 100644
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); | ... | ... |
slirp/cksum.c
0 → 100644
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 | +} | ... | ... |
slirp/ctl.h
0 → 100644
slirp/debug.c
0 → 100644
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 | ... | ... |
slirp/debug.h
0 → 100644
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 | + | ... | ... |
slirp/icmp_var.h
0 → 100644
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 | ... | ... |
slirp/if.c
0 → 100644
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 | +} | ... | ... |
slirp/if.h
0 → 100644
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 | ... | ... |
slirp/ip.h
0 → 100644
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 */ | |
95 | +#define IP_DF 0x4000 /* don't fragment flag */ | |
96 | +#define IP_MF 0x2000 /* more fragments flag */ | |
97 | +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ | |
98 | + u_int8_t ip_ttl; /* time to live */ | |
99 | + u_int8_t ip_p; /* protocol */ | |
100 | + u_int16_t ip_sum; /* checksum */ | |
101 | + struct in_addr ip_src,ip_dst; /* source and dest address */ | |
102 | +}; | |
103 | + | |
104 | +#define IP_MAXPACKET 65535 /* maximum packet size */ | |
105 | + | |
106 | +/* | |
107 | + * Definitions for IP type of service (ip_tos) | |
108 | + */ | |
109 | +#define IPTOS_LOWDELAY 0x10 | |
110 | +#define IPTOS_THROUGHPUT 0x08 | |
111 | +#define IPTOS_RELIABILITY 0x04 | |
112 | + | |
113 | +/* | |
114 | + * Definitions for options. | |
115 | + */ | |
116 | +#define IPOPT_COPIED(o) ((o)&0x80) | |
117 | +#define IPOPT_CLASS(o) ((o)&0x60) | |
118 | +#define IPOPT_NUMBER(o) ((o)&0x1f) | |
119 | + | |
120 | +#define IPOPT_CONTROL 0x00 | |
121 | +#define IPOPT_RESERVED1 0x20 | |
122 | +#define IPOPT_DEBMEAS 0x40 | |
123 | +#define IPOPT_RESERVED2 0x60 | |
124 | + | |
125 | +#define IPOPT_EOL 0 /* end of option list */ | |
126 | +#define IPOPT_NOP 1 /* no operation */ | |
127 | + | |
128 | +#define IPOPT_RR 7 /* record packet route */ | |
129 | +#define IPOPT_TS 68 /* timestamp */ | |
130 | +#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ | |
131 | +#define IPOPT_LSRR 131 /* loose source route */ | |
132 | +#define IPOPT_SATID 136 /* satnet id */ | |
133 | +#define IPOPT_SSRR 137 /* strict source route */ | |
134 | + | |
135 | +/* | |
136 | + * Offsets to fields in options other than EOL and NOP. | |
137 | + */ | |
138 | +#define IPOPT_OPTVAL 0 /* option ID */ | |
139 | +#define IPOPT_OLEN 1 /* option length */ | |
140 | +#define IPOPT_OFFSET 2 /* offset within option */ | |
141 | +#define IPOPT_MINOFF 4 /* min value of above */ | |
142 | + | |
143 | +/* | |
144 | + * Time stamp option structure. | |
145 | + */ | |
146 | +struct ip_timestamp { | |
147 | + u_int8_t ipt_code; /* IPOPT_TS */ | |
148 | + u_int8_t ipt_len; /* size of structure (variable) */ | |
149 | + u_int8_t ipt_ptr; /* index of current entry */ | |
150 | +#ifdef WORDS_BIGENDIAN | |
151 | + u_int ipt_oflw:4, /* overflow counter */ | |
152 | + ipt_flg:4; /* flags, see below */ | |
153 | +#else | |
154 | + u_int ipt_flg:4, /* flags, see below */ | |
155 | + ipt_oflw:4; /* overflow counter */ | |
156 | +#endif | |
157 | + union ipt_timestamp { | |
158 | + n_long ipt_time[1]; | |
159 | + struct ipt_ta { | |
160 | + struct in_addr ipt_addr; | |
161 | + n_long ipt_time; | |
162 | + } ipt_ta[1]; | |
163 | + } ipt_timestamp; | |
164 | +}; | |
165 | + | |
166 | +/* flag bits for ipt_flg */ | |
167 | +#define IPOPT_TS_TSONLY 0 /* timestamps only */ | |
168 | +#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ | |
169 | +#define IPOPT_TS_PRESPEC 3 /* specified modules only */ | |
170 | + | |
171 | +/* bits for security (not byte swapped) */ | |
172 | +#define IPOPT_SECUR_UNCLASS 0x0000 | |
173 | +#define IPOPT_SECUR_CONFID 0xf135 | |
174 | +#define IPOPT_SECUR_EFTO 0x789a | |
175 | +#define IPOPT_SECUR_MMMM 0xbc4d | |
176 | +#define IPOPT_SECUR_RESTR 0xaf13 | |
177 | +#define IPOPT_SECUR_SECRET 0xd788 | |
178 | +#define IPOPT_SECUR_TOPSECRET 0x6bc5 | |
179 | + | |
180 | +/* | |
181 | + * Internet implementation parameters. | |
182 | + */ | |
183 | +#define MAXTTL 255 /* maximum time to live (seconds) */ | |
184 | +#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ | |
185 | +#define IPFRAGTTL 60 /* time to live for frags, slowhz */ | |
186 | +#define IPTTLDEC 1 /* subtracted when forwarding */ | |
187 | + | |
188 | +#define IP_MSS 576 /* default maximum segment size */ | |
189 | + | |
190 | +#ifdef HAVE_SYS_TYPES32_H /* Overcome some Solaris 2.x junk */ | |
191 | +#include <sys/types32.h> | |
192 | +#else | |
193 | +#if SIZEOF_CHAR_P == 4 | |
194 | +typedef caddr_t caddr32_t; | |
195 | +#else | |
196 | +typedef u_int32_t caddr32_t; | |
197 | +#endif | |
198 | +#endif | |
199 | + | |
200 | +#if SIZEOF_CHAR_P == 4 | |
201 | +typedef struct ipq *ipqp_32; | |
202 | +typedef struct ipasfrag *ipasfragp_32; | |
203 | +#else | |
204 | +typedef caddr32_t ipqp_32; | |
205 | +typedef caddr32_t ipasfragp_32; | |
206 | +#endif | |
207 | + | |
208 | +/* | |
209 | + * Overlay for ip header used by other protocols (tcp, udp). | |
210 | + */ | |
211 | +struct ipovly { | |
212 | + caddr32_t ih_next, ih_prev; /* for protocol sequence q's */ | |
213 | + u_int8_t ih_x1; /* (unused) */ | |
214 | + u_int8_t ih_pr; /* protocol */ | |
215 | + int16_t ih_len; /* protocol length */ | |
216 | + struct in_addr ih_src; /* source internet address */ | |
217 | + struct in_addr ih_dst; /* destination internet address */ | |
218 | +}; | |
219 | + | |
220 | +/* | |
221 | + * Ip reassembly queue structure. Each fragment | |
222 | + * being reassembled is attached to one of these structures. | |
223 | + * They are timed out after ipq_ttl drops to 0, and may also | |
224 | + * be reclaimed if memory becomes tight. | |
225 | + * size 28 bytes | |
226 | + */ | |
227 | +struct ipq { | |
228 | + ipqp_32 next,prev; /* to other reass headers */ | |
229 | + u_int8_t ipq_ttl; /* time for reass q to live */ | |
230 | + u_int8_t ipq_p; /* protocol of this fragment */ | |
231 | + u_int16_t ipq_id; /* sequence id for reassembly */ | |
232 | + ipasfragp_32 ipq_next,ipq_prev; | |
233 | + /* to ip headers of fragments */ | |
234 | + struct in_addr ipq_src,ipq_dst; | |
235 | +}; | |
236 | + | |
237 | +/* | |
238 | + * Ip header, when holding a fragment. | |
239 | + * | |
240 | + * Note: ipf_next must be at same offset as ipq_next above | |
241 | + */ | |
242 | +struct ipasfrag { | |
243 | +#ifdef WORDS_BIGENDIAN | |
244 | + u_int ip_v:4, | |
245 | + ip_hl:4; | |
246 | +#else | |
247 | + u_int ip_hl:4, | |
248 | + ip_v:4; | |
249 | +#endif | |
250 | + /* BUG : u_int changed to u_int8_t. | |
251 | + * sizeof(u_int)==4 on linux 2.0 | |
252 | + */ | |
253 | + u_int8_t ipf_mff; /* XXX overlays ip_tos: use low bit | |
254 | + * to avoid destroying tos (PPPDTRuu); | |
255 | + * copied from (ip_off&IP_MF) */ | |
256 | + int16_t ip_len; | |
257 | + u_int16_t ip_id; | |
258 | + int16_t ip_off; | |
259 | + u_int8_t ip_ttl; | |
260 | + u_int8_t ip_p; | |
261 | + u_int16_t ip_sum; | |
262 | + ipasfragp_32 ipf_next; /* next fragment */ | |
263 | + ipasfragp_32 ipf_prev; /* previous fragment */ | |
264 | +}; | |
265 | + | |
266 | +/* | |
267 | + * Structure stored in mbuf in inpcb.ip_options | |
268 | + * and passed to ip_output when ip options are in use. | |
269 | + * The actual length of the options (including ipopt_dst) | |
270 | + * is in m_len. | |
271 | + */ | |
272 | +#define MAX_IPOPTLEN 40 | |
273 | + | |
274 | +struct ipoption { | |
275 | + struct in_addr ipopt_dst; /* first-hop dst if source routed */ | |
276 | + int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ | |
277 | +}; | |
278 | + | |
279 | +/* | |
280 | + * Structure attached to inpcb.ip_moptions and | |
281 | + * passed to ip_output when IP multicast options are in use. | |
282 | + */ | |
283 | + | |
284 | +struct ipstat { | |
285 | + u_long ips_total; /* total packets received */ | |
286 | + u_long ips_badsum; /* checksum bad */ | |
287 | + u_long ips_tooshort; /* packet too short */ | |
288 | + u_long ips_toosmall; /* not enough data */ | |
289 | + u_long ips_badhlen; /* ip header length < data size */ | |
290 | + u_long ips_badlen; /* ip length < ip header length */ | |
291 | + u_long ips_fragments; /* fragments received */ | |
292 | + u_long ips_fragdropped; /* frags dropped (dups, out of space) */ | |
293 | + u_long ips_fragtimeout; /* fragments timed out */ | |
294 | + u_long ips_forward; /* packets forwarded */ | |
295 | + u_long ips_cantforward; /* packets rcvd for unreachable dest */ | |
296 | + u_long ips_redirectsent; /* packets forwarded on same net */ | |
297 | + u_long ips_noproto; /* unknown or unsupported protocol */ | |
298 | + u_long ips_delivered; /* datagrams delivered to upper level*/ | |
299 | + u_long ips_localout; /* total ip packets generated here */ | |
300 | + u_long ips_odropped; /* lost packets due to nobufs, etc. */ | |
301 | + u_long ips_reassembled; /* total packets reassembled ok */ | |
302 | + u_long ips_fragmented; /* datagrams successfully fragmented */ | |
303 | + u_long ips_ofragments; /* output fragments created */ | |
304 | + u_long ips_cantfrag; /* don't fragment flag was set, etc. */ | |
305 | + u_long ips_badoptions; /* error in option processing */ | |
306 | + u_long ips_noroute; /* packets discarded due to no route */ | |
307 | + u_long ips_badvers; /* ip version != 4 */ | |
308 | + u_long ips_rawout; /* total raw ip packets generated */ | |
309 | + u_long ips_unaligned; /* times the ip packet was not aligned */ | |
310 | +}; | |
311 | + | |
312 | +extern struct ipstat ipstat; | |
313 | +extern struct ipq ipq; /* ip reass. queue */ | |
314 | +extern u_int16_t ip_id; /* ip packet ctr, for ids */ | |
315 | +extern int ip_defttl; /* default IP ttl */ | |
316 | + | |
317 | +#endif | ... | ... |
slirp/ip_icmp.c
0 → 100644
1 | +/* | |
2 | + * Copyright (c) 1982, 1986, 1988, 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_icmp.c 8.2 (Berkeley) 1/4/94 | |
34 | + * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp | |
35 | + */ | |
36 | + | |
37 | +#include "slirp.h" | |
38 | +#include "ip_icmp.h" | |
39 | + | |
40 | +struct icmpstat icmpstat; | |
41 | + | |
42 | +/* The message sent when emulating PING */ | |
43 | +/* Be nice and tell them it's just a psuedo-ping packet */ | |
44 | +char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; | |
45 | + | |
46 | +/* list of actions for icmp_error() on RX of an icmp message */ | |
47 | +static int icmp_flush[19] = { | |
48 | +/* ECHO REPLY (0) */ 0, | |
49 | + 1, | |
50 | + 1, | |
51 | +/* DEST UNREACH (3) */ 1, | |
52 | +/* SOURCE QUENCH (4)*/ 1, | |
53 | +/* REDIRECT (5) */ 1, | |
54 | + 1, | |
55 | + 1, | |
56 | +/* ECHO (8) */ 0, | |
57 | +/* ROUTERADVERT (9) */ 1, | |
58 | +/* ROUTERSOLICIT (10) */ 1, | |
59 | +/* TIME EXCEEDED (11) */ 1, | |
60 | +/* PARAMETER PROBLEM (12) */ 1, | |
61 | +/* TIMESTAMP (13) */ 0, | |
62 | +/* TIMESTAMP REPLY (14) */ 0, | |
63 | +/* INFO (15) */ 0, | |
64 | +/* INFO REPLY (16) */ 0, | |
65 | +/* ADDR MASK (17) */ 0, | |
66 | +/* ADDR MASK REPLY (18) */ 0 | |
67 | +}; | |
68 | + | |
69 | +/* | |
70 | + * Process a received ICMP message. | |
71 | + */ | |
72 | +void | |
73 | +icmp_input(m, hlen) | |
74 | + struct mbuf *m; | |
75 | + int hlen; | |
76 | +{ | |
77 | + register struct icmp *icp; | |
78 | + register struct ip *ip=mtod(m, struct ip *); | |
79 | + int icmplen=ip->ip_len; | |
80 | + /* int code; */ | |
81 | + | |
82 | + DEBUG_CALL("icmp_input"); | |
83 | + DEBUG_ARG("m = %lx", (long )m); | |
84 | + DEBUG_ARG("m_len = %d", m->m_len); | |
85 | + | |
86 | + icmpstat.icps_received++; | |
87 | + | |
88 | + /* | |
89 | + * Locate icmp structure in mbuf, and check | |
90 | + * that its not corrupted and of at least minimum length. | |
91 | + */ | |
92 | + if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ | |
93 | + icmpstat.icps_tooshort++; | |
94 | + freeit: | |
95 | + m_freem(m); | |
96 | + goto end_error; | |
97 | + } | |
98 | + | |
99 | + m->m_len -= hlen; | |
100 | + m->m_data += hlen; | |
101 | + icp = mtod(m, struct icmp *); | |
102 | + if (cksum(m, icmplen)) { | |
103 | + icmpstat.icps_checksum++; | |
104 | + goto freeit; | |
105 | + } | |
106 | + m->m_len += hlen; | |
107 | + m->m_data -= hlen; | |
108 | + | |
109 | + /* icmpstat.icps_inhist[icp->icmp_type]++; */ | |
110 | + /* code = icp->icmp_code; */ | |
111 | + | |
112 | + DEBUG_ARG("icmp_type = %d", icp->icmp_type); | |
113 | + switch (icp->icmp_type) { | |
114 | + case ICMP_ECHO: | |
115 | + icp->icmp_type = ICMP_ECHOREPLY; | |
116 | + ip->ip_len += hlen; /* since ip_input subtracts this */ | |
117 | + if (ip->ip_dst.s_addr == our_addr.s_addr || | |
118 | + (ip->ip_dst.s_addr == (special_addr.s_addr|htonl(CTL_ALIAS))) ) { | |
119 | + icmp_reflect(m); | |
120 | + } else { | |
121 | + struct socket *so; | |
122 | + struct sockaddr_in addr; | |
123 | + if ((so = socreate()) == NULL) goto freeit; | |
124 | + if(udp_attach(so) == -1) { | |
125 | + DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", | |
126 | + errno,strerror(errno))); | |
127 | + sofree(so); | |
128 | + m_free(m); | |
129 | + goto end_error; | |
130 | + } | |
131 | + so->so_m = m; | |
132 | + so->so_faddr = ip->ip_dst; | |
133 | + so->so_fport = htons(7); | |
134 | + so->so_laddr = ip->ip_src; | |
135 | + so->so_lport = htons(9); | |
136 | + so->so_iptos = ip->ip_tos; | |
137 | + so->so_type = IPPROTO_ICMP; | |
138 | + so->so_state = SS_ISFCONNECTED; | |
139 | + | |
140 | + /* Send the packet */ | |
141 | + addr.sin_family = AF_INET; | |
142 | + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { | |
143 | + /* It's an alias */ | |
144 | + switch(ntohl(so->so_faddr.s_addr) & 0xff) { | |
145 | + case CTL_DNS: | |
146 | + addr.sin_addr = dns_addr; | |
147 | + break; | |
148 | + case CTL_ALIAS: | |
149 | + default: | |
150 | + addr.sin_addr = loopback_addr; | |
151 | + break; | |
152 | + } | |
153 | + } else { | |
154 | + addr.sin_addr = so->so_faddr; | |
155 | + } | |
156 | + addr.sin_port = so->so_fport; | |
157 | + if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0, | |
158 | + (struct sockaddr *)&addr, sizeof(addr)) == -1) { | |
159 | + DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n", | |
160 | + errno,strerror(errno))); | |
161 | + icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); | |
162 | + udp_detach(so); | |
163 | + } | |
164 | + } /* if ip->ip_dst.s_addr == our_addr.s_addr */ | |
165 | + break; | |
166 | + case ICMP_UNREACH: | |
167 | + /* XXX? report error? close socket? */ | |
168 | + case ICMP_TIMXCEED: | |
169 | + case ICMP_PARAMPROB: | |
170 | + case ICMP_SOURCEQUENCH: | |
171 | + case ICMP_TSTAMP: | |
172 | + case ICMP_MASKREQ: | |
173 | + case ICMP_REDIRECT: | |
174 | + icmpstat.icps_notsupp++; | |
175 | + m_freem(m); | |
176 | + break; | |
177 | + | |
178 | + default: | |
179 | + icmpstat.icps_badtype++; | |
180 | + m_freem(m); | |
181 | + } /* swith */ | |
182 | + | |
183 | +end_error: | |
184 | + /* m is m_free()'d xor put in a socket xor or given to ip_send */ | |
185 | + return; | |
186 | +} | |
187 | + | |
188 | + | |
189 | +/* | |
190 | + * Send an ICMP message in response to a situation | |
191 | + * | |
192 | + * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we do). | |
193 | + * MUST NOT change this header information. | |
194 | + * MUST NOT reply to a multicast/broadcast IP address. | |
195 | + * MUST NOT reply to a multicast/broadcast MAC address. | |
196 | + * MUST reply to only the first fragment. | |
197 | + */ | |
198 | +/* | |
199 | + * Send ICMP_UNREACH back to the source regarding msrc. | |
200 | + * mbuf *msrc is used as a template, but is NOT m_free()'d. | |
201 | + * It is reported as the bad ip packet. The header should | |
202 | + * be fully correct and in host byte order. | |
203 | + * ICMP fragmentation is illegal. All machines must accept 576 bytes in one | |
204 | + * packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548 | |
205 | + */ | |
206 | + | |
207 | +#define ICMP_MAXDATALEN (IP_MSS-28) | |
208 | +void | |
209 | +icmp_error(msrc, type, code, minsize, message) | |
210 | + struct mbuf *msrc; | |
211 | + u_char type; | |
212 | + u_char code; | |
213 | + int minsize; | |
214 | + char *message; | |
215 | +{ | |
216 | + unsigned hlen, shlen, s_ip_len; | |
217 | + register struct ip *ip; | |
218 | + register struct icmp *icp; | |
219 | + register struct mbuf *m; | |
220 | + | |
221 | + DEBUG_CALL("icmp_error"); | |
222 | + DEBUG_ARG("msrc = %lx", (long )msrc); | |
223 | + DEBUG_ARG("msrc_len = %d", msrc->m_len); | |
224 | + | |
225 | + if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error; | |
226 | + | |
227 | + /* check msrc */ | |
228 | + if(!msrc) goto end_error; | |
229 | + ip = mtod(msrc, struct ip *); | |
230 | +#if DEBUG | |
231 | + { char bufa[20], bufb[20]; | |
232 | + strcpy(bufa, inet_ntoa(ip->ip_src)); | |
233 | + strcpy(bufb, inet_ntoa(ip->ip_dst)); | |
234 | + DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb)); | |
235 | + } | |
236 | +#endif | |
237 | + if(ip->ip_off & IP_OFFMASK) goto end_error; /* Only reply to fragment 0 */ | |
238 | + | |
239 | + shlen=ip->ip_hl << 2; | |
240 | + s_ip_len=ip->ip_len; | |
241 | + if(ip->ip_p == IPPROTO_ICMP) { | |
242 | + icp = (struct icmp *)((char *)ip + shlen); | |
243 | + /* | |
244 | + * Assume any unknown ICMP type is an error. This isn't | |
245 | + * specified by the RFC, but think about it.. | |
246 | + */ | |
247 | + if(icp->icmp_type>18 || icmp_flush[icp->icmp_type]) goto end_error; | |
248 | + } | |
249 | + | |
250 | + /* make a copy */ | |
251 | + if(!(m=m_get())) goto end_error; /* get mbuf */ | |
252 | + { int new_m_size; | |
253 | + new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN; | |
254 | + if(new_m_size>m->m_size) m_inc(m, new_m_size); | |
255 | + } | |
256 | + memcpy(m->m_data, msrc->m_data, msrc->m_len); | |
257 | + m->m_len = msrc->m_len; /* copy msrc to m */ | |
258 | + | |
259 | + /* make the header of the reply packet */ | |
260 | + ip = mtod(m, struct ip *); | |
261 | + hlen= sizeof(struct ip ); /* no options in reply */ | |
262 | + | |
263 | + /* fill in icmp */ | |
264 | + m->m_data += hlen; | |
265 | + m->m_len -= hlen; | |
266 | + | |
267 | + icp = mtod(m, struct icmp *); | |
268 | + | |
269 | + if(minsize) s_ip_len=shlen+ICMP_MINLEN; /* return header+8b only */ | |
270 | + else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */ | |
271 | + s_ip_len=ICMP_MAXDATALEN; | |
272 | + | |
273 | + m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */ | |
274 | + | |
275 | + /* min. size = 8+sizeof(struct ip)+8 */ | |
276 | + | |
277 | + icp->icmp_type = type; | |
278 | + icp->icmp_code = code; | |
279 | + icp->icmp_id = 0; | |
280 | + icp->icmp_seq = 0; | |
281 | + | |
282 | + memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len); /* report the ip packet */ | |
283 | + HTONS(icp->icmp_ip.ip_len); | |
284 | + HTONS(icp->icmp_ip.ip_id); | |
285 | + HTONS(icp->icmp_ip.ip_off); | |
286 | + | |
287 | +#if DEBUG | |
288 | + if(message) { /* DEBUG : append message to ICMP packet */ | |
289 | + int message_len; | |
290 | + char *cpnt; | |
291 | + message_len=strlen(message); | |
292 | + if(message_len>ICMP_MAXDATALEN) message_len=ICMP_MAXDATALEN; | |
293 | + cpnt=(char *)m->m_data+m->m_len; | |
294 | + memcpy(cpnt, message, message_len); | |
295 | + m->m_len+=message_len; | |
296 | + } | |
297 | +#endif | |
298 | + | |
299 | + icp->icmp_cksum = 0; | |
300 | + icp->icmp_cksum = cksum(m, m->m_len); | |
301 | + | |
302 | + m->m_data -= hlen; | |
303 | + m->m_len += hlen; | |
304 | + | |
305 | + /* fill in ip */ | |
306 | + ip->ip_hl = hlen >> 2; | |
307 | + ip->ip_len = m->m_len; | |
308 | + | |
309 | + ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */ | |
310 | + | |
311 | + ip->ip_ttl = MAXTTL; | |
312 | + ip->ip_p = IPPROTO_ICMP; | |
313 | + ip->ip_dst = ip->ip_src; /* ip adresses */ | |
314 | + ip->ip_src = our_addr; | |
315 | + | |
316 | + (void ) ip_output((struct socket *)NULL, m); | |
317 | + | |
318 | + icmpstat.icps_reflect++; | |
319 | + | |
320 | +end_error: | |
321 | + return; | |
322 | +} | |
323 | +#undef ICMP_MAXDATALEN | |
324 | + | |
325 | +/* | |
326 | + * Reflect the ip packet back to the source | |
327 | + */ | |
328 | +void | |
329 | +icmp_reflect(m) | |
330 | + struct mbuf *m; | |
331 | +{ | |
332 | + register struct ip *ip = mtod(m, struct ip *); | |
333 | + int hlen = ip->ip_hl << 2; | |
334 | + int optlen = hlen - sizeof(struct ip ); | |
335 | + register struct icmp *icp; | |
336 | + | |
337 | + /* | |
338 | + * Send an icmp packet back to the ip level, | |
339 | + * after supplying a checksum. | |
340 | + */ | |
341 | + m->m_data += hlen; | |
342 | + m->m_len -= hlen; | |
343 | + icp = mtod(m, struct icmp *); | |
344 | + | |
345 | + icp->icmp_cksum = 0; | |
346 | + icp->icmp_cksum = cksum(m, ip->ip_len - hlen); | |
347 | + | |
348 | + m->m_data -= hlen; | |
349 | + m->m_len += hlen; | |
350 | + | |
351 | + /* fill in ip */ | |
352 | + if (optlen > 0) { | |
353 | + /* | |
354 | + * Strip out original options by copying rest of first | |
355 | + * mbuf's data back, and adjust the IP length. | |
356 | + */ | |
357 | + memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen, | |
358 | + (unsigned )(m->m_len - hlen)); | |
359 | + hlen -= optlen; | |
360 | + ip->ip_hl = hlen >> 2; | |
361 | + ip->ip_len -= optlen; | |
362 | + m->m_len -= optlen; | |
363 | + } | |
364 | + | |
365 | + ip->ip_ttl = MAXTTL; | |
366 | + { /* swap */ | |
367 | + struct in_addr icmp_dst; | |
368 | + icmp_dst = ip->ip_dst; | |
369 | + ip->ip_dst = ip->ip_src; | |
370 | + ip->ip_src = icmp_dst; | |
371 | + } | |
372 | + | |
373 | + (void ) ip_output((struct socket *)NULL, m); | |
374 | + | |
375 | + icmpstat.icps_reflect++; | |
376 | +} | ... | ... |
slirp/ip_icmp.h
0 → 100644
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_icmp.h 8.1 (Berkeley) 6/10/93 | |
34 | + * ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp | |
35 | + */ | |
36 | + | |
37 | +#ifndef _NETINET_IP_ICMP_H_ | |
38 | +#define _NETINET_IP_ICMP_H_ | |
39 | + | |
40 | +/* | |
41 | + * Interface Control Message Protocol Definitions. | |
42 | + * Per RFC 792, September 1981. | |
43 | + */ | |
44 | + | |
45 | +typedef u_int32_t n_time; | |
46 | + | |
47 | +/* | |
48 | + * Structure of an icmp header. | |
49 | + */ | |
50 | +struct icmp { | |
51 | + u_char icmp_type; /* type of message, see below */ | |
52 | + u_char icmp_code; /* type sub code */ | |
53 | + u_short icmp_cksum; /* ones complement cksum of struct */ | |
54 | + union { | |
55 | + u_char ih_pptr; /* ICMP_PARAMPROB */ | |
56 | + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ | |
57 | + struct ih_idseq { | |
58 | + u_short icd_id; | |
59 | + u_short icd_seq; | |
60 | + } ih_idseq; | |
61 | + int ih_void; | |
62 | + | |
63 | + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ | |
64 | + struct ih_pmtu { | |
65 | + u_short ipm_void; | |
66 | + u_short ipm_nextmtu; | |
67 | + } ih_pmtu; | |
68 | + } icmp_hun; | |
69 | +#define icmp_pptr icmp_hun.ih_pptr | |
70 | +#define icmp_gwaddr icmp_hun.ih_gwaddr | |
71 | +#define icmp_id icmp_hun.ih_idseq.icd_id | |
72 | +#define icmp_seq icmp_hun.ih_idseq.icd_seq | |
73 | +#define icmp_void icmp_hun.ih_void | |
74 | +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void | |
75 | +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu | |
76 | + union { | |
77 | + struct id_ts { | |
78 | + n_time its_otime; | |
79 | + n_time its_rtime; | |
80 | + n_time its_ttime; | |
81 | + } id_ts; | |
82 | + struct id_ip { | |
83 | + struct ip idi_ip; | |
84 | + /* options and then 64 bits of data */ | |
85 | + } id_ip; | |
86 | + u_long id_mask; | |
87 | + char id_data[1]; | |
88 | + } icmp_dun; | |
89 | +#define icmp_otime icmp_dun.id_ts.its_otime | |
90 | +#define icmp_rtime icmp_dun.id_ts.its_rtime | |
91 | +#define icmp_ttime icmp_dun.id_ts.its_ttime | |
92 | +#define icmp_ip icmp_dun.id_ip.idi_ip | |
93 | +#define icmp_mask icmp_dun.id_mask | |
94 | +#define icmp_data icmp_dun.id_data | |
95 | +}; | |
96 | + | |
97 | +/* | |
98 | + * Lower bounds on packet lengths for various types. | |
99 | + * For the error advice packets must first insure that the | |
100 | + * packet is large enought to contain the returned ip header. | |
101 | + * Only then can we do the check to see if 64 bits of packet | |
102 | + * data have been returned, since we need to check the returned | |
103 | + * ip header length. | |
104 | + */ | |
105 | +#define ICMP_MINLEN 8 /* abs minimum */ | |
106 | +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ | |
107 | +#define ICMP_MASKLEN 12 /* address mask */ | |
108 | +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ | |
109 | +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) | |
110 | + /* N.B.: must separately check that ip_hl >= 5 */ | |
111 | + | |
112 | +/* | |
113 | + * Definition of type and code field values. | |
114 | + */ | |
115 | +#define ICMP_ECHOREPLY 0 /* echo reply */ | |
116 | +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ | |
117 | +#define ICMP_UNREACH_NET 0 /* bad net */ | |
118 | +#define ICMP_UNREACH_HOST 1 /* bad host */ | |
119 | +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ | |
120 | +#define ICMP_UNREACH_PORT 3 /* bad port */ | |
121 | +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ | |
122 | +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ | |
123 | +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ | |
124 | +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ | |
125 | +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ | |
126 | +#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */ | |
127 | +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */ | |
128 | +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ | |
129 | +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ | |
130 | +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ | |
131 | +#define ICMP_REDIRECT 5 /* shorter route, codes: */ | |
132 | +#define ICMP_REDIRECT_NET 0 /* for network */ | |
133 | +#define ICMP_REDIRECT_HOST 1 /* for host */ | |
134 | +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ | |
135 | +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ | |
136 | +#define ICMP_ECHO 8 /* echo service */ | |
137 | +#define ICMP_ROUTERADVERT 9 /* router advertisement */ | |
138 | +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ | |
139 | +#define ICMP_TIMXCEED 11 /* time exceeded, code: */ | |
140 | +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ | |
141 | +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ | |
142 | +#define ICMP_PARAMPROB 12 /* ip header bad */ | |
143 | +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ | |
144 | +#define ICMP_TSTAMP 13 /* timestamp request */ | |
145 | +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ | |
146 | +#define ICMP_IREQ 15 /* information request */ | |
147 | +#define ICMP_IREQREPLY 16 /* information reply */ | |
148 | +#define ICMP_MASKREQ 17 /* address mask request */ | |
149 | +#define ICMP_MASKREPLY 18 /* address mask reply */ | |
150 | + | |
151 | +#define ICMP_MAXTYPE 18 | |
152 | + | |
153 | +#define ICMP_INFOTYPE(type) \ | |
154 | + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ | |
155 | + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ | |
156 | + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ | |
157 | + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ | |
158 | + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) | |
159 | + | |
160 | +void icmp_input _P((struct mbuf *, int)); | |
161 | +void icmp_error _P((struct mbuf *, u_char, u_char, int, char *)); | |
162 | +void icmp_reflect _P((struct mbuf *)); | |
163 | + | |
164 | +#endif | ... | ... |
slirp/ip_input.c
0 → 100644
1 | +/* | |
2 | + * Copyright (c) 1982, 1986, 1988, 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_input.c 8.2 (Berkeley) 1/4/94 | |
34 | + * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp | |
35 | + */ | |
36 | + | |
37 | +/* | |
38 | + * Changes and additions relating to SLiRP are | |
39 | + * Copyright (c) 1995 Danny Gasparovski. | |
40 | + * | |
41 | + * Please read the file COPYRIGHT for the | |
42 | + * terms and conditions of the copyright. | |
43 | + */ | |
44 | + | |
45 | +#include <slirp.h> | |
46 | +#include "ip_icmp.h" | |
47 | + | |
48 | +int ip_defttl; | |
49 | +struct ipstat ipstat; | |
50 | +struct ipq ipq; | |
51 | + | |
52 | +/* | |
53 | + * IP initialization: fill in IP protocol switch table. | |
54 | + * All protocols not implemented in kernel go to raw IP protocol handler. | |
55 | + */ | |
56 | +void | |
57 | +ip_init() | |
58 | +{ | |
59 | + ipq.next = ipq.prev = (ipqp_32)&ipq; | |
60 | + ip_id = tt.tv_sec & 0xffff; | |
61 | + udp_init(); | |
62 | + tcp_init(); | |
63 | + ip_defttl = IPDEFTTL; | |
64 | +} | |
65 | + | |
66 | +/* | |
67 | + * Ip input routine. Checksum and byte swap header. If fragmented | |
68 | + * try to reassemble. Process options. Pass to next level. | |
69 | + */ | |
70 | +void | |
71 | +ip_input(m) | |
72 | + struct mbuf *m; | |
73 | +{ | |
74 | + register struct ip *ip; | |
75 | + int hlen; | |
76 | + | |
77 | + DEBUG_CALL("ip_input"); | |
78 | + DEBUG_ARG("m = %lx", (long)m); | |
79 | + DEBUG_ARG("m_len = %d", m->m_len); | |
80 | + | |
81 | + ipstat.ips_total++; | |
82 | + | |
83 | + if (m->m_len < sizeof (struct ip)) { | |
84 | + ipstat.ips_toosmall++; | |
85 | + return; | |
86 | + } | |
87 | + | |
88 | + ip = mtod(m, struct ip *); | |
89 | + | |
90 | + if (ip->ip_v != IPVERSION) { | |
91 | + ipstat.ips_badvers++; | |
92 | + goto bad; | |
93 | + } | |
94 | + | |
95 | + hlen = ip->ip_hl << 2; | |
96 | + if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */ | |
97 | + ipstat.ips_badhlen++; /* or packet too short */ | |
98 | + goto bad; | |
99 | + } | |
100 | + | |
101 | + /* keep ip header intact for ICMP reply | |
102 | + * ip->ip_sum = cksum(m, hlen); | |
103 | + * if (ip->ip_sum) { | |
104 | + */ | |
105 | + if(cksum(m,hlen)) { | |
106 | + ipstat.ips_badsum++; | |
107 | + goto bad; | |
108 | + } | |
109 | + | |
110 | + /* | |
111 | + * Convert fields to host representation. | |
112 | + */ | |
113 | + NTOHS(ip->ip_len); | |
114 | + if (ip->ip_len < hlen) { | |
115 | + ipstat.ips_badlen++; | |
116 | + goto bad; | |
117 | + } | |
118 | + NTOHS(ip->ip_id); | |
119 | + NTOHS(ip->ip_off); | |
120 | + | |
121 | + /* | |
122 | + * Check that the amount of data in the buffers | |
123 | + * is as at least much as the IP header would have us expect. | |
124 | + * Trim mbufs if longer than we expect. | |
125 | + * Drop packet if shorter than we expect. | |
126 | + */ | |
127 | + if (m->m_len < ip->ip_len) { | |
128 | + ipstat.ips_tooshort++; | |
129 | + goto bad; | |
130 | + } | |
131 | + /* Should drop packet if mbuf too long? hmmm... */ | |
132 | + if (m->m_len > ip->ip_len) | |
133 | + m_adj(m, ip->ip_len - m->m_len); | |
134 | + | |
135 | + /* check ip_ttl for a correct ICMP reply */ | |
136 | + if(ip->ip_ttl==0 || ip->ip_ttl==1) { | |
137 | + icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); | |
138 | + goto bad; | |
139 | + } | |
140 | + | |
141 | + /* | |
142 | + * Process options and, if not destined for us, | |
143 | + * ship it on. ip_dooptions returns 1 when an | |
144 | + * error was detected (causing an icmp message | |
145 | + * to be sent and the original packet to be freed). | |
146 | + */ | |
147 | +/* We do no IP options */ | |
148 | +/* if (hlen > sizeof (struct ip) && ip_dooptions(m)) | |
149 | + * goto next; | |
150 | + */ | |
151 | + /* | |
152 | + * If offset or IP_MF are set, must reassemble. | |
153 | + * Otherwise, nothing need be done. | |
154 | + * (We could look in the reassembly queue to see | |
155 | + * if the packet was previously fragmented, | |
156 | + * but it's not worth the time; just let them time out.) | |
157 | + * | |
158 | + * XXX This should fail, don't fragment yet | |
159 | + */ | |
160 | + if (ip->ip_off &~ IP_DF) { | |
161 | + register struct ipq *fp; | |
162 | + /* | |
163 | + * Look for queue of fragments | |
164 | + * of this datagram. | |
165 | + */ | |
166 | + for (fp = (struct ipq *) ipq.next; fp != &ipq; | |
167 | + fp = (struct ipq *) fp->next) | |
168 | + if (ip->ip_id == fp->ipq_id && | |
169 | + ip->ip_src.s_addr == fp->ipq_src.s_addr && | |
170 | + ip->ip_dst.s_addr == fp->ipq_dst.s_addr && | |
171 | + ip->ip_p == fp->ipq_p) | |
172 | + goto found; | |
173 | + fp = 0; | |
174 | + found: | |
175 | + | |
176 | + /* | |
177 | + * Adjust ip_len to not reflect header, | |
178 | + * set ip_mff if more fragments are expected, | |
179 | + * convert offset of this to bytes. | |
180 | + */ | |
181 | + ip->ip_len -= hlen; | |
182 | + if (ip->ip_off & IP_MF) | |
183 | + ((struct ipasfrag *)ip)->ipf_mff |= 1; | |
184 | + else | |
185 | + ((struct ipasfrag *)ip)->ipf_mff &= ~1; | |
186 | + | |
187 | + ip->ip_off <<= 3; | |
188 | + | |
189 | + /* | |
190 | + * If datagram marked as having more fragments | |
191 | + * or if this is not the first fragment, | |
192 | + * attempt reassembly; if it succeeds, proceed. | |
193 | + */ | |
194 | + if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { | |
195 | + ipstat.ips_fragments++; | |
196 | + ip = ip_reass((struct ipasfrag *)ip, fp); | |
197 | + if (ip == 0) | |
198 | + return; | |
199 | + ipstat.ips_reassembled++; | |
200 | + m = dtom(ip); | |
201 | + } else | |
202 | + if (fp) | |
203 | + ip_freef(fp); | |
204 | + | |
205 | + } else | |
206 | + ip->ip_len -= hlen; | |
207 | + | |
208 | + /* | |
209 | + * Switch out to protocol's input routine. | |
210 | + */ | |
211 | + ipstat.ips_delivered++; | |
212 | + switch (ip->ip_p) { | |
213 | + case IPPROTO_TCP: | |
214 | + tcp_input(m, hlen, (struct socket *)NULL); | |
215 | + break; | |
216 | + case IPPROTO_UDP: | |
217 | + udp_input(m, hlen); | |
218 | + break; | |
219 | + case IPPROTO_ICMP: | |
220 | + icmp_input(m, hlen); | |
221 | + break; | |
222 | + default: | |
223 | + ipstat.ips_noproto++; | |
224 | + m_free(m); | |
225 | + } | |
226 | + return; | |
227 | +bad: | |
228 | + m_freem(m); | |
229 | + return; | |
230 | +} | |
231 | + | |
232 | +/* | |
233 | + * Take incoming datagram fragment and try to | |
234 | + * reassemble it into whole datagram. If a chain for | |
235 | + * reassembly of this datagram already exists, then it | |
236 | + * is given as fp; otherwise have to make a chain. | |
237 | + */ | |
238 | +struct ip * | |
239 | +ip_reass(ip, fp) | |
240 | + register struct ipasfrag *ip; | |
241 | + register struct ipq *fp; | |
242 | +{ | |
243 | + register struct mbuf *m = dtom(ip); | |
244 | + register struct ipasfrag *q; | |
245 | + int hlen = ip->ip_hl << 2; | |
246 | + int i, next; | |
247 | + | |
248 | + DEBUG_CALL("ip_reass"); | |
249 | + DEBUG_ARG("ip = %lx", (long)ip); | |
250 | + DEBUG_ARG("fp = %lx", (long)fp); | |
251 | + DEBUG_ARG("m = %lx", (long)m); | |
252 | + | |
253 | + /* | |
254 | + * Presence of header sizes in mbufs | |
255 | + * would confuse code below. | |
256 | + * Fragment m_data is concatenated. | |
257 | + */ | |
258 | + m->m_data += hlen; | |
259 | + m->m_len -= hlen; | |
260 | + | |
261 | + /* | |
262 | + * If first fragment to arrive, create a reassembly queue. | |
263 | + */ | |
264 | + if (fp == 0) { | |
265 | + struct mbuf *t; | |
266 | + if ((t = m_get()) == NULL) goto dropfrag; | |
267 | + fp = mtod(t, struct ipq *); | |
268 | + insque_32(fp, &ipq); | |
269 | + fp->ipq_ttl = IPFRAGTTL; | |
270 | + fp->ipq_p = ip->ip_p; | |
271 | + fp->ipq_id = ip->ip_id; | |
272 | + fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp; | |
273 | + fp->ipq_src = ((struct ip *)ip)->ip_src; | |
274 | + fp->ipq_dst = ((struct ip *)ip)->ip_dst; | |
275 | + q = (struct ipasfrag *)fp; | |
276 | + goto insert; | |
277 | + } | |
278 | + | |
279 | + /* | |
280 | + * Find a segment which begins after this one does. | |
281 | + */ | |
282 | + for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp; | |
283 | + q = (struct ipasfrag *)q->ipf_next) | |
284 | + if (q->ip_off > ip->ip_off) | |
285 | + break; | |
286 | + | |
287 | + /* | |
288 | + * If there is a preceding segment, it may provide some of | |
289 | + * our data already. If so, drop the data from the incoming | |
290 | + * segment. If it provides all of our data, drop us. | |
291 | + */ | |
292 | + if (q->ipf_prev != (ipasfragp_32)fp) { | |
293 | + i = ((struct ipasfrag *)(q->ipf_prev))->ip_off + | |
294 | + ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off; | |
295 | + if (i > 0) { | |
296 | + if (i >= ip->ip_len) | |
297 | + goto dropfrag; | |
298 | + m_adj(dtom(ip), i); | |
299 | + ip->ip_off += i; | |
300 | + ip->ip_len -= i; | |
301 | + } | |
302 | + } | |
303 | + | |
304 | + /* | |
305 | + * While we overlap succeeding segments trim them or, | |
306 | + * if they are completely covered, dequeue them. | |
307 | + */ | |
308 | + while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { | |
309 | + i = (ip->ip_off + ip->ip_len) - q->ip_off; | |
310 | + if (i < q->ip_len) { | |
311 | + q->ip_len -= i; | |
312 | + q->ip_off += i; | |
313 | + m_adj(dtom(q), i); | |
314 | + break; | |
315 | + } | |
316 | + q = (struct ipasfrag *) q->ipf_next; | |
317 | + m_freem(dtom((struct ipasfrag *) q->ipf_prev)); | |
318 | + ip_deq((struct ipasfrag *) q->ipf_prev); | |
319 | + } | |
320 | + | |
321 | +insert: | |
322 | + /* | |
323 | + * Stick new segment in its place; | |
324 | + * check for complete reassembly. | |
325 | + */ | |
326 | + ip_enq(ip, (struct ipasfrag *) q->ipf_prev); | |
327 | + next = 0; | |
328 | + for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; | |
329 | + q = (struct ipasfrag *) q->ipf_next) { | |
330 | + if (q->ip_off != next) | |
331 | + return (0); | |
332 | + next += q->ip_len; | |
333 | + } | |
334 | + if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1) | |
335 | + return (0); | |
336 | + | |
337 | + /* | |
338 | + * Reassembly is complete; concatenate fragments. | |
339 | + */ | |
340 | + q = (struct ipasfrag *) fp->ipq_next; | |
341 | + m = dtom(q); | |
342 | + | |
343 | + q = (struct ipasfrag *) q->ipf_next; | |
344 | + while (q != (struct ipasfrag *)fp) { | |
345 | + struct mbuf *t; | |
346 | + t = dtom(q); | |
347 | + m_cat(m, t); | |
348 | + q = (struct ipasfrag *) q->ipf_next; | |
349 | + } | |
350 | + | |
351 | + /* | |
352 | + * Create header for new ip packet by | |
353 | + * modifying header of first packet; | |
354 | + * dequeue and discard fragment reassembly header. | |
355 | + * Make header visible. | |
356 | + */ | |
357 | + ip = (struct ipasfrag *) fp->ipq_next; | |
358 | + | |
359 | + /* | |
360 | + * If the fragments concatenated to an mbuf that's | |
361 | + * bigger than the total size of the fragment, then and | |
362 | + * m_ext buffer was alloced. But fp->ipq_next points to | |
363 | + * the old buffer (in the mbuf), so we must point ip | |
364 | + * into the new buffer. | |
365 | + */ | |
366 | + if (m->m_flags & M_EXT) { | |
367 | + int delta; | |
368 | + delta = (char *)ip - m->m_dat; | |
369 | + ip = (struct ipasfrag *)(m->m_ext + delta); | |
370 | + } | |
371 | + | |
372 | + /* DEBUG_ARG("ip = %lx", (long)ip); | |
373 | + * ip=(struct ipasfrag *)m->m_data; */ | |
374 | + | |
375 | + ip->ip_len = next; | |
376 | + ip->ipf_mff &= ~1; | |
377 | + ((struct ip *)ip)->ip_src = fp->ipq_src; | |
378 | + ((struct ip *)ip)->ip_dst = fp->ipq_dst; | |
379 | + remque_32(fp); | |
380 | + (void) m_free(dtom(fp)); | |
381 | + m = dtom(ip); | |
382 | + m->m_len += (ip->ip_hl << 2); | |
383 | + m->m_data -= (ip->ip_hl << 2); | |
384 | + | |
385 | + return ((struct ip *)ip); | |
386 | + | |
387 | +dropfrag: | |
388 | + ipstat.ips_fragdropped++; | |
389 | + m_freem(m); | |
390 | + return (0); | |
391 | +} | |
392 | + | |
393 | +/* | |
394 | + * Free a fragment reassembly header and all | |
395 | + * associated datagrams. | |
396 | + */ | |
397 | +void | |
398 | +ip_freef(fp) | |
399 | + struct ipq *fp; | |
400 | +{ | |
401 | + register struct ipasfrag *q, *p; | |
402 | + | |
403 | + for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp; | |
404 | + q = p) { | |
405 | + p = (struct ipasfrag *) q->ipf_next; | |
406 | + ip_deq(q); | |
407 | + m_freem(dtom(q)); | |
408 | + } | |
409 | + remque_32(fp); | |
410 | + (void) m_free(dtom(fp)); | |
411 | +} | |
412 | + | |
413 | +/* | |
414 | + * Put an ip fragment on a reassembly chain. | |
415 | + * Like insque, but pointers in middle of structure. | |
416 | + */ | |
417 | +void | |
418 | +ip_enq(p, prev) | |
419 | + register struct ipasfrag *p, *prev; | |
420 | +{ | |
421 | + DEBUG_CALL("ip_enq"); | |
422 | + DEBUG_ARG("prev = %lx", (long)prev); | |
423 | + p->ipf_prev = (ipasfragp_32) prev; | |
424 | + p->ipf_next = prev->ipf_next; | |
425 | + ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p; | |
426 | + prev->ipf_next = (ipasfragp_32) p; | |
427 | +} | |
428 | + | |
429 | +/* | |
430 | + * To ip_enq as remque is to insque. | |
431 | + */ | |
432 | +void | |
433 | +ip_deq(p) | |
434 | + register struct ipasfrag *p; | |
435 | +{ | |
436 | + ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; | |
437 | + ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; | |
438 | +} | |
439 | + | |
440 | +/* | |
441 | + * IP timer processing; | |
442 | + * if a timer expires on a reassembly | |
443 | + * queue, discard it. | |
444 | + */ | |
445 | +void | |
446 | +ip_slowtimo() | |
447 | +{ | |
448 | + register struct ipq *fp; | |
449 | + | |
450 | + DEBUG_CALL("ip_slowtimo"); | |
451 | + | |
452 | + fp = (struct ipq *) ipq.next; | |
453 | + if (fp == 0) | |
454 | + return; | |
455 | + | |
456 | + while (fp != &ipq) { | |
457 | + --fp->ipq_ttl; | |
458 | + fp = (struct ipq *) fp->next; | |
459 | + if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { | |
460 | + ipstat.ips_fragtimeout++; | |
461 | + ip_freef((struct ipq *) fp->prev); | |
462 | + } | |
463 | + } | |
464 | +} | |
465 | + | |
466 | +/* | |
467 | + * Do option processing on a datagram, | |
468 | + * possibly discarding it if bad options are encountered, | |
469 | + * or forwarding it if source-routed. | |
470 | + * Returns 1 if packet has been forwarded/freed, | |
471 | + * 0 if the packet should be processed further. | |
472 | + */ | |
473 | + | |
474 | +#ifdef notdef | |
475 | + | |
476 | +int | |
477 | +ip_dooptions(m) | |
478 | + struct mbuf *m; | |
479 | +{ | |
480 | + register struct ip *ip = mtod(m, struct ip *); | |
481 | + register u_char *cp; | |
482 | + register struct ip_timestamp *ipt; | |
483 | + register struct in_ifaddr *ia; | |
484 | +/* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */ | |
485 | + int opt, optlen, cnt, off, code, type, forward = 0; | |
486 | + struct in_addr *sin, dst; | |
487 | +typedef u_int32_t n_time; | |
488 | + n_time ntime; | |
489 | + | |
490 | + dst = ip->ip_dst; | |
491 | + cp = (u_char *)(ip + 1); | |
492 | + cnt = (ip->ip_hl << 2) - sizeof (struct ip); | |
493 | + for (; cnt > 0; cnt -= optlen, cp += optlen) { | |
494 | + opt = cp[IPOPT_OPTVAL]; | |
495 | + if (opt == IPOPT_EOL) | |
496 | + break; | |
497 | + if (opt == IPOPT_NOP) | |
498 | + optlen = 1; | |
499 | + else { | |
500 | + optlen = cp[IPOPT_OLEN]; | |
501 | + if (optlen <= 0 || optlen > cnt) { | |
502 | + code = &cp[IPOPT_OLEN] - (u_char *)ip; | |
503 | + goto bad; | |
504 | + } | |
505 | + } | |
506 | + switch (opt) { | |
507 | + | |
508 | + default: | |
509 | + break; | |
510 | + | |
511 | + /* | |
512 | + * Source routing with record. | |
513 | + * Find interface with current destination address. | |
514 | + * If none on this machine then drop if strictly routed, | |
515 | + * or do nothing if loosely routed. | |
516 | + * Record interface address and bring up next address | |
517 | + * component. If strictly routed make sure next | |
518 | + * address is on directly accessible net. | |
519 | + */ | |
520 | + case IPOPT_LSRR: | |
521 | + case IPOPT_SSRR: | |
522 | + if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { | |
523 | + code = &cp[IPOPT_OFFSET] - (u_char *)ip; | |
524 | + goto bad; | |
525 | + } | |
526 | + ipaddr.sin_addr = ip->ip_dst; | |
527 | + ia = (struct in_ifaddr *) | |
528 | + ifa_ifwithaddr((struct sockaddr *)&ipaddr); | |
529 | + if (ia == 0) { | |
530 | + if (opt == IPOPT_SSRR) { | |
531 | + type = ICMP_UNREACH; | |
532 | + code = ICMP_UNREACH_SRCFAIL; | |
533 | + goto bad; | |
534 | + } | |
535 | + /* | |
536 | + * Loose routing, and not at next destination | |
537 | + * yet; nothing to do except forward. | |
538 | + */ | |
539 | + break; | |
540 | + } | |
541 | + off--; / * 0 origin * / | |
542 | + if (off > optlen - sizeof(struct in_addr)) { | |
543 | + /* | |
544 | + * End of source route. Should be for us. | |
545 | + */ | |
546 | + save_rte(cp, ip->ip_src); | |
547 | + break; | |
548 | + } | |
549 | + /* | |
550 | + * locate outgoing interface | |
551 | + */ | |
552 | + bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, | |
553 | + sizeof(ipaddr.sin_addr)); | |
554 | + if (opt == IPOPT_SSRR) { | |
555 | +#define INA struct in_ifaddr * | |
556 | +#define SA struct sockaddr * | |
557 | + if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) | |
558 | + ia = (INA)ifa_ifwithnet((SA)&ipaddr); | |
559 | + } else | |
560 | + ia = ip_rtaddr(ipaddr.sin_addr); | |
561 | + if (ia == 0) { | |
562 | + type = ICMP_UNREACH; | |
563 | + code = ICMP_UNREACH_SRCFAIL; | |
564 | + goto bad; | |
565 | + } | |
566 | + ip->ip_dst = ipaddr.sin_addr; | |
567 | + bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), | |
568 | + (caddr_t)(cp + off), sizeof(struct in_addr)); | |
569 | + cp[IPOPT_OFFSET] += sizeof(struct in_addr); | |
570 | + /* | |
571 | + * Let ip_intr's mcast routing check handle mcast pkts | |
572 | + */ | |
573 | + forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); | |
574 | + break; | |
575 | + | |
576 | + case IPOPT_RR: | |
577 | + if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { | |
578 | + code = &cp[IPOPT_OFFSET] - (u_char *)ip; | |
579 | + goto bad; | |
580 | + } | |
581 | + /* | |
582 | + * If no space remains, ignore. | |
583 | + */ | |
584 | + off--; * 0 origin * | |
585 | + if (off > optlen - sizeof(struct in_addr)) | |
586 | + break; | |
587 | + bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, | |
588 | + sizeof(ipaddr.sin_addr)); | |
589 | + /* | |
590 | + * locate outgoing interface; if we're the destination, | |
591 | + * use the incoming interface (should be same). | |
592 | + */ | |
593 | + if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && | |
594 | + (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { | |
595 | + type = ICMP_UNREACH; | |
596 | + code = ICMP_UNREACH_HOST; | |
597 | + goto bad; | |
598 | + } | |
599 | + bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), | |
600 | + (caddr_t)(cp + off), sizeof(struct in_addr)); | |
601 | + cp[IPOPT_OFFSET] += sizeof(struct in_addr); | |
602 | + break; | |
603 | + | |
604 | + case IPOPT_TS: | |
605 | + code = cp - (u_char *)ip; | |
606 | + ipt = (struct ip_timestamp *)cp; | |
607 | + if (ipt->ipt_len < 5) | |
608 | + goto bad; | |
609 | + if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) { | |
610 | + if (++ipt->ipt_oflw == 0) | |
611 | + goto bad; | |
612 | + break; | |
613 | + } | |
614 | + sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); | |
615 | + switch (ipt->ipt_flg) { | |
616 | + | |
617 | + case IPOPT_TS_TSONLY: | |
618 | + break; | |
619 | + | |
620 | + case IPOPT_TS_TSANDADDR: | |
621 | + if (ipt->ipt_ptr + sizeof(n_time) + | |
622 | + sizeof(struct in_addr) > ipt->ipt_len) | |
623 | + goto bad; | |
624 | + ipaddr.sin_addr = dst; | |
625 | + ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr, | |
626 | + m->m_pkthdr.rcvif); | |
627 | + if (ia == 0) | |
628 | + continue; | |
629 | + bcopy((caddr_t)&IA_SIN(ia)->sin_addr, | |
630 | + (caddr_t)sin, sizeof(struct in_addr)); | |
631 | + ipt->ipt_ptr += sizeof(struct in_addr); | |
632 | + break; | |
633 | + | |
634 | + case IPOPT_TS_PRESPEC: | |
635 | + if (ipt->ipt_ptr + sizeof(n_time) + | |
636 | + sizeof(struct in_addr) > ipt->ipt_len) | |
637 | + goto bad; | |
638 | + bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, | |
639 | + sizeof(struct in_addr)); | |
640 | + if (ifa_ifwithaddr((SA)&ipaddr) == 0) | |
641 | + continue; | |
642 | + ipt->ipt_ptr += sizeof(struct in_addr); | |
643 | + break; | |
644 | + | |
645 | + default: | |
646 | + goto bad; | |
647 | + } | |
648 | + ntime = iptime(); | |
649 | + bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, | |
650 | + sizeof(n_time)); | |
651 | + ipt->ipt_ptr += sizeof(n_time); | |
652 | + } | |
653 | + } | |
654 | + if (forward) { | |
655 | + ip_forward(m, 1); | |
656 | + return (1); | |
657 | + } | |
658 | + } | |
659 | + } | |
660 | + return (0); | |
661 | +bad: | |
662 | + /* ip->ip_len -= ip->ip_hl << 2; XXX icmp_error adds in hdr length */ | |
663 | + | |
664 | +/* Not yet */ | |
665 | + icmp_error(m, type, code, 0, 0); | |
666 | + | |
667 | + ipstat.ips_badoptions++; | |
668 | + return (1); | |
669 | +} | |
670 | + | |
671 | +#endif /* notdef */ | |
672 | + | |
673 | +/* | |
674 | + * Strip out IP options, at higher | |
675 | + * level protocol in the kernel. | |
676 | + * Second argument is buffer to which options | |
677 | + * will be moved, and return value is their length. | |
678 | + * (XXX) should be deleted; last arg currently ignored. | |
679 | + */ | |
680 | +void | |
681 | +ip_stripoptions(m, mopt) | |
682 | + register struct mbuf *m; | |
683 | + struct mbuf *mopt; | |
684 | +{ | |
685 | + register int i; | |
686 | + struct ip *ip = mtod(m, struct ip *); | |
687 | + register caddr_t opts; | |
688 | + int olen; | |
689 | + | |
690 | + olen = (ip->ip_hl<<2) - sizeof (struct ip); | |
691 | + opts = (caddr_t)(ip + 1); | |
692 | + i = m->m_len - (sizeof (struct ip) + olen); | |
693 | + memcpy(opts, opts + olen, (unsigned)i); | |
694 | + m->m_len -= olen; | |
695 | + | |
696 | + ip->ip_hl = sizeof(struct ip) >> 2; | |
697 | +} | ... | ... |
slirp/ip_output.c
0 → 100644
1 | +/* | |
2 | + * Copyright (c) 1982, 1986, 1988, 1990, 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_output.c 8.3 (Berkeley) 1/21/94 | |
34 | + * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp | |
35 | + */ | |
36 | + | |
37 | +/* | |
38 | + * Changes and additions relating to SLiRP are | |
39 | + * Copyright (c) 1995 Danny Gasparovski. | |
40 | + * | |
41 | + * Please read the file COPYRIGHT for the | |
42 | + * terms and conditions of the copyright. | |
43 | + */ | |
44 | + | |
45 | +#include <slirp.h> | |
46 | + | |
47 | +u_int16_t ip_id; | |
48 | + | |
49 | +/* | |
50 | + * IP output. The packet in mbuf chain m contains a skeletal IP | |
51 | + * header (with len, off, ttl, proto, tos, src, dst). | |
52 | + * The mbuf chain containing the packet will be freed. | |
53 | + * The mbuf opt, if present, will not be freed. | |
54 | + */ | |
55 | +int | |
56 | +ip_output(so, m0) | |
57 | + struct socket *so; | |
58 | + struct mbuf *m0; | |
59 | +{ | |
60 | + register struct ip *ip; | |
61 | + register struct mbuf *m = m0; | |
62 | + register int hlen = sizeof(struct ip ); | |
63 | + int len, off, error = 0; | |
64 | + | |
65 | + DEBUG_CALL("ip_output"); | |
66 | + DEBUG_ARG("so = %lx", (long)so); | |
67 | + DEBUG_ARG("m0 = %lx", (long)m0); | |
68 | + | |
69 | + /* We do no options */ | |
70 | +/* if (opt) { | |
71 | + * m = ip_insertoptions(m, opt, &len); | |
72 | + * hlen = len; | |
73 | + * } | |
74 | + */ | |
75 | + ip = mtod(m, struct ip *); | |
76 | + /* | |
77 | + * Fill in IP header. | |
78 | + */ | |
79 | + ip->ip_v = IPVERSION; | |
80 | + ip->ip_off &= IP_DF; | |
81 | + ip->ip_id = htons(ip_id++); | |
82 | + ip->ip_hl = hlen >> 2; | |
83 | + ipstat.ips_localout++; | |
84 | + | |
85 | + /* | |
86 | + * Verify that we have any chance at all of being able to queue | |
87 | + * the packet or packet fragments | |
88 | + */ | |
89 | + /* XXX Hmmm... */ | |
90 | +/* if (if_queued > if_thresh && towrite <= 0) { | |
91 | + * error = ENOBUFS; | |
92 | + * goto bad; | |
93 | + * } | |
94 | + */ | |
95 | + | |
96 | + /* | |
97 | + * If small enough for interface, can just send directly. | |
98 | + */ | |
99 | + if ((u_int16_t)ip->ip_len <= if_mtu) { | |
100 | + ip->ip_len = htons((u_int16_t)ip->ip_len); | |
101 | + ip->ip_off = htons((u_int16_t)ip->ip_off); | |
102 | + ip->ip_sum = 0; | |
103 | + ip->ip_sum = cksum(m, hlen); | |
104 | + | |
105 | + if_output(so, m); | |
106 | + goto done; | |
107 | + } | |
108 | + | |
109 | + /* | |
110 | + * Too large for interface; fragment if possible. | |
111 | + * Must be able to put at least 8 bytes per fragment. | |
112 | + */ | |
113 | + if (ip->ip_off & IP_DF) { | |
114 | + error = -1; | |
115 | + ipstat.ips_cantfrag++; | |
116 | + goto bad; | |
117 | + } | |
118 | + | |
119 | + len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ | |
120 | + if (len < 8) { | |
121 | + error = -1; | |
122 | + goto bad; | |
123 | + } | |
124 | + | |
125 | + { | |
126 | + int mhlen, firstlen = len; | |
127 | + struct mbuf **mnext = &m->m_nextpkt; | |
128 | + | |
129 | + /* | |
130 | + * Loop through length of segment after first fragment, | |
131 | + * make new header and copy data of each part and link onto chain. | |
132 | + */ | |
133 | + m0 = m; | |
134 | + mhlen = sizeof (struct ip); | |
135 | + for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { | |
136 | + register struct ip *mhip; | |
137 | + m = m_get(); | |
138 | + if (m == 0) { | |
139 | + error = -1; | |
140 | + ipstat.ips_odropped++; | |
141 | + goto sendorfree; | |
142 | + } | |
143 | + m->m_data += if_maxlinkhdr; | |
144 | + mhip = mtod(m, struct ip *); | |
145 | + *mhip = *ip; | |
146 | + | |
147 | + /* No options */ | |
148 | +/* if (hlen > sizeof (struct ip)) { | |
149 | + * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); | |
150 | + * mhip->ip_hl = mhlen >> 2; | |
151 | + * } | |
152 | + */ | |
153 | + m->m_len = mhlen; | |
154 | + mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); | |
155 | + if (ip->ip_off & IP_MF) | |
156 | + mhip->ip_off |= IP_MF; | |
157 | + if (off + len >= (u_int16_t)ip->ip_len) | |
158 | + len = (u_int16_t)ip->ip_len - off; | |
159 | + else | |
160 | + mhip->ip_off |= IP_MF; | |
161 | + mhip->ip_len = htons((u_int16_t)(len + mhlen)); | |
162 | + | |
163 | + if (m_copy(m, m0, off, len) < 0) { | |
164 | + error = -1; | |
165 | + goto sendorfree; | |
166 | + } | |
167 | + | |
168 | + mhip->ip_off = htons((u_int16_t)mhip->ip_off); | |
169 | + mhip->ip_sum = 0; | |
170 | + mhip->ip_sum = cksum(m, mhlen); | |
171 | + *mnext = m; | |
172 | + mnext = &m->m_nextpkt; | |
173 | + ipstat.ips_ofragments++; | |
174 | + } | |
175 | + /* | |
176 | + * Update first fragment by trimming what's been copied out | |
177 | + * and updating header, then send each fragment (in order). | |
178 | + */ | |
179 | + m = m0; | |
180 | + m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len); | |
181 | + ip->ip_len = htons((u_int16_t)m->m_len); | |
182 | + ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF)); | |
183 | + ip->ip_sum = 0; | |
184 | + ip->ip_sum = cksum(m, hlen); | |
185 | +sendorfree: | |
186 | + for (m = m0; m; m = m0) { | |
187 | + m0 = m->m_nextpkt; | |
188 | + m->m_nextpkt = 0; | |
189 | + if (error == 0) | |
190 | + if_output(so, m); | |
191 | + else | |
192 | + m_freem(m); | |
193 | + } | |
194 | + | |
195 | + if (error == 0) | |
196 | + ipstat.ips_fragmented++; | |
197 | + } | |
198 | + | |
199 | +done: | |
200 | + return (error); | |
201 | + | |
202 | +bad: | |
203 | + m_freem(m0); | |
204 | + goto done; | |
205 | +} | ... | ... |
slirp/libslirp.h
0 → 100644
1 | +#ifndef _LIBSLIRP_H | |
2 | +#define _LIBSLIRP_H | |
3 | + | |
4 | +#include <sys/select.h> | |
5 | + | |
6 | +void slirp_init(void); | |
7 | + | |
8 | +void slirp_select_fill(int *pnfds, | |
9 | + fd_set *readfds, fd_set *writefds, fd_set *xfds); | |
10 | + | |
11 | +void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds); | |
12 | + | |
13 | +void slirp_input(const uint8_t *pkt, int pkt_len); | |
14 | + | |
15 | +/* you must provide the following functions: */ | |
16 | +int slirp_can_output(void); | |
17 | +void slirp_output(const uint8_t *pkt, int pkt_len); | |
18 | + | |
19 | +#endif | ... | ... |
slirp/main.h
0 → 100644
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 | +#ifdef HAVE_SYS_SELECT_H | |
9 | +#include <sys/select.h> | |
10 | +#endif | |
11 | + | |
12 | +#define TOWRITEMAX 512 | |
13 | +#define min(x,y) ((x) < (y) ? (x) : (y)) | |
14 | + | |
15 | +extern struct timeval tt; | |
16 | +extern int link_up; | |
17 | +extern int slirp_socket; | |
18 | +extern int slirp_socket_unit; | |
19 | +extern int slirp_socket_port; | |
20 | +extern u_int32_t slirp_socket_addr; | |
21 | +extern char *slirp_socket_passwd; | |
22 | +extern int ctty_closed; | |
23 | + | |
24 | +/* | |
25 | + * Get the difference in 2 times from updtim() | |
26 | + * Allow for wraparound times, "just in case" | |
27 | + * x is the greater of the 2 (current time) and y is | |
28 | + * what it's being compared against. | |
29 | + */ | |
30 | +#define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y) | |
31 | + | |
32 | +extern char *slirp_tty; | |
33 | +extern char *exec_shell; | |
34 | +extern u_int curtime; | |
35 | +extern fd_set *global_readfds, *global_writefds, *global_xfds; | |
36 | +extern struct in_addr ctl_addr; | |
37 | +extern struct in_addr special_addr; | |
38 | +extern struct in_addr our_addr; | |
39 | +extern struct in_addr loopback_addr; | |
40 | +extern struct in_addr dns_addr; | |
41 | +extern char *username; | |
42 | +extern char *socket_path; | |
43 | +extern int towrite_max; | |
44 | +extern int ppp_exit; | |
45 | +extern int so_options; | |
46 | +extern int tcp_keepintvl; | |
47 | +extern uint8_t client_ethaddr[6]; | |
48 | + | |
49 | +#define PROTO_SLIP 0x1 | |
50 | +#ifdef USE_PPP | |
51 | +#define PROTO_PPP 0x2 | |
52 | +#endif | |
53 | + | |
54 | +void if_encap(const uint8_t *ip_data, int ip_data_len); | ... | ... |
slirp/mbuf.c
0 → 100644
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 | +/* | |
9 | + * mbuf's in SLiRP are much simpler than the real mbufs in | |
10 | + * FreeBSD. They are fixed size, determined by the MTU, | |
11 | + * so that one whole packet can fit. Mbuf's cannot be | |
12 | + * chained together. If there's more data than the mbuf | |
13 | + * could hold, an external malloced buffer is pointed to | |
14 | + * by m_ext (and the data pointers) and M_EXT is set in | |
15 | + * the flags | |
16 | + */ | |
17 | + | |
18 | +#include <slirp.h> | |
19 | + | |
20 | +struct mbuf *mbutl; | |
21 | +char *mclrefcnt; | |
22 | +int mbuf_alloced = 0; | |
23 | +struct mbuf m_freelist, m_usedlist; | |
24 | +int mbuf_thresh = 30; | |
25 | +int mbuf_max = 0; | |
26 | +int msize; | |
27 | + | |
28 | +void | |
29 | +m_init() | |
30 | +{ | |
31 | + m_freelist.m_next = m_freelist.m_prev = &m_freelist; | |
32 | + m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; | |
33 | + msize_init(); | |
34 | +} | |
35 | + | |
36 | +void | |
37 | +msize_init() | |
38 | +{ | |
39 | + /* | |
40 | + * Find a nice value for msize | |
41 | + * XXX if_maxlinkhdr already in mtu | |
42 | + */ | |
43 | + msize = (if_mtu>if_mru?if_mtu:if_mru) + | |
44 | + if_maxlinkhdr + sizeof(struct m_hdr ) + 6; | |
45 | +} | |
46 | + | |
47 | +/* | |
48 | + * Get an mbuf from the free list, if there are none | |
49 | + * malloc one | |
50 | + * | |
51 | + * Because fragmentation can occur if we alloc new mbufs and | |
52 | + * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, | |
53 | + * which tells m_free to actually free() it | |
54 | + */ | |
55 | +struct mbuf * | |
56 | +m_get() | |
57 | +{ | |
58 | + register struct mbuf *m; | |
59 | + int flags = 0; | |
60 | + | |
61 | + DEBUG_CALL("m_get"); | |
62 | + | |
63 | + if (m_freelist.m_next == &m_freelist) { | |
64 | + m = (struct mbuf *)malloc(msize); | |
65 | + if (m == NULL) goto end_error; | |
66 | + mbuf_alloced++; | |
67 | + if (mbuf_alloced > mbuf_thresh) | |
68 | + flags = M_DOFREE; | |
69 | + if (mbuf_alloced > mbuf_max) | |
70 | + mbuf_max = mbuf_alloced; | |
71 | + } else { | |
72 | + m = m_freelist.m_next; | |
73 | + remque(m); | |
74 | + } | |
75 | + | |
76 | + /* Insert it in the used list */ | |
77 | + insque(m,&m_usedlist); | |
78 | + m->m_flags = (flags | M_USEDLIST); | |
79 | + | |
80 | + /* Initialise it */ | |
81 | + m->m_size = msize - sizeof(struct m_hdr); | |
82 | + m->m_data = m->m_dat; | |
83 | + m->m_len = 0; | |
84 | + m->m_nextpkt = 0; | |
85 | + m->m_prevpkt = 0; | |
86 | +end_error: | |
87 | + DEBUG_ARG("m = %lx", (long )m); | |
88 | + return m; | |
89 | +} | |
90 | + | |
91 | +void | |
92 | +m_free(m) | |
93 | + struct mbuf *m; | |
94 | +{ | |
95 | + | |
96 | + DEBUG_CALL("m_free"); | |
97 | + DEBUG_ARG("m = %lx", (long )m); | |
98 | + | |
99 | + if(m) { | |
100 | + /* Remove from m_usedlist */ | |
101 | + if (m->m_flags & M_USEDLIST) | |
102 | + remque(m); | |
103 | + | |
104 | + /* If it's M_EXT, free() it */ | |
105 | + if (m->m_flags & M_EXT) | |
106 | + free(m->m_ext); | |
107 | + | |
108 | + /* | |
109 | + * Either free() it or put it on the free list | |
110 | + */ | |
111 | + if (m->m_flags & M_DOFREE) { | |
112 | + free(m); | |
113 | + mbuf_alloced--; | |
114 | + } else if ((m->m_flags & M_FREELIST) == 0) { | |
115 | + insque(m,&m_freelist); | |
116 | + m->m_flags = M_FREELIST; /* Clobber other flags */ | |
117 | + } | |
118 | + } /* if(m) */ | |
119 | +} | |
120 | + | |
121 | +/* | |
122 | + * Copy data from one mbuf to the end of | |
123 | + * the other.. if result is too big for one mbuf, malloc() | |
124 | + * an M_EXT data segment | |
125 | + */ | |
126 | +void | |
127 | +m_cat(m, n) | |
128 | + register struct mbuf *m, *n; | |
129 | +{ | |
130 | + /* | |
131 | + * If there's no room, realloc | |
132 | + */ | |
133 | + if (M_FREEROOM(m) < n->m_len) | |
134 | + m_inc(m,m->m_size+MINCSIZE); | |
135 | + | |
136 | + memcpy(m->m_data+m->m_len, n->m_data, n->m_len); | |
137 | + m->m_len += n->m_len; | |
138 | + | |
139 | + m_free(n); | |
140 | +} | |
141 | + | |
142 | + | |
143 | +/* make m size bytes large */ | |
144 | +void | |
145 | +m_inc(m, size) | |
146 | + struct mbuf *m; | |
147 | + int size; | |
148 | +{ | |
149 | + /* some compiles throw up on gotos. This one we can fake. */ | |
150 | + if(m->m_size>size) return; | |
151 | + | |
152 | + if (m->m_flags & M_EXT) { | |
153 | + /* datasize = m->m_data - m->m_ext; */ | |
154 | + m->m_ext = (char *)realloc(m->m_ext,size); | |
155 | +/* if (m->m_ext == NULL) | |
156 | + * return (struct mbuf *)NULL; | |
157 | + */ | |
158 | + /* m->m_data = m->m_ext + datasize; */ | |
159 | + } else { | |
160 | + int datasize; | |
161 | + char *dat; | |
162 | + datasize = m->m_data - m->m_dat; | |
163 | + dat = (char *)malloc(size); | |
164 | +/* if (dat == NULL) | |
165 | + * return (struct mbuf *)NULL; | |
166 | + */ | |
167 | + memcpy(dat, m->m_dat, m->m_size); | |
168 | + | |
169 | + m->m_ext = dat; | |
170 | + m->m_data = m->m_ext + datasize; | |
171 | + m->m_flags |= M_EXT; | |
172 | + } | |
173 | + | |
174 | + m->m_size = size; | |
175 | + | |
176 | +} | |
177 | + | |
178 | + | |
179 | + | |
180 | +void | |
181 | +m_adj(m, len) | |
182 | + struct mbuf *m; | |
183 | + int len; | |
184 | +{ | |
185 | + if (m == NULL) | |
186 | + return; | |
187 | + if (len >= 0) { | |
188 | + /* Trim from head */ | |
189 | + m->m_data += len; | |
190 | + m->m_len -= len; | |
191 | + } else { | |
192 | + /* Trim from tail */ | |
193 | + len = -len; | |
194 | + m->m_len -= len; | |
195 | + } | |
196 | +} | |
197 | + | |
198 | + | |
199 | +/* | |
200 | + * Copy len bytes from m, starting off bytes into n | |
201 | + */ | |
202 | +int | |
203 | +m_copy(n, m, off, len) | |
204 | + struct mbuf *n, *m; | |
205 | + int off, len; | |
206 | +{ | |
207 | + if (len > M_FREEROOM(n)) | |
208 | + return -1; | |
209 | + | |
210 | + memcpy((n->m_data + n->m_len), (m->m_data + off), len); | |
211 | + n->m_len += len; | |
212 | + return 0; | |
213 | +} | |
214 | + | |
215 | + | |
216 | +/* | |
217 | + * Given a pointer into an mbuf, return the mbuf | |
218 | + * XXX This is a kludge, I should eliminate the need for it | |
219 | + * Fortunately, it's not used often | |
220 | + */ | |
221 | +struct mbuf * | |
222 | +dtom(dat) | |
223 | + void *dat; | |
224 | +{ | |
225 | + struct mbuf *m; | |
226 | + | |
227 | + DEBUG_CALL("dtom"); | |
228 | + DEBUG_ARG("dat = %lx", (long )dat); | |
229 | + | |
230 | + /* bug corrected for M_EXT buffers */ | |
231 | + for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) { | |
232 | + if (m->m_flags & M_EXT) { | |
233 | + if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) | |
234 | + return m; | |
235 | + } else { | |
236 | + if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) ) | |
237 | + return m; | |
238 | + } | |
239 | + } | |
240 | + | |
241 | + DEBUG_ERROR((dfd, "dtom failed")); | |
242 | + | |
243 | + return (struct mbuf *)0; | |
244 | +} | |
245 | + | ... | ... |
slirp/mbuf.h
0 → 100644
1 | +/* | |
2 | + * Copyright (c) 1982, 1986, 1988, 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 | + * @(#)mbuf.h 8.3 (Berkeley) 1/21/94 | |
34 | + * mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp | |
35 | + */ | |
36 | + | |
37 | +#ifndef _MBUF_H_ | |
38 | +#define _MBUF_H_ | |
39 | + | |
40 | +#define m_freem m_free | |
41 | + | |
42 | + | |
43 | +#define MINCSIZE 4096 /* Amount to increase mbuf if too small */ | |
44 | + | |
45 | +/* | |
46 | + * Macros for type conversion | |
47 | + * mtod(m,t) - convert mbuf pointer to data pointer of correct type | |
48 | + * dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX) | |
49 | + */ | |
50 | +#define mtod(m,t) ((t)(m)->m_data) | |
51 | +/* #define dtom(x) ((struct mbuf *)((int)(x) & ~(M_SIZE-1))) */ | |
52 | + | |
53 | +/* XXX About mbufs for slirp: | |
54 | + * Only one mbuf is ever used in a chain, for each "cell" of data. | |
55 | + * m_nextpkt points to the next packet, if fragmented. | |
56 | + * If the data is too large, the M_EXT is used, and a larger block | |
57 | + * is alloced. Therefore, m_free[m] must check for M_EXT and if set | |
58 | + * free the m_ext. This is inefficient memory-wise, but who cares. | |
59 | + */ | |
60 | + | |
61 | +/* XXX should union some of these! */ | |
62 | +/* header at beginning of each mbuf: */ | |
63 | +struct m_hdr { | |
64 | + struct mbuf *mh_next; /* Linked list of mbufs */ | |
65 | + struct mbuf *mh_prev; | |
66 | + struct mbuf *mh_nextpkt; /* Next packet in queue/record */ | |
67 | + struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ | |
68 | + int mh_flags; /* Misc flags */ | |
69 | + | |
70 | + int mh_size; /* Size of data */ | |
71 | + struct socket *mh_so; | |
72 | + | |
73 | + caddr_t mh_data; /* Location of data */ | |
74 | + int mh_len; /* Amount of data in this mbuf */ | |
75 | +}; | |
76 | + | |
77 | +/* | |
78 | + * How much room is in the mbuf, from m_data to the end of the mbuf | |
79 | + */ | |
80 | +#define M_ROOM(m) ((m->m_flags & M_EXT)? \ | |
81 | + (((m)->m_ext + (m)->m_size) - (m)->m_data) \ | |
82 | + : \ | |
83 | + (((m)->m_dat + (m)->m_size) - (m)->m_data)) | |
84 | + | |
85 | +/* | |
86 | + * How much free room there is | |
87 | + */ | |
88 | +#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len) | |
89 | +#define M_TRAILINGSPACE M_FREEROOM | |
90 | + | |
91 | +struct mbuf { | |
92 | + struct m_hdr m_hdr; | |
93 | + union M_dat { | |
94 | + char m_dat_[1]; /* ANSI don't like 0 sized arrays */ | |
95 | + char *m_ext_; | |
96 | + } M_dat; | |
97 | +}; | |
98 | + | |
99 | +#define m_next m_hdr.mh_next | |
100 | +#define m_prev m_hdr.mh_prev | |
101 | +#define m_nextpkt m_hdr.mh_nextpkt | |
102 | +#define m_prevpkt m_hdr.mh_prevpkt | |
103 | +#define m_flags m_hdr.mh_flags | |
104 | +#define m_len m_hdr.mh_len | |
105 | +#define m_data m_hdr.mh_data | |
106 | +#define m_size m_hdr.mh_size | |
107 | +#define m_dat M_dat.m_dat_ | |
108 | +#define m_ext M_dat.m_ext_ | |
109 | +#define m_so m_hdr.mh_so | |
110 | + | |
111 | +#define ifq_prev m_prev | |
112 | +#define ifq_next m_next | |
113 | +#define ifs_prev m_prevpkt | |
114 | +#define ifs_next m_nextpkt | |
115 | +#define ifq_so m_so | |
116 | + | |
117 | +#define M_EXT 0x01 /* m_ext points to more (malloced) data */ | |
118 | +#define M_FREELIST 0x02 /* mbuf is on free list */ | |
119 | +#define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */ | |
120 | +#define M_DOFREE 0x08 /* when m_free is called on the mbuf, free() | |
121 | + * it rather than putting it on the free list */ | |
122 | + | |
123 | +/* | |
124 | + * Mbuf statistics. XXX | |
125 | + */ | |
126 | + | |
127 | +struct mbstat { | |
128 | + int mbs_alloced; /* Number of mbufs allocated */ | |
129 | + | |
130 | +}; | |
131 | + | |
132 | +extern struct mbstat mbstat; | |
133 | +extern int mbuf_alloced; | |
134 | +extern struct mbuf m_freelist, m_usedlist; | |
135 | +extern int mbuf_max; | |
136 | + | |
137 | +void m_init _P((void)); | |
138 | +void msize_init _P((void)); | |
139 | +struct mbuf * m_get _P((void)); | |
140 | +void m_free _P((struct mbuf *)); | |
141 | +void m_cat _P((register struct mbuf *, register struct mbuf *)); | |
142 | +void m_inc _P((struct mbuf *, int)); | |
143 | +void m_adj _P((struct mbuf *, int)); | |
144 | +int m_copy _P((struct mbuf *, struct mbuf *, int, int)); | |
145 | +struct mbuf * dtom _P((void *)); | |
146 | + | |
147 | +#endif | ... | ... |
slirp/misc.c
0 → 100644
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 WANT_SYS_IOCTL_H | |
9 | +#include <slirp.h> | |
10 | + | |
11 | +u_int curtime, time_fasttimo, last_slowtimo, detach_time; | |
12 | +u_int detach_wait = 600000; /* 10 minutes */ | |
13 | + | |
14 | +#if 0 | |
15 | +int x_port = -1; | |
16 | +int x_display = 0; | |
17 | +int x_screen = 0; | |
18 | + | |
19 | +int | |
20 | +show_x(buff, inso) | |
21 | + char *buff; | |
22 | + struct socket *inso; | |
23 | +{ | |
24 | + if (x_port < 0) { | |
25 | + lprint("X Redir: X not being redirected.\r\n"); | |
26 | + } else { | |
27 | + lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n", | |
28 | + inet_ntoa(our_addr), x_port, x_screen); | |
29 | + lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n", | |
30 | + inet_ntoa(our_addr), x_port, x_screen); | |
31 | + if (x_display) | |
32 | + lprint("X Redir: Redirecting to display %d\r\n", x_display); | |
33 | + } | |
34 | + | |
35 | + return CFG_OK; | |
36 | +} | |
37 | + | |
38 | + | |
39 | +/* | |
40 | + * XXX Allow more than one X redirection? | |
41 | + */ | |
42 | +void | |
43 | +redir_x(inaddr, start_port, display, screen) | |
44 | + u_int32_t inaddr; | |
45 | + int start_port; | |
46 | + int display; | |
47 | + int screen; | |
48 | +{ | |
49 | + int i; | |
50 | + | |
51 | + if (x_port >= 0) { | |
52 | + lprint("X Redir: X already being redirected.\r\n"); | |
53 | + show_x(0, 0); | |
54 | + } else { | |
55 | + for (i = 6001 + (start_port-1); i <= 6100; i++) { | |
56 | + if (solisten(htons(i), inaddr, htons(6000 + display), 0)) { | |
57 | + /* Success */ | |
58 | + x_port = i - 6000; | |
59 | + x_display = display; | |
60 | + x_screen = screen; | |
61 | + show_x(0, 0); | |
62 | + return; | |
63 | + } | |
64 | + } | |
65 | + lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n"); | |
66 | + } | |
67 | +} | |
68 | +#endif | |
69 | + | |
70 | +#ifndef HAVE_INET_ATON | |
71 | +int | |
72 | +inet_aton(cp, ia) | |
73 | + const char *cp; | |
74 | + struct in_addr *ia; | |
75 | +{ | |
76 | + u_int32_t addr = inet_addr(cp); | |
77 | + if (addr == 0xffffffff) | |
78 | + return 0; | |
79 | + ia->s_addr = addr; | |
80 | + return 1; | |
81 | +} | |
82 | +#endif | |
83 | + | |
84 | +/* | |
85 | + * Get our IP address and put it in our_addr | |
86 | + */ | |
87 | +void | |
88 | +getouraddr() | |
89 | +{ | |
90 | + char buff[256]; | |
91 | + struct hostent *he; | |
92 | + | |
93 | + if (gethostname(buff,256) < 0) | |
94 | + return; | |
95 | + | |
96 | + if ((he = gethostbyname(buff)) == NULL) | |
97 | + return; | |
98 | + | |
99 | + our_addr = *(struct in_addr *)he->h_addr; | |
100 | +} | |
101 | + | |
102 | +#if SIZEOF_CHAR_P == 8 | |
103 | + | |
104 | +struct quehead_32 { | |
105 | + u_int32_t qh_link; | |
106 | + u_int32_t qh_rlink; | |
107 | +}; | |
108 | + | |
109 | +inline void | |
110 | +insque_32(a, b) | |
111 | + void *a; | |
112 | + void *b; | |
113 | +{ | |
114 | + register struct quehead_32 *element = (struct quehead_32 *) a; | |
115 | + register struct quehead_32 *head = (struct quehead_32 *) b; | |
116 | + element->qh_link = head->qh_link; | |
117 | + head->qh_link = (u_int32_t)element; | |
118 | + element->qh_rlink = (u_int32_t)head; | |
119 | + ((struct quehead_32 *)(element->qh_link))->qh_rlink | |
120 | + = (u_int32_t)element; | |
121 | +} | |
122 | + | |
123 | +inline void | |
124 | +remque_32(a) | |
125 | + void *a; | |
126 | +{ | |
127 | + register struct quehead_32 *element = (struct quehead_32 *) a; | |
128 | + ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; | |
129 | + ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link; | |
130 | + element->qh_rlink = 0; | |
131 | +} | |
132 | + | |
133 | +#endif /* SIZEOF_CHAR_P == 8 */ | |
134 | + | |
135 | +struct quehead { | |
136 | + struct quehead *qh_link; | |
137 | + struct quehead *qh_rlink; | |
138 | +}; | |
139 | + | |
140 | +inline void | |
141 | +insque(a, b) | |
142 | + void *a, *b; | |
143 | +{ | |
144 | + register struct quehead *element = (struct quehead *) a; | |
145 | + register struct quehead *head = (struct quehead *) b; | |
146 | + element->qh_link = head->qh_link; | |
147 | + head->qh_link = (struct quehead *)element; | |
148 | + element->qh_rlink = (struct quehead *)head; | |
149 | + ((struct quehead *)(element->qh_link))->qh_rlink | |
150 | + = (struct quehead *)element; | |
151 | +} | |
152 | + | |
153 | +inline void | |
154 | +remque(a) | |
155 | + void *a; | |
156 | +{ | |
157 | + register struct quehead *element = (struct quehead *) a; | |
158 | + ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; | |
159 | + ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link; | |
160 | + element->qh_rlink = NULL; | |
161 | + /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */ | |
162 | +} | |
163 | + | |
164 | +/* #endif */ | |
165 | + | |
166 | + | |
167 | +int | |
168 | +add_exec(ex_ptr, do_pty, exec, addr, port) | |
169 | + struct ex_list **ex_ptr; | |
170 | + int do_pty; | |
171 | + char *exec; | |
172 | + int addr; | |
173 | + int port; | |
174 | +{ | |
175 | + struct ex_list *tmp_ptr; | |
176 | + | |
177 | + /* First, check if the port is "bound" */ | |
178 | + for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { | |
179 | + if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) | |
180 | + return -1; | |
181 | + } | |
182 | + | |
183 | + tmp_ptr = *ex_ptr; | |
184 | + *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); | |
185 | + (*ex_ptr)->ex_fport = port; | |
186 | + (*ex_ptr)->ex_addr = addr; | |
187 | + (*ex_ptr)->ex_pty = do_pty; | |
188 | + (*ex_ptr)->ex_exec = strdup(exec); | |
189 | + (*ex_ptr)->ex_next = tmp_ptr; | |
190 | + return 0; | |
191 | +} | |
192 | + | |
193 | +#ifndef HAVE_STRERROR | |
194 | + | |
195 | +/* | |
196 | + * For systems with no strerror | |
197 | + */ | |
198 | + | |
199 | +extern int sys_nerr; | |
200 | +extern char *sys_errlist[]; | |
201 | + | |
202 | +char * | |
203 | +strerror(error) | |
204 | + int error; | |
205 | +{ | |
206 | + if (error < sys_nerr) | |
207 | + return sys_errlist[error]; | |
208 | + else | |
209 | + return "Unknown error."; | |
210 | +} | |
211 | + | |
212 | +#endif | |
213 | + | |
214 | + | |
215 | +#if 0 | |
216 | +int | |
217 | +openpty(amaster, aslave) | |
218 | + int *amaster, *aslave; | |
219 | +{ | |
220 | + register int master, slave; | |
221 | + | |
222 | +#ifdef HAVE_GRANTPT | |
223 | + char *ptr; | |
224 | + | |
225 | + if ((master = open("/dev/ptmx", O_RDWR)) < 0 || | |
226 | + grantpt(master) < 0 || | |
227 | + unlockpt(master) < 0 || | |
228 | + (ptr = ptsname(master)) == NULL) { | |
229 | + close(master); | |
230 | + return -1; | |
231 | + } | |
232 | + | |
233 | + if ((slave = open(ptr, O_RDWR)) < 0 || | |
234 | + ioctl(slave, I_PUSH, "ptem") < 0 || | |
235 | + ioctl(slave, I_PUSH, "ldterm") < 0 || | |
236 | + ioctl(slave, I_PUSH, "ttcompat") < 0) { | |
237 | + close(master); | |
238 | + close(slave); | |
239 | + return -1; | |
240 | + } | |
241 | + | |
242 | + *amaster = master; | |
243 | + *aslave = slave; | |
244 | + return 0; | |
245 | + | |
246 | +#else | |
247 | + | |
248 | + static char line[] = "/dev/ptyXX"; | |
249 | + register const char *cp1, *cp2; | |
250 | + | |
251 | + for (cp1 = "pqrsPQRS"; *cp1; cp1++) { | |
252 | + line[8] = *cp1; | |
253 | + for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { | |
254 | + line[9] = *cp2; | |
255 | + if ((master = open(line, O_RDWR, 0)) == -1) { | |
256 | + if (errno == ENOENT) | |
257 | + return (-1); /* out of ptys */ | |
258 | + } else { | |
259 | + line[5] = 't'; | |
260 | + /* These will fail */ | |
261 | + (void) chown(line, getuid(), 0); | |
262 | + (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); | |
263 | +#ifdef HAVE_REVOKE | |
264 | + (void) revoke(line); | |
265 | +#endif | |
266 | + if ((slave = open(line, O_RDWR, 0)) != -1) { | |
267 | + *amaster = master; | |
268 | + *aslave = slave; | |
269 | + return 0; | |
270 | + } | |
271 | + (void) close(master); | |
272 | + line[5] = 'p'; | |
273 | + } | |
274 | + } | |
275 | + } | |
276 | + errno = ENOENT; /* out of ptys */ | |
277 | + return (-1); | |
278 | +#endif | |
279 | +} | |
280 | + | |
281 | +/* | |
282 | + * XXX This is ugly | |
283 | + * We create and bind a socket, then fork off to another | |
284 | + * process, which connects to this socket, after which we | |
285 | + * exec the wanted program. If something (strange) happens, | |
286 | + * the accept() call could block us forever. | |
287 | + * | |
288 | + * do_pty = 0 Fork/exec inetd style | |
289 | + * do_pty = 1 Fork/exec using slirp.telnetd | |
290 | + * do_ptr = 2 Fork/exec using pty | |
291 | + */ | |
292 | +int | |
293 | +fork_exec(so, ex, do_pty) | |
294 | + struct socket *so; | |
295 | + char *ex; | |
296 | + int do_pty; | |
297 | +{ | |
298 | + int s; | |
299 | + struct sockaddr_in addr; | |
300 | + int addrlen = sizeof(addr); | |
301 | + int opt; | |
302 | + int master; | |
303 | + char *argv[256]; | |
304 | + char buff[256]; | |
305 | + /* don't want to clobber the original */ | |
306 | + char *bptr; | |
307 | + char *curarg; | |
308 | + int c, i; | |
309 | + | |
310 | + DEBUG_CALL("fork_exec"); | |
311 | + DEBUG_ARG("so = %lx", (long)so); | |
312 | + DEBUG_ARG("ex = %lx", (long)ex); | |
313 | + DEBUG_ARG("do_pty = %lx", (long)do_pty); | |
314 | + | |
315 | + if (do_pty == 2) { | |
316 | + if (openpty(&master, &s) == -1) { | |
317 | + lprint("Error: openpty failed: %s\n", strerror(errno)); | |
318 | + return 0; | |
319 | + } | |
320 | + } else { | |
321 | + addr.sin_family = AF_INET; | |
322 | + addr.sin_port = 0; | |
323 | + addr.sin_addr.s_addr = INADDR_ANY; | |
324 | + | |
325 | + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || | |
326 | + bind(s, (struct sockaddr *)&addr, addrlen) < 0 || | |
327 | + listen(s, 1) < 0) { | |
328 | + lprint("Error: inet socket: %s\n", strerror(errno)); | |
329 | + close(s); | |
330 | + | |
331 | + return 0; | |
332 | + } | |
333 | + } | |
334 | + | |
335 | + switch(fork()) { | |
336 | + case -1: | |
337 | + lprint("Error: fork failed: %s\n", strerror(errno)); | |
338 | + close(s); | |
339 | + if (do_pty == 2) | |
340 | + close(master); | |
341 | + return 0; | |
342 | + | |
343 | + case 0: | |
344 | + /* Set the DISPLAY */ | |
345 | + if (do_pty == 2) { | |
346 | + (void) close(master); | |
347 | +#ifdef TIOCSCTTY /* XXXXX */ | |
348 | + (void) setsid(); | |
349 | + ioctl(s, TIOCSCTTY, (char *)NULL); | |
350 | +#endif | |
351 | + } else { | |
352 | + getsockname(s, (struct sockaddr *)&addr, &addrlen); | |
353 | + close(s); | |
354 | + /* | |
355 | + * Connect to the socket | |
356 | + * XXX If any of these fail, we're in trouble! | |
357 | + */ | |
358 | + s = socket(AF_INET, SOCK_STREAM, 0); | |
359 | + addr.sin_addr = loopback_addr; | |
360 | + connect(s, (struct sockaddr *)&addr, addrlen); | |
361 | + } | |
362 | + | |
363 | + if (x_port >= 0) { | |
364 | +#ifdef HAVE_SETENV | |
365 | + sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); | |
366 | + setenv("DISPLAY", buff, 1); | |
367 | +#else | |
368 | + sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); | |
369 | + putenv(buff); | |
370 | +#endif | |
371 | + } | |
372 | + | |
373 | + dup2(s, 0); | |
374 | + dup2(s, 1); | |
375 | + dup2(s, 2); | |
376 | + for (s = 3; s <= 255; s++) | |
377 | + close(s); | |
378 | + | |
379 | + i = 0; | |
380 | + bptr = strdup(ex); /* No need to free() this */ | |
381 | + if (do_pty == 1) { | |
382 | + /* Setup "slirp.telnetd -x" */ | |
383 | + argv[i++] = "slirp.telnetd"; | |
384 | + argv[i++] = "-x"; | |
385 | + argv[i++] = bptr; | |
386 | + } else | |
387 | + do { | |
388 | + /* Change the string into argv[] */ | |
389 | + curarg = bptr; | |
390 | + while (*bptr != ' ' && *bptr != (char)0) | |
391 | + bptr++; | |
392 | + c = *bptr; | |
393 | + *bptr++ = (char)0; | |
394 | + argv[i++] = strdup(curarg); | |
395 | + } while (c); | |
396 | + | |
397 | + argv[i] = 0; | |
398 | + execvp(argv[0], argv); | |
399 | + | |
400 | + /* Ooops, failed, let's tell the user why */ | |
401 | + { | |
402 | + char buff[256]; | |
403 | + | |
404 | + sprintf(buff, "Error: execvp of %s failed: %s\n", | |
405 | + argv[0], strerror(errno)); | |
406 | + write(2, buff, strlen(buff)+1); | |
407 | + } | |
408 | + close(0); close(1); close(2); /* XXX */ | |
409 | + exit(1); | |
410 | + | |
411 | + default: | |
412 | + if (do_pty == 2) { | |
413 | + close(s); | |
414 | + so->s = master; | |
415 | + } else { | |
416 | + /* | |
417 | + * XXX this could block us... | |
418 | + * XXX Should set a timer here, and if accept() doesn't | |
419 | + * return after X seconds, declare it a failure | |
420 | + * The only reason this will block forever is if socket() | |
421 | + * of connect() fail in the child process | |
422 | + */ | |
423 | + so->s = accept(s, (struct sockaddr *)&addr, &addrlen); | |
424 | + close(s); | |
425 | + opt = 1; | |
426 | + setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); | |
427 | + opt = 1; | |
428 | + setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); | |
429 | + } | |
430 | + fd_nonblock(so->s); | |
431 | + | |
432 | + /* Append the telnet options now */ | |
433 | + if (so->so_m != 0 && do_pty == 1) { | |
434 | + sbappend(so, so->so_m); | |
435 | + so->so_m = 0; | |
436 | + } | |
437 | + | |
438 | + return 1; | |
439 | + } | |
440 | +} | |
441 | +#endif | |
442 | + | |
443 | +#ifndef HAVE_STRDUP | |
444 | +char * | |
445 | +strdup(str) | |
446 | + const char *str; | |
447 | +{ | |
448 | + char *bptr; | |
449 | + | |
450 | + bptr = (char *)malloc(strlen(str)+1); | |
451 | + strcpy(bptr, str); | |
452 | + | |
453 | + return bptr; | |
454 | +} | |
455 | +#endif | |
456 | + | |
457 | +#if 0 | |
458 | +void | |
459 | +snooze_hup(num) | |
460 | + int num; | |
461 | +{ | |
462 | + int s, ret; | |
463 | +#ifndef NO_UNIX_SOCKETS | |
464 | + struct sockaddr_un sock_un; | |
465 | +#endif | |
466 | + struct sockaddr_in sock_in; | |
467 | + char buff[256]; | |
468 | + | |
469 | + ret = -1; | |
470 | + if (slirp_socket_passwd) { | |
471 | + s = socket(AF_INET, SOCK_STREAM, 0); | |
472 | + if (s < 0) | |
473 | + slirp_exit(1); | |
474 | + sock_in.sin_family = AF_INET; | |
475 | + sock_in.sin_addr.s_addr = slirp_socket_addr; | |
476 | + sock_in.sin_port = htons(slirp_socket_port); | |
477 | + if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0) | |
478 | + slirp_exit(1); /* just exit...*/ | |
479 | + sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit); | |
480 | + write(s, buff, strlen(buff)+1); | |
481 | + } | |
482 | +#ifndef NO_UNIX_SOCKETS | |
483 | + else { | |
484 | + s = socket(AF_UNIX, SOCK_STREAM, 0); | |
485 | + if (s < 0) | |
486 | + slirp_exit(1); | |
487 | + sock_un.sun_family = AF_UNIX; | |
488 | + strcpy(sock_un.sun_path, socket_path); | |
489 | + if (connect(s, (struct sockaddr *)&sock_un, | |
490 | + sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0) | |
491 | + slirp_exit(1); | |
492 | + sprintf(buff, "kill none:%d", slirp_socket_unit); | |
493 | + write(s, buff, strlen(buff)+1); | |
494 | + } | |
495 | +#endif | |
496 | + slirp_exit(0); | |
497 | +} | |
498 | + | |
499 | + | |
500 | +void | |
501 | +snooze() | |
502 | +{ | |
503 | + sigset_t s; | |
504 | + int i; | |
505 | + | |
506 | + /* Don't need our data anymore */ | |
507 | + /* XXX This makes SunOS barf */ | |
508 | +/* brk(0); */ | |
509 | + | |
510 | + /* Close all fd's */ | |
511 | + for (i = 255; i >= 0; i--) | |
512 | + close(i); | |
513 | + | |
514 | + signal(SIGQUIT, slirp_exit); | |
515 | + signal(SIGHUP, snooze_hup); | |
516 | + sigemptyset(&s); | |
517 | + | |
518 | + /* Wait for any signal */ | |
519 | + sigsuspend(&s); | |
520 | + | |
521 | + /* Just in case ... */ | |
522 | + exit(255); | |
523 | +} | |
524 | + | |
525 | +void | |
526 | +relay(s) | |
527 | + int s; | |
528 | +{ | |
529 | + char buf[8192]; | |
530 | + int n; | |
531 | + fd_set readfds; | |
532 | + struct ttys *ttyp; | |
533 | + | |
534 | + /* Don't need our data anymore */ | |
535 | + /* XXX This makes SunOS barf */ | |
536 | +/* brk(0); */ | |
537 | + | |
538 | + signal(SIGQUIT, slirp_exit); | |
539 | + signal(SIGHUP, slirp_exit); | |
540 | + signal(SIGINT, slirp_exit); | |
541 | + signal(SIGTERM, slirp_exit); | |
542 | + | |
543 | + /* Fudge to get term_raw and term_restore to work */ | |
544 | + if (NULL == (ttyp = tty_attach (0, slirp_tty))) { | |
545 | + lprint ("Error: tty_attach failed in misc.c:relay()\r\n"); | |
546 | + slirp_exit (1); | |
547 | + } | |
548 | + ttyp->fd = 0; | |
549 | + ttyp->flags |= TTY_CTTY; | |
550 | + term_raw(ttyp); | |
551 | + | |
552 | + while (1) { | |
553 | + FD_ZERO(&readfds); | |
554 | + | |
555 | + FD_SET(0, &readfds); | |
556 | + FD_SET(s, &readfds); | |
557 | + | |
558 | + n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); | |
559 | + | |
560 | + if (n <= 0) | |
561 | + slirp_exit(0); | |
562 | + | |
563 | + if (FD_ISSET(0, &readfds)) { | |
564 | + n = read(0, buf, 8192); | |
565 | + if (n <= 0) | |
566 | + slirp_exit(0); | |
567 | + n = writen(s, buf, n); | |
568 | + if (n <= 0) | |
569 | + slirp_exit(0); | |
570 | + } | |
571 | + | |
572 | + if (FD_ISSET(s, &readfds)) { | |
573 | + n = read(s, buf, 8192); | |
574 | + if (n <= 0) | |
575 | + slirp_exit(0); | |
576 | + n = writen(0, buf, n); | |
577 | + if (n <= 0) | |
578 | + slirp_exit(0); | |
579 | + } | |
580 | + } | |
581 | + | |
582 | + /* Just in case.... */ | |
583 | + exit(1); | |
584 | +} | |
585 | +#endif | |
586 | + | |
587 | +int (*lprint_print) _P((void *, const char *, va_list)); | |
588 | +char *lprint_ptr, *lprint_ptr2, **lprint_arg; | |
589 | + | |
590 | +void | |
591 | +#ifdef __STDC__ | |
592 | +lprint(const char *format, ...) | |
593 | +#else | |
594 | +lprint(va_alist) va_dcl | |
595 | +#endif | |
596 | +{ | |
597 | + va_list args; | |
598 | + | |
599 | +#ifdef __STDC__ | |
600 | + va_start(args, format); | |
601 | +#else | |
602 | + char *format; | |
603 | + va_start(args); | |
604 | + format = va_arg(args, char *); | |
605 | +#endif | |
606 | +#if 0 | |
607 | + /* If we're printing to an sbuf, make sure there's enough room */ | |
608 | + /* XXX +100? */ | |
609 | + if (lprint_sb) { | |
610 | + if ((lprint_ptr - lprint_sb->sb_wptr) >= | |
611 | + (lprint_sb->sb_datalen - (strlen(format) + 100))) { | |
612 | + int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data; | |
613 | + int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data; | |
614 | + int deltap = lprint_ptr - lprint_sb->sb_data; | |
615 | + | |
616 | + lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data, | |
617 | + lprint_sb->sb_datalen + TCP_SNDSPACE); | |
618 | + | |
619 | + /* Adjust all values */ | |
620 | + lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw; | |
621 | + lprint_sb->sb_rptr = lprint_sb->sb_data + deltar; | |
622 | + lprint_ptr = lprint_sb->sb_data + deltap; | |
623 | + | |
624 | + lprint_sb->sb_datalen += TCP_SNDSPACE; | |
625 | + } | |
626 | + } | |
627 | +#endif | |
628 | + if (lprint_print) | |
629 | + lprint_ptr += (*lprint_print)(*lprint_arg, format, args); | |
630 | + | |
631 | + /* Check if they want output to be logged to file as well */ | |
632 | + if (lfd) { | |
633 | + /* | |
634 | + * Remove \r's | |
635 | + * otherwise you'll get ^M all over the file | |
636 | + */ | |
637 | + int len = strlen(format); | |
638 | + char *bptr1, *bptr2; | |
639 | + | |
640 | + bptr1 = bptr2 = strdup(format); | |
641 | + | |
642 | + while (len--) { | |
643 | + if (*bptr1 == '\r') | |
644 | + memcpy(bptr1, bptr1+1, len+1); | |
645 | + else | |
646 | + bptr1++; | |
647 | + } | |
648 | + vfprintf(lfd, bptr2, args); | |
649 | + free(bptr2); | |
650 | + } | |
651 | + va_end(args); | |
652 | +} | |
653 | + | |
654 | +void | |
655 | +add_emu(buff) | |
656 | + char *buff; | |
657 | +{ | |
658 | + u_int lport, fport; | |
659 | + u_int8_t tos = 0, emu = 0; | |
660 | + char buff1[256], buff2[256], buff4[128]; | |
661 | + char *buff3 = buff4; | |
662 | + struct emu_t *emup; | |
663 | + struct socket *so; | |
664 | + | |
665 | + if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) { | |
666 | + lprint("Error: Bad arguments\r\n"); | |
667 | + return; | |
668 | + } | |
669 | + | |
670 | + if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) { | |
671 | + lport = 0; | |
672 | + if (sscanf(buff1, "%d", &fport) != 1) { | |
673 | + lprint("Error: Bad first argument\r\n"); | |
674 | + return; | |
675 | + } | |
676 | + } | |
677 | + | |
678 | + if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) { | |
679 | + buff3 = 0; | |
680 | + if (sscanf(buff2, "%256s", buff1) != 1) { | |
681 | + lprint("Error: Bad second argument\r\n"); | |
682 | + return; | |
683 | + } | |
684 | + } | |
685 | + | |
686 | + if (buff3) { | |
687 | + if (strcmp(buff3, "lowdelay") == 0) | |
688 | + tos = IPTOS_LOWDELAY; | |
689 | + else if (strcmp(buff3, "throughput") == 0) | |
690 | + tos = IPTOS_THROUGHPUT; | |
691 | + else { | |
692 | + lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n"); | |
693 | + return; | |
694 | + } | |
695 | + } | |
696 | + | |
697 | + if (strcmp(buff1, "ftp") == 0) | |
698 | + emu = EMU_FTP; | |
699 | + else if (strcmp(buff1, "irc") == 0) | |
700 | + emu = EMU_IRC; | |
701 | + else if (strcmp(buff1, "none") == 0) | |
702 | + emu = EMU_NONE; /* ie: no emulation */ | |
703 | + else { | |
704 | + lprint("Error: Unknown service\r\n"); | |
705 | + return; | |
706 | + } | |
707 | + | |
708 | + /* First, check that it isn't already emulated */ | |
709 | + for (emup = tcpemu; emup; emup = emup->next) { | |
710 | + if (emup->lport == lport && emup->fport == fport) { | |
711 | + lprint("Error: port already emulated\r\n"); | |
712 | + return; | |
713 | + } | |
714 | + } | |
715 | + | |
716 | + /* link it */ | |
717 | + emup = (struct emu_t *)malloc(sizeof (struct emu_t)); | |
718 | + emup->lport = (u_int16_t)lport; | |
719 | + emup->fport = (u_int16_t)fport; | |
720 | + emup->tos = tos; | |
721 | + emup->emu = emu; | |
722 | + emup->next = tcpemu; | |
723 | + tcpemu = emup; | |
724 | + | |
725 | + /* And finally, mark all current sessions, if any, as being emulated */ | |
726 | + for (so = tcb.so_next; so != &tcb; so = so->so_next) { | |
727 | + if ((lport && lport == ntohs(so->so_lport)) || | |
728 | + (fport && fport == ntohs(so->so_fport))) { | |
729 | + if (emu) | |
730 | + so->so_emu = emu; | |
731 | + if (tos) | |
732 | + so->so_iptos = tos; | |
733 | + } | |
734 | + } | |
735 | + | |
736 | + lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); | |
737 | +} | |
738 | + | |
739 | +#ifdef BAD_SPRINTF | |
740 | + | |
741 | +#undef vsprintf | |
742 | +#undef sprintf | |
743 | + | |
744 | +/* | |
745 | + * Some BSD-derived systems have a sprintf which returns char * | |
746 | + */ | |
747 | + | |
748 | +int | |
749 | +vsprintf_len(string, format, args) | |
750 | + char *string; | |
751 | + const char *format; | |
752 | + va_list args; | |
753 | +{ | |
754 | + vsprintf(string, format, args); | |
755 | + return strlen(string); | |
756 | +} | |
757 | + | |
758 | +int | |
759 | +#ifdef __STDC__ | |
760 | +sprintf_len(char *string, const char *format, ...) | |
761 | +#else | |
762 | +sprintf_len(va_alist) va_dcl | |
763 | +#endif | |
764 | +{ | |
765 | + va_list args; | |
766 | +#ifdef __STDC__ | |
767 | + va_start(args, format); | |
768 | +#else | |
769 | + char *string; | |
770 | + char *format; | |
771 | + va_start(args); | |
772 | + string = va_arg(args, char *); | |
773 | + format = va_arg(args, char *); | |
774 | +#endif | |
775 | + vsprintf(string, format, args); | |
776 | + return strlen(string); | |
777 | +} | |
778 | + | |
779 | +#endif | |
780 | + | |
781 | +void | |
782 | +u_sleep(usec) | |
783 | + int usec; | |
784 | +{ | |
785 | + struct timeval t; | |
786 | + fd_set fdset; | |
787 | + | |
788 | + FD_ZERO(&fdset); | |
789 | + | |
790 | + t.tv_sec = 0; | |
791 | + t.tv_usec = usec * 1000; | |
792 | + | |
793 | + select(0, &fdset, &fdset, &fdset, &t); | |
794 | +} | |
795 | + | |
796 | +/* | |
797 | + * Set fd blocking and non-blocking | |
798 | + */ | |
799 | + | |
800 | +void | |
801 | +fd_nonblock(fd) | |
802 | + int fd; | |
803 | +{ | |
804 | +#ifdef FIONBIO | |
805 | + int opt = 1; | |
806 | + | |
807 | + ioctl(fd, FIONBIO, &opt); | |
808 | +#else | |
809 | + int opt; | |
810 | + | |
811 | + opt = fcntl(fd, F_GETFL, 0); | |
812 | + opt |= O_NONBLOCK; | |
813 | + fcntl(fd, F_SETFL, opt); | |
814 | +#endif | |
815 | +} | |
816 | + | |
817 | +void | |
818 | +fd_block(fd) | |
819 | + int fd; | |
820 | +{ | |
821 | +#ifdef FIONBIO | |
822 | + int opt = 0; | |
823 | + | |
824 | + ioctl(fd, FIONBIO, &opt); | |
825 | +#else | |
826 | + int opt; | |
827 | + | |
828 | + opt = fcntl(fd, F_GETFL, 0); | |
829 | + opt &= ~O_NONBLOCK; | |
830 | + fcntl(fd, F_SETFL, opt); | |
831 | +#endif | |
832 | +} | |
833 | + | |
834 | + | |
835 | +#if 0 | |
836 | +/* | |
837 | + * invoke RSH | |
838 | + */ | |
839 | +int | |
840 | +rsh_exec(so,ns, user, host, args) | |
841 | + struct socket *so; | |
842 | + struct socket *ns; | |
843 | + char *user; | |
844 | + char *host; | |
845 | + char *args; | |
846 | +{ | |
847 | + int fd[2]; | |
848 | + int fd0[2]; | |
849 | + int s; | |
850 | + char buff[256]; | |
851 | + | |
852 | + DEBUG_CALL("rsh_exec"); | |
853 | + DEBUG_ARG("so = %lx", (long)so); | |
854 | + | |
855 | + if (pipe(fd)<0) { | |
856 | + lprint("Error: pipe failed: %s\n", strerror(errno)); | |
857 | + return 0; | |
858 | + } | |
859 | +/* #ifdef HAVE_SOCKETPAIR */ | |
860 | +#if 1 | |
861 | + if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) { | |
862 | + close(fd[0]); | |
863 | + close(fd[1]); | |
864 | + lprint("Error: openpty failed: %s\n", strerror(errno)); | |
865 | + return 0; | |
866 | + } | |
867 | +#else | |
868 | + if (openpty(&fd0[0], &fd0[1]) == -1) { | |
869 | + close(fd[0]); | |
870 | + close(fd[1]); | |
871 | + lprint("Error: openpty failed: %s\n", strerror(errno)); | |
872 | + return 0; | |
873 | + } | |
874 | +#endif | |
875 | + | |
876 | + switch(fork()) { | |
877 | + case -1: | |
878 | + lprint("Error: fork failed: %s\n", strerror(errno)); | |
879 | + close(fd[0]); | |
880 | + close(fd[1]); | |
881 | + close(fd0[0]); | |
882 | + close(fd0[1]); | |
883 | + return 0; | |
884 | + | |
885 | + case 0: | |
886 | + close(fd[0]); | |
887 | + close(fd0[0]); | |
888 | + | |
889 | + /* Set the DISPLAY */ | |
890 | + if (x_port >= 0) { | |
891 | +#ifdef HAVE_SETENV | |
892 | + sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); | |
893 | + setenv("DISPLAY", buff, 1); | |
894 | +#else | |
895 | + sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); | |
896 | + putenv(buff); | |
897 | +#endif | |
898 | + } | |
899 | + | |
900 | + dup2(fd0[1], 0); | |
901 | + dup2(fd0[1], 1); | |
902 | + dup2(fd[1], 2); | |
903 | + for (s = 3; s <= 255; s++) | |
904 | + close(s); | |
905 | + | |
906 | + execlp("rsh","rsh","-l", user, host, args, NULL); | |
907 | + | |
908 | + /* Ooops, failed, let's tell the user why */ | |
909 | + | |
910 | + sprintf(buff, "Error: execlp of %s failed: %s\n", | |
911 | + "rsh", strerror(errno)); | |
912 | + write(2, buff, strlen(buff)+1); | |
913 | + close(0); close(1); close(2); /* XXX */ | |
914 | + exit(1); | |
915 | + | |
916 | + default: | |
917 | + close(fd[1]); | |
918 | + close(fd0[1]); | |
919 | + ns->s=fd[0]; | |
920 | + so->s=fd0[0]; | |
921 | + | |
922 | + return 1; | |
923 | + } | |
924 | +} | |
925 | +#endif | ... | ... |
slirp/misc.h
0 → 100644
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 _MISC_H_ | |
9 | +#define _MISC_H_ | |
10 | + | |
11 | +struct ex_list { | |
12 | + int ex_pty; /* Do we want a pty? */ | |
13 | + int ex_addr; /* The last byte of the address */ | |
14 | + int ex_fport; /* Port to telnet to */ | |
15 | + char *ex_exec; /* Command line of what to exec */ | |
16 | + struct ex_list *ex_next; | |
17 | +}; | |
18 | + | |
19 | +extern struct ex_list *exec_list; | |
20 | +extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait; | |
21 | + | |
22 | +extern int (*lprint_print) _P((void *, const char *, va_list)); | |
23 | +extern char *lprint_ptr, *lprint_ptr2, **lprint_arg; | |
24 | +extern struct sbuf *lprint_sb; | |
25 | + | |
26 | +#ifndef HAVE_STRDUP | |
27 | +char *strdup _P((const char *)); | |
28 | +#endif | |
29 | + | |
30 | +void do_wait _P((int)); | |
31 | + | |
32 | +#define EMU_NONE 0x0 | |
33 | + | |
34 | +/* TCP emulations */ | |
35 | +#define EMU_CTL 0x1 | |
36 | +#define EMU_FTP 0x2 | |
37 | +#define EMU_KSH 0x3 | |
38 | +#define EMU_IRC 0x4 | |
39 | +#define EMU_REALAUDIO 0x5 | |
40 | +#define EMU_RLOGIN 0x6 | |
41 | +#define EMU_IDENT 0x7 | |
42 | +#define EMU_RSH 0x8 | |
43 | + | |
44 | +#define EMU_NOCONNECT 0x10 /* Don't connect */ | |
45 | + | |
46 | +/* UDP emulations */ | |
47 | +#define EMU_TALK 0x1 | |
48 | +#define EMU_NTALK 0x2 | |
49 | +#define EMU_CUSEEME 0x3 | |
50 | + | |
51 | +struct tos_t { | |
52 | + u_int16_t lport; | |
53 | + u_int16_t fport; | |
54 | + u_int8_t tos; | |
55 | + u_int8_t emu; | |
56 | +}; | |
57 | + | |
58 | +struct emu_t { | |
59 | + u_int16_t lport; | |
60 | + u_int16_t fport; | |
61 | + u_int8_t tos; | |
62 | + u_int8_t emu; | |
63 | + struct emu_t *next; | |
64 | +}; | |
65 | + | |
66 | +extern struct emu_t *tcpemu; | |
67 | + | |
68 | +extern int x_port, x_server, x_display; | |
69 | + | |
70 | +int show_x _P((char *, struct socket *)); | |
71 | +void redir_x _P((u_int32_t, int, int, int)); | |
72 | +void getouraddr _P((void)); | |
73 | +inline void slirp_insque _P((void *, void *)); | |
74 | +inline void slirp_remque _P((void *)); | |
75 | +int add_exec _P((struct ex_list **, int, char *, int, int)); | |
76 | +int openpty _P((int *, int *)); | |
77 | +int fork_exec _P((struct socket *, char *, int)); | |
78 | +void snooze_hup _P((int)); | |
79 | +void snooze _P((void)); | |
80 | +void relay _P((int)); | |
81 | +void add_emu _P((char *)); | |
82 | +void u_sleep _P((int)); | |
83 | +void fd_nonblock _P((int)); | |
84 | +void fd_block _P((int)); | |
85 | +int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *)); | |
86 | + | |
87 | +#endif | ... | ... |
slirp/sbuf.c
0 → 100644
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 | +/* Done as a macro in socket.h */ | |
11 | +/* int | |
12 | + * sbspace(struct sockbuff *sb) | |
13 | + * { | |
14 | + * return SB_DATALEN - sb->sb_cc; | |
15 | + * } | |
16 | + */ | |
17 | + | |
18 | +void | |
19 | +sbfree(sb) | |
20 | + struct sbuf *sb; | |
21 | +{ | |
22 | + free(sb->sb_data); | |
23 | +} | |
24 | + | |
25 | +void | |
26 | +sbdrop(sb, num) | |
27 | + struct sbuf *sb; | |
28 | + int num; | |
29 | +{ | |
30 | + /* | |
31 | + * We can only drop how much we have | |
32 | + * This should never succeed | |
33 | + */ | |
34 | + if(num > sb->sb_cc) | |
35 | + num = sb->sb_cc; | |
36 | + sb->sb_cc -= num; | |
37 | + sb->sb_rptr += num; | |
38 | + if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen) | |
39 | + sb->sb_rptr -= sb->sb_datalen; | |
40 | + | |
41 | +} | |
42 | + | |
43 | +void | |
44 | +sbreserve(sb, size) | |
45 | + struct sbuf *sb; | |
46 | + int size; | |
47 | +{ | |
48 | + if (sb->sb_data) { | |
49 | + /* Already alloced, realloc if necessary */ | |
50 | + if (sb->sb_datalen != size) { | |
51 | + sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size); | |
52 | + sb->sb_cc = 0; | |
53 | + if (sb->sb_wptr) | |
54 | + sb->sb_datalen = size; | |
55 | + else | |
56 | + sb->sb_datalen = 0; | |
57 | + } | |
58 | + } else { | |
59 | + sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size); | |
60 | + sb->sb_cc = 0; | |
61 | + if (sb->sb_wptr) | |
62 | + sb->sb_datalen = size; | |
63 | + else | |
64 | + sb->sb_datalen = 0; | |
65 | + } | |
66 | +} | |
67 | + | |
68 | +/* | |
69 | + * Try and write() to the socket, whatever doesn't get written | |
70 | + * append to the buffer... for a host with a fast net connection, | |
71 | + * this prevents an unnecessary copy of the data | |
72 | + * (the socket is non-blocking, so we won't hang) | |
73 | + */ | |
74 | +void | |
75 | +sbappend(so, m) | |
76 | + struct socket *so; | |
77 | + struct mbuf *m; | |
78 | +{ | |
79 | + int ret = 0; | |
80 | + | |
81 | + DEBUG_CALL("sbappend"); | |
82 | + DEBUG_ARG("so = %lx", (long)so); | |
83 | + DEBUG_ARG("m = %lx", (long)m); | |
84 | + DEBUG_ARG("m->m_len = %d", m->m_len); | |
85 | + | |
86 | + /* Shouldn't happen, but... e.g. foreign host closes connection */ | |
87 | + if (m->m_len <= 0) { | |
88 | + m_free(m); | |
89 | + return; | |
90 | + } | |
91 | + | |
92 | + /* | |
93 | + * If there is urgent data, call sosendoob | |
94 | + * if not all was sent, sowrite will take care of the rest | |
95 | + * (The rest of this function is just an optimisation) | |
96 | + */ | |
97 | + if (so->so_urgc) { | |
98 | + sbappendsb(&so->so_rcv, m); | |
99 | + m_free(m); | |
100 | + sosendoob(so); | |
101 | + return; | |
102 | + } | |
103 | + | |
104 | + /* | |
105 | + * We only write if there's nothing in the buffer, | |
106 | + * ottherwise it'll arrive out of order, and hence corrupt | |
107 | + */ | |
108 | + if (!so->so_rcv.sb_cc) | |
109 | + ret = write(so->s, m->m_data, m->m_len); | |
110 | + | |
111 | + if (ret <= 0) { | |
112 | + /* | |
113 | + * Nothing was written | |
114 | + * It's possible that the socket has closed, but | |
115 | + * we don't need to check because if it has closed, | |
116 | + * it will be detected in the normal way by soread() | |
117 | + */ | |
118 | + sbappendsb(&so->so_rcv, m); | |
119 | + } else if (ret != m->m_len) { | |
120 | + /* | |
121 | + * Something was written, but not everything.. | |
122 | + * sbappendsb the rest | |
123 | + */ | |
124 | + m->m_len -= ret; | |
125 | + m->m_data += ret; | |
126 | + sbappendsb(&so->so_rcv, m); | |
127 | + } /* else */ | |
128 | + /* Whatever happened, we free the mbuf */ | |
129 | + m_free(m); | |
130 | +} | |
131 | + | |
132 | +/* | |
133 | + * Copy the data from m into sb | |
134 | + * The caller is responsible to make sure there's enough room | |
135 | + */ | |
136 | +void | |
137 | +sbappendsb(sb, m) | |
138 | + struct sbuf *sb; | |
139 | + struct mbuf *m; | |
140 | +{ | |
141 | + int len, n, nn; | |
142 | + | |
143 | + len = m->m_len; | |
144 | + | |
145 | + if (sb->sb_wptr < sb->sb_rptr) { | |
146 | + n = sb->sb_rptr - sb->sb_wptr; | |
147 | + if (n > len) n = len; | |
148 | + memcpy(sb->sb_wptr, m->m_data, n); | |
149 | + } else { | |
150 | + /* Do the right edge first */ | |
151 | + n = sb->sb_data + sb->sb_datalen - sb->sb_wptr; | |
152 | + if (n > len) n = len; | |
153 | + memcpy(sb->sb_wptr, m->m_data, n); | |
154 | + len -= n; | |
155 | + if (len) { | |
156 | + /* Now the left edge */ | |
157 | + nn = sb->sb_rptr - sb->sb_data; | |
158 | + if (nn > len) nn = len; | |
159 | + memcpy(sb->sb_data,m->m_data+n,nn); | |
160 | + n += nn; | |
161 | + } | |
162 | + } | |
163 | + | |
164 | + sb->sb_cc += n; | |
165 | + sb->sb_wptr += n; | |
166 | + if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen) | |
167 | + sb->sb_wptr -= sb->sb_datalen; | |
168 | +} | |
169 | + | |
170 | +/* | |
171 | + * Copy data from sbuf to a normal, straight buffer | |
172 | + * Don't update the sbuf rptr, this will be | |
173 | + * done in sbdrop when the data is acked | |
174 | + */ | |
175 | +void | |
176 | +sbcopy(sb, off, len, to) | |
177 | + struct sbuf *sb; | |
178 | + int off; | |
179 | + int len; | |
180 | + char *to; | |
181 | +{ | |
182 | + char *from; | |
183 | + | |
184 | + from = sb->sb_rptr + off; | |
185 | + if (from >= sb->sb_data + sb->sb_datalen) | |
186 | + from -= sb->sb_datalen; | |
187 | + | |
188 | + if (from < sb->sb_wptr) { | |
189 | + if (len > sb->sb_cc) len = sb->sb_cc; | |
190 | + memcpy(to,from,len); | |
191 | + } else { | |
192 | + /* re-use off */ | |
193 | + off = (sb->sb_data + sb->sb_datalen) - from; | |
194 | + if (off > len) off = len; | |
195 | + memcpy(to,from,off); | |
196 | + len -= off; | |
197 | + if (len) | |
198 | + memcpy(to+off,sb->sb_data,len); | |
199 | + } | |
200 | +} | |
201 | + | ... | ... |
slirp/sbuf.h
0 → 100644
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 _SBUF_H_ | |
9 | +#define _SBUF_H_ | |
10 | + | |
11 | +#define sbflush(sb) sbdrop((sb),(sb)->sb_cc) | |
12 | +#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc) | |
13 | + | |
14 | +struct sbuf { | |
15 | + u_int sb_cc; /* actual chars in buffer */ | |
16 | + u_int sb_datalen; /* Length of data */ | |
17 | + char *sb_wptr; /* write pointer. points to where the next | |
18 | + * bytes should be written in the sbuf */ | |
19 | + char *sb_rptr; /* read pointer. points to where the next | |
20 | + * byte should be read from the sbuf */ | |
21 | + char *sb_data; /* Actual data */ | |
22 | +}; | |
23 | + | |
24 | +void sbfree _P((struct sbuf *)); | |
25 | +void sbdrop _P((struct sbuf *, int)); | |
26 | +void sbreserve _P((struct sbuf *, int)); | |
27 | +void sbappend _P((struct socket *, struct mbuf *)); | |
28 | +void sbappendsb _P((struct sbuf *, struct mbuf *)); | |
29 | +void sbcopy _P((struct sbuf *, int, int, char *)); | |
30 | + | |
31 | +#endif | ... | ... |