Changeset 15450 in vbox for trunk/src/VBox/Devices/Network/slirp
- Timestamp:
- Dec 13, 2008 10:06:40 PM (16 years ago)
- Location:
- trunk/src/VBox/Devices/Network/slirp
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/ip.h
r15056 r15450 122 122 #define IPTOS_RELIABILITY 0x04 123 123 124 /*125 * Definitions for options.126 */127 #define IPOPT_COPIED(o) ((o)&0x80)128 #define IPOPT_CLASS(o) ((o)&0x60)129 #define IPOPT_NUMBER(o) ((o)&0x1f)130 131 #define IPOPT_CONTROL 0x00132 #define IPOPT_RESERVED1 0x20133 #define IPOPT_DEBMEAS 0x40134 #define IPOPT_RESERVED2 0x60135 136 #define IPOPT_EOL 0 /* end of option list */137 #define IPOPT_NOP 1 /* no operation */138 139 #define IPOPT_RR 7 /* record packet route */140 #define IPOPT_TS 68 /* timestamp */141 #define IPOPT_SECURITY 130 /* provide s,c,h,tcc */142 #define IPOPT_LSRR 131 /* loose source route */143 #define IPOPT_SATID 136 /* satnet id */144 #define IPOPT_SSRR 137 /* strict source route */145 146 /*147 * Offsets to fields in options other than EOL and NOP.148 */149 #define IPOPT_OPTVAL 0 /* option ID */150 #define IPOPT_OLEN 1 /* option length */151 #define IPOPT_OFFSET 2 /* offset within option */152 #define IPOPT_MINOFF 4 /* min value of above */153 124 154 125 /* … … 188 159 }; 189 160 AssertCompileSize(struct ip_timestamp, 12); 190 191 /* flag bits for ipt_flg */192 #define IPOPT_TS_TSONLY 0 /* timestamps only */193 #define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */194 #define IPOPT_TS_PRESPEC 3 /* specified modules only */195 196 /* bits for security (not byte swapped) */197 #define IPOPT_SECUR_UNCLASS 0x0000198 #define IPOPT_SECUR_CONFID 0xf135199 #define IPOPT_SECUR_EFTO 0x789a200 #define IPOPT_SECUR_MMMM 0xbc4d201 #define IPOPT_SECUR_RESTR 0xaf13202 #define IPOPT_SECUR_SECRET 0xd788203 #define IPOPT_SECUR_TOPSECRET 0x6bc5204 161 205 162 /* … … 335 292 336 293 #endif /* !VBOX_WITH_BSD_REASS */ 337 338 /*339 * Structure stored in mbuf in inpcb.ip_options340 * and passed to ip_output when ip options are in use.341 * The actual length of the options (including ipopt_dst)342 * is in m_len.343 */344 #define MAX_IPOPTLEN 40345 346 struct ipoption347 {348 struct in_addr ipopt_dst; /* first-hop dst if source routed */349 int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */350 };351 294 352 295 /* -
trunk/src/VBox/Devices/Network/slirp/ip_input.c
r15035 r15450 55 55 { 56 56 #ifndef VBOX_WITH_BSD_REASS 57 57 ipq.next = ipq.prev = ptr_to_u32(pData, &ipq); 58 58 #else /* !VBOX_WITH_BSD_REASS */ 59 60 61 62 63 64 59 int i = 0; 60 for (i = 0; i < IPREASS_NHASH; ++i) 61 TAILQ_INIT(&ipq[i]); 62 maxnipq = 100; /* ??? */ 63 maxfragsperpacket = 16; 64 nipq = 0; 65 65 #endif /* VBOX_WITH_BSD_REASS */ 66 67 68 66 ip_currid = tt.tv_sec & 0xffff; 67 udp_init(pData); 68 tcp_init(pData); 69 69 } 70 70 … … 76 76 ip_input(PNATState pData, struct mbuf *m) 77 77 { 78 register struct ip *ip; 79 int hlen; 80 81 DEBUG_CALL("ip_input"); 82 DEBUG_ARG("m = %lx", (long)m); 83 DEBUG_ARG("m_len = %d", m->m_len); 84 85 ipstat.ips_total++; 86 87 if (m->m_len < sizeof (struct ip)) { 88 ipstat.ips_toosmall++; 78 register struct ip *ip; 79 int hlen; 80 81 DEBUG_CALL("ip_input"); 82 DEBUG_ARG("m = %lx", (long)m); 83 DEBUG_ARG("m_len = %d", m->m_len); 84 85 ipstat.ips_total++; 86 87 if (m->m_len < sizeof(struct ip)) 88 { 89 ipstat.ips_toosmall++; 90 return; 91 } 92 93 ip = mtod(m, struct ip *); 94 if (ip->ip_v != IPVERSION) 95 { 96 ipstat.ips_badvers++; 97 goto bad; 98 } 99 100 hlen = ip->ip_hl << 2; 101 if ( hlen < sizeof(struct ip) 102 || hlen > m->m_len) 103 { 104 /* min header length */ 105 ipstat.ips_badhlen++; /* or packet too short */ 106 goto bad; 107 } 108 109 /* keep ip header intact for ICMP reply 110 * ip->ip_sum = cksum(m, hlen); 111 * if (ip->ip_sum) { 112 */ 113 if(cksum(m,hlen)) 114 { 115 ipstat.ips_badsum++; 116 goto bad; 117 } 118 119 /* 120 * Convert fields to host representation. 121 */ 122 NTOHS(ip->ip_len); 123 if (ip->ip_len < hlen) 124 { 125 ipstat.ips_badlen++; 126 goto bad; 127 } 128 NTOHS(ip->ip_id); 129 NTOHS(ip->ip_off); 130 131 /* 132 * Check that the amount of data in the buffers 133 * is as at least much as the IP header would have us expect. 134 * Trim mbufs if longer than we expect. 135 * Drop packet if shorter than we expect. 136 */ 137 if (m->m_len < ip->ip_len) 138 { 139 ipstat.ips_tooshort++; 140 goto bad; 141 } 142 /* Should drop packet if mbuf too long? hmmm... */ 143 if (m->m_len > ip->ip_len) 144 m_adj(m, ip->ip_len - m->m_len); 145 146 /* check ip_ttl for a correct ICMP reply */ 147 if (ip->ip_ttl==0 || ip->ip_ttl == 1) 148 { 149 icmp_error(pData, m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); 150 goto bad; 151 } 152 153 #ifdef VBOX_WITH_SLIRP_ICMP 154 ip->ip_ttl--; 155 #endif 156 /* 157 * If offset or IP_MF are set, must reassemble. 158 * Otherwise, nothing need be done. 159 * (We could look in the reassembly queue to see 160 * if the packet was previously fragmented, 161 * but it's not worth the time; just let them time out.) 162 * 163 * XXX This should fail, don't fragment yet 164 */ 165 #ifndef VBOX_WITH_BSD_REASS 166 if (ip->ip_off &~ IP_DF) 167 { 168 register struct ipq_t *fp; 169 /* 170 * Look for queue of fragments 171 * of this datagram. 172 */ 173 for (fp = u32_to_ptr(pData, ipq.next, struct ipq_t *); 174 fp != &ipq; 175 fp = u32_to_ptr(pData, fp->next, struct ipq_t *)) 176 if ( ip->ip_id == fp->ipq_id 177 && ip->ip_src.s_addr == fp->ipq_src.s_addr 178 && ip->ip_dst.s_addr == fp->ipq_dst.s_addr 179 && ip->ip_p == fp->ipq_p) 180 goto found; 181 fp = 0; 182 found: 183 184 /* 185 * Adjust ip_len to not reflect header, 186 * set ip_mff if more fragments are expected, 187 * convert offset of this to bytes. 188 */ 189 ip->ip_len -= hlen; 190 if (ip->ip_off & IP_MF) 191 ((struct ipasfrag *)ip)->ipf_mff |= 1; 192 else 193 ((struct ipasfrag *)ip)->ipf_mff &= ~1; 194 195 ip->ip_off <<= 3; 196 197 /* 198 * If datagram marked as having more fragments 199 * or if this is not the first fragment, 200 * attempt reassembly; if it succeeds, proceed. 201 */ 202 if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) 203 { 204 ipstat.ips_fragments++; 205 ip = ip_reass(pData, (struct ipasfrag *)ip, fp); 206 if (ip == 0) 89 207 return; 90 } 91 208 ipstat.ips_reassembled++; 209 m = dtom(pData, ip); 210 } 211 else 212 if (fp) 213 ip_freef(pData, fp); 214 215 } 216 else 217 ip->ip_len -= hlen; 218 #else /* !VBOX_WITH_BSD_REASS */ 219 if (ip->ip_off & (IP_MF | IP_OFFMASK)) 220 { 221 m = ip_reass(pData, m); 222 if (m == NULL) 223 return; 92 224 ip = mtod(m, struct ip *); 93 94 if (ip->ip_v != IPVERSION) { 95 ipstat.ips_badvers++; 96 goto bad; 97 } 98 99 hlen = ip->ip_hl << 2; 100 if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */ 101 ipstat.ips_badhlen++; /* or packet too short */ 102 goto bad; 103 } 104 105 /* keep ip header intact for ICMP reply 106 * ip->ip_sum = cksum(m, hlen); 107 * if (ip->ip_sum) { 108 */ 109 if(cksum(m,hlen)) { 110 ipstat.ips_badsum++; 111 goto bad; 112 } 113 114 /* 115 * Convert fields to host representation. 116 */ 117 NTOHS(ip->ip_len); 118 if (ip->ip_len < hlen) { 119 ipstat.ips_badlen++; 120 goto bad; 121 } 122 NTOHS(ip->ip_id); 123 NTOHS(ip->ip_off); 124 125 /* 126 * Check that the amount of data in the buffers 127 * is as at least much as the IP header would have us expect. 128 * Trim mbufs if longer than we expect. 129 * Drop packet if shorter than we expect. 130 */ 131 if (m->m_len < ip->ip_len) { 132 ipstat.ips_tooshort++; 133 goto bad; 134 } 135 /* Should drop packet if mbuf too long? hmmm... */ 136 if (m->m_len > ip->ip_len) 137 m_adj(m, ip->ip_len - m->m_len); 138 139 /* check ip_ttl for a correct ICMP reply */ 140 if(ip->ip_ttl==0 || ip->ip_ttl == 1) { 141 icmp_error(pData, m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); 142 goto bad; 143 } 144 145 #ifdef VBOX_WITH_SLIRP_ICMP 146 ip->ip_ttl--; 147 #endif 148 /* 149 * Process options and, if not destined for us, 150 * ship it on. ip_dooptions returns 1 when an 151 * error was detected (causing an icmp message 152 * to be sent and the original packet to be freed). 153 */ 154 /* We do no IP options */ 155 /* if (hlen > sizeof (struct ip) && ip_dooptions(m)) 156 * goto next; 157 */ 158 /* 159 * If offset or IP_MF are set, must reassemble. 160 * Otherwise, nothing need be done. 161 * (We could look in the reassembly queue to see 162 * if the packet was previously fragmented, 163 * but it's not worth the time; just let them time out.) 164 * 165 * XXX This should fail, don't fragment yet 166 */ 167 #ifndef VBOX_WITH_BSD_REASS 168 if (ip->ip_off &~ IP_DF) { 169 register struct ipq_t *fp; 170 /* 171 * Look for queue of fragments 172 * of this datagram. 173 */ 174 for (fp = u32_to_ptr(pData, ipq.next, struct ipq_t *); fp != &ipq; 175 fp = u32_to_ptr(pData, fp->next, struct ipq_t *)) 176 if (ip->ip_id == fp->ipq_id && 177 ip->ip_src.s_addr == fp->ipq_src.s_addr && 178 ip->ip_dst.s_addr == fp->ipq_dst.s_addr && 179 ip->ip_p == fp->ipq_p) 180 goto found; 181 fp = 0; 182 found: 183 184 /* 185 * Adjust ip_len to not reflect header, 186 * set ip_mff if more fragments are expected, 187 * convert offset of this to bytes. 188 */ 189 ip->ip_len -= hlen; 190 if (ip->ip_off & IP_MF) 191 ((struct ipasfrag *)ip)->ipf_mff |= 1; 192 else 193 ((struct ipasfrag *)ip)->ipf_mff &= ~1; 194 195 ip->ip_off <<= 3; 196 197 /* 198 * If datagram marked as having more fragments 199 * or if this is not the first fragment, 200 * attempt reassembly; if it succeeds, proceed. 201 */ 202 if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { 203 ipstat.ips_fragments++; 204 ip = ip_reass(pData, (struct ipasfrag *)ip, fp); 205 if (ip == 0) 206 return; 207 ipstat.ips_reassembled++; 208 m = dtom(pData, ip); 209 } else 210 if (fp) 211 ip_freef(pData, fp); 212 213 } else 214 ip->ip_len -= hlen; 215 #else /* !VBOX_WITH_BSD_REASS */ 216 if (ip->ip_off & (IP_MF | IP_OFFMASK)) { 217 m = ip_reass(pData, m); 218 if (m == NULL) 219 return; 220 ip = mtod(m, struct ip *); 221 hlen = ip->ip_len; 222 } 223 else 224 ip->ip_len -= hlen; 225 hlen = ip->ip_len; 226 } 227 else 228 ip->ip_len -= hlen; 225 229 #endif /* VBOX_WITH_BSD_REASS */ 226 230 227 /* 228 * Switch out to protocol's input routine. 229 */ 230 ipstat.ips_delivered++; 231 switch (ip->ip_p) { 232 case IPPROTO_TCP: 233 tcp_input(pData, m, hlen, (struct socket *)NULL); 234 break; 235 case IPPROTO_UDP: 236 udp_input(pData, m, hlen); 237 break; 238 case IPPROTO_ICMP: 239 icmp_input(pData, m, hlen); 240 break; 241 default: 242 ipstat.ips_noproto++; 243 m_free(pData, m); 244 } 245 return; 231 /* 232 * Switch out to protocol's input routine. 233 */ 234 ipstat.ips_delivered++; 235 switch (ip->ip_p) 236 { 237 case IPPROTO_TCP: 238 tcp_input(pData, m, hlen, (struct socket *)NULL); 239 break; 240 case IPPROTO_UDP: 241 udp_input(pData, m, hlen); 242 break; 243 case IPPROTO_ICMP: 244 icmp_input(pData, m, hlen); 245 break; 246 default: 247 ipstat.ips_noproto++; 248 m_free(pData, m); 249 } 250 return; 246 251 bad: 247 248 252 m_freem(pData, m); 253 return; 249 254 } 250 255 … … 259 264 ip_reass(PNATState pData, register struct ipasfrag *ip, register struct ipq_t *fp) 260 265 { 261 register struct mbuf *m = dtom(pData, ip); 262 register struct ipasfrag *q; 263 int hlen = ip->ip_hl << 2; 264 int i, next; 265 266 DEBUG_CALL("ip_reass"); 267 DEBUG_ARG("ip = %lx", (long)ip); 268 DEBUG_ARG("fp = %lx", (long)fp); 269 DEBUG_ARG("m = %lx", (long)m); 270 271 /* 272 * Presence of header sizes in mbufs 273 * would confuse code below. 274 * Fragment m_data is concatenated. 275 */ 276 m->m_data += hlen; 277 m->m_len -= hlen; 278 279 /* 280 * If first fragment to arrive, create a reassembly queue. 281 */ 282 if (fp == 0) { 283 struct mbuf *t; 284 if ((t = m_get(pData)) == NULL) goto dropfrag; 285 fp = mtod(t, struct ipq_t *); 286 insque_32(pData, fp, &ipq); 287 fp->ipq_ttl = IPFRAGTTL; 288 fp->ipq_p = ip->ip_p; 289 fp->ipq_id = ip->ip_id; 290 fp->ipq_next = fp->ipq_prev = ptr_to_u32(pData, (struct ipasfrag *)fp); 291 fp->ipq_src = ((struct ip *)ip)->ip_src; 292 fp->ipq_dst = ((struct ip *)ip)->ip_dst; 293 q = (struct ipasfrag *)fp; 294 goto insert; 295 } 296 297 /* 298 * Find a segment which begins after this one does. 299 */ 300 for (q = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); q != (struct ipasfrag *)fp; 301 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *)) 302 if (q->ip_off > ip->ip_off) 303 break; 304 305 /* 306 * If there is a preceding segment, it may provide some of 307 * our data already. If so, drop the data from the incoming 308 * segment. If it provides all of our data, drop us. 309 */ 310 if (u32_to_ptr(pData, q->ipf_prev, struct ipq_t *) != fp) { 311 i = (u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *))->ip_off + 312 (u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *))->ip_len - ip->ip_off; 313 if (i > 0) { 314 if (i >= ip->ip_len) 315 goto dropfrag; 316 m_adj(dtom(pData, ip), i); 317 ip->ip_off += i; 318 ip->ip_len -= i; 319 } 320 } 321 322 /* 323 * While we overlap succeeding segments trim them or, 324 * if they are completely covered, dequeue them. 325 */ 326 while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { 327 i = (ip->ip_off + ip->ip_len) - q->ip_off; 328 if (i < q->ip_len) { 329 q->ip_len -= i; 330 q->ip_off += i; 331 m_adj(dtom(pData, q), i); 332 break; 333 } 334 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *); 335 m_freem(pData, dtom(pData, u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *))); 336 ip_deq(pData, u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *)); 337 } 266 register struct mbuf *m = dtom(pData, ip); 267 register struct ipasfrag *q; 268 int hlen = ip->ip_hl << 2; 269 int i, next; 270 271 DEBUG_CALL("ip_reass"); 272 DEBUG_ARG("ip = %lx", (long)ip); 273 DEBUG_ARG("fp = %lx", (long)fp); 274 DEBUG_ARG("m = %lx", (long)m); 275 276 /* 277 * Presence of header sizes in mbufs 278 * would confuse code below. 279 * Fragment m_data is concatenated. 280 */ 281 m->m_data += hlen; 282 m->m_len -= hlen; 283 284 /* 285 * If first fragment to arrive, create a reassembly queue. 286 */ 287 if (fp == 0) 288 { 289 struct mbuf *t; 290 if ((t = m_get(pData)) == NULL) goto dropfrag; 291 fp = mtod(t, struct ipq_t *); 292 insque_32(pData, fp, &ipq); 293 fp->ipq_ttl = IPFRAGTTL; 294 fp->ipq_p = ip->ip_p; 295 fp->ipq_id = ip->ip_id; 296 fp->ipq_next = fp->ipq_prev = ptr_to_u32(pData, (struct ipasfrag *)fp); 297 fp->ipq_src = ((struct ip *)ip)->ip_src; 298 fp->ipq_dst = ((struct ip *)ip)->ip_dst; 299 q = (struct ipasfrag *)fp; 300 goto insert; 301 } 302 303 /* 304 * Find a segment which begins after this one does. 305 */ 306 for (q = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); 307 q != (struct ipasfrag *)fp; 308 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *)) 309 if (q->ip_off > ip->ip_off) 310 break; 311 312 /* 313 * If there is a preceding segment, it may provide some of 314 * our data already. If so, drop the data from the incoming 315 * segment. If it provides all of our data, drop us. 316 */ 317 if (u32_to_ptr(pData, q->ipf_prev, struct ipq_t *) != fp) 318 { 319 i = (u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *))->ip_off + 320 (u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *))->ip_len - ip->ip_off; 321 if (i > 0) 322 { 323 if (i >= ip->ip_len) 324 goto dropfrag; 325 m_adj(dtom(pData, ip), i); 326 ip->ip_off += i; 327 ip->ip_len -= i; 328 } 329 } 330 331 /* 332 * While we overlap succeeding segments trim them or, 333 * if they are completely covered, dequeue them. 334 */ 335 while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) 336 { 337 i = (ip->ip_off + ip->ip_len) - q->ip_off; 338 if (i < q->ip_len) { 339 q->ip_len -= i; 340 q->ip_off += i; 341 m_adj(dtom(pData, q), i); 342 break; 343 } 344 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *); 345 m_freem(pData, dtom(pData, u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *))); 346 ip_deq(pData, u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *)); 347 } 338 348 339 349 insert: 340 /* 341 * Stick new segment in its place; 342 * check for complete reassembly. 343 */ 344 ip_enq(pData, ip, u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *)); 345 next = 0; 346 for (q = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); q != (struct ipasfrag *)fp; 347 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *)) { 348 if (q->ip_off != next) 349 return (0); 350 next += q->ip_len; 351 } 352 if (u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *)->ipf_mff & 1) 353 return (0); 354 355 /* 356 * Reassembly is complete; concatenate fragments. 357 */ 358 q = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); 359 m = dtom(pData, q); 360 350 /* 351 * Stick new segment in its place; 352 * check for complete reassembly. 353 */ 354 ip_enq(pData, ip, u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *)); 355 next = 0; 356 for (q = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); 357 q != (struct ipasfrag *)fp; 358 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *)) 359 { 360 if (q->ip_off != next) 361 return (0); 362 next += q->ip_len; 363 } 364 if (u32_to_ptr(pData, q->ipf_prev, struct ipasfrag *)->ipf_mff & 1) 365 return (0); 366 367 /* 368 * Reassembly is complete; concatenate fragments. 369 */ 370 q = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); 371 m = dtom(pData, q); 372 373 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *); 374 while (q != (struct ipasfrag *)fp) 375 { 376 struct mbuf *t; 377 t = dtom(pData, q); 361 378 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *); 362 while (q != (struct ipasfrag *)fp) { 363 struct mbuf *t; 364 t = dtom(pData, q); 365 q = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *); 366 m_cat(pData, m, t); 367 } 368 369 /* 370 * Create header for new ip packet by 371 * modifying header of first packet; 372 * dequeue and discard fragment reassembly header. 373 * Make header visible. 374 */ 375 ip = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); 376 377 /* 378 * If the fragments concatenated to an mbuf that's 379 * bigger than the total size of the fragment, then and 380 * m_ext buffer was alloced. But fp->ipq_next points to 381 * the old buffer (in the mbuf), so we must point ip 382 * into the new buffer. 383 */ 384 if (m->m_flags & M_EXT) { 385 int delta; 386 delta = (char *)ip - m->m_dat; 387 ip = (struct ipasfrag *)(m->m_ext + delta); 388 } 389 390 /* DEBUG_ARG("ip = %lx", (long)ip); 391 * ip=(struct ipasfrag *)m->m_data; */ 392 393 ip->ip_len = next; 394 ip->ipf_mff &= ~1; 395 ((struct ip *)ip)->ip_src = fp->ipq_src; 396 ((struct ip *)ip)->ip_dst = fp->ipq_dst; 397 remque_32(pData, fp); 398 (void) m_free(pData, dtom(pData, fp)); 399 m = dtom(pData, ip); 400 m->m_len += (ip->ip_hl << 2); 401 m->m_data -= (ip->ip_hl << 2); 402 403 return ((struct ip *)ip); 379 m_cat(pData, m, t); 380 } 381 382 /* 383 * Create header for new ip packet by 384 * modifying header of first packet; 385 * dequeue and discard fragment reassembly header. 386 * Make header visible. 387 */ 388 ip = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); 389 390 /* 391 * If the fragments concatenated to an mbuf that's 392 * bigger than the total size of the fragment, then and 393 * m_ext buffer was alloced. But fp->ipq_next points to 394 * the old buffer (in the mbuf), so we must point ip 395 * into the new buffer. 396 */ 397 if (m->m_flags & M_EXT) 398 { 399 int delta; 400 delta = (char *)ip - m->m_dat; 401 ip = (struct ipasfrag *)(m->m_ext + delta); 402 } 403 404 /* DEBUG_ARG("ip = %lx", (long)ip); 405 * ip=(struct ipasfrag *)m->m_data; */ 406 407 ip->ip_len = next; 408 ip->ipf_mff &= ~1; 409 ((struct ip *)ip)->ip_src = fp->ipq_src; 410 ((struct ip *)ip)->ip_dst = fp->ipq_dst; 411 remque_32(pData, fp); 412 (void) m_free(pData, dtom(pData, fp)); 413 m = dtom(pData, ip); 414 m->m_len += (ip->ip_hl << 2); 415 m->m_data -= (ip->ip_hl << 2); 416 417 return ((struct ip *)ip); 404 418 405 419 dropfrag: 406 407 408 420 ipstat.ips_fragdropped++; 421 m_freem(pData, m); 422 return (0); 409 423 } 410 424 … … 416 430 ip_freef(PNATState pData, struct ipq_t *fp) 417 431 { 418 register struct ipasfrag *q, *p; 419 420 for (q = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); q != (struct ipasfrag *)fp; 421 q = p) { 422 p = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *); 423 ip_deq(pData, q); 424 m_freem(pData, dtom(pData, q)); 425 } 426 remque_32(pData, fp); 427 (void) m_free(pData, dtom(pData, fp)); 428 } 429 #else /* !VBOX_WITH_BSD_REASS */ 432 register struct ipasfrag *q, *p; 433 434 for (q = u32_to_ptr(pData, fp->ipq_next, struct ipasfrag *); 435 q != (struct ipasfrag *)fp; 436 q = p) 437 { 438 p = u32_to_ptr(pData, q->ipf_next, struct ipasfrag *); 439 ip_deq(pData, q); 440 m_freem(pData, dtom(pData, q)); 441 } 442 remque_32(pData, fp); 443 (void) m_free(pData, dtom(pData, fp)); 444 } 445 446 #else /* VBOX_WITH_BSD_REASS */ 447 430 448 struct mbuf * 431 ip_reass(PNATState pData, struct mbuf* m) { 449 ip_reass(PNATState pData, struct mbuf* m) 450 { 432 451 struct ip *ip; 433 452 struct mbuf *p, *q, *nq, *t; … … 438 457 439 458 /* If maxnipq or maxfragsperpacket are 0, never accept fragments. */ 440 if (maxnipq == 0 441 || maxfragsperpacket == 0) { 459 if ( maxnipq == 0 460 || maxfragsperpacket == 0) 461 { 442 462 ipstat.ips_fragments++; 443 463 ipstat.ips_fragdropped++; … … 469 489 * exceeds the administrative limit. 470 490 */ 471 if ((nipq > maxnipq) && (maxnipq > 0)) { 491 if ((nipq > maxnipq) && (maxnipq > 0)) 492 { 472 493 /* 473 494 * drop something from the tail of the current queue … … 475 496 */ 476 497 struct ipq_t *q = TAILQ_LAST(head, ipqhead); 477 if (q == NULL) { /* gak */ 478 for (i = 0; i < IPREASS_NHASH; i++) { 498 if (q == NULL) 499 { 500 /* gak */ 501 for (i = 0; i < IPREASS_NHASH; i++) 502 { 479 503 struct ipq_t *r = TAILQ_LAST(&ipq[i], ipqhead); 480 if (r) { 504 if (r) 505 { 481 506 ipstat.ips_fragtimeout += r->ipq_nfrags; 482 507 ip_freef(pData, &ipq[i], r); … … 484 509 } 485 510 } 486 } else { 511 } 512 else 513 { 487 514 ipstat.ips_fragtimeout += q->ipq_nfrags; 488 515 ip_freef(pData, head, q); … … 496 523 */ 497 524 ip->ip_len -= hlen; 498 if (ip->ip_off & IP_MF) { 525 if (ip->ip_off & IP_MF) 526 { 499 527 /* 500 528 * Make sure that fragments have a data length 501 529 * that's a non-zero multiple of 8 bytes. 502 530 */ 503 if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) { 531 if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) 532 { 504 533 ipstat.ips_toosmall++; /* XXX */ 505 534 goto dropfrag; 506 535 } 507 536 m->m_flags |= M_FRAG; 508 } else 537 } 538 else 509 539 m->m_flags &= ~M_FRAG; 510 540 ip->ip_off <<= 3; … … 529 559 * If first fragment to arrive, create a reassembly queue. 530 560 */ 531 if (fp == NULL) { 561 if (fp == NULL) 562 { 532 563 fp = malloc(sizeof(struct ipq_t)); 533 564 if (fp == NULL) … … 544 575 m->m_nextpkt = NULL; 545 576 goto done; 546 } else { 577 } 578 else 579 { 547 580 fp->ipq_nfrags++; 548 581 } … … 567 600 * segment, then it's checksum is invalidated. 568 601 */ 569 if (p) { 602 if (p) 603 { 570 604 i = GETIP(p)->ip_off + GETIP(p)->ip_len - ip->ip_off; 571 if (i > 0) { 605 if (i > 0) 606 { 572 607 if (i >= ip->ip_len) 573 608 goto dropfrag; … … 578 613 m->m_nextpkt = p->m_nextpkt; 579 614 p->m_nextpkt = m; 580 } else { 615 } 616 else 617 { 581 618 m->m_nextpkt = fp->ipq_frags; 582 619 fp->ipq_frags = m; … … 588 625 */ 589 626 for (; q != NULL && ip->ip_off + ip->ip_len > GETIP(q)->ip_off; 590 q = nq) { 627 q = nq) 628 { 591 629 i = (ip->ip_off + ip->ip_len) - GETIP(q)->ip_off; 592 if (i < GETIP(q)->ip_len) { 630 if (i < GETIP(q)->ip_len) 631 { 593 632 GETIP(q)->ip_len -= i; 594 633 GETIP(q)->ip_off += i; … … 614 653 */ 615 654 next = 0; 616 for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) { 617 if (GETIP(q)->ip_off != next) { 618 if (fp->ipq_nfrags > maxfragsperpacket) { 655 for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) 656 { 657 if (GETIP(q)->ip_off != next) 658 { 659 if (fp->ipq_nfrags > maxfragsperpacket) 660 { 619 661 ipstat.ips_fragdropped += fp->ipq_nfrags; 620 662 ip_freef(pData, head, fp); … … 625 667 } 626 668 /* Make sure the last packet didn't have the IP_MF flag */ 627 if (p->m_flags & M_FRAG) { 628 if (fp->ipq_nfrags > maxfragsperpacket) { 669 if (p->m_flags & M_FRAG) 670 { 671 if (fp->ipq_nfrags > maxfragsperpacket) 672 { 629 673 ipstat.ips_fragdropped += fp->ipq_nfrags; 630 674 ip_freef(pData, head, fp); … … 638 682 q = fp->ipq_frags; 639 683 ip = GETIP(q); 640 if (next + (ip->ip_hl << 2) > IP_MAXPACKET) { 684 if (next + (ip->ip_hl << 2) > IP_MAXPACKET) 685 { 641 686 ipstat.ips_fragdropped += fp->ipq_nfrags; 642 687 ip_freef(pData, head, fp); … … 655 700 nq = q->m_nextpkt; 656 701 q->m_nextpkt = NULL; 657 for (q = nq; q != NULL; q = nq) { 702 for (q = nq; q != NULL; q = nq) 703 { 658 704 nq = q->m_nextpkt; 659 705 q->m_nextpkt = NULL; … … 692 738 fp->ipq_nfrags--; 693 739 m_freem(pData, m); 740 694 741 done: 695 return (NULL);742 return NULL; 696 743 697 744 #undef GETIP … … 699 746 700 747 void 701 ip_freef(PNATState pData, struct ipqhead *fhp, struct ipq_t *fp) { 748 ip_freef(PNATState pData, struct ipqhead *fhp, struct ipq_t *fp) 749 { 702 750 struct mbuf *q; 703 751 704 while (fp->ipq_frags) { 752 while (fp->ipq_frags) 753 { 705 754 q = fp->ipq_frags; 706 755 fp->ipq_frags = q->m_nextpkt; … … 721 770 ip_enq(PNATState pData, register struct ipasfrag *p, register struct ipasfrag *prev) 722 771 { 723 724 725 726 727 728 772 DEBUG_CALL("ip_enq"); 773 DEBUG_ARG("prev = %lx", (long)prev); 774 p->ipf_prev = ptr_to_u32(pData, prev); 775 p->ipf_next = prev->ipf_next; 776 u32_to_ptr(pData, prev->ipf_next, struct ipasfrag *)->ipf_prev = ptr_to_u32(pData, p); 777 prev->ipf_next = ptr_to_u32(pData, p); 729 778 } 730 779 … … 735 784 ip_deq(PNATState pData, register struct ipasfrag *p) 736 785 { 737 738 739 740 741 786 struct ipasfrag *prev = u32_to_ptr(pData, p->ipf_prev, struct ipasfrag *); 787 struct ipasfrag *next = u32_to_ptr(pData, p->ipf_next, struct ipasfrag *); 788 u32ptr_done(pData, prev->ipf_next, p); 789 prev->ipf_next = p->ipf_next; 790 next->ipf_prev = p->ipf_prev; 742 791 } 743 792 #endif /* !VBOX_WITH_BSD_REASS */ … … 751 800 ip_slowtimo(PNATState pData) 752 801 { 753 802 register struct ipq_t *fp; 754 803 755 804 #ifndef VBOX_WITH_BSD_REASS 756 DEBUG_CALL("ip_slowtimo"); 757 758 fp = u32_to_ptr(pData, ipq.next, struct ipq_t *); 759 if (fp == 0) 760 return; 761 762 while (fp != &ipq) { 763 --fp->ipq_ttl; 764 fp = u32_to_ptr(pData, fp->next, struct ipq_t *); 765 if (u32_to_ptr(pData, fp->prev, struct ipq_t *)->ipq_ttl == 0) { 766 ipstat.ips_fragtimeout++; 767 ip_freef(pData, u32_to_ptr(pData, fp->prev, struct ipq_t *)); 768 } 769 } 770 #else /* !VBOX_WITH_BSD_REASS */ 805 DEBUG_CALL("ip_slowtimo"); 806 807 fp = u32_to_ptr(pData, ipq.next, struct ipq_t *); 808 if (fp == 0) 809 return; 810 811 while (fp != &ipq) 812 { 813 --fp->ipq_ttl; 814 fp = u32_to_ptr(pData, fp->next, struct ipq_t *); 815 if (u32_to_ptr(pData, fp->prev, struct ipq_t *)->ipq_ttl == 0) 816 { 817 ipstat.ips_fragtimeout++; 818 ip_freef(pData, u32_to_ptr(pData, fp->prev, struct ipq_t *)); 819 } 820 } 821 #else /* VBOX_WITH_BSD_REASS */ 771 822 /* XXX: the fragment expiration is the same but requier 772 823 * additional loop see (see ip_input.c in FreeBSD tree) … … 774 825 int i; 775 826 DEBUG_CALL("ip_slowtimo"); 776 for (i = 0; i < IPREASS_NHASH; i++) { 777 for(fp = TAILQ_FIRST(&ipq[i]); fp;) { 827 for (i = 0; i < IPREASS_NHASH; i++) 828 { 829 for(fp = TAILQ_FIRST(&ipq[i]); fp;) 830 { 778 831 struct ipq_t *fpp; 779 832 … … 791 844 * enough to get down to the new limit. 792 845 */ 793 if (maxnipq >= 0 && nipq > maxnipq) { 794 for (i = 0; i < IPREASS_NHASH; i++) { 795 while (nipq > maxnipq && !TAILQ_EMPTY(&ipq[i])) { 796 ipstat.ips_fragdropped += 797 TAILQ_FIRST(&ipq[i])->ipq_nfrags; 846 if (maxnipq >= 0 && nipq > maxnipq) 847 { 848 for (i = 0; i < IPREASS_NHASH; i++) 849 { 850 while (nipq > maxnipq && !TAILQ_EMPTY(&ipq[i])) 851 { 852 ipstat.ips_fragdropped += TAILQ_FIRST(&ipq[i])->ipq_nfrags; 798 853 ip_freef(pData, &ipq[i], TAILQ_FIRST(&ipq[i])); 799 854 } … … 803 858 } 804 859 805 /*806 * Do option processing on a datagram,807 * possibly discarding it if bad options are encountered,808 * or forwarding it if source-routed.809 * Returns 1 if packet has been forwarded/freed,810 * 0 if the packet should be processed further.811 */812 813 #ifdef notdef814 815 int816 ip_dooptions(m)817 struct mbuf *m;818 {819 register struct ip *ip = mtod(m, struct ip *);820 register u_char *cp;821 register struct ip_timestamp *ipt;822 register struct in_ifaddr *ia;823 /* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */824 int opt, optlen, cnt, off, code, type, forward = 0;825 struct in_addr *sin, dst;826 typedef u_int32_t n_time;827 n_time ntime;828 829 dst = ip->ip_dst;830 cp = (u_char *)(ip + 1);831 cnt = (ip->ip_hl << 2) - sizeof (struct ip);832 for (; cnt > 0; cnt -= optlen, cp += optlen) {833 opt = cp[IPOPT_OPTVAL];834 if (opt == IPOPT_EOL)835 break;836 if (opt == IPOPT_NOP)837 optlen = 1;838 else {839 optlen = cp[IPOPT_OLEN];840 if (optlen <= 0 || optlen > cnt) {841 code = &cp[IPOPT_OLEN] - (u_char *)ip;842 goto bad;843 }844 }845 switch (opt) {846 847 default:848 break;849 850 /*851 * Source routing with record.852 * Find interface with current destination address.853 * If none on this machine then drop if strictly routed,854 * or do nothing if loosely routed.855 * Record interface address and bring up next address856 * component. If strictly routed make sure next857 * address is on directly accessible net.858 */859 case IPOPT_LSRR:860 case IPOPT_SSRR:861 if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {862 code = &cp[IPOPT_OFFSET] - (u_char *)ip;863 goto bad;864 }865 ipaddr.sin_addr = ip->ip_dst;866 ia = (struct in_ifaddr *)867 ifa_ifwithaddr((struct sockaddr *)&ipaddr);868 if (ia == 0) {869 if (opt == IPOPT_SSRR) {870 type = ICMP_UNREACH;871 code = ICMP_UNREACH_SRCFAIL;872 goto bad;873 }874 /*875 * Loose routing, and not at next destination876 * yet; nothing to do except forward.877 */878 break;879 }880 off--; / * 0 origin * /881 if (off > optlen - sizeof(struct in_addr)) {882 /*883 * End of source route. Should be for us.884 */885 save_rte(cp, ip->ip_src);886 break;887 }888 /*889 * locate outgoing interface890 */891 bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,892 sizeof(ipaddr.sin_addr));893 if (opt == IPOPT_SSRR) {894 #define INA struct in_ifaddr *895 #define SA struct sockaddr *896 if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)897 ia = (INA)ifa_ifwithnet((SA)&ipaddr);898 } else899 ia = ip_rtaddr(ipaddr.sin_addr);900 if (ia == 0) {901 type = ICMP_UNREACH;902 code = ICMP_UNREACH_SRCFAIL;903 goto bad;904 }905 ip->ip_dst = ipaddr.sin_addr;906 bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),907 (caddr_t)(cp + off), sizeof(struct in_addr));908 cp[IPOPT_OFFSET] += sizeof(struct in_addr);909 /*910 * Let ip_intr's mcast routing check handle mcast pkts911 */912 forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));913 break;914 915 case IPOPT_RR:916 if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {917 code = &cp[IPOPT_OFFSET] - (u_char *)ip;918 goto bad;919 }920 /*921 * If no space remains, ignore.922 */923 off--; * 0 origin *924 if (off > optlen - sizeof(struct in_addr))925 break;926 bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,927 sizeof(ipaddr.sin_addr));928 /*929 * locate outgoing interface; if we're the destination,930 * use the incoming interface (should be same).931 */932 if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&933 (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {934 type = ICMP_UNREACH;935 code = ICMP_UNREACH_HOST;936 goto bad;937 }938 bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),939 (caddr_t)(cp + off), sizeof(struct in_addr));940 cp[IPOPT_OFFSET] += sizeof(struct in_addr);941 break;942 943 case IPOPT_TS:944 code = cp - (u_char *)ip;945 ipt = (struct ip_timestamp *)cp;946 if (ipt->ipt_len < 5)947 goto bad;948 if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {949 if (++ipt->ipt_oflw == 0)950 goto bad;951 break;952 }953 sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);954 switch (ipt->ipt_flg) {955 956 case IPOPT_TS_TSONLY:957 break;958 959 case IPOPT_TS_TSANDADDR:960 if (ipt->ipt_ptr + sizeof(n_time) +961 sizeof(struct in_addr) > ipt->ipt_len)962 goto bad;963 ipaddr.sin_addr = dst;964 ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,965 m->m_pkthdr.rcvif);966 if (ia == 0)967 continue;968 bcopy((caddr_t)&IA_SIN(ia)->sin_addr,969 (caddr_t)sin, sizeof(struct in_addr));970 ipt->ipt_ptr += sizeof(struct in_addr);971 break;972 973 case IPOPT_TS_PRESPEC:974 if (ipt->ipt_ptr + sizeof(n_time) +975 sizeof(struct in_addr) > ipt->ipt_len)976 goto bad;977 bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,978 sizeof(struct in_addr));979 if (ifa_ifwithaddr((SA)&ipaddr) == 0)980 continue;981 ipt->ipt_ptr += sizeof(struct in_addr);982 break;983 984 default:985 goto bad;986 }987 ntime = iptime();988 bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,989 sizeof(n_time));990 ipt->ipt_ptr += sizeof(n_time);991 }992 }993 if (forward) {994 ip_forward(m, 1);995 return (1);996 }997 }998 }999 return (0);1000 bad:1001 /* ip->ip_len -= ip->ip_hl << 2; XXX icmp_error adds in hdr length */1002 1003 /* Not yet */1004 icmp_error(m, type, code, 0, 0);1005 1006 ipstat.ips_badoptions++;1007 return (1);1008 }1009 1010 #endif /* notdef */1011 860 1012 861 /* … … 1018 867 */ 1019 868 void 1020 ip_stripoptions(m, mopt) 1021 register struct mbuf *m; 1022 struct mbuf *mopt; 1023 { 1024 register int i; 1025 struct ip *ip = mtod(m, struct ip *); 1026 register caddr_t opts; 1027 int olen; 1028 1029 olen = (ip->ip_hl<<2) - sizeof (struct ip); 1030 opts = (caddr_t)(ip + 1); 1031 i = m->m_len - (sizeof (struct ip) + olen); 1032 memcpy(opts, opts + olen, (unsigned)i); 1033 m->m_len -= olen; 1034 1035 ip->ip_hl = sizeof(struct ip) >> 2; 1036 } 869 ip_stripoptions(struct mbuf *m, struct mbuf *mopt) 870 { 871 register int i; 872 struct ip *ip = mtod(m, struct ip *); 873 register caddr_t opts; 874 int olen; 875 876 olen = (ip->ip_hl<<2) - sizeof(struct ip); 877 opts = (caddr_t)(ip + 1); 878 i = m->m_len - (sizeof(struct ip) + olen); 879 memcpy(opts, opts + olen, (unsigned)i); 880 m->m_len -= olen; 881 882 ip->ip_hl = sizeof(struct ip) >> 2; 883 } -
trunk/src/VBox/Devices/Network/slirp/mbuf.c
r14964 r15450 58 58 { 59 59 m = (struct mbuf *)malloc(msize); 60 if (m == NULL) goto61 end_error;60 if (m == NULL) 61 goto end_error; 62 62 mbuf_alloced++; 63 63 if (mbuf_alloced > mbuf_thresh) … … 150 150 151 151 /* some compiles throw up on gotos. This one we can fake. */ 152 if (m->m_size >size)152 if (m->m_size > size) 153 153 return; 154 154 … … 156 156 { 157 157 datasize = m->m_data - m->m_ext; 158 m->m_ext = (char *)realloc(m->m_ext, size);158 m->m_ext = (char *)realloc(m->m_ext, size); 159 159 #if 0 160 160 if (m->m_ext == NULL) -
trunk/src/VBox/Devices/Network/slirp/socket.c
r15447 r15450 17 17 #include <icmpapi.h> 18 18 #endif 19 19 20 20 21 #ifdef VBOX_WITH_SLIRP_ICMP -
trunk/src/VBox/Devices/Network/slirp/tcp_subr.c
r15293 r15450 292 292 m_freem(pData, m); 293 293 } 294 /* It's static */295 #if 0296 if (tp->t_template)297 (void) m_free(dtom(tp->t_template));298 299 free(tp, M_PCB);300 #endif301 294 u32ptr_done(pData, ptr_to_u32(pData, tp), tp); 302 295 #else /* VBOX_WITH_BSD_REASS */ -
trunk/src/VBox/Devices/Network/slirp/udp.c
r15443 r15450 713 713 714 714 if ((so = socreate()) == NULL) 715 {716 free(so);717 715 return NULL; 718 } 716 719 717 so->s = socket(AF_INET,SOCK_DGRAM,0); 720 718 so->so_expire = curtime + SO_EXPIRE;
Note:
See TracChangeset
for help on using the changeset viewer.