mcpcap 0.3.1__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mcpcap/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.3.1'
32
- __version_tuple__ = version_tuple = (0, 3, 1)
31
+ __version__ = version = '0.4.0'
32
+ __version_tuple__ = version_tuple = (0, 4, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
mcpcap/cli.py CHANGED
@@ -42,11 +42,6 @@ def main():
42
42
  help="Comma-separated list of modules to load (default: dns)",
43
43
  default="dns",
44
44
  )
45
- parser.add_argument(
46
- "--protocols",
47
- help="Comma-separated list of protocols to analyze (default: dns)",
48
- default="dns",
49
- )
50
45
  parser.add_argument(
51
46
  "--max-packets",
52
47
  type=int,
@@ -56,12 +51,16 @@ def main():
56
51
  args = parser.parse_args()
57
52
 
58
53
  try:
54
+ # Parse modules and automatically set protocols to match
55
+ modules = args.modules.split(",") if args.modules else ["dns"]
56
+ protocols = modules # Protocols automatically match loaded modules
57
+
59
58
  # Initialize configuration
60
59
  config = Config(
61
60
  pcap_path=args.pcap_path,
62
61
  pcap_url=args.pcap_url,
63
- modules=args.modules.split(",") if args.modules else ["dns"],
64
- protocols=args.protocols.split(",") if args.protocols else ["dns"],
62
+ modules=modules,
63
+ protocols=protocols,
65
64
  max_packets=args.max_packets,
66
65
  )
67
66
 
mcpcap/core/server.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from fastmcp import FastMCP
4
4
 
5
+ from ..modules.dhcp import DHCPModule
5
6
  from ..modules.dns import DNSModule
6
7
  from .config import Config
7
8
 
@@ -18,20 +19,34 @@ class MCPServer:
18
19
  self.config = config
19
20
  self.mcp = FastMCP("mcpcap")
20
21
 
21
- # Initialize modules
22
- self.dns_module = DNSModule(config)
22
+ # Initialize modules based on configuration
23
+ self.modules = {}
24
+ if "dns" in self.config.modules:
25
+ self.modules["dns"] = DNSModule(config)
26
+ if "dhcp" in self.config.modules:
27
+ self.modules["dhcp"] = DHCPModule(config)
23
28
 
24
29
  # Register tools
25
30
  self._register_tools()
26
31
 
27
32
  # Setup prompts
28
- self.dns_module.setup_prompts(self.mcp)
33
+ for module in self.modules.values():
34
+ module.setup_prompts(self.mcp)
29
35
 
30
36
  def _register_tools(self) -> None:
31
37
  """Register all available tools with the MCP server."""
32
- # Register DNS module tools
33
- self.mcp.tool(self.dns_module.list_dns_packets)
34
- self.mcp.tool(self.dns_module.list_pcap_files)
38
+ # Register tools for each loaded module
39
+ for module_name, module in self.modules.items():
40
+ if module_name == "dns":
41
+ self.mcp.tool(module.list_dns_packets)
42
+ elif module_name == "dhcp":
43
+ self.mcp.tool(module.list_dhcp_packets)
44
+
45
+ # Register shared list_pcap_files tool (same for all modules)
46
+ if self.modules:
47
+ # Use the first available module for listing PCAP files
48
+ first_module = next(iter(self.modules.values()))
49
+ self.mcp.tool(first_module.list_pcap_files)
35
50
 
36
51
  def run(self) -> None:
37
52
  """Start the MCP server."""
@@ -1,6 +1,7 @@
1
1
  """Protocol analysis modules for mcpcap."""
2
2
 
3
3
  from .base import BaseModule
4
+ from .dhcp import DHCPModule
4
5
  from .dns import DNSModule
5
6
 
6
- __all__ = ["BaseModule", "DNSModule"]
7
+ __all__ = ["BaseModule", "DHCPModule", "DNSModule"]
mcpcap/modules/dhcp.py ADDED
@@ -0,0 +1,446 @@
1
+ """DHCP analysis module."""
2
+
3
+ import os
4
+ import tempfile
5
+ from typing import Any
6
+
7
+ from fastmcp import FastMCP
8
+ from scapy.all import BOOTP, DHCP, IP, UDP, rdpcap
9
+
10
+ from .base import BaseModule
11
+
12
+
13
+ class DHCPModule(BaseModule):
14
+ """Module for analyzing DHCP packets in PCAP files."""
15
+
16
+ @property
17
+ def protocol_name(self) -> str:
18
+ """Return the name of the protocol this module analyzes."""
19
+ return "DHCP"
20
+
21
+ def list_dhcp_packets(self, pcap_file: str = "") -> dict[str, Any]:
22
+ """
23
+ Analyze DHCP packets from a PCAP file and return a summary of each packet.
24
+
25
+ Args:
26
+ pcap_file: Path to the PCAP file to analyze. Leave empty for direct URL remotes
27
+ or when using the first available file in local directories.
28
+
29
+ Returns:
30
+ A structured dictionary containing DHCP packet analysis results
31
+ """
32
+ # Handle remote files
33
+ if self.config.is_remote:
34
+ # For direct file URLs, always use the URL file (ignore pcap_file parameter)
35
+ if self.config.is_direct_file_url:
36
+ available_files = self.config.list_pcap_files()
37
+ if not available_files:
38
+ return {
39
+ "error": "No PCAP file found at the provided URL",
40
+ "pcap_url": self.config.pcap_url,
41
+ }
42
+ pcap_file = available_files[0] # Use the actual filename from URL
43
+ elif not pcap_file:
44
+ # For directory URLs, if no file specified, use the first available
45
+ available_files = self.config.list_pcap_files()
46
+ if not available_files:
47
+ return {
48
+ "error": "No PCAP files found at the provided URL",
49
+ "pcap_url": self.config.pcap_url,
50
+ "available_files": [],
51
+ }
52
+ pcap_file = available_files[0]
53
+
54
+ # Download remote file to temporary location
55
+ try:
56
+ with tempfile.NamedTemporaryFile(
57
+ suffix=".pcap", delete=False
58
+ ) as tmp_file:
59
+ temp_path = tmp_file.name
60
+
61
+ local_path = self.config.download_pcap_file(pcap_file, temp_path)
62
+ result = self.analyze_packets(local_path)
63
+
64
+ # Clean up temporary file
65
+ try:
66
+ os.unlink(local_path)
67
+ except OSError:
68
+ pass # Ignore cleanup errors
69
+
70
+ return result
71
+
72
+ except Exception as e:
73
+ # List available PCAP files for help
74
+ available_files = self.config.list_pcap_files()
75
+ return {
76
+ "error": f"Failed to download PCAP file '{pcap_file}': {str(e)}",
77
+ "pcap_url": self.config.pcap_url,
78
+ "available_files": available_files,
79
+ }
80
+
81
+ else:
82
+ # Handle local files
83
+ if not pcap_file:
84
+ # If no file specified, use the first available file
85
+ available_files = self.config.list_pcap_files()
86
+ if not available_files:
87
+ return {
88
+ "error": "No PCAP files found in directory",
89
+ "pcap_directory": self.config.pcap_path,
90
+ "available_files": [],
91
+ }
92
+ pcap_file = available_files[0]
93
+
94
+ full_path = self.config.get_pcap_file_path(pcap_file)
95
+
96
+ # Check if local file exists
97
+ if not os.path.exists(full_path):
98
+ available_files = self.config.list_pcap_files()
99
+ return {
100
+ "error": f"PCAP file '{pcap_file}' not found",
101
+ "file_path": full_path,
102
+ "available_files": available_files,
103
+ "pcap_directory": self.config.pcap_path,
104
+ }
105
+
106
+ return self.analyze_packets(full_path)
107
+
108
+ def list_pcap_files(self) -> str:
109
+ """
110
+ List all available PCAP files in the configured directory or remote URL.
111
+
112
+ Returns:
113
+ A list of available PCAP files that can be analyzed
114
+ """
115
+ files = self.config.list_pcap_files()
116
+ source = (
117
+ self.config.pcap_url if self.config.is_remote else self.config.pcap_path
118
+ )
119
+
120
+ if files:
121
+ if self.config.is_remote and self.config.is_direct_file_url:
122
+ return f"Direct PCAP file URL: {source}\\n- {files[0]}"
123
+ elif not self.config.is_remote and self.config.is_direct_file_path:
124
+ return f"Direct PCAP file path: {source}\\n- {files[0]}"
125
+ else:
126
+ source_type = "remote server" if self.config.is_remote else "directory"
127
+ return (
128
+ f"Available PCAP files in {source_type} {source}:\\n"
129
+ + "\\n".join(f"- {f}" for f in sorted(files))
130
+ )
131
+ else:
132
+ source_type = "remote server" if self.config.is_remote else "directory"
133
+ return f"No PCAP files found in {source_type} {source}"
134
+
135
+ def analyze_packets(self, pcap_file: str) -> dict[str, Any]:
136
+ """Analyze DHCP packets in a PCAP file.
137
+
138
+ Args:
139
+ pcap_file: Path to the PCAP file to analyze
140
+
141
+ Returns:
142
+ Dictionary containing DHCP packet analysis results
143
+ """
144
+ try:
145
+ packets = rdpcap(pcap_file)
146
+ dhcp_packets = [pkt for pkt in packets if pkt.haslayer(BOOTP)]
147
+
148
+ if not dhcp_packets:
149
+ return {
150
+ "file": pcap_file,
151
+ "total_packets": len(packets),
152
+ "dhcp_packets_found": 0,
153
+ "message": "No DHCP packets found in this capture",
154
+ }
155
+
156
+ # Apply max_packets limit if specified
157
+ packets_to_analyze = dhcp_packets
158
+ limited = False
159
+ if self.config.max_packets and len(dhcp_packets) > self.config.max_packets:
160
+ packets_to_analyze = dhcp_packets[: self.config.max_packets]
161
+ limited = True
162
+
163
+ packet_details = []
164
+ for i, pkt in enumerate(packets_to_analyze, 1):
165
+ packet_info = self._analyze_dhcp_packet(pkt, i)
166
+ packet_details.append(packet_info)
167
+
168
+ # Generate statistics
169
+ stats = self._generate_statistics(packet_details)
170
+
171
+ result = {
172
+ "file": pcap_file,
173
+ "total_packets": len(packets),
174
+ "dhcp_packets_found": len(dhcp_packets),
175
+ "dhcp_packets_analyzed": len(packet_details),
176
+ "statistics": stats,
177
+ "packets": packet_details,
178
+ }
179
+
180
+ # Add information about packet limiting
181
+ if limited:
182
+ result["note"] = (
183
+ f"Analysis limited to first {self.config.max_packets} DHCP packets due to --max-packets setting"
184
+ )
185
+
186
+ return result
187
+
188
+ except Exception as e:
189
+ return {
190
+ "error": f"Error reading PCAP file '{pcap_file}': {str(e)}",
191
+ "file": pcap_file,
192
+ }
193
+
194
+ def _analyze_dhcp_packet(self, packet, packet_num: int) -> dict[str, Any]:
195
+ """Analyze a single DHCP packet and extract relevant information."""
196
+ info = {
197
+ "packet_number": packet_num,
198
+ "timestamp": packet.time,
199
+ }
200
+
201
+ # Basic IP information
202
+ if packet.haslayer(IP):
203
+ ip_layer = packet[IP]
204
+ info.update(
205
+ {
206
+ "src_ip": ip_layer.src,
207
+ "dst_ip": ip_layer.dst,
208
+ }
209
+ )
210
+
211
+ # UDP information
212
+ if packet.haslayer(UDP):
213
+ udp_layer = packet[UDP]
214
+ info.update(
215
+ {
216
+ "src_port": udp_layer.sport,
217
+ "dst_port": udp_layer.dport,
218
+ }
219
+ )
220
+
221
+ # BOOTP/DHCP information
222
+ if packet.haslayer(BOOTP):
223
+ bootp_layer = packet[BOOTP]
224
+ info.update(
225
+ {
226
+ "op": "Request" if bootp_layer.op == 1 else "Reply",
227
+ "transaction_id": f"0x{bootp_layer.xid:08x}",
228
+ "client_ip": str(bootp_layer.ciaddr),
229
+ "your_ip": str(bootp_layer.yiaddr),
230
+ "server_ip": str(bootp_layer.siaddr),
231
+ "relay_ip": str(bootp_layer.giaddr),
232
+ "client_mac": bootp_layer.chaddr[:6].hex(":"),
233
+ }
234
+ )
235
+
236
+ # DHCP options analysis
237
+ if packet.haslayer(DHCP):
238
+ dhcp_layer = packet[DHCP]
239
+ dhcp_info = self._parse_dhcp_options(dhcp_layer.options)
240
+ info.update(dhcp_info)
241
+
242
+ return info
243
+
244
+ def _parse_dhcp_options(self, options) -> dict[str, Any]:
245
+ """Parse DHCP options and return structured information."""
246
+ dhcp_info = {"options": {}}
247
+
248
+ # DHCP message type mappings
249
+ message_types = {
250
+ 1: "DISCOVER",
251
+ 2: "OFFER",
252
+ 3: "REQUEST",
253
+ 4: "DECLINE",
254
+ 5: "ACK",
255
+ 6: "NAK",
256
+ 7: "RELEASE",
257
+ 8: "INFORM",
258
+ }
259
+
260
+ for opt in options:
261
+ if isinstance(opt, tuple) and len(opt) == 2:
262
+ key, value = opt
263
+
264
+ if key == "message-type":
265
+ dhcp_info["message_type"] = message_types.get(
266
+ value, f"Unknown({value})"
267
+ )
268
+ dhcp_info["message_type_code"] = value
269
+ elif key == "lease_time":
270
+ dhcp_info["lease_time"] = value
271
+ dhcp_info["options"]["lease_time"] = f"{value} seconds"
272
+ elif key == "renewal_time":
273
+ dhcp_info["renewal_time"] = value
274
+ dhcp_info["options"]["renewal_time"] = f"{value} seconds"
275
+ elif key == "rebinding_time":
276
+ dhcp_info["rebinding_time"] = value
277
+ dhcp_info["options"]["rebinding_time"] = f"{value} seconds"
278
+ elif key == "server_id":
279
+ dhcp_info["server_id"] = str(value)
280
+ elif key == "subnet_mask":
281
+ dhcp_info["options"]["subnet_mask"] = str(value)
282
+ elif key == "router":
283
+ dhcp_info["options"]["router"] = str(value)
284
+ elif key == "name_server":
285
+ dhcp_info["options"]["dns_servers"] = str(value)
286
+ elif key == "requested_addr":
287
+ dhcp_info["requested_ip"] = str(value)
288
+ elif key == "client_id":
289
+ if isinstance(value, bytes):
290
+ dhcp_info["client_id"] = value.hex(":")
291
+ else:
292
+ dhcp_info["client_id"] = str(value)
293
+ elif key == "param_req_list":
294
+ dhcp_info["options"]["parameter_request_list"] = list(value)
295
+ else:
296
+ # Store other options as strings
297
+ dhcp_info["options"][key] = str(value)
298
+
299
+ return dhcp_info
300
+
301
+ def _generate_statistics(self, packets: list[dict[str, Any]]) -> dict[str, Any]:
302
+ """Generate statistics from analyzed DHCP packets."""
303
+ stats = {
304
+ "unique_clients": set(),
305
+ "unique_servers": set(),
306
+ "message_types": {},
307
+ "transactions": {},
308
+ }
309
+
310
+ for pkt in packets:
311
+ # Count unique clients and servers
312
+ if "client_mac" in pkt:
313
+ stats["unique_clients"].add(pkt["client_mac"])
314
+ if "server_id" in pkt:
315
+ stats["unique_servers"].add(pkt["server_id"])
316
+
317
+ # Count message types
318
+ if "message_type" in pkt:
319
+ msg_type = pkt["message_type"]
320
+ stats["message_types"][msg_type] = (
321
+ stats["message_types"].get(msg_type, 0) + 1
322
+ )
323
+
324
+ # Track transactions
325
+ if "transaction_id" in pkt:
326
+ tx_id = pkt["transaction_id"]
327
+ if tx_id not in stats["transactions"]:
328
+ stats["transactions"][tx_id] = []
329
+ stats["transactions"][tx_id].append(
330
+ {
331
+ "packet_number": pkt["packet_number"],
332
+ "message_type": pkt.get("message_type", "Unknown"),
333
+ "timestamp": pkt["timestamp"],
334
+ }
335
+ )
336
+
337
+ # Convert sets to counts for JSON serialization
338
+ return {
339
+ "unique_clients_count": len(stats["unique_clients"]),
340
+ "unique_servers_count": len(stats["unique_servers"]),
341
+ "unique_clients": list(stats["unique_clients"]),
342
+ "unique_servers": list(stats["unique_servers"]),
343
+ "message_type_counts": stats["message_types"],
344
+ "transaction_count": len(stats["transactions"]),
345
+ "transactions": stats["transactions"],
346
+ }
347
+
348
+ def setup_prompts(self, mcp: FastMCP) -> None:
349
+ """Set up DHCP-specific analysis prompts for the MCP server.
350
+
351
+ Args:
352
+ mcp: FastMCP server instance
353
+ """
354
+
355
+ @mcp.prompt
356
+ def dhcp_network_analysis():
357
+ """Prompt for analyzing DHCP traffic from a network perspective"""
358
+ return """You are a network administrator analyzing DHCP traffic. Focus your analysis on:
359
+
360
+ 1. **IP Address Management:**
361
+ - Track DHCP lease assignments and renewals
362
+ - Identify IP address pool usage and availability
363
+ - Look for lease conflicts or duplicate IP assignments
364
+ - Monitor lease duration patterns and optimization
365
+
366
+ 2. **Client Behavior Analysis:**
367
+ - Identify DHCP client types and operating systems
368
+ - Track client renewal patterns and timing
369
+ - Look for unusual client behavior (rapid requests, failures)
370
+ - Monitor mobile devices vs. static clients
371
+
372
+ 3. **Server Performance:**
373
+ - Analyze DHCP server response times
374
+ - Look for server failures or timeouts
375
+ - Check for multiple DHCP servers (potential conflicts)
376
+ - Monitor server load and capacity planning
377
+
378
+ 4. **Network Troubleshooting:**
379
+ - Identify DHCP DISCOVER floods or storms
380
+ - Look for relay agent issues
381
+ - Check for scope exhaustion problems
382
+ - Find misconfigurations in options delivery
383
+
384
+ Provide specific recommendations for network optimization and problem resolution."""
385
+
386
+ @mcp.prompt
387
+ def dhcp_security_analysis():
388
+ """Prompt for analyzing DHCP traffic from a security perspective"""
389
+ return """You are a security analyst examining DHCP traffic for threats. Focus on:
390
+
391
+ 1. **Rogue DHCP Detection:**
392
+ - Identify unauthorized DHCP servers on the network
393
+ - Look for conflicting server responses or options
394
+ - Check for suspicious server_id values
395
+ - Monitor for DHCP server impersonation attempts
396
+
397
+ 2. **DHCP Attacks:**
398
+ - Detect DHCP starvation attacks (rapid lease consumption)
399
+ - Look for DHCP spoofing or man-in-the-middle attempts
400
+ - Identify abnormal request patterns or frequencies
401
+ - Check for MAC address spoofing in client requests
402
+
403
+ 3. **Client Anomalies:**
404
+ - Find clients with suspicious hostnames or identifiers
405
+ - Look for rapid MAC address changes from single sources
406
+ - Detect clients requesting unusual or dangerous options
407
+ - Monitor for clients bypassing expected DHCP flow
408
+
409
+ 4. **Data Exfiltration Risks:**
410
+ - Check for unusual data in DHCP option fields
411
+ - Look for DNS server redirection attempts
412
+ - Monitor for suspicious router or gateway assignments
413
+ - Identify potential DNS tunneling via DHCP options
414
+
415
+ Provide threat assessment and recommended security controls."""
416
+
417
+ @mcp.prompt
418
+ def dhcp_forensic_investigation():
419
+ """Prompt for forensic analysis of DHCP traffic"""
420
+ return """You are conducting a digital forensics investigation involving DHCP traffic. Approach systematically:
421
+
422
+ 1. **Timeline Reconstruction:**
423
+ - Create chronological sequence of DHCP transactions
424
+ - Map client activity periods and network presence
425
+ - Correlate DHCP assignments with incident timeframes
426
+ - Track device mobility through IP address changes
427
+
428
+ 2. **Device Attribution:**
429
+ - Link MAC addresses to specific devices or users
430
+ - Track device behavior patterns across time
431
+ - Identify device types through DHCP fingerprinting
432
+ - Document lease history for evidence correlation
433
+
434
+ 3. **Network Mapping:**
435
+ - Reconstruct network topology from DHCP data
436
+ - Identify network segments and VLAN assignments
437
+ - Map DHCP server infrastructure and relationships
438
+ - Document network configuration at incident time
439
+
440
+ 4. **Evidence Collection:**
441
+ - Extract client identifiers and hostnames
442
+ - Document IP address assignments for legal proceedings
443
+ - Preserve transaction timing for event correlation
444
+ - Collect option data that may contain forensic artifacts
445
+
446
+ Present findings with precise timestamps, evidence preservation notes, and clear documentation suitable for legal proceedings."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcpcap
3
- Version: 0.3.1
3
+ Version: 0.4.0
4
4
  Summary: A modular Python MCP Server for analyzing PCAP files
5
5
  Author: mcpcap contributors
6
6
  License: MIT
@@ -115,6 +115,8 @@ uvx mcpcap
115
115
 
116
116
  ## Modules
117
117
 
118
+ mcpcap supports multiple protocol analysis modules:
119
+
118
120
  ### DNS Module
119
121
 
120
122
  The DNS module analyzes Domain Name System packets in PCAP files.
@@ -127,11 +129,26 @@ The DNS module analyzes Domain Name System packets in PCAP files.
127
129
  - Track query frequency and patterns
128
130
  - Identify DNS servers used
129
131
 
132
+ ### DHCP Module
133
+
134
+ The DHCP module analyzes Dynamic Host Configuration Protocol packets in PCAP files.
135
+
136
+ **Capabilities**:
137
+
138
+ - Track DHCP transactions (DISCOVER, OFFER, REQUEST, ACK)
139
+ - Identify DHCP clients and servers
140
+ - Monitor IP address assignments and lease information
141
+ - Analyze DHCP options and configurations
142
+ - Detect DHCP anomalies and security issues
143
+
130
144
  **Example Usage**:
131
145
 
132
- ```python
133
- # LLM can ask: "What domains were queried in this PCAP?"
134
- # mcpcap will return structured JSON with DNS query information
146
+ ```bash
147
+ # Analyze DHCP traffic only
148
+ mcpcap --pcap-path /path/to/dhcp.pcap --modules dhcp
149
+
150
+ # Analyze both DNS and DHCP
151
+ mcpcap --pcap-path /path/to/mixed.pcap --modules dns,dhcp
135
152
  ```
136
153
 
137
154
  ## Configuration
@@ -164,12 +181,23 @@ mcpcap --pcap-url http://example.com/pcaps/
164
181
 
165
182
  **Module Selection**:
166
183
  ```bash
184
+ # Single module
167
185
  mcpcap --modules dns --pcap-path /path/to/files
186
+
187
+ # Multiple modules
188
+ mcpcap --modules dns,dhcp --pcap-path /path/to/files
168
189
  ```
169
190
 
170
- **Protocol Filtering**:
191
+ **Protocol Selection** (automatically matches loaded modules):
171
192
  ```bash
172
- mcpcap --protocols dns --pcap-path /path/to/files
193
+ # DNS analysis only
194
+ mcpcap --modules dns --pcap-path /path/to/files
195
+
196
+ # DHCP analysis only
197
+ mcpcap --modules dhcp --pcap-path /path/to/files
198
+
199
+ # Both DNS and DHCP analysis
200
+ mcpcap --modules dns,dhcp --pcap-path /path/to/files
173
201
  ```
174
202
 
175
203
  **Packet Limiting** (for large files):
@@ -179,7 +207,7 @@ mcpcap --max-packets 1000 --pcap-path /path/to/files
179
207
 
180
208
  **Combined Options**:
181
209
  ```bash
182
- mcpcap --pcap-path /data/capture.pcap --max-packets 500 --protocols dns
210
+ mcpcap --pcap-path /data/capture.pcap --max-packets 500 --modules dns,dhcp
183
211
  ```
184
212
 
185
213
  ## CLI Reference
@@ -194,7 +222,8 @@ mcpcap [--pcap-path PATH | --pcap-url URL] [OPTIONS]
194
222
 
195
223
  **Analysis Options**:
196
224
  - `--modules MODULES`: Comma-separated modules to load (default: dns)
197
- - `--protocols PROTOCOLS`: Comma-separated protocols to analyze (default: dns)
225
+ - Available modules: `dns`, `dhcp`
226
+ - Protocols are automatically set to match loaded modules
198
227
  - `--max-packets N`: Maximum packets to analyze per file (default: unlimited)
199
228
 
200
229
  **Examples**:
@@ -205,8 +234,8 @@ mcpcap --pcap-path ./capture.pcap
205
234
  # Remote file with packet limit
206
235
  mcpcap --pcap-url https://example.com/dns.cap --max-packets 100
207
236
 
208
- # Directory with protocol filter
209
- mcpcap --pcap-path /captures --protocols dns --modules dns
237
+ # Directory with DHCP analysis
238
+ mcpcap --pcap-path /captures --modules dhcp
210
239
  ```
211
240
 
212
241
  ## Example
@@ -0,0 +1,16 @@
1
+ mcpcap/__init__.py,sha256=rJwCpBXkhIvmsqHFpeR33Vg8kuipNPJ2JdlAjsTk7I4,1408
2
+ mcpcap/_version.py,sha256=2_0GUP7yBCXRus-qiJKxQD62z172WSs1sQ6DVpPsbmM,704
3
+ mcpcap/cli.py,sha256=nsHg-c72BrJaIUiVPoj-JWahQu8k0ldxYmWzbnljEBk,2448
4
+ mcpcap/core/__init__.py,sha256=WM5GTl06ZwwqHTPiKaYB-9hwOOXe3hyHG16FshwSsjE,127
5
+ mcpcap/core/config.py,sha256=WdHYu14Cvn9C3xs3KsQ-SVRru00IH86nQfnDL57V9zE,8190
6
+ mcpcap/core/server.py,sha256=H2ttfokMzW3vICxjCOFCoQTe78HHs-bGUxMd6i7rE1k,2011
7
+ mcpcap/modules/__init__.py,sha256=kA91h_-f7RE7pvEgcsQTZigDptK5v17-mbqTXZTRTK8,183
8
+ mcpcap/modules/base.py,sha256=3h8lGt6d6ob4SbgP6THC5PnTeMRcKfTGoJ9ZlZsQje0,826
9
+ mcpcap/modules/dhcp.py,sha256=3t9_2Tci5ZKhJlSMfgFbgCg44l5-0FKefAWoDZ_sY-Y,17251
10
+ mcpcap/modules/dns.py,sha256=cc77RxJOf-JxTLTCY8kfc_64uMawWKB3rjme9Q5H1pI,16632
11
+ mcpcap-0.4.0.dist-info/licenses/LICENSE,sha256=Ltj0zxftQyBYQMNva935v0i5QXQQOF8ygE8dQxGEtjk,1063
12
+ mcpcap-0.4.0.dist-info/METADATA,sha256=r_YjdfhT8soaAhLvS23nkEqp4c9_T0InXaFiM5YWKfc,8614
13
+ mcpcap-0.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ mcpcap-0.4.0.dist-info/entry_points.txt,sha256=ck69gPBEopmU6mzQy9P6o6ssMr89bQbrvv51IaJ50Gc,39
15
+ mcpcap-0.4.0.dist-info/top_level.txt,sha256=YkRkVGjuM3nI7cVB1l8zIAeqiS_5_vrzbUcHNkH3OXE,7
16
+ mcpcap-0.4.0.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- mcpcap/__init__.py,sha256=rJwCpBXkhIvmsqHFpeR33Vg8kuipNPJ2JdlAjsTk7I4,1408
2
- mcpcap/_version.py,sha256=gGLpQUQx-ty9SEy9PYw9OgJWWzJLBnCpfJOfzL7SjlI,704
3
- mcpcap/cli.py,sha256=DflEb7i2ATn9lBx4rK43Qpf-aQjKhwSqT20BofzVrFs,2480
4
- mcpcap/core/__init__.py,sha256=WM5GTl06ZwwqHTPiKaYB-9hwOOXe3hyHG16FshwSsjE,127
5
- mcpcap/core/config.py,sha256=WdHYu14Cvn9C3xs3KsQ-SVRru00IH86nQfnDL57V9zE,8190
6
- mcpcap/core/server.py,sha256=BrLgT-zsa2uFQ2B_bNSSrCFID3xXruinnnfRrHo1GKs,1312
7
- mcpcap/modules/__init__.py,sha256=iIeoZuLA-EOv0OS8WU8qDCitXJnarq9F0hA5-Y97zis,140
8
- mcpcap/modules/base.py,sha256=3h8lGt6d6ob4SbgP6THC5PnTeMRcKfTGoJ9ZlZsQje0,826
9
- mcpcap/modules/dns.py,sha256=cc77RxJOf-JxTLTCY8kfc_64uMawWKB3rjme9Q5H1pI,16632
10
- mcpcap-0.3.1.dist-info/licenses/LICENSE,sha256=Ltj0zxftQyBYQMNva935v0i5QXQQOF8ygE8dQxGEtjk,1063
11
- mcpcap-0.3.1.dist-info/METADATA,sha256=GCTSg601dKs06-KMnD6IqwSqXSubYSdYbsLY_eUVxhA,7854
12
- mcpcap-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- mcpcap-0.3.1.dist-info/entry_points.txt,sha256=ck69gPBEopmU6mzQy9P6o6ssMr89bQbrvv51IaJ50Gc,39
14
- mcpcap-0.3.1.dist-info/top_level.txt,sha256=YkRkVGjuM3nI7cVB1l8zIAeqiS_5_vrzbUcHNkH3OXE,7
15
- mcpcap-0.3.1.dist-info/RECORD,,
File without changes