Changeset 49637 in vbox for trunk/src/VBox
- Timestamp:
- Nov 25, 2013 3:43:54 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 90862
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/NAT/pxping.c
r49617 r49637 46 46 #endif 47 47 48 #if defined(RT_OS_LINUX) && !defined(__USE_GNU) 49 /* XXX: https://sourceware.org/bugzilla/show_bug.cgi?id=6775 */ 50 struct in6_pktinfo { 51 struct in6_addr ipi6_addr; 52 unsigned int ipi6_ifindex; 53 }; 54 #endif 55 48 56 49 57 /* forward */ … … 190 198 static void pxping_pmgr_icmp6(struct pxping *pxping); 191 199 static void pxping_pmgr_icmp6_echo(struct pxping *pxping, 192 u16_t iplen, struct sockaddr_in6 *peer); 200 ip6_addr_t *src, ip6_addr_t *dst, 201 int hopl, int tclass, u16_t icmplen); 193 202 static void pxping_pmgr_icmp6_error(struct pxping *pxping, 194 u16_t iplen, struct sockaddr_in6 *peer); 203 ip6_addr_t *src, ip6_addr_t *dst, 204 int hopl, int tclass, u16_t icmplen); 195 205 196 206 static void pxping_pmgr_forward_inbound(struct pxping *pxping, u16_t iplen); … … 257 267 if (status < 0) { 258 268 perror("IPV6_RECVPKTINFO"); 259 /* XXX: this is fatal */269 /* XXX: for now this is fatal */ 260 270 } 261 271 … … 286 296 287 297 static u32_t 288 update16_with_chksum(u16_t *oldp, u16_t h) 289 { 290 u32_t sum = (u16_t)~*oldp; 291 sum += h; 292 293 *oldp = h; 298 chksum_delta_16(u16_t oval, u16_t nval) 299 { 300 u32_t sum = (u16_t)~oval; 301 sum += nval; 294 302 return sum; 295 303 } … … 297 305 298 306 static u32_t 299 update32_with_chksum(u32_t *oldp, u32_t u) 300 { 301 u32_t sum = ~*oldp; 307 chksum_update_16(u16_t *oldp, u16_t nval) 308 { 309 u32_t sum = chksum_delta_16(*oldp, nval); 310 *oldp = nval; 311 return sum; 312 } 313 314 315 static u32_t 316 chksum_delta_32(u32_t oval, u32_t nval) 317 { 318 u32_t sum = ~oval; 302 319 sum = FOLD_U32T(sum); 303 sum += FOLD_U32T(u); 304 305 *oldp = u; 320 sum += FOLD_U32T(nval); 306 321 return sum; 307 322 } … … 309 324 310 325 static u32_t 311 updateip6_with_chksum(ip6_addr_t *oldp, const ip6_addr_t *ip6) 326 chksum_update_32(u32_t *oldp, u32_t nval) 327 { 328 u32_t sum = chksum_delta_32(*oldp, nval); 329 *oldp = nval; 330 return sum; 331 } 332 333 334 static u32_t 335 chksum_delta_ipv6(const ip6_addr_t *oldp, const ip6_addr_t *newp) 312 336 { 313 337 u32_t sum; 314 338 315 sum = update32_with_chksum(&oldp->addr[0], ip6->addr[0]); 316 sum += update32_with_chksum(&oldp->addr[1], ip6->addr[1]); 317 sum += update32_with_chksum(&oldp->addr[2], ip6->addr[2]); 318 sum += update32_with_chksum(&oldp->addr[3], ip6->addr[3]); 339 sum = chksum_delta_32(oldp->addr[0], newp->addr[0]); 340 sum += chksum_delta_32(oldp->addr[1], newp->addr[1]); 341 sum += chksum_delta_32(oldp->addr[2], newp->addr[2]); 342 sum += chksum_delta_32(oldp->addr[3], newp->addr[3]); 343 344 return sum; 345 } 346 347 348 static u32_t 349 chksum_update_ipv6(ip6_addr_t *oldp, const ip6_addr_t *newp) 350 { 351 u32_t sum; 352 353 sum = chksum_update_32(&oldp->addr[0], newp->addr[0]); 354 sum += chksum_update_32(&oldp->addr[1], newp->addr[1]); 355 sum += chksum_update_32(&oldp->addr[2], newp->addr[2]); 356 sum += chksum_update_32(&oldp->addr[3], newp->addr[3]); 319 357 320 358 return sum; … … 372 410 /* rewrite ICMP echo header */ 373 411 sum = (u16_t)~icmph->chksum; 374 sum += update16_with_chksum(&icmph->id, pcb->host_id);412 sum += chksum_update_16(&icmph->id, pcb->host_id); 375 413 sum = FOLD_U32T(sum); 376 414 icmph->chksum = ~sum; … … 984 1022 /* rewrite ICMP echo header */ 985 1023 sum = (u16_t)~icmph->chksum; 986 sum += update16_with_chksum(&icmph->id, guest_id);1024 sum += chksum_update_16(&icmph->id, guest_id); 987 1025 sum = FOLD_U32T(sum); 988 1026 icmph->chksum = ~sum; … … 990 1028 /* rewrite IP header */ 991 1029 sum = (u16_t)~IPH_CHKSUM(iph); 992 sum += update32_with_chksum((u32_t *)&iph->dest,1030 sum += chksum_update_32((u32_t *)&iph->dest, 993 1031 ip4_addr_get_u32(&guest_ip)); 994 1032 if (mapped == PXREMAP_MAPPED) { 995 sum += update32_with_chksum((u32_t *)&iph->src,1033 sum += chksum_update_32((u32_t *)&iph->src, 996 1034 ip4_addr_get_u32(&target_ip)); 997 1035 } … … 1142 1180 /* rewrite inner ICMP echo header */ 1143 1181 sum = (u16_t)~oicmph->chksum; 1144 sum += update16_with_chksum(&oicmph->id, guest_id);1182 sum += chksum_update_16(&oicmph->id, guest_id); 1145 1183 sum = FOLD_U32T(sum); 1146 1184 oicmph->chksum = ~sum; … … 1148 1186 /* rewrite inner IP header */ 1149 1187 sum = (u16_t)~IPH_CHKSUM(oiph); 1150 sum += update32_with_chksum((u32_t *)&oiph->src, 1151 ip4_addr_get_u32(&guest_ip)); 1188 sum += chksum_update_32((u32_t *)&oiph->src, ip4_addr_get_u32(&guest_ip)); 1152 1189 if (target_mapped == PXREMAP_MAPPED) { 1153 sum += update32_with_chksum((u32_t *)&oiph->dest, 1154 ip4_addr_get_u32(&target_ip)); 1190 sum += chksum_update_32((u32_t *)&oiph->dest, ip4_addr_get_u32(&target_ip)); 1155 1191 } 1156 1192 sum = FOLD_U32T(sum); … … 1159 1195 /* rewrite outer IP header */ 1160 1196 sum = (u16_t)~IPH_CHKSUM(iph); 1161 sum += update32_with_chksum((u32_t *)&iph->dest, 1162 ip4_addr_get_u32(&guest_ip)); 1197 sum += chksum_update_32((u32_t *)&iph->dest, ip4_addr_get_u32(&guest_ip)); 1163 1198 if (error_mapped == PXREMAP_MAPPED) { 1164 sum += update32_with_chksum((u32_t *)&iph->src, 1165 ip4_addr_get_u32(&error_ip)); 1199 sum += chksum_update_32((u32_t *)&iph->src, ip4_addr_get_u32(&error_ip)); 1166 1200 } 1167 1201 else { … … 1187 1221 ssize_t nread; 1188 1222 struct icmp6_echo_hdr *icmph; 1189 #if defined(RT_OS_LINUX) && !defined(__USE_GNU)1190 /* XXX: https://sourceware.org/bugzilla/show_bug.cgi?id=6775 */1191 struct in6_pktinfo {1192 struct in6_addr ipi6_addr;1193 unsigned int ipi6_ifindex;1194 };1195 #endif1196 1223 struct in6_pktinfo *pktinfo; 1197 1224 int hopl, tclass; 1198 1199 int mapped;1200 struct ping_pcb *pcb;1201 ip6_addr_t guest_ip, target_ip, unmapped_target_ip;1202 u16_t id, guest_id;1203 u32_t sum;1204 1225 1205 1226 char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; … … 1231 1252 DPRINTF2(("%s: %s ICMPv6: ", __func__, addrstr)); 1232 1253 1233 id = 0;1234 1254 if (icmph->type == ICMP6_TYPE_EREP) { 1235 id = icmph->id;1236 1255 DPRINTF2(("echo reply %04x %u\n", 1237 1256 (unsigned int)icmph->id, (unsigned int)icmph->seqno)); … … 1259 1278 return; 1260 1279 } 1261 1262 /* XXX: refactor into pxping_pmgr_icmp6_echo(), pxping_pmgr_icmp6_error() */1263 1280 1264 1281 pktinfo = NULL; … … 1291 1308 * manually recompute it - for this we must know the 1292 1309 * destination address of the pseudo-header that we will 1293 * rewrite with guest's address. 1310 * rewrite with guest's address. (TODO: yeah, yeah, we can 1311 * compute it from scratch...) 1294 1312 */ 1295 1313 DPRINTF2(("%s: unable to get pktinfo\n", __func__)); … … 1297 1315 } 1298 1316 1299 ip6_addr_copy(target_ip, *(ip6_addr_t *)&sin6.sin6_addr);1300 mapped = pxremap_inbound_ip6(&unmapped_target_ip, &target_ip);1301 if (mapped == PXREMAP_FAILED) {1302 return;1303 }1304 1305 sys_mutex_lock(&pxping->lock);1306 pcb = pxping_pcb_for_reply(pxping, 1, ip6_2_ipX(&unmapped_target_ip), id);1307 if (pcb == NULL) {1308 sys_mutex_unlock(&pxping->lock);1309 DPRINTF2(("%s: no match\n", __func__));1310 return;1311 }1312 1313 DPRINTF2(("%s: pcb %p\n", __func__, (void *)pcb));1314 1315 /* save info before unlocking since pcb may expire */1316 ip6_addr_copy(guest_ip, *ipX_2_ip6(&pcb->src));1317 guest_id = pcb->guest_id;1318 1319 sys_mutex_unlock(&pxping->lock);1320 1321 /* rewrite ICMPv6 echo header */1322 sum = (u16_t)~icmph->chksum;1323 sum += update16_with_chksum(&icmph->id, guest_id);1324 1325 /* dst address in pseudo header (clobbers pktinfo) */1326 sum += updateip6_with_chksum((ip6_addr_t *)&pktinfo->ipi6_addr, &guest_ip);1327 1328 /* src address in pseudo header (clobbers target_ip) */1329 if (mapped) {1330 sum += updateip6_with_chksum(&target_ip, &unmapped_target_ip);1331 }1332 1333 sum = FOLD_U32T(sum);1334 icmph->chksum = ~sum;1335 1336 1317 if (hopl < 0) { 1337 1318 hopl = LWIP_ICMP6_HL; 1338 1319 } 1339 else if (!mapped) { 1340 if (hopl == 1) { 1341 return; 1342 } 1343 --hopl; 1344 } 1345 1346 if (tclass < 0) { 1347 tclass = 0; 1348 } 1349 1350 pxping_pmgr_forward_inbound6(pxping, 1351 &unmapped_target_ip, /* echo reply src */ 1352 &guest_ip, /* echo reply dst */ 1353 hopl, tclass, (u16_t)nread); 1320 1321 if (icmph->type == ICMP6_TYPE_EREP) { 1322 pxping_pmgr_icmp6_echo(pxping, 1323 (ip6_addr_t *)&sin6.sin6_addr, 1324 (ip6_addr_t *)&pktinfo->ipi6_addr, 1325 hopl, tclass, (u16_t)nread); 1326 } 1327 else { 1328 pxping_pmgr_icmp6_error(pxping, 1329 (ip6_addr_t *)&sin6.sin6_addr, 1330 (ip6_addr_t *)&pktinfo->ipi6_addr, 1331 hopl, tclass, (u16_t)nread); 1332 } 1354 1333 } 1355 1334 … … 1357 1336 static void 1358 1337 pxping_pmgr_icmp6_echo(struct pxping *pxping, 1359 u16_t iplen, struct sockaddr_in6 *peer) 1360 { 1361 } 1338 ip6_addr_t *src, ip6_addr_t *dst, 1339 int hopl, int tclass, u16_t icmplen) 1340 { 1341 struct ip6_hdr *oiph; 1342 struct icmp6_hdr *icmph, *oicmph; 1343 struct ping_pcb *pcb; 1344 ip6_addr_t guest_ip, target_ip, error_ip; 1345 int target_mapped, error_mapped; 1346 u16_t id, guest_id; 1347 u32_t sum; 1348 1349 icmph = (struct icmp6_hdr *)pollmgr_udpbuf; 1350 1351 /* 1352 * Inner IP datagram is not checked by the kernel and may be 1353 * anything, possibly malicious. 1354 */ 1355 oiph = (struct ip6_hdr *)(pollmgr_udpbuf + sizeof(*icmph)); 1356 1357 if (IP6H_V(oiph) != 6) { 1358 DPRINTF2(("%s: unexpected IP version %d\n", __func__, IP6H_V(oiph))); 1359 return; 1360 } 1361 1362 DPRINTF2(("%s: nexth = %d\n", __func__, IP6H_NEXTH(oiph))); 1363 } 1364 1362 1365 1363 1366 static void 1364 1367 pxping_pmgr_icmp6_error(struct pxping *pxping, 1365 u16_t iplen, struct sockaddr_in6 *peer) 1366 { 1368 ip6_addr_t *src, ip6_addr_t *dst, 1369 int hopl, int tclass, u16_t icmplen) 1370 { 1371 struct icmp6_echo_hdr *icmph; 1372 int mapped; 1373 struct ping_pcb *pcb; 1374 ip6_addr_t guest_ip, target_ip; 1375 u16_t id, guest_id; 1376 u32_t sum; 1367 1377 } 1368 1378
Note:
See TracChangeset
for help on using the changeset viewer.