- Timestamp:
- Dec 5, 2008 12:36:46 PM (16 years ago)
- Location:
- trunk/src/VBox/Devices/Network/slirp
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/ip_icmp.c
r14684 r15035 67 67 68 68 #ifdef VBOX_WITH_SLIRP_ICMP 69 int 70 icmp_init(PNATState pData) 71 { 72 pData->icmp_socket.so_type = IPPROTO_ICMP; 73 pData->icmp_socket.so_state = SS_ISFCONNECTED; 74 pData->icmp_socket.s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); 75 insque(pData, &pData->icmp_socket, &udb); 76 LIST_INIT(&pData->icmp_msg_head); 77 return (0); 78 } 79 80 /* 81 * ip here is ip header + 64bytes readed from ICMP packet 82 */ 83 struct icmp_msg * 84 icmp_find_original_mbuf(PNATState pData, struct ip *ip) 85 { 86 struct mbuf *m0; 87 struct ip *ip0; 88 struct icmp *icp, *icp0; 89 struct icmp_msg *icm; 90 int found = 0; 91 struct socket *head_socket; 92 struct in_addr laddr, faddr; 93 u_int lport, fport; 94 95 switch (ip->ip_p) { 96 case IPPROTO_ICMP: 97 icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2)); 98 LIST_FOREACH(icm, &pData->icmp_msg_head, im_list) 99 { 100 m0 = icm->im_m; 101 ip0 = mtod(m0, struct ip *); 102 AssertRelease(ip0->ip_p == IPPROTO_ICMP); 103 icp0 = (struct icmp *)((char *)ip0 + (ip0->ip_hl << 2)); 104 LogRel(("ip(src:%R[IP4], dst:%R[IP4],id:%x) ip0(src:%R[IP4],dst:%R[IP4],id:%x)\n", 105 ip->ip_src.s_addr, 106 ip->ip_dst.s_addr, 107 ip->ip_id, 108 ip0->ip_src.s_addr, 109 ip0->ip_dst.s_addr, 110 ip0->ip_id)); 111 LogRel(("icp(id:%x, seq:%x, type=%d) icp0(id:%x, seq:%x)\n",icp->icmp_id, icp->icmp_seq, icp->icmp_type, icp0->icmp_id, icp0->icmp_seq)); 112 if ( 113 ((icp->icmp_type != ICMP_ECHO && ip->ip_src.s_addr == ip0->ip_dst.s_addr) 114 ||(icp->icmp_type == ICMP_ECHO && ip->ip_dst.s_addr == ip0->ip_dst.s_addr)) 115 && icp->icmp_id == icp0->icmp_id 116 && icp->icmp_seq == icp->icmp_seq) { 117 found = 1; 118 break; 119 } 120 } 121 case IPPROTO_UDP: 122 head_socket = &udb; 123 case IPPROTO_TCP: 124 head_socket = (head_socket != NULL ? head_socket : &tcb); /* head_socket could be initialized with udb*/ 125 } 126 if (found == 1) { 127 return (icm); 128 } 129 return (NULL); 130 } 131 69 132 static int 70 icmp_attach(PNATState pData, struct socket *so) { 71 AssertRelease(so != NULL); 72 so->s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); 73 insque(pData, so, &udb); /*adding it udb queue*/ 74 return (so->s); 133 icmp_attach(PNATState pData, struct mbuf *m) { 134 struct icmp_msg *icm; 135 struct ip *ip; 136 ip = mtod(m, struct ip *); 137 Assert(ip->ip_p == IPPROTO_ICMP); 138 icm = malloc(sizeof(struct icmp_msg)); 139 icm->im_m = m; 140 LIST_INSERT_HEAD(&pData->icmp_msg_head, icm, im_list); 141 return (0); 75 142 } 76 143 #endif /* VBOX_WITH_SLIRP_ICMP */ … … 85 152 register struct ip *ip=mtod(m, struct ip *); 86 153 int icmplen=ip->ip_len; 154 int status; 87 155 /* int code; */ 88 156 … … 123 191 icp->icmp_type = ICMP_ECHOREPLY; 124 192 #endif /* !VBOX_WITH_SLIRP_ICMP */ 193 125 194 ip->ip_len += hlen; /* since ip_input subtracts this */ 126 if (ip->ip_dst.s_addr == alias_addr.s_addr) { 195 if (ip->ip_dst.s_addr == alias_addr.s_addr 196 ) { 127 197 #ifdef VBOX_WITH_SLIRP_ICMP 128 198 icp->icmp_type = ICMP_ECHOREPLY; … … 132 202 struct socket *so; 133 203 struct sockaddr_in addr; 204 #ifndef VBOX_WITH_SLIRP_ICMP 134 205 if ((so = socreate()) == NULL) goto freeit; 135 #ifndef VBOX_WITH_SLIRP_ICMP136 206 if(udp_attach(pData, so) == -1) 137 #else138 if(icmp_attach(pData, so) == -1)139 #endif140 207 { 141 208 DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", … … 154 221 so->so_state = SS_ISFCONNECTED; 155 222 156 /* Send the packet */157 223 addr.sin_family = AF_INET; 158 224 if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr) { … … 171 237 } 172 238 addr.sin_port = so->so_fport; 173 #ifndef VBOX_WITH_SLIRP_ICMP174 239 if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0, 175 240 (struct sockaddr *)&addr, sizeof(addr)) == -1) { … … 180 245 } 181 246 #else /* !VBOX_WITH_SLIRP_ICMP */ 182 if(sendto(so->s, icp, icmplen, 0, 247 addr.sin_family = AF_INET; 248 if ((ip->ip_dst.s_addr & htonl(pData->netmask)) == special_addr.s_addr) { 249 /* It's an alias */ 250 switch(ntohl(ip->ip_dst.s_addr) & ~pData->netmask) { 251 case CTL_DNS: 252 addr.sin_addr = dns_addr; 253 break; 254 case CTL_ALIAS: 255 default: 256 addr.sin_addr = loopback_addr; 257 break; 258 } 259 } else { 260 addr.sin_addr.s_addr = ip->ip_dst.s_addr; 261 } 262 icmp_attach(pData, m); 263 /* Send the packet */ 264 status = setsockopt(pData->icmp_socket.s, IPPROTO_IP, IP_TTL, (void *)&ip->ip_ttl, sizeof(ip->ip_ttl)); 265 if (status < 0) { 266 LogRel(("error(%s) occured while setting TTL attribute of IP packet\n", strerror(errno))); 267 } 268 if(sendto(pData->icmp_socket.s, icp, icmplen, 0, 183 269 (struct sockaddr *)&addr, sizeof(addr)) == -1) { 184 270 DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n", 185 271 errno,strerror(errno))); 186 272 icmp_error(pData, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); 187 udp_detach(pData, so);273 m_free(pData, m); 188 274 } 189 275 … … 382 468 m->m_len -= optlen; 383 469 } 384 470 LogRel(("%s, ttl %d msg_type=%d code=%d\n", __FUNCTION__, ip->ip_ttl, icp->icmp_type, icp->icmp_code )); 471 #ifndef VBOX_WITH_SLIRP_ICMP 385 472 ip->ip_ttl = MAXTTL; 386 #ifndef VBOX_WITH_SLIRP_ICMP387 473 { /* swap */ 388 474 struct in_addr icmp_dst; -
trunk/src/VBox/Devices/Network/slirp/ip_icmp.h
r1076 r15035 37 37 #ifndef _NETINET_IP_ICMP_H_ 38 38 #define _NETINET_IP_ICMP_H_ 39 #ifdef VBOX_WITH_SLIRP_ICMP 40 #include <queue.h> 41 #endif 39 42 40 43 /* … … 162 165 void icmp_reflect _P((PNATState, struct mbuf *)); 163 166 167 #ifdef VBOX_WITH_SLIRP_ICMP 168 struct icmp_msg{ 169 LIST_ENTRY(icmp_msg) im_list; 170 struct mbuf *im_m; 171 }; 172 173 LIST_HEAD(icmp_storage, icmp_msg); 174 175 int icmp_init _P((PNATState )); 176 struct icmp_msg * icmp_find_original_mbuf _P((PNATState , struct ip *)); 177 #endif /* VBOX_WITH_SLIRP_ICMP */ 178 164 179 #endif -
trunk/src/VBox/Devices/Network/slirp/ip_input.c
r14795 r15035 138 138 139 139 /* check ip_ttl for a correct ICMP reply */ 140 if(ip->ip_ttl==0 || ip->ip_ttl ==1) {140 if(ip->ip_ttl==0 || ip->ip_ttl == 1) { 141 141 icmp_error(pData, m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl"); 142 142 goto bad; 143 143 } 144 144 145 #ifdef VBOX_WITH_SLIRP_ICMP 146 ip->ip_ttl--; 147 #endif 145 148 /* 146 149 * Process options and, if not destined for us, -
trunk/src/VBox/Devices/Network/slirp/slirp.c
r14964 r15035 246 246 if_init(pData); 247 247 ip_init(pData); 248 #ifdef VBOX_WITH_SLIRP_ICMP 249 icmp_init(pData); 250 #endif /* VBOX_WITH_SLIRP_ICMP */ 248 251 249 252 /* Initialise mbufs *after* setting the MTU */ … … 555 558 * the session could have more queued if the packets needed 556 559 * to be fragmented. 557 * 560 * 558 561 * (XXX <= 4 ?) 559 562 */ -
trunk/src/VBox/Devices/Network/slirp/slirp_state.h
r14684 r15035 21 21 #ifndef _slirp_state_h_ 22 22 #define _slirp_state_h_ 23 #ifdef VBOX_WITH_SLIRP_ICMP 24 #include "ip_icmp.h" 25 #endif 23 26 24 27 /** Number of DHCP clients supported by NAT. */ … … 129 132 struct socket udb; 130 133 struct socket *udp_last_so; 134 #ifdef VBOX_WITH_SLIRP_ICMP 135 struct socket icmp_socket; 136 struct icmp_storage icmp_msg_head; 137 #endif 131 138 #if defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS) 132 139 # define VBOX_SOCKET_EVENT (pData->phEvents[VBOX_SOCKET_EVENT_INDEX]) -
trunk/src/VBox/Devices/Network/slirp/socket.c
r14964 r15035 423 423 DEBUG_ARG("so = %lx", (long)so); 424 424 425 if (so->so_type == IPPROTO_ICMP) 426 { 427 /* This is a "ping" reply */ 428 char buff[256]; 429 int len; 430 431 len = recvfrom(so->s, buff, sizeof(buff), 0, 432 (struct sockaddr *)&addr, &addrlen); 433 /* XXX Check if reply is "correct"? */ 425 if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ 426 char buff[1500]; 427 int len; 428 len = recvfrom(so->s, buff, 1500, 0, 429 (struct sockaddr *)&addr, &addrlen); 430 /* XXX Check if reply is "correct"? */ 434 431 435 432 if(len == -1 || len == 0) … … 441 438 else if(errno == ENETUNREACH) 442 439 code=ICMP_UNREACH_NET; 440 443 441 444 442 DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", … … 450 448 #ifdef VBOX_WITH_SLIRP_ICMP 451 449 struct ip *ip; 452 uint32_t dst; 453 ip = mtod(so->so_m, struct ip *); 454 dst = ip->ip_src.s_addr; 455 memcpy(so->so_m->m_data, buff, len); /* ovveride ther tail of old packet */ 450 uint32_t dst,src; 451 char ip_copy[256]; 452 struct icmp *icp; 453 int old_ip_len; 454 struct mbuf *orig_m; 455 struct icmp_msg *icm; 456 457 ip = (struct ip *)buff; 458 icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2)); 459 Assert(icp->icmp_type != ICMP_ECHO); 460 if (icp->icmp_type >= ICMP_UNREACH ) { 461 ip = &icp->icmp_ip; 462 } 463 icm = icmp_find_original_mbuf(pData, ip); 464 if (icm == NULL) { 465 LogRel(("Can't find the corresponding packet for the received ICMP\n")); 466 return; 467 } 468 orig_m = icm->im_m; 469 Assert(orig_m != NULL); 470 471 LogRel(("ICMP message arrived on socket %d\n", so->s)); 472 src = addr.sin_addr.s_addr; 473 474 ip = mtod(orig_m, struct ip *); /* Now ip is old header */ 475 old_ip_len = (ip->ip_hl << 2) + 64; 476 memcpy(ip_copy, ip, old_ip_len); 477 478 dst = ip->ip_src.s_addr; /* source address from original IP packet*/ 479 480 memcpy(orig_m->m_data, buff, len); /* overide ther tail of old packet */ 481 orig_m->m_len = len; 482 ip = mtod(orig_m, struct ip *); /* ip is from mbuf we've overrided */ 483 484 icp = (struct icmp *)((char *)ip + (ip->ip_hl << 2)); 485 NTOHS(ip->ip_len); 486 if (icp->icmp_type >= ICMP_UNREACH && icp->icmp_type != ICMP_ECHO) { 487 memcpy(&icp->icmp_ip, ip_copy, old_ip_len); /* according RFC 793 error messages required copy of initial IP header + 64 bit */ 488 ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */ 489 } 456 490 /* the low level expects fields to be in host format so let's convert them*/ 457 ip = mtod(so->so_m, struct ip *);458 NTOHS(ip->ip_len);459 491 NTOHS(ip->ip_off); 460 492 NTOHS(ip->ip_id); 493 ip->ip_src.s_addr = src; 461 494 ip->ip_dst.s_addr = dst; 462 #endif 495 icmp_reflect(pData, orig_m); 496 LIST_REMOVE(icm, im_list); 497 /* Don't call m_free here*/ 498 free(icm); 499 #else 463 500 icmp_reflect(pData, so->so_m); 464 501 so->so_m = 0; /* Don't m_free() it again! */ 465 } 466 /* No need for this socket anymore, udp_detach it */ 467 udp_detach(pData, so); 468 } 469 else 470 { 471 /* A "normal" UDP packet */ 472 struct mbuf *m; 473 int len, n; 502 #endif 503 } 504 /* No need for this socket anymore, udp_detach it */ 505 udp_detach(pData, so); 506 } else { /* A "normal" UDP packet */ 507 struct mbuf *m; 508 int len, n; 474 509 475 510 if (!(m = m_get(pData))) … … 533 568 m->m_len = 0; 534 569 } 535 #endif 570 #endif 536 571 537 572 /* … … 753 788 so->so_state &= ~(SS_ISFCONNECTING); 754 789 if (so->so_state & SS_FCANTSENDMORE) 755 so->so_state = SS_NOFDREF; /* Don't select it */ 790 so->so_state = SS_NOFDREF; /* Don't select it */ 756 791 /* XXX close() here as well? */ 757 792 else -
trunk/src/VBox/Devices/Network/slirp/udp.c
r14951 r15035 367 367 /* Correctly update list if detaching last socket in list. */ 368 368 if (so == udp_last_so) udp_last_so = &udb; 369 #ifndef VBOX_WITH_SLIRP_ICMP 369 370 closesocket(so->s); 370 371 /* if (so->so_m) m_free(so->so_m); done by sofree */ 371 372 372 373 sofree(pData, so); 374 #else /*! VBOX_WITH_SLIRP_ICMP */ 375 if (so != &pData->icmp_socket) { 376 closesocket(so->s); 377 sofree(pData, so); 378 } 379 #endif /* VBOX_WITH_SLIRP_ICMP */ 373 380 } 374 381
Note:
See TracChangeset
for help on using the changeset viewer.