0

What I'm doing is specifying a range of IP addresses for nmap, say (192.168.0.0-50), to scan and for each IP it scans I need to use the output in different functions.

Here is a bit of code from what I'm doing:

def revLookup(ips):
    revCmd = "nmap -R -sP " + ips
    revargs = shlex.split(revCmd)
    revOut = subprocess.Popen(revargs, shell=False, stdout=subprocess.PIPE)
    for rline in revOut.stdout:
        if "Nmap scan report for " in rline:
            nmapNmIp = rline.strip("Nmap scan report for")
            rname, rip = nmapNmIp.split(" ")[0], nmapNmIp.split(" ")[-1]
            if rname.strip() == rip.strip():
                rname = "NO Name Provided"
            revNmapName = rname.split('.', 1)[0]
            rip = re.sub('[\(\)]', '', rip.strip())
        elif "MAC Address: " in rline:
            rnmapmac = rline.split(': ', 1)[-1]
            rnmapmac = rnmapmac.split(" ")[0]

    return revNmapName, rip, rnmapmac

The value that is returning is only the last value from the list. I have other functions that are using the various values to create other information, but I need to produce these one by one. I can do this is if I create one long messy function, I know that's not the right way.

Any advice is appreciated, thanks.

digitalbyte
  • 95
  • 10
  • So you want to `yield` one value for each line in `revOut.stdout`? – mgilson Apr 15 '16 at 19:30
  • So your suggesting to use yield in place of return? Sorry, I'm sort of new to python – digitalbyte Apr 15 '16 at 19:32
  • Actually, I'm trying to understand what you're trying to accomplish with your function. You said that you're only getting the last value (which is because `return` only returns once), but I'm unclear on what you actually want. If you want one value per line, the `yield` was a hint, but I'm happy to write it up more explicitly if I know that's what you actually want. – mgilson Apr 15 '16 at 19:34
  • I'm looking up yield as we speak... What I need is to return each value, use those values in other functions to create a dictionary, and then continue with the next value in this original function. I need to do this for every value in the ips list – digitalbyte Apr 15 '16 at 19:38

2 Answers2

1

Use yield instead of return and move it inside the loop, like something like this:

for rline in revOut.stdout:
    if "Nmap scan report for " in rline:
        ...
    elif "MAC Address: " in rline:
        ...
    yield revNmapName, rip, rnmapmac

And later on you can use the created generator (function that returns with yield is one of those) in a for loop, e.g.:

for rev, rip, rnmap in revLookup(ips):
    print rev, rip, rnmap

You can look at a great answer to this question What does the "yield" keyword do in Python?

EDIT: added usage of the method

Community
  • 1
  • 1
Krzysztof Krasoń
  • 26,515
  • 16
  • 89
  • 115
  • Im pretty sure what @mgilson and you are saying bu using yield. I'm going to try it out, thanks – digitalbyte Apr 15 '16 at 19:40
  • @rayray84 -- Yep. note that the `yield` is _in the for loop_. Then, you can easily construct a list of the results or just iterate over them directly: `list(revLookup(ips))` or `for item in revLookup(ips): ...` – mgilson Apr 15 '16 at 19:47
0

The answer to "return" after each time in a loop is to yield, however it may be better to make a function to work with a single ip and iterate over your ips:

def my_function(ip):
    new_data = dosomething
    return new_data

for ip in ips:
    result = my_function(ip)

Also, for working with Nmap you should look into python-nmap It is pretty nice.

James Robinson
  • 822
  • 6
  • 13