Repository: secdev/scapy

Issue:
TypeError: not all arguments converted during string formatting
<!--
Things to consider

1.  Please check that you are using the latest scapy version, e.g. installed via:

    `pip install --upgrade git+git://github.com/secdev/scapy`

2.  If you are here to ask a question - please check previous issues and online resources, and consider using gitter instead: <https://gitter.im/secdev/scapy>

3.  Please understand that **this is not a forum** but an issue tracker. The following article explains why you should limit questions asked on Github issues: <https://medium.com/@methane/why-you-must-not-ask-questions-on-github-issues-51d741d83fde>
-->

#### Brief description

./run_scapy does not run on macOS Catalina 10.15.7

<!-- describe the main issue in one sentence -->
<!-- if possible, describe what components / protocols could be affected by the issue (e.g. wrpcap() + IPv6, it is likely this also affects XXX) -->

#### Environment

-   Scapy version: `100b2ca7d01128e059330d34f11d4b01d2744c7e`
-   Python version: `3.8.6`
-   Operating System: `macOS Catalina 10.15.7`

<!-- if needed - further information to get a picture of your setup (e.g. a sketch of your network setup) -->

#### How to reproduce

`$ ./run_scapy`

<!-- step-by-step explanation or a short script, may reference section 'Related resources' -->

#### Actual result

<!-- dump results that outline the issue, please format your code -->
```
Traceback (most recent call last):
  File "/usr/local/Cellar/python@3.8/3.8.6_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/local/Cellar/python@3.8/3.8.6_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/Users/slyoldfox/scapy/scapy/__main__.py", line 15, in <module>
    interact()
  File "/Users/slyoldfox/scapy/scapy/main.py", line 550, in interact
    SESSION, GLOBKEYS = init_session(session_name, mydict)
  File "/Users/slyoldfox/scapy/scapy/main.py", line 411, in init_session
    importlib.import_module(".all", "scapy").__dict__
  File "/usr/local/Cellar/python@3.8/3.8.6_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/Users/slyoldfox/scapy/scapy/all.py", line 16, in <module>
    from scapy.arch import *
  File "/Users/slyoldfox/scapy/scapy/arch/__init__.py", line 130, in <module>
    from scapy.arch.bpf.supersocket import *  # noqa F403
  File "/Users/slyoldfox/scapy/scapy/arch/bpf/supersocket.py", line 27, in <module>
    from scapy.layers.l2 import Loopback
  File "/Users/slyoldfox/scapy/scapy/layers/l2.py", line 17, in <module>
    from scapy.ansmachine import AnsweringMachine
  File "/Users/slyoldfox/scapy/scapy/ansmachine.py", line 20, in <module>
    from scapy.sendrecv import send, sniff
  File "/Users/slyoldfox/scapy/scapy/sendrecv.py", line 61, in <module>
    import scapy.route  # noqa: F401
  File "/Users/slyoldfox/scapy/scapy/route.py", line 221, in <module>
    conf.ifaces.reload()
  File "/Users/slyoldfox/scapy/scapy/interfaces.py", line 238, in reload
    self._reload_provs()
  File "/Users/slyoldfox/scapy/scapy/interfaces.py", line 234, in _reload_provs
    self._load(prov.reload(), prov)
  File "/Users/slyoldfox/scapy/scapy/interfaces.py", line 53, in reload
    return self.load()
  File "/Users/slyoldfox/scapy/scapy/arch/bpf/core.py", line 226, in load
    mac = scapy.utils.str2mac(get_if_raw_hwaddr(ifname)[1])
  File "/Users/slyoldfox/scapy/scapy/utils.py", line 581, in str2mac
    return ("%02x:" * 6)[:-1] % tuple(map(ord, s))
TypeError: not all arguments converted during string formatting
```
#### Expected result

<!-- describe the expected result and outline the difference to the actual one, could also be a screen shot (e.g. wireshark) -->

A result :-)

#### Related resources

I added some debug output in the utils.py class and it seems to be breaking on the `fw0` interface.
```
fw0
(
 \ÿþ#Rô
it is a string
(40, 11, 92, 255, 254, 35, 82, 244)
```

<!-- traces / sample pcaps (stripped to the relevant frames), related standards, RFCs or other resources -->



Discussion:
Thanks for the report! I am a bit surprised, as we tested Scapy on macOS 10.15

Could you share the output of `ifconfig`, `netstat -rn -f inet`, and `netstat -rn -f inet6` ?
Another way to help, is to share the output of `print(type(s), repr(s))` after adding the line to `strmac()`
@guedou can I post the output somewhere private for you?

the print command just before the `if instance` check in `str2mac` yields for the `fw0` interface:

`<class 'str'> '(\x0b\\ÿþ#Rô'`

The output of `networksetup -listallhardwareports` for that interface is.

```
Hardware Port: FireWire
Device: fw0
Ethernet Address: 28:0b:5c:ff:fe:23:52:f4
```

Might have been you tested on a mac without Firewire ports (this is a Mac Mini with one Firewire port)? The mac address is slightly longer than a usual ethernet mac address
You can sent it to me via email (see the commits logs to retrieve my address).
Should be in your mailbox :-)

Resolving patch:
diff --git a/scapy/arch/bpf/core.py b/scapy/arch/bpf/core.py
--- a/scapy/arch/bpf/core.py
+++ b/scapy/arch/bpf/core.py
@@ -122,6 +122,11 @@ def get_if_raw_hwaddr(ifname):
     # Pack and return the MAC address
     mac = addresses[0].split(' ')[1]
     mac = [chr(int(b, 16)) for b in mac.split(':')]
+
+    # Check that the address length is correct
+    if len(mac) != 6:
+        raise Scapy_Exception("No MAC address found on %s !" % ifname)
+
     return (ARPHDR_ETHER, ''.join(mac))
 
 


Test patch:
diff --git a/test/regression.uts b/test/regression.uts
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -188,6 +188,8 @@ assert p == "127.0.0.1"
 
 = Interface related functions
 
+import mock
+
 conf.iface
 
 get_if_raw_hwaddr(conf.iface)
@@ -207,6 +209,16 @@ get_working_if()
 
 get_if_raw_addr6(conf.iface)
 
+if not WINDOWS:
+    addr = u"lladdr 29:0b:c2:ff:fe:53:21:e9\n"
+    b = Bunch(returncode=0, communicate=lambda *args, **kargs: (addr, None))
+    with mock.patch('scapy.arch.bpf.core.subprocess.Popen', return_value=b) as popen:
+        try:
+            scapy.arch.bpf.core.get_if_raw_hwaddr("fw0")
+            assert False
+        except Scapy_Exception:
+            assert True
+
 = More Interfaces related functions
 
 # Test name resolution