analyze_dhcp_packets
Parse PCAP files to extract and analyze DHCP packets, revealing device addresses, lease durations, and server configurations for network troubleshooting.
Instructions
Analyze DHCP packets from a PCAP file and return comprehensive analysis results.
FILE UPLOAD LIMITATION: This MCP tool cannot process files uploaded through Claude's web interface. Files must be accessible via URL or local file path.
SUPPORTED INPUT FORMATS:
Remote files: "https://example.com/capture.pcap"
Local files: "/absolute/path/to/capture.pcap"
UNSUPPORTED:
Files uploaded through Claude's file upload feature
Base64 file content
Relative file paths
Args: pcap_file: HTTP URL or absolute local file path to PCAP file
Returns: A structured dictionary containing DHCP packet analysis results
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pcap_file | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/mcpcap/modules/dhcp.py:19-41 (handler)The main tool handler for analyze_dhcp_packets. This is the public method registered as an MCP tool. It delegates to self.analyze_packets(pcap_file) from the base class, which handles local and remote PCAP files.
def analyze_dhcp_packets(self, pcap_file: str) -> dict[str, Any]: """ Analyze DHCP packets from a PCAP file and return comprehensive analysis results. FILE UPLOAD LIMITATION: This MCP tool cannot process files uploaded through Claude's web interface. Files must be accessible via URL or local file path. SUPPORTED INPUT FORMATS: - Remote files: "https://example.com/capture.pcap" - Local files: "/absolute/path/to/capture.pcap" UNSUPPORTED: - Files uploaded through Claude's file upload feature - Base64 file content - Relative file paths Args: pcap_file: HTTP URL or absolute local file path to PCAP file Returns: A structured dictionary containing DHCP packet analysis results """ return self.analyze_packets(pcap_file) - src/mcpcap/modules/dhcp.py:43-93 (handler)The actual protocol-specific analysis implementation (_analyze_protocol_file). Reads PCAP with scapy, filters BOOTP/DHCP packets, analyzes each packet, generates statistics, and applies max_packets limits.
def _analyze_protocol_file(self, pcap_file: str) -> dict[str, Any]: """Perform the actual DHCP packet analysis on a local PCAP file.""" try: packets = rdpcap(pcap_file) dhcp_packets = [pkt for pkt in packets if pkt.haslayer(BOOTP)] if not dhcp_packets: return { "file": pcap_file, "total_packets": len(packets), "dhcp_packets_found": 0, "message": "No DHCP packets found in this capture", } # Apply max_packets limit if specified packets_to_analyze = dhcp_packets limited = False if self.config.max_packets and len(dhcp_packets) > self.config.max_packets: packets_to_analyze = dhcp_packets[: self.config.max_packets] limited = True packet_details = [] for i, pkt in enumerate(packets_to_analyze, 1): packet_info = self._analyze_dhcp_packet(pkt, i) packet_details.append(packet_info) # Generate statistics stats = self._generate_statistics(packet_details) result = { "file": pcap_file, "total_packets": len(packets), "dhcp_packets_found": len(dhcp_packets), "dhcp_packets_analyzed": len(packet_details), "statistics": stats, "packets": packet_details, } # Add information about packet limiting if limited: result["note"] = ( f"Analysis limited to first {self.config.max_packets} DHCP packets due to --max-packets setting" ) return result except Exception as e: return { "error": f"Error reading PCAP file '{pcap_file}': {str(e)}", "file": pcap_file, } - src/mcpcap/modules/dhcp.py:95-143 (handler)Per-packet DHCP analysis (_analyze_dhcp_packet). Extracts IP/UDP info, BOOTP fields (op, xid, IPs, MAC), and parses DHCP options (message type, lease time, server ID, etc.).
def _analyze_dhcp_packet(self, packet, packet_num: int) -> dict[str, Any]: """Analyze a single DHCP packet and extract relevant information.""" info = { "packet_number": packet_num, "timestamp": packet.time, } # Basic IP information if packet.haslayer(IP): ip_layer = packet[IP] info.update( { "src_ip": ip_layer.src, "dst_ip": ip_layer.dst, } ) # UDP information if packet.haslayer(UDP): udp_layer = packet[UDP] info.update( { "src_port": udp_layer.sport, "dst_port": udp_layer.dport, } ) # BOOTP/DHCP information if packet.haslayer(BOOTP): bootp_layer = packet[BOOTP] info.update( { "op": "Request" if bootp_layer.op == 1 else "Reply", "transaction_id": f"0x{bootp_layer.xid:08x}", "client_ip": str(bootp_layer.ciaddr), "your_ip": str(bootp_layer.yiaddr), "server_ip": str(bootp_layer.siaddr), "relay_ip": str(bootp_layer.giaddr), "client_mac": bootp_layer.chaddr[:6].hex(":"), } ) # DHCP options analysis if packet.haslayer(DHCP): dhcp_layer = packet[DHCP] dhcp_info = self._parse_dhcp_options(dhcp_layer.options) info.update(dhcp_info) return info - src/mcpcap/modules/dhcp.py:145-200 (helper)DHCP options parser (_parse_dhcp_options). Maps message-type codes to names (DISCOVER, OFFER, etc.) and extracts key options like lease_time, server_id, subnet_mask, router, DNS, etc.
def _parse_dhcp_options(self, options) -> dict[str, Any]: """Parse DHCP options and return structured information.""" dhcp_info = {"options": {}} # DHCP message type mappings message_types = { 1: "DISCOVER", 2: "OFFER", 3: "REQUEST", 4: "DECLINE", 5: "ACK", 6: "NAK", 7: "RELEASE", 8: "INFORM", } for opt in options: if isinstance(opt, tuple) and len(opt) == 2: key, value = opt if key == "message-type": dhcp_info["message_type"] = message_types.get( value, f"Unknown({value})" ) dhcp_info["message_type_code"] = value elif key == "lease_time": dhcp_info["lease_time"] = value dhcp_info["options"]["lease_time"] = f"{value} seconds" elif key == "renewal_time": dhcp_info["renewal_time"] = value dhcp_info["options"]["renewal_time"] = f"{value} seconds" elif key == "rebinding_time": dhcp_info["rebinding_time"] = value dhcp_info["options"]["rebinding_time"] = f"{value} seconds" elif key == "server_id": dhcp_info["server_id"] = str(value) elif key == "subnet_mask": dhcp_info["options"]["subnet_mask"] = str(value) elif key == "router": dhcp_info["options"]["router"] = str(value) elif key == "name_server": dhcp_info["options"]["dns_servers"] = str(value) elif key == "requested_addr": dhcp_info["requested_ip"] = str(value) elif key == "client_id": if isinstance(value, bytes): dhcp_info["client_id"] = value.hex(":") else: dhcp_info["client_id"] = str(value) elif key == "param_req_list": dhcp_info["options"]["parameter_request_list"] = list(value) else: # Store other options as strings dhcp_info["options"][key] = str(value) return dhcp_info - src/mcpcap/core/server.py:56-56 (registration)Tool registration in the MCP server. Located in server.py line 56: self.mcp.tool(module.analyze_dhcp_packets) registers the DHCP packet analysis tool when the 'dhcp' module is loaded.
self.mcp.tool(module.analyze_dhcp_packets)