Changeset 64299 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Oct 17, 2016 1:56:50 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/bootp.c
r63562 r64299 49 49 uint32_t xid; 50 50 bool allocated; 51 uint8_t macaddr[ 6];51 uint8_t macaddr[ETH_ALEN]; 52 52 struct in_addr addr; 53 53 int number; … … 63 63 static void bootp_reply(PNATState pData, struct mbuf *m0, int offReply, uint16_t flags); 64 64 65 static uint8_t *dhcp_find_option(uint8_t *vend, uint8_t tag) 66 { 67 uint8_t *q = vend; 68 uint8_t len; 69 /** @todo magic validation */ 70 q += 4; /*magic*/ 71 while(*q != RFC1533_END) 72 { 73 if (*q == RFC1533_PAD) 74 { 75 q++; 65 66 static uint8_t *dhcp_find_option(uint8_t *vendor, size_t vlen, uint8_t tag, ssize_t checklen) 67 { 68 uint8_t *q = vendor; 69 size_t len = vlen; 70 71 q += sizeof(rfc1533_cookie); 72 len -= sizeof(rfc1533_cookie); 73 74 while (len > 0) 75 { 76 uint8_t *optptr = q; 77 uint8_t opt; 78 uint8_t optlen; 79 80 opt = *q++; 81 --len; 82 83 if (opt == RFC1533_END) 84 break; 85 86 if (opt == RFC1533_PAD) 76 87 continue; 77 } 78 if (*q == tag) 79 return q; 80 q++; 81 len = *q; 82 q += 1 + len; 83 } 88 89 if (len == 0) 90 break; /* no option length byte */ 91 92 optlen = *q++; 93 --len; 94 95 if (len < optlen) 96 break; /* option value truncated */ 97 98 if (opt == tag) 99 { 100 if (checklen > 0 && optlen != checklen) 101 break; /* wrong option size */ 102 103 return optptr; 104 } 105 106 q += optlen; 107 len -= optlen; 108 } 109 84 110 return NULL; 85 111 } … … 399 425 }; 400 426 401 static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, s truct mbuf *m)427 static int dhcp_decode_request(PNATState pData, struct bootp_t *bp, size_t vlen, struct mbuf *m) 402 428 { 403 429 BOOTPClient *bc = NULL; … … 410 436 411 437 /* need to understand which type of request we get */ 412 req_ip = dhcp_find_option(&bp->bp_vend[0], RFC2132_REQ_ADDR); 413 server_ip = dhcp_find_option(&bp->bp_vend[0], RFC2132_SRV_ID); 438 req_ip = dhcp_find_option(bp->bp_vend, vlen, 439 RFC2132_REQ_ADDR, sizeof(struct in_addr)); 440 server_ip = dhcp_find_option(bp->bp_vend, vlen, 441 RFC2132_SRV_ID, sizeof(struct in_addr)); 414 442 415 443 bc = find_addr(pData, &daddr, bp->bp_hwaddr); … … 498 526 } 499 527 500 Assert((bp->bp_hlen == ETH_ALEN)); 501 memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen); 528 memcpy(bc->macaddr, bp->bp_hwaddr, ETH_ALEN); 502 529 bc->addr.s_addr = bp->bp_ciaddr.s_addr; 503 530 } … … 544 571 } 545 572 } 546 Assert((bp->bp_hlen == ETH_ALEN)); 547 memcpy(bc->macaddr, bp->bp_hwaddr, bp->bp_hlen);573 574 memcpy(bc->macaddr, bp->bp_hwaddr, ETH_ALEN); 548 575 bc->addr.s_addr = ui32; 549 576 break; … … 584 611 return -1; 585 612 } 586 memcpy(bc->macaddr, bp->bp_hwaddr, 6);613 memcpy(bc->macaddr, bp->bp_hwaddr, ETH_ALEN); 587 614 } 588 615 … … 679 706 * 680 707 */ 681 static void dhcp_decode(PNATState pData, struct bootp_t *bp, const uint8_t *buf, int size)708 static void dhcp_decode(PNATState pData, struct bootp_t *bp, size_t vlen) 682 709 { 683 710 const uint8_t *pu8RawDhcpObject; … … 688 715 struct mbuf *m = NULL; 689 716 690 pu8RawDhcpObject = buf; 691 if (size < 5) 717 if (memcmp(bp->bp_vend, rfc1533_cookie, sizeof(rfc1533_cookie)) != 0) 692 718 return; 693 719 694 if (memcmp(pu8RawDhcpObject, rfc1533_cookie, 4) != 0) 720 pu8RawDhcpObject = dhcp_find_option(bp->bp_vend, vlen, RFC2132_MSG_TYPE, 1); 721 if (pu8RawDhcpObject == NULL) 695 722 return; 696 697 /* note: pu8RawDhcpObject doesn't point to parameter buf */ 698 pu8RawDhcpObject = dhcp_find_option(bp->bp_vend, RFC2132_MSG_TYPE); 699 Assert(pu8RawDhcpObject); 700 if (!pu8RawDhcpObject) 723 if (pu8RawDhcpObject[1] != 1) /* option length */ 701 724 return; 725 702 726 /** 703 727 * We're going update dns list at least once per DHCP transaction (!not on every operation … … 720 744 || pData->fUseHostResolver)) 721 745 { 722 uint8_t i = 2; /* i = 0 - tag, i == 1 - length */ 723 parameter_list = dhcp_find_option(&bp->bp_vend[0], RFC2132_PARAM_LIST); 724 for (;parameter_list && i < parameter_list[1]; ++i) 725 { 726 if (parameter_list[i] == RFC1533_DNS) 746 uint8_t i; 747 748 parameter_list = dhcp_find_option(bp->bp_vend, vlen, RFC2132_PARAM_LIST, -1); 749 for (i = 0; parameter_list && i < parameter_list[1]; ++i) 750 { 751 if (parameter_list[2 + i] == RFC1533_DNS) 727 752 { 728 753 /* XXX: How differs it from host Suspend/Resume? */ … … 754 779 755 780 case DHCPREQUEST: 756 rc = dhcp_decode_request(pData, bp, m);781 rc = dhcp_decode_request(pData, bp, vlen, m); 757 782 if (rc > 0) 758 783 goto reply; … … 765 790 766 791 case DHCPDECLINE: 767 /* note: pu8RawDhcpObject doesn't point to DHCP header, now it's expected it points 768 * to Dhcp Option RFC2132_REQ_ADDR 769 */ 770 pu8RawDhcpObject = dhcp_find_option(&bp->bp_vend[0], RFC2132_REQ_ADDR); 771 if (!pu8RawDhcpObject) 792 pu8RawDhcpObject = dhcp_find_option(bp->bp_vend, vlen, 793 RFC2132_REQ_ADDR, sizeof(struct in_addr)); 794 if (pu8RawDhcpObject == NULL) 772 795 { 773 796 Log(("NAT: RFC2132_REQ_ADDR not found\n")); 774 797 break; 775 798 } 799 776 800 req_ip.s_addr = *(uint32_t *)(pu8RawDhcpObject + 2); 777 801 rc = bootp_cache_lookup_ether_by_ip(pData, req_ip.s_addr, NULL); … … 843 867 { 844 868 struct bootp_t *bp = mtod(m, struct bootp_t *); 845 846 if (bp->bp_op == BOOTP_REQUEST) 847 dhcp_decode(pData, bp, bp->bp_vend, DHCP_OPT_LEN); 869 u_int mlen = m_length(m, NULL); 870 size_t vlen; 871 872 if (mlen < RT_OFFSETOF(struct bootp_t, bp_vend) + BOOTP_VENDOR_LEN) 873 return; 874 875 if (bp->bp_op != BOOTP_REQUEST) 876 return; 877 878 if (bp->bp_htype != RTNET_ARP_ETHER) 879 return; 880 881 if (bp->bp_hlen != ETH_ALEN) 882 return; 883 884 if (bp->bp_hops != 0) 885 return; 886 887 vlen = mlen - RT_OFFSETOF(struct bootp_t, bp_vend); 888 dhcp_decode(pData, bp, vlen); 848 889 } 849 890
Note:
See TracChangeset
for help on using the changeset viewer.