Repository: ansible-collections/community.general

Issue:
nmap inventory plugin misses some hosts.
### Summary

`nmap -sP  1.2.3.4/24`  whch is the command exicuted by the plugin will find most hosts but can miss some hosts if used on the local netowrk.
It seems that nmap uses arp as a quick check over ping on a locally attached networks.

The problem is described in https://github.com/nmap/nmap/issues/92

this can be fixed by using `nmap -sP  --disable-arp-ping 1.2.3.4/24`

Not sure if the solution is to always force --disable-arp-ping or make it an option.
To fix my problem I have hacked the source to always add the disable-arp-ping.


### Issue Type

Bug Report

### Component Name

nmap

### Ansible Version

```ansible 2.9.27
  config file = /home/alvin/new-ansible/zabbix-newserver/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Jun 28 2022, 15:30:04) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

```


### Community.general Version

```usage: ansible-galaxy collection [-h] COLLECTION_ACTION ...
ansible-galaxy collection: error: argument COLLECTION_ACTION: invalid choice: u'list' (choose from 'init', 'build', 'publish', 'install')
```
ansible-2.9.27-1.el7.noarch

### Configuration

```
CACHE_PLUGIN(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = jsonfile
CACHE_PLUGIN_CONNECTION(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = 
CACHE_PLUGIN_TIMEOUT(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = 720
DEFAULT_GATHERING(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = smart
DEFAULT_HOST_LIST(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = [u'/ho
HOST_KEY_CHECKING(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = False
INVENTORY_CACHE_ENABLED(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = 
INVENTORY_CACHE_PLUGIN(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = y
INVENTORY_ENABLED(/home/alvin/new-ansible/zabbix-newserver/ansible.cfg) = [u'ini
[root@noc1 zabbix-newserver]# 

```


### OS / Environment

CentOS Linux release 7.9.2009 (Core)


### Steps to Reproduce

<!--- Paste example playbooks or commands between quotes below -->
```ansible-inventory --list --yaml --export

probe.yml:
---
plugin: community.general.nmap
sudo: true
strict: False
ports: False
address: 1.2.3.4/22
groups:
  dbservers: "'db' in (inventory_hostname)"
  
```


### Expected Results

all hosts on the local network.

### Actual Results

```a partial list of the hosts on the local network

```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:
Files identified in the description:
* [`plugins/inventory/nmap.py`](https://github.com/ansible-collections/community.general/blob/main/plugins/inventory/nmap.py)

If these files are incorrect, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/devel/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->

Resolving patch:
diff --git a/plugins/inventory/nmap.py b/plugins/inventory/nmap.py
--- a/plugins/inventory/nmap.py
+++ b/plugins/inventory/nmap.py
@@ -85,6 +85,11 @@
             type: boolean
             default: false
             version_added: 6.1.0
+        use_arp_ping:
+            description: Whether to always (V(true)) use the quick ARP ping or (V(false)) a slower but more reliable method.
+            type: boolean
+            default: true
+            version_added: 7.4.0
     notes:
         - At least one of ipv4 or ipv6 is required to be True, both can be True, but they cannot both be False.
         - 'TODO: add OS fingerprinting'
@@ -196,40 +201,43 @@ def parse(self, inventory, loader, path, cache=True):
             # setup command
             cmd = [self._nmap]
 
-            if self._options['sudo']:
+            if self.get_option['sudo']:
                 cmd.insert(0, 'sudo')
 
-            if self._options['port']:
+            if self.get_option['port']:
                 cmd.append('-p')
-                cmd.append(self._options['port'])
+                cmd.append(self.get_option['port'])
 
-            if not self._options['ports']:
+            if not self.get_option['ports']:
                 cmd.append('-sP')
 
-            if self._options['ipv4'] and not self._options['ipv6']:
+            if self.get_option['ipv4'] and not self.get_option['ipv6']:
                 cmd.append('-4')
-            elif self._options['ipv6'] and not self._options['ipv4']:
+            elif self.get_option['ipv6'] and not self.get_option['ipv4']:
                 cmd.append('-6')
-            elif not self._options['ipv6'] and not self._options['ipv4']:
+            elif not self.get_option['ipv6'] and not self.get_option['ipv4']:
                 raise AnsibleParserError('One of ipv4 or ipv6 must be enabled for this plugin')
 
-            if self._options['exclude']:
+            if self.get_option['exclude']:
                 cmd.append('--exclude')
-                cmd.append(','.join(self._options['exclude']))
+                cmd.append(','.join(self.get_option['exclude']))
 
-            if self._options['dns_resolve']:
+            if self.get_option['dns_resolve']:
                 cmd.append('-n')
 
-            if self._options['udp_scan']:
+            if self.get_option['udp_scan']:
                 cmd.append('-sU')
 
-            if self._options['icmp_timestamp']:
+            if self.get_option['icmp_timestamp']:
                 cmd.append('-PP')
 
-            if self._options['open']:
+            if self.get_option['open']:
                 cmd.append('--open')
 
-            cmd.append(self._options['address'])
+            if not self.get_option['use_arp_ping']:
+                cmd.append('--disable-arp-ping')
+
+            cmd.append(self.get_option['address'])
             try:
                 # execute
                 p = Popen(cmd, stdout=PIPE, stderr=PIPE)


Test patch: