(data)
| 690 | } |
| 691 | |
| 692 | handleDHCP(data) { |
| 693 | if (data.length < 240) return; // Minimum DHCP packet size |
| 694 | |
| 695 | const op = data[0]; |
| 696 | if (op !== 1) return; // Only handle BOOTREQUEST (1) |
| 697 | |
| 698 | const htype = data[1]; |
| 699 | const hlen = data[2]; |
| 700 | const xid = data.readUInt32BE(4); // Transaction ID |
| 701 | const flags = data.readUInt16BE(10); |
| 702 | const chaddr = data.subarray(28, 28 + 16); // Client hardware address |
| 703 | |
| 704 | // Check magic cookie at offset 236 |
| 705 | const magic = data.readUInt32BE(236); |
| 706 | if (magic !== DHCP_MAGIC_COOKIE) return; |
| 707 | |
| 708 | // Parse options starting at offset 240 |
| 709 | let msgType = 0; |
| 710 | let requestedIP = null; |
| 711 | let i = 240; |
| 712 | while (i < data.length) { |
| 713 | const opt = data[i]; |
| 714 | if (opt === DHCP_OPT_END) break; |
| 715 | if (opt === 0) { i++; continue; } // Pad |
| 716 | |
| 717 | const len = data[i + 1]; |
| 718 | const optData = data.subarray(i + 2, i + 2 + len); |
| 719 | |
| 720 | if (opt === DHCP_OPT_MSG_TYPE && len >= 1) { |
| 721 | msgType = optData[0]; |
| 722 | } else if (opt === DHCP_OPT_REQUESTED_IP && len >= 4) { |
| 723 | requestedIP = optData.subarray(0, 4); |
| 724 | } |
| 725 | |
| 726 | i += 2 + len; |
| 727 | } |
| 728 | |
| 729 | if (msgType === DHCP_DISCOVER) { |
| 730 | this.sendDHCPOffer(xid, chaddr, flags); |
| 731 | } else if (msgType === DHCP_REQUEST) { |
| 732 | this.sendDHCPAck(xid, chaddr, flags); |
| 733 | } |
| 734 | } |
| 735 | |
| 736 | sendDHCPOffer(xid, chaddr, flags) { |
| 737 | this.sendDHCPReply(DHCP_OFFER, xid, chaddr, flags); |
no test coverage detected