Changeset 50980 in vbox for trunk/src/VBox/Devices/Network/slirp
- Timestamp:
- Apr 5, 2014 2:21:29 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 93155
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/ip_icmp.c
r50136 r50980 610 610 void icmp_error(PNATState pData, struct mbuf *msrc, u_char type, u_char code, int minsize, const char *message) 611 611 { 612 unsigned hlen, shlen, s_ip_len; 613 register struct ip *ip; 614 register struct icmp *icp; 615 register struct mbuf *m; 616 int new_ip_size = 0; 617 int new_m_size = 0; 618 int size = 0; 619 620 LogFlow(("icmp_error: msrc = %lx, msrc_len = %d\n", (long)msrc, msrc ? msrc->m_len : 0)); 621 if (msrc != NULL) 622 M_ASSERTPKTHDR(msrc); 612 unsigned ohlen, olen; 613 struct mbuf *m; 614 struct ip *oip, *ip; 615 struct icmp *icp; 616 void *payload; 617 618 LogFlow(("icmp_error: msrc = %p, msrc_len = %d\n", 619 (void *)msrc, msrc ? msrc->m_len : 0)); 620 621 if (RT_UNLIKELY(msrc == NULL)) 622 goto end_error; 623 624 M_ASSERTPKTHDR(msrc); 623 625 624 626 if ( type != ICMP_UNREACH … … 627 629 goto end_error; 628 630 629 /* check msrc */ 630 if (!msrc) 631 oip = mtod(msrc, struct ip *); 632 LogFunc(("msrc: %RTnaipv4 -> %RTnaipv4\n", oip->ip_src, oip->ip_dst)); 633 634 if (oip->ip_src.s_addr == INADDR_ANY) 631 635 goto end_error; 632 636 633 ip = mtod(msrc, struct ip *); 634 LogFunc(("msrc: %RTnaipv4 -> %RTnaipv4\n", ip->ip_src, ip->ip_dst)); 635 636 /* if source IP datagram hasn't got src address don't bother with sending ICMP error */ 637 if (ip->ip_src.s_addr == INADDR_ANY) 638 goto end_error; 639 640 if ( ip->ip_off & IP_OFFMASK 641 && type != ICMP_SOURCEQUENCH) 637 if (oip->ip_off & IP_OFFMASK) 642 638 goto end_error; /* Only reply to fragment 0 */ 643 639 644 shlen = ip->ip_hl << 2; 645 s_ip_len = ip->ip_len; 646 if (ip->ip_p == IPPROTO_ICMP) 647 { 648 icp = (struct icmp *)((char *)ip + shlen); 640 ohlen = oip->ip_hl * 4; 641 AssertStmt(ohlen >= sizeof(struct ip), goto end_error); 642 643 olen = oip->ip_len; 644 AssertStmt(olen >= ohlen, goto end_error); 645 646 if (oip->ip_p == IPPROTO_ICMP) 647 { 648 struct icmp *oicp = (struct icmp *)((char *)oip + ohlen); 649 649 /* 650 650 * Assume any unknown ICMP type is an error. This isn't 651 651 * specified by the RFC, but think about it.. 652 652 */ 653 if ( icp->icmp_type>18 || icmp_flush[icp->icmp_type])653 if (oicp->icmp_type > ICMP_MAXTYPE || icmp_flush[oicp->icmp_type]) 654 654 goto end_error; 655 655 } 656 656 657 /* undo byte order conversions done in ip_input() */ 658 HTONS(oip->ip_len); 659 HTONS(oip->ip_id); 660 HTONS(oip->ip_off); 661 657 662 m = m_gethdr(pData, M_NOWAIT, MT_HEADER); 658 if ( !m)663 if (RT_UNLIKELY(m == NULL)) 659 664 goto end_error; 660 665 661 666 m->m_flags |= M_SKIP_FIREWALL; 662 667 m->m_data += if_maxlinkhdr; 663 m->m_pkthdr.header = mtod(m, void *); 664 665 memcpy(m->m_pkthdr.header, ip, shlen); /* initialize respond IP header with data from original one. */ 666 667 ip = mtod(m, struct ip *); /* ip points to new IP header */ 668 hlen = sizeof(struct ip); /* trim the IP header no options in reply */ 668 669 ip = mtod(m, struct ip *); 670 m->m_pkthdr.header = (void *)ip; 671 672 /* fill in ip (ip_output0() does the boilerplate for us) */ 673 ip->ip_tos = ((oip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */ 674 /* ip->ip_len will be set later */ 675 ip->ip_off = 0; 676 ip->ip_ttl = MAXTTL; 677 ip->ip_p = IPPROTO_ICMP; 678 ip->ip_src = alias_addr; 679 ip->ip_dst = oip->ip_src; 669 680 670 681 /* fill in icmp */ 671 m->m_data += hlen; /* shifts m_data to ICMP header */ 672 icp = mtod(m, struct icmp *); /* _icp_: points to the ICMP header */ 673 m->m_data += RT_OFFSETOF(struct icmp, icmp_ip); /* shifts m_data to IP header payload */ 674 682 icp = (struct icmp *)((char *)ip + sizeof(*ip)); 675 683 icp->icmp_type = type; 676 684 icp->icmp_code = code; … … 678 686 icp->icmp_seq = 0; 679 687 680 HTONS(icp->icmp_ip.ip_len); 681 HTONS(icp->icmp_ip.ip_id); 682 HTONS(icp->icmp_ip.ip_off); 683 684 memcpy(mtod(m, void *), mtod(msrc, void *), shlen); /* copy original IP header (with options) */ 685 msrc->m_data += shlen; /* _msrc_: shifts m_data of original mbuf to the end of original IP header */ 686 msrc->m_len -= shlen; /* _msrc_: alter m_len to size of original IP datagram payload */ 687 m->m_data += shlen; /* _m_: shifts m_data to the end of reported IP datagram */ 688 /* initialize reported payload of original datagram with MUST size RFC792 or with rest of allocated mbuf */ 689 s_ip_len = minsize ? 8 : M_TRAILINGSPACE(m); 690 /* trims original IP datagram's payload to the lenght of its mbuf size or already reserved space if it's smaller */ 691 s_ip_len = RT_MIN(s_ip_len, msrc->m_len); 692 memcpy(mtod(m, void *), mtod(msrc, void *), s_ip_len); 693 694 #if DEBUG 695 if (message) 696 { 697 698 size_t message_len; 699 /** 700 * Trim reported payload to first eight bytes (RFC792) to let sniffering tools do 701 * their audit duties, and add hint message to the tail of mandatory piece. 702 */ 703 s_ip_len = 8; 704 /** 705 * _m_: shifts m_data to the end of mandatory 8b piece to let M_TRAILINGSPACE 706 * to returns available space with counting mandatory region. 707 */ 708 m->m_data += s_ip_len; 709 message_len = strlen(message); 710 if (message_len > M_TRAILINGSPACE(m)) 711 message_len = M_TRAILINGSPACE(m); 712 713 /** 714 * m->m_data points to the end of 8 bytes payload, and m->m_len is length of appended 715 * message. 716 */ 717 m_append(pData, m, (int)message_len, message); 718 m->m_data -= s_ip_len; /* now we're ready for further processing, with pointing to mandatory payload */ 719 } 720 #else 688 /* fill in icmp payload: original ip header plus 8 bytes of its payload */ 689 if (olen > ohlen + 8) 690 olen = ohlen + 8; 691 payload = (void *)((char *)icp + ICMP_MINLEN); 692 memcpy(payload, oip, olen); 693 694 /* 695 * Original code appended this message after the payload. This 696 * might have been a good idea for real slirp, as it provided a 697 * communication channel with the remote host. But 90s are over. 698 */ 721 699 NOREF(message); 722 #endif 723 724 m->m_data -= shlen + RT_OFFSETOF(struct icmp, icmp_ip); /* _m_: shifts m_data to the start of ICMP header */ 725 m->m_len += s_ip_len + shlen + RT_OFFSETOF(struct icmp, icmp_ip); /* _m_: m_len counts bytes in IP payload */ 726 727 /** 728 * It asserts if calculation above is wrong. 729 */ 730 Assert(icp == mtod(m, struct icmp*)); 700 701 /* hide ip header for icmp checksum calculation */ 702 m->m_data += sizeof(struct ip); 703 m->m_len = ICMP_MINLEN + /* truncated */ olen; 731 704 732 705 icp->icmp_cksum = 0; 733 706 icp->icmp_cksum = cksum(m, m->m_len); 734 707 735 /* fill in ip */ 736 ip->ip_hl = hlen >> 2; 708 /* reveal ip header */ 709 m->m_data -= sizeof(struct ip); 710 m->m_len += sizeof(struct ip); 737 711 ip->ip_len = m->m_len; 738 712 739 ip->ip_tos = ((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */740 741 ip->ip_ttl = MAXTTL;742 ip->ip_p = IPPROTO_ICMP;743 ip->ip_dst = ip->ip_src; /* ip adresses */744 ip->ip_src = alias_addr;745 746 /* returns pointer back. */747 m->m_data -= hlen;748 m->m_len += hlen;749 750 /**751 * paranoid. if something goes wrong previous assert should be triggered.752 */753 Assert(ip == mtod(m, struct ip*));754 713 (void) ip_output0(pData, (struct socket *)NULL, m, 1); 755 714
Note:
See TracChangeset
for help on using the changeset viewer.