Changeset 49593 in vbox for trunk/src/VBox/NetworkServices
- Timestamp:
- Nov 21, 2013 1:56:20 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 90798
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/NAT/pxping.c
r49555 r49593 62 62 63 63 SOCKET sock6; 64 int hopl; 64 65 65 66 struct pollmgr_handler pmhdl4; … … 128 129 129 130 /** 130 * lwIP thread callback message. 131 * lwIP thread callback message for IPv4 ping. 132 * 133 * We pass raw IP datagram for ip_output_if() so we only need pbuf and 134 * netif (from pxping). 131 135 */ 132 136 struct ping_msg { … … 137 141 138 142 143 /** 144 * lwIP thread callback message for IPv6 ping. 145 * 146 * We cannot obtain raw IPv6 datagram from host without extra trouble, 147 * so we pass ICMPv6 payload in pbuf and also other parameters to 148 * ip6_output_if(). 149 */ 150 struct ping6_msg { 151 struct tcpip_msg msg; 152 struct pxping *pxping; 153 struct pbuf *p; 154 ip6_addr_t src, dst; 155 int hopl, tclass; 156 }; 157 158 139 159 static void pxping_recv4(void *arg, struct pbuf *p); 160 static void pxping_recv6(void *arg, struct pbuf *p); 140 161 141 162 static void pxping_timer(void *arg); … … 157 178 static void pxping_pcb_debug_print(struct ping_pcb *pcb); 158 179 159 static struct ping_msg *pxping_msg_allocate(struct pxping *pxping, struct pbuf *p);160 161 180 static int pxping_pmgr_pump(struct pollmgr_handler *handler, SOCKET fd, int revents); 162 static void pxping_pmgr_icmp4(struct pxping *pxping, 163 size_t nread, struct sockaddr_in *peer);181 182 static void pxping_pmgr_icmp4(struct pxping *pxping); 164 183 static void pxping_pmgr_icmp4_echo(struct pxping *pxping, 165 184 u16_t iplen, struct sockaddr_in *peer); 166 185 static void pxping_pmgr_icmp4_error(struct pxping *pxping, 167 186 u16_t iplen, struct sockaddr_in *peer); 187 static void pxping_pmgr_icmp6(struct pxping *pxping); 188 static void pxping_pmgr_icmp6_echo(struct pxping *pxping, 189 u16_t iplen, struct sockaddr_in6 *peer); 190 static void pxping_pmgr_icmp6_error(struct pxping *pxping, 191 u16_t iplen, struct sockaddr_in6 *peer); 192 168 193 static void pxping_pmgr_forward_inbound(struct pxping *pxping, u16_t iplen); 169 194 static void pxping_pcb_forward_inbound(void *arg); 195 196 static void pxping_pmgr_forward_inbound6(struct pxping *pxping, 197 ip6_addr_t *src, ip6_addr_t *dst, 198 u8_t hopl, u8_t tclass, 199 u16_t icmplen); 200 static void pxping_pcb_forward_inbound6(void *arg); 170 201 171 202 /* … … 187 218 188 219 err_t 189 pxping_init(struct netif *netif, SOCKET sock) 190 { 191 if (sock == INVALID_SOCKET) { 220 pxping_init(struct netif *netif, SOCKET sock4, SOCKET sock6) 221 { 222 const int on = 1; 223 int status; 224 225 if (sock4 == INVALID_SOCKET && sock6 == INVALID_SOCKET) { 192 226 return ERR_VAL; 193 227 } 194 228 195 229 g_pxping.netif = netif; 196 197 g_pxping.sock4 = sock;198 g_pxping.ttl = -1;199 g_pxping.tos = 0;200 201 230 sys_mutex_new(&g_pxping.lock); 202 231 203 g_pxping.pmhdl4.callback = pxping_pmgr_pump; 204 g_pxping.pmhdl4.data = (void *)&g_pxping; 205 g_pxping.pmhdl4.slot = -1; 206 207 pollmgr_add(&g_pxping.pmhdl4, g_pxping.sock4, POLLIN); 208 209 ping_proxy_accept(pxping_recv4, &g_pxping); 232 g_pxping.sock4 = sock4; 233 if (g_pxping.sock4 != INVALID_SOCKET) { 234 g_pxping.ttl = -1; 235 g_pxping.tos = 0; 236 237 g_pxping.pmhdl4.callback = pxping_pmgr_pump; 238 g_pxping.pmhdl4.data = (void *)&g_pxping; 239 g_pxping.pmhdl4.slot = -1; 240 pollmgr_add(&g_pxping.pmhdl4, g_pxping.sock4, POLLIN); 241 242 ping_proxy_accept(pxping_recv4, &g_pxping); 243 } 244 245 g_pxping.sock6 = sock6; 246 if (g_pxping.sock6 != INVALID_SOCKET) { 247 g_pxping.hopl = -1; 248 249 #if !defined(IPV6_RECVPKTINFO) 250 #define IPV6_RECVPKTINFO (IPV6_PKTINFO) 251 #endif 252 status = setsockopt(sock6, IPPROTO_IPV6, IPV6_RECVPKTINFO, 253 (const char *)&on, sizeof(on)); 254 if (status < 0) { 255 perror("IPV6_RECVPKTINFO"); 256 /* XXX: this is fatal */ 257 } 258 259 #if !defined(IPV6_RECVHOPLIMIT) 260 #define IPV6_RECVHOPLIMIT (IPV6_HOPLIMIT) 261 #endif 262 status = setsockopt(sock6, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, 263 (const char *)&on, sizeof(on)); 264 if (status < 0) { 265 perror("IPV6_RECVHOPLIMIT"); 266 } 267 268 #ifdef IPV6_RECVTCLASS 269 /* TODO: IPV6_RECVTCLASS */ 270 #endif 271 272 g_pxping.pmhdl6.callback = pxping_pmgr_pump; 273 g_pxping.pmhdl6.data = (void *)&g_pxping; 274 g_pxping.pmhdl6.slot = -1; 275 pollmgr_add(&g_pxping.pmhdl6, g_pxping.sock6, POLLIN); 276 277 ping6_proxy_accept(pxping_recv6, &g_pxping); 278 } 279 210 280 return ERR_OK; 211 281 } … … 231 301 232 302 *oldp = u; 303 return sum; 304 } 305 306 307 static u32_t 308 updateip6_with_chksum(ip6_addr_t *oldp, const ip6_addr_t *ip6) 309 { 310 u32_t sum; 311 312 sum = update32_with_chksum(&oldp->addr[0], ip6->addr[0]); 313 sum += update32_with_chksum(&oldp->addr[1], ip6->addr[1]); 314 sum += update32_with_chksum(&oldp->addr[2], ip6->addr[2]); 315 sum += update32_with_chksum(&oldp->addr[3], ip6->addr[3]); 316 233 317 return sum; 234 318 } … … 260 344 261 345 pcb = pxping_pcb_for_request(pxping, 0, 262 ip _2_ipX(ip_current_src_addr()),263 ip _2_ipX(ip_current_dest_addr()),346 ipX_current_src_addr(), 347 ipX_current_dest_addr(), 264 348 id); 265 349 if (pcb == NULL) { … … 319 403 320 404 405 /** 406 * ICMPv6 Echo Request in pbuf "p" is to be proxied. 407 */ 408 static void 409 pxping_recv6(void *arg, struct pbuf *p) 410 { 411 struct pxping *pxping = (struct pxping *)arg; 412 struct ping_pcb *pcb; 413 struct ip6_hdr *iph; 414 struct icmp6_echo_hdr *icmph; 415 int hopl; 416 u32_t sum; 417 u16_t iphlen; 418 u16_t id, seq; 419 int status; 420 421 iph = (/* UNCONST */ struct ip6_hdr *)ip6_current_header(); 422 iphlen = ip_current_header_tot_len(); 423 424 icmph = (struct icmp6_echo_hdr *)p->payload; 425 426 id = icmph->id; 427 seq = icmph->seqno; 428 429 pcb = pxping_pcb_for_request(pxping, 1, 430 ipX_current_src_addr(), 431 ipX_current_dest_addr(), 432 id); 433 if (pcb == NULL) { 434 pbuf_free(p); 435 return; 436 } 437 438 pxping_pcb_debug_print(pcb); /* XXX */ 439 printf(" seq %d len %u hopl %d\n", 440 ntohs(seq), (unsigned int)p->tot_len, 441 IP6H_HOPLIM(iph)); 442 443 hopl = IP6H_HOPLIM(iph); 444 if (!pcb->is_mapped) { 445 if (hopl == 1) { 446 pbuf_header(p, iphlen); /* back to IP header */ 447 icmp6_time_exceeded(p, ICMP6_TE_HL); 448 return; 449 } 450 --hopl; 451 } 452 453 /* 454 * Rewrite ICMPv6 echo header. We don't need to recompute the 455 * checksum since, unlike IPv4, checksum includes pseudo-header. 456 * OS computes checksum for us on send() since it needs to select 457 * source address. 458 */ 459 icmph->id = pcb->host_id; 460 461 /* TODO: use control messages to save a syscall? */ 462 if (hopl != pxping->hopl) { 463 status = setsockopt(pxping->sock6, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 464 (char *)&hopl, sizeof(hopl)); 465 if (status == 0) { 466 pxping->hopl = hopl; 467 } 468 else { 469 perror("IPV6_HOPLIMIT"); 470 } 471 } 472 473 proxy_sendto(pxping->sock6, p, 474 &pcb->peer.sin6, sizeof(pcb->peer.sin6)); 475 476 pbuf_free(p); 477 } 478 479 321 480 static void 322 481 pxping_pcb_debug_print(struct ping_pcb *pcb) 323 482 { 324 printf("ping %p: %d.%d.%d.%d -> %d.%d.%d.%d id %04x->%04x", 325 (void *)pcb, 326 ip4_addr1(&pcb->src), ip4_addr2(&pcb->src), 327 ip4_addr3(&pcb->src), ip4_addr4(&pcb->src), 328 ip4_addr1(&pcb->dst), ip4_addr2(&pcb->dst), 329 ip4_addr3(&pcb->dst), ip4_addr4(&pcb->dst), 330 ntohs(pcb->guest_id), 331 ntohs(pcb->host_id)); 483 char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; 484 const char *addrstr; 485 int sdom = pcb->is_ipv6 ? AF_INET6 : AF_INET; 486 487 DPRINTF(("ping %p:", (void *)pcb)); 488 489 addrstr = inet_ntop(sdom, (void *)&pcb->src, addrbuf, sizeof(addrbuf)); 490 DPRINTF((" %s", addrstr)); 491 492 DPRINTF((" ->")); 493 494 addrstr = inet_ntop(sdom, (void *)&pcb->dst, addrbuf, sizeof(addrbuf)); 495 DPRINTF((" %s", addrstr)); 496 497 DPRINTF((" id %04x->%04x", ntohs(pcb->guest_id), ntohs(pcb->host_id))); 332 498 } 333 499 … … 442 608 443 609 if (pcb == NULL) { 610 int mapped; 611 444 612 pcb = pxping_pcb_allocate(pxping); 445 613 if (pcb == NULL) { … … 461 629 462 630 if (is_ipv6) { 631 pcb->peer.sin6.sin6_family = AF_INET6; 632 #if HAVE_SA_LEN 633 pcb->peer.sin6.sin6_len = sizeof(pcb->peer.sin6); 634 #endif 635 pcb->peer.sin.sin_port = htons(IPPROTO_ICMPV6); 636 mapped = pxremap_outbound_ip6((ip6_addr_t *)&pcb->peer.sin6.sin6_addr, 637 ipX_2_ip6(&pcb->dst)); 463 638 } 464 639 else { 465 int mapped;466 467 640 pcb->peer.sin.sin_family = AF_INET; 468 641 #if HAVE_SA_LEN 469 642 pcb->peer.sin.sin_len = sizeof(pcb->peer.sin); 470 643 #endif 644 pcb->peer.sin.sin_port = htons(IPPROTO_ICMP); 471 645 mapped = pxremap_outbound_ip4((ip_addr_t *)&pcb->peer.sin.sin_addr, 472 646 ipX_2_ip(&pcb->dst)); 473 if (mapped == PXREMAP_FAILED) {474 free(pcb); 475 return NULL;476 }477 else {478 pcb->is_mapped = (mapped == PXREMAP_MAPPED);479 }480 pcb-> peer.sin.sin_port = htons(IP_PROTO_ICMP);647 } 648 649 if (mapped == PXREMAP_FAILED) { 650 free(pcb); 651 return NULL; 652 } 653 else { 654 pcb->is_mapped = (mapped == PXREMAP_MAPPED); 481 655 } 482 656 … … 596 770 597 771 598 static struct ping_msg *599 pxping_msg_allocate(struct pxping *pxping, struct pbuf *p)600 {601 struct ping_msg *msg;602 603 msg = (struct ping_msg *)malloc(sizeof(*msg));604 if (msg == NULL) {605 return NULL;606 }607 608 msg->msg.type = TCPIP_MSG_CALLBACK_STATIC;609 msg->msg.sem = NULL;610 msg->msg.msg.cb.function = pxping_pcb_forward_inbound;611 msg->msg.msg.cb.ctx = (void *)msg;612 613 msg->pxping = pxping;614 msg->p = p;615 616 return msg;617 }618 619 620 772 static int 621 773 pxping_pmgr_pump(struct pollmgr_handler *handler, SOCKET fd, int revents) 622 774 { 623 775 struct pxping *pxping; 624 struct sockaddr_storage ss;625 socklen_t sslen = sizeof(ss);626 ssize_t nread;627 776 628 777 pxping = (struct pxping *)handler->data; 778 LWIP_ASSERT1(fd == pxping->sock4 || fd == pxping->sock6); 629 779 630 780 if (revents & ~(POLLIN|POLLERR)) { … … 654 804 } 655 805 656 memset(&ss, 0, sizeof(ss)); 657 nread = recvfrom(fd, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0, 658 (struct sockaddr *)&ss, &sslen); 659 if (nread < 0) { 660 perror(__func__); 661 return POLLIN; 662 } 663 664 pxping_pmgr_icmp4(pxping, nread, (struct sockaddr_in *)&ss); 806 if (fd == pxping->sock4) { 807 pxping_pmgr_icmp4(pxping); 808 } 809 else /* fd == pxping->sock6 */ { 810 pxping_pmgr_icmp6(pxping); 811 } 665 812 666 813 return POLLIN; … … 673 820 */ 674 821 static void 675 pxping_pmgr_icmp4(struct pxping *pxping, 676 size_t nread, struct sockaddr_in *peer) 677 { 822 pxping_pmgr_icmp4(struct pxping *pxping) 823 { 824 struct sockaddr_in sin; 825 socklen_t salen = sizeof(sin); 826 ssize_t nread; 678 827 struct ip_hdr *iph; 679 828 struct icmp_echo_hdr *icmph; 680 829 u16_t iplen; 830 831 memset(&sin, 0, sizeof(sin)); 832 833 /* 834 * Reads from raw IPv4 sockets deliver complete IP datagrams with 835 * IP header included. 836 */ 837 nread = recvfrom(pxping->sock4, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0, 838 (struct sockaddr *)&sin, &salen); 839 if (nread < 0) { 840 perror(__func__); 841 return; 842 } 681 843 682 844 if (nread < IP_HLEN) { … … 712 874 } 713 875 876 /* XXX: TODO: not for loopback */ 714 877 if (IPH_TTL(iph) == 1) { 715 878 DPRINTF2(("%s: dropping packet with ttl 1\n", __func__)); … … 741 904 icmph = (struct icmp_echo_hdr *)(pollmgr_udpbuf + IP_HLEN); 742 905 if (ICMPH_TYPE(icmph) == ICMP_ER) { 743 pxping_pmgr_icmp4_echo(pxping, iplen, peer);906 pxping_pmgr_icmp4_echo(pxping, iplen, &sin); 744 907 } 745 908 else if (ICMPH_TYPE(icmph) == ICMP_DUR || ICMPH_TYPE(icmph) == ICMP_TE) { 746 pxping_pmgr_icmp4_error(pxping, iplen, peer);909 pxping_pmgr_icmp4_error(pxping, iplen, &sin); 747 910 } 748 911 #if 1 … … 808 971 sys_mutex_unlock(&pxping->lock); 809 972 810 /* rewrite innerICMP echo header */973 /* rewrite ICMP echo header */ 811 974 sum = (u16_t)~icmph->chksum; 812 975 sum += update16_with_chksum(&icmph->id, guest_id); … … 814 977 icmph->chksum = ~sum; 815 978 816 /* rewrite outerIP header */979 /* rewrite IP header */ 817 980 sum = (u16_t)~IPH_CHKSUM(iph); 818 981 sum += update32_with_chksum((u32_t *)&iph->dest, … … 848 1011 ip_addr_t pcb_src, pcb_dst; 849 1012 u16_t guest_id; 1013 int mapped; 850 1014 u32_t sum; 851 1015 … … 928 1092 929 1093 /* save info before unlocking since pcb may expire */ 1094 mapped = pcb->is_mapped; 930 1095 ip_addr_copy(pcb_src, *ipX_2_ip(&pcb->src)); 931 1096 ip_addr_copy(pcb_dst, *ipX_2_ip(&pcb->dst)); … … 948 1113 sum = (u16_t)~IPH_CHKSUM(oiph); 949 1114 sum += update32_with_chksum((u32_t *)&oiph->src, ip4_addr_get_u32(&pcb_src)); 1115 /* XXX: FIXME: rewrite dst if mapped */ 950 1116 sum = FOLD_U32T(sum); 951 1117 IPH_CHKSUM_SET(oiph, ~sum); … … 954 1120 sum = (u16_t)~IPH_CHKSUM(iph); 955 1121 sum += update32_with_chksum((u32_t *)&iph->dest, ip4_addr_get_u32(&pcb_src)); 956 IPH_TTL_SET(iph, IPH_TTL(iph) - 1); 957 sum += PP_NTOHS(~0x0100); 1122 if (!mapped) { /* XXX: FIXME: error may be from elsewhere */ 1123 IPH_TTL_SET(iph, IPH_TTL(iph) - 1); 1124 sum += PP_NTOHS(~0x0100); 1125 } 958 1126 sum = FOLD_U32T(sum); 959 1127 IPH_CHKSUM_SET(iph, ~sum); 960 1128 961 1129 pxping_pmgr_forward_inbound(pxping, iplen); 1130 } 1131 1132 1133 static void 1134 pxping_pmgr_icmp6(struct pxping *pxping) 1135 { 1136 struct msghdr mh; 1137 struct iovec iov[1]; 1138 static u8_t cmsgbuf[128]; 1139 struct cmsghdr *cmh; 1140 struct sockaddr_in6 sin6; 1141 socklen_t salen = sizeof(sin6); 1142 ssize_t nread; 1143 struct icmp6_echo_hdr *icmph; 1144 #if defined(RT_OS_LINUX) && !defined(__USE_GNU) 1145 /* XXX: https://sourceware.org/bugzilla/show_bug.cgi?id=6775 */ 1146 struct in6_pktinfo { 1147 struct in6_addr ipi6_addr; 1148 unsigned int ipi6_ifindex; 1149 }; 1150 #endif 1151 struct in6_pktinfo *pktinfo; 1152 int hopl, tclass; 1153 1154 int mapped; 1155 struct ping_pcb *pcb; 1156 ip6_addr_t guest_ip, target_ip, unmapped_target_ip; 1157 u16_t id, guest_id; 1158 u32_t sum; 1159 1160 char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; 1161 const char *addrstr; 1162 1163 /* 1164 * Reads from raw IPv6 sockets deliver only the payload. Full 1165 * headers are available via recvmsg(2)/cmsg(3). 1166 */ 1167 memset(&mh, 0, sizeof(mh)); 1168 mh.msg_name = &sin6; 1169 mh.msg_namelen = sizeof(sin6); 1170 iov[0].iov_base = pollmgr_udpbuf; 1171 iov[0].iov_len = sizeof(pollmgr_udpbuf); 1172 mh.msg_iov = iov; 1173 mh.msg_iovlen = 1; 1174 mh.msg_control = cmsgbuf; 1175 mh.msg_controllen = sizeof(cmsgbuf); 1176 mh.msg_flags = 0; 1177 1178 nread = recvmsg(pxping->sock6, &mh, 0); 1179 if (nread < 0) { 1180 perror(__func__); 1181 return; 1182 } 1183 addrstr = inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, addrbuf, sizeof(addrbuf)); 1184 1185 icmph = (struct icmp6_echo_hdr *)pollmgr_udpbuf; 1186 DPRINTF2(("%s: %s ICMPv6: ", __func__, addrstr)); 1187 1188 id = 0; 1189 if (icmph->type == ICMP6_TYPE_EREP) { 1190 id = icmph->id; 1191 DPRINTF2(("echo reply %04x %u\n", 1192 (unsigned int)icmph->id, (unsigned int)icmph->seqno)); 1193 } 1194 else { /* XXX */ 1195 if (icmph->type == ICMP6_TYPE_EREQ) { 1196 DPRINTF2(("echo request %04x %u\n", 1197 (unsigned int)icmph->id, (unsigned int)icmph->seqno)); 1198 } 1199 else if (icmph->type == ICMP6_TYPE_DUR) { 1200 DPRINTF2(("destination unreachable\n")); 1201 } 1202 else if (icmph->type == ICMP6_TYPE_PTB) { 1203 DPRINTF2(("packet too big\n")); 1204 } 1205 else if (icmph->type == ICMP6_TYPE_TE) { 1206 DPRINTF2(("time exceeded\n")); 1207 } 1208 else if (icmph->type == ICMP6_TYPE_PP) { 1209 DPRINTF2(("parameter problem\n")); 1210 } 1211 else { 1212 DPRINTF2(("type %d len %u\n", icmph->type, (unsigned int)nread)); 1213 } 1214 return; 1215 } 1216 1217 /* XXX: refactor into pxping_pmgr_icmp6_echo(), pxping_pmgr_icmp6_error() */ 1218 1219 pktinfo = NULL; 1220 hopl = -1; 1221 tclass = -1; 1222 for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) { 1223 if (cmh->cmsg_len == 0) 1224 break; 1225 1226 if (cmh->cmsg_level == IPPROTO_IPV6 1227 && cmh->cmsg_type == IPV6_HOPLIMIT 1228 && cmh->cmsg_len == CMSG_LEN(sizeof(int))) 1229 { 1230 hopl = *(int *)CMSG_DATA(cmh); 1231 DPRINTF2(("hoplimit = %d\n", hopl)); 1232 } 1233 1234 if (cmh->cmsg_level == IPPROTO_IPV6 1235 && cmh->cmsg_type == IPV6_PKTINFO 1236 && cmh->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) 1237 { 1238 pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmh); 1239 DPRINTF2(("pktinfo found\n")); 1240 } 1241 } 1242 1243 if (pktinfo == NULL) { 1244 /* 1245 * ip6_output_if() doesn't do checksum for us so we need to 1246 * manually recompute it - for this we must know the 1247 * destination address of the pseudo-header that we will 1248 * rewrite with guest's address. 1249 */ 1250 DPRINTF2(("%s: unable to get pktinfo\n", __func__)); 1251 return; 1252 } 1253 1254 ip6_addr_copy(target_ip, *(ip6_addr_t *)&sin6.sin6_addr); 1255 mapped = pxremap_inbound_ip6(&unmapped_target_ip, &target_ip); 1256 if (mapped == PXREMAP_FAILED) { 1257 return; 1258 } 1259 1260 sys_mutex_lock(&pxping->lock); 1261 pcb = pxping_pcb_for_reply(pxping, 1, ip6_2_ipX(&unmapped_target_ip), id); 1262 if (pcb == NULL) { 1263 sys_mutex_unlock(&pxping->lock); 1264 DPRINTF2(("%s: no match\n", __func__)); 1265 return; 1266 } 1267 1268 DPRINTF2(("%s: pcb %p\n", __func__, (void *)pcb)); 1269 1270 /* save info before unlocking since pcb may expire */ 1271 ip6_addr_copy(guest_ip, *ipX_2_ip6(&pcb->src)); 1272 guest_id = pcb->guest_id; 1273 1274 sys_mutex_unlock(&pxping->lock); 1275 1276 /* rewrite ICMPv6 echo header */ 1277 sum = (u16_t)~icmph->chksum; 1278 sum += update16_with_chksum(&icmph->id, guest_id); 1279 1280 /* dst address in pseudo header (clobbers pktinfo) */ 1281 sum += updateip6_with_chksum((ip6_addr_t *)&pktinfo->ipi6_addr, &guest_ip); 1282 1283 /* src address in pseudo header (clobbers target_ip) */ 1284 if (mapped) { 1285 sum += updateip6_with_chksum(&target_ip, &unmapped_target_ip); 1286 } 1287 1288 sum = FOLD_U32T(sum); 1289 icmph->chksum = ~sum; 1290 1291 if (hopl < 0) { 1292 hopl = LWIP_ICMP6_HL; 1293 } 1294 else if (!mapped) { 1295 if (hopl == 1) { 1296 return; 1297 } 1298 --hopl; 1299 } 1300 1301 if (tclass < 0) { 1302 tclass = 0; 1303 } 1304 1305 pxping_pmgr_forward_inbound6(pxping, 1306 &unmapped_target_ip, /* echo reply src */ 1307 &guest_ip, /* echo reply dst */ 1308 hopl, tclass, (u16_t)nread); 1309 } 1310 1311 1312 static void 1313 pxping_pmgr_icmp6_echo(struct pxping *pxping, 1314 u16_t iplen, struct sockaddr_in6 *peer) 1315 { 1316 } 1317 1318 static void 1319 pxping_pmgr_icmp6_error(struct pxping *pxping, 1320 u16_t iplen, struct sockaddr_in6 *peer) 1321 { 962 1322 } 963 1323 … … 985 1345 } 986 1346 987 error = pbuf_take(p, pollmgr_udpbuf, (u16_t)iplen);1347 error = pbuf_take(p, pollmgr_udpbuf, iplen); 988 1348 if (error != ERR_OK) { 989 1349 DPRINTF(("%s: pbuf_take(%d) failed\n", … … 993 1353 } 994 1354 995 msg = pxping_msg_allocate(pxping, p);1355 msg = (struct ping_msg *)malloc(sizeof(*msg)); 996 1356 if (msg == NULL) { 997 1357 pbuf_free(p); … … 999 1359 } 1000 1360 1001 /* call pxping_pcb_forward_inbound() on lwip thread */ 1361 msg->msg.type = TCPIP_MSG_CALLBACK_STATIC; 1362 msg->msg.sem = NULL; 1363 msg->msg.msg.cb.function = pxping_pcb_forward_inbound; 1364 msg->msg.msg.cb.ctx = (void *)msg; 1365 1366 msg->pxping = pxping; 1367 msg->p = p; 1368 1002 1369 proxy_lwip_post(&msg->msg); 1003 1370 } … … 1018 1385 DPRINTF(("%s: ip_output_if: %s\n", 1019 1386 __func__, proxy_lwip_strerr(error))); 1387 pbuf_free(msg->p); 1020 1388 } 1021 1389 1022 1390 free(msg); 1023 1391 } 1392 1393 1394 static void 1395 pxping_pmgr_forward_inbound6(struct pxping *pxping, 1396 ip6_addr_t *src, ip6_addr_t *dst, 1397 u8_t hopl, u8_t tclass, 1398 u16_t icmplen) 1399 { 1400 struct pbuf *p; 1401 struct ping6_msg *msg; 1402 1403 err_t error; 1404 1405 p = pbuf_alloc(PBUF_IP, icmplen, PBUF_RAM); 1406 if (p == NULL) { 1407 DPRINTF(("%s: pbuf_alloc(%d) failed\n", 1408 __func__, (unsigned int)icmplen)); 1409 return; 1410 } 1411 1412 error = pbuf_take(p, pollmgr_udpbuf, icmplen); 1413 if (error != ERR_OK) { 1414 DPRINTF(("%s: pbuf_take(%d) failed\n", 1415 __func__, (unsigned int)icmplen)); 1416 pbuf_free(p); 1417 return; 1418 } 1419 1420 msg = (struct ping6_msg *)malloc(sizeof(*msg)); 1421 if (msg == NULL) { 1422 pbuf_free(p); 1423 return; 1424 } 1425 1426 msg->msg.type = TCPIP_MSG_CALLBACK_STATIC; 1427 msg->msg.sem = NULL; 1428 msg->msg.msg.cb.function = pxping_pcb_forward_inbound6; 1429 msg->msg.msg.cb.ctx = (void *)msg; 1430 1431 msg->pxping = pxping; 1432 msg->p = p; 1433 ip6_addr_copy(msg->src, *src); 1434 ip6_addr_copy(msg->dst, *dst); 1435 msg->hopl = hopl; 1436 msg->tclass = tclass; 1437 1438 proxy_lwip_post(&msg->msg); 1439 } 1440 1441 1442 static void 1443 pxping_pcb_forward_inbound6(void *arg) 1444 { 1445 struct ping6_msg *msg = (struct ping6_msg *)arg; 1446 err_t error; 1447 1448 LWIP_ASSERT1(msg != NULL); 1449 LWIP_ASSERT1(msg->pxping != NULL); 1450 LWIP_ASSERT1(msg->p != NULL); 1451 1452 error = ip6_output_if(msg->p, 1453 &msg->src, &msg->dst, msg->hopl, msg->tclass, 1454 IP6_NEXTH_ICMP6, msg->pxping->netif); 1455 if (error != ERR_OK) { 1456 DPRINTF(("%s: ip6_output_if: %s\n", 1457 __func__, proxy_lwip_strerr(error))); 1458 pbuf_free(msg->p); 1459 } 1460 1461 free(msg); 1462 }
Note:
See TracChangeset
for help on using the changeset viewer.