44import yaml
55import os
66from pathlib import Path
7+ from typing import List , Optional
78from dotenv import load_dotenv
9+
810from .engine import CamelRouterEngine
11+ from .scanner import NetworkScanner , NetworkService
912
1013
1114@click .group ()
@@ -306,5 +309,55 @@ def main():
306309 cli ()
307310
308311
312+ @cli .command ()
313+ @click .option ('--network' , '-n' , default = '192.168.1.0/24' ,
314+ help = 'Network to scan in CIDR notation' )
315+ @click .option ('--service' , '-s' , multiple = True ,
316+ type = click .Choice (['rtsp' , 'smtp' , 'imap' , 'http' , 'all' ]),
317+ help = 'Service types to scan for' )
318+ @click .option ('--output' , '-o' , type = click .Path (),
319+ help = 'Save results to a file' )
320+ @click .option ('--timeout' , '-t' , type = float , default = 2.0 ,
321+ help = 'Timeout in seconds for each connection attempt' )
322+ @click .option ('--verbose/--quiet' , default = True ,
323+ help = 'Show/hide detailed output' )
324+ async def scan (network : str , service : List [str ], output : Optional [str ],
325+ timeout : float , verbose : bool ):
326+ """Scan network for common services like RTSP, SMTP, IMAP, etc."""
327+ try :
328+ if not service or 'all' in service :
329+ service_types = None
330+ else :
331+ service_types = list (service )
332+
333+ if verbose :
334+ click .echo (f"🔍 Scanning network { network } for services: { service_types or 'all' } " )
335+
336+ scanner = NetworkScanner (timeout = timeout )
337+ services = await scanner .scan_network (network = network , service_types = service_types )
338+
339+ # Format and display results
340+ result = NetworkScanner .format_service_list (services )
341+ click .echo ("\n " + result )
342+
343+ # Save to file if requested
344+ if output :
345+ output_path = Path (output )
346+ output_path .write_text (result )
347+ click .echo (f"\n ✓ Results saved to { output_path } " )
348+
349+ except Exception as e :
350+ click .echo (f"❌ Error during scan: { e } " , err = True )
351+ if verbose :
352+ import traceback
353+ traceback .print_exc ()
354+ return 1
355+
356+
357+ def main ():
358+ """Entry point for the CLI."""
359+ cli ()
360+
361+
309362if __name__ == '__main__' :
310363 main ()
0 commit comments