Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ziflist selftest fails #1802

Closed
paddor opened this issue Nov 26, 2017 · 8 comments
Closed

ziflist selftest fails #1802

paddor opened this issue Nov 26, 2017 · 8 comments

Comments

@paddor
Copy link
Contributor

paddor commented Nov 26, 2017

I'm running MacOS 10.13.1. When I try to install CZMQ HEAD (with --enable-drafts), either with Homebrew or manually, the make check-verbose step fails with this:

Assertion failed: (rc == 0), function s_interface_new, file src/ziflist.c, line 95.

I tried to track the problem down and it seems that this assertion happens while reading the netmask information of my interface vboxnet2. The function getnameinfo(netmask, ...) returns error code EAI_FAMILY. I printed netmask->sa_family, and it is 0 (AF_UNSPEC according to /usr/include/sys/socket.h). Since that netmask is passed in as an argument, the error seems to be in the calling function s_reload(), probably in the part that reads the netmask:

inaddr_t netmask = { 0 };
if (!ioctl (sock, SIOCGIFNETMASK, (caddr_t) ifr, sizeof (struct ifreq)))
    netmask = *((inaddr_t *) &ifr->ifr_addr);
else
    is_valid = false;

Now my C/systems programming knowledge is very limited. It seems that for an invalid/unsupported interface, it should simply set is_valid = false and thus skip the s_interface_new() call for that interface, but it doesn't.

What might be interesting is the information about my interface:

For this interface, it does not assert:

$ ifconfig -v en0
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 index 5
	eflags=412008c0<ACCEPT_RTADV,TXSTART,ARPLL,NOACKPRI,ECN_ENABLE,FASTLN_ON>
	ether 3c:15:c2:e3:e8:c4
	inet6 fe80::c13:c221:c739:cd74%en0 prefixlen 64 secured scopeid 0x5
	inet 192.168.178.21 netmask 0xffffff00 broadcast 192.168.178.255
	nd6 options=201<PERFORMNUD,DAD>
	media: autoselect
	status: active
	type: Wi-Fi
	link quality: 100 (good)
	state availability: 0 (true)
	scheduler: FQ_CODEL (driver managed)
	uplink rate: 43.07 Mbps [eff] / 304.20 Mbps
	downlink rate: 43.07 Mbps [eff] / 304.20 Mbps [max]
	qosmarking enabled: yes mode: none

For this interface, it asserts:

$ ifconfig -v vboxnet2
vboxnet2: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500 index 16
	eflags=41000000<ECN_ENABLE,FASTLN_ON>
	ether 0a:00:27:00:00:02
	inet 192.168.99.1 netmask 0xffffff00 broadcast 192.168.99.255
	type: Ethernet
	state availability: 0 (true)
	qosmarking enabled: yes mode: none

Thanks for any help.

@bluca
Copy link
Member

bluca commented Nov 26, 2017

Doesn't OSX have getifaddr? Google would suggest it does, which means it should run this block instead:
https://github.com/zeromq/czmq/blob/master/src/ziflist.c#L205

@paddor
Copy link
Contributor Author

paddor commented Nov 26, 2017

You're totally right. That explains why I couldn't see my debugging output from the #if defined (__UNIX__) block. 😅 I'll take a closer look at the other block.

@bluca
Copy link
Member

bluca commented Nov 26, 2017

We might have missed something that happens only on OSX in the s_valid_flags function, where it checks the if flags - unfortunately I don't have access to OSX so I cannot test it directly

@paddor
Copy link
Contributor Author

paddor commented Nov 26, 2017

I printed the actual flags for each interface being processed (most of them are actually skipped before the call to s_valid_flags()):

I: 17-11-26 20:50:40 s_reload(): ifa_name=lo0
I: 17-11-26 20:50:40 s_reload(): ifa_name=lo0
I: 17-11-26 20:50:40 s_valid_flags(): flags=0xffff8049, ipv6=0
I: 17-11-26 20:50:40 s_reload(): ifa_name=lo0
I: 17-11-26 20:50:40 s_reload(): ifa_name=lo0
I: 17-11-26 20:50:40 s_reload(): ifa_name=gif0
I: 17-11-26 20:50:40 s_reload(): ifa_name=stf0
I: 17-11-26 20:50:40 s_reload(): ifa_name=XHC20
I: 17-11-26 20:50:40 s_reload(): ifa_name=en0
I: 17-11-26 20:50:40 s_reload(): ifa_name=en0
I: 17-11-26 20:50:40 s_reload(): ifa_name=en0
I: 17-11-26 20:50:40 s_valid_flags(): flags=0xffff8863, ipv6=0
I: 17-11-26 20:50:40 s_interface_new(): netmask->sa_family=2
I: 17-11-26 20:50:40 s_reload(): ifa_name=p2p0
I: 17-11-26 20:50:40 s_reload(): ifa_name=awdl0
I: 17-11-26 20:50:40 s_reload(): ifa_name=awdl0
I: 17-11-26 20:50:40 s_reload(): ifa_name=en1
I: 17-11-26 20:50:40 s_reload(): ifa_name=en2
I: 17-11-26 20:50:40 s_reload(): ifa_name=bridge0
I: 17-11-26 20:50:40 s_reload(): ifa_name=utun0
I: 17-11-26 20:50:40 s_reload(): ifa_name=utun0
I: 17-11-26 20:50:40 s_reload(): ifa_name=utun1
I: 17-11-26 20:50:40 s_reload(): ifa_name=utun1
I: 17-11-26 20:50:40 s_reload(): ifa_name=vboxnet0
I: 17-11-26 20:50:40 s_reload(): ifa_name=vboxnet1
I: 17-11-26 20:50:40 s_reload(): ifa_name=vboxnet2
I: 17-11-26 20:50:40 s_reload(): ifa_name=vboxnet2
I: 17-11-26 20:50:40 s_valid_flags(): flags=0xffff8943, ipv6=0
I: 17-11-26 20:50:40 s_interface_new(): netmask->sa_family=0
E: 17-11-26 20:50:40  - getnameinfo error : ai_family not supported
Assertion failed: (rc == 0), function s_interface_new, file src/ziflist.c, line 94.

And from /usr/include/net/if.h:

#define IFF_UP      0x1     /* interface is up */
#define IFF_BROADCAST   0x2     /* broadcast address valid */
#define IFF_DEBUG   0x4     /* turn on debugging */
#define IFF_LOOPBACK    0x8     /* is a loopback net */
#define IFF_POINTOPOINT 0x10        /* interface is point-to-point link */
#define IFF_NOTRAILERS  0x20        /* obsolete: avoid use of trailers */
#define IFF_RUNNING 0x40        /* resources allocated */
#define IFF_NOARP   0x80        /* no address resolution protocol */
#define IFF_PROMISC 0x100       /* receive all packets */
#define IFF_ALLMULTI    0x200       /* receive all multicast packets */
#define IFF_OACTIVE 0x400       /* transmission in progress */
#define IFF_SIMPLEX 0x800       /* can't hear own transmissions */
#define IFF_LINK0   0x1000      /* per link layer defined bit */
#define IFF_LINK1   0x2000      /* per link layer defined bit */
#define IFF_LINK2   0x4000      /* per link layer defined bit */
#define IFF_ALTPHYS IFF_LINK2   /* use alternate physical connection */
#define IFF_MULTICAST   0x8000      /* supports multicast */

@paddor
Copy link
Contributor Author

paddor commented Nov 26, 2017

So if I'm correct, compared to en0, the failing vboxnet2 interface has IFF_PROMISC set but no IFF_NOTRAILERS.

@paddor
Copy link
Contributor Author

paddor commented Nov 26, 2017

Instead of focusing on the flags, I changed s_reload() to simply perform the same check on interface->ifa_netmask as for interface->ifa_addr:

struct ifaddrs *interfaces;
if (getifaddrs (&interfaces) == 0) {
    struct ifaddrs *interface = interfaces;
    while (interface) {
        zsys_info("s_reload(): ifa_name=%s", interface->ifa_name);

        //  On Solaris, loopback interfaces have a NULL in ifa_broadaddr
        if (interface->ifa_addr
        && (interface->ifa_broadaddr
                || (ipv6 && (interface->ifa_addr->sa_family == AF_INET6)))
        &&(interface->ifa_addr->sa_family == AF_INET
                || (ipv6 && (interface->ifa_addr->sa_family == AF_INET6)))
+        &&(interface->ifa_netmask->sa_family == AF_INET
+                || (ipv6 && (interface->ifa_netmask->sa_family == AF_INET6)))
        &&  s_valid_flags (interface->ifa_flags,
                ipv6 && (interface->ifa_addr->sa_family == AF_INET6))) {

            interface_t *item = s_interface_new (interface->ifa_name,
                    interface->ifa_addr, interface->ifa_netmask,
                    interface->ifa_broadaddr);
            if (item)
                zlistx_add_end (list, item);
        }
        interface = interface->ifa_next;
    }
}
freeifaddrs (interfaces);

And the selftest doesn't assert anymore. Does this change make sense? The only interface it really loads now is en0, the only "real" and working interface on my MacBook. Is that what it's supposed to do?

I: 17-11-26 21:08:30 s_reload(): ifa_name=lo0
I: 17-11-26 21:08:30 s_reload(): ifa_name=lo0
I: 17-11-26 21:08:30 s_valid_flags(): flags=0xffff8049, ipv6=0
I: 17-11-26 21:08:30 s_reload(): ifa_name=lo0
I: 17-11-26 21:08:30 s_reload(): ifa_name=lo0
I: 17-11-26 21:08:30 s_reload(): ifa_name=gif0
I: 17-11-26 21:08:30 s_reload(): ifa_name=stf0
I: 17-11-26 21:08:30 s_reload(): ifa_name=XHC20
I: 17-11-26 21:08:30 s_reload(): ifa_name=en0
I: 17-11-26 21:08:30 s_reload(): ifa_name=en0
I: 17-11-26 21:08:30 s_reload(): ifa_name=en0
I: 17-11-26 21:08:30 s_valid_flags(): flags=0xffff8863, ipv6=0
I: 17-11-26 21:08:30 s_interface_new(): netmask->sa_family=2
I: 17-11-26 21:08:30 s_reload(): ifa_name=p2p0
I: 17-11-26 21:08:30 s_reload(): ifa_name=awdl0
I: 17-11-26 21:08:30 s_reload(): ifa_name=awdl0
I: 17-11-26 21:08:30 s_reload(): ifa_name=en1
I: 17-11-26 21:08:30 s_reload(): ifa_name=en2
I: 17-11-26 21:08:30 s_reload(): ifa_name=bridge0
I: 17-11-26 21:08:30 s_reload(): ifa_name=utun0
I: 17-11-26 21:08:30 s_reload(): ifa_name=utun0
I: 17-11-26 21:08:30 s_reload(): ifa_name=utun1
I: 17-11-26 21:08:30 s_reload(): ifa_name=utun1
I: 17-11-26 21:08:30 s_reload(): ifa_name=vboxnet0
I: 17-11-26 21:08:30 s_reload(): ifa_name=vboxnet1
I: 17-11-26 21:08:30 s_reload(): ifa_name=vboxnet2
I: 17-11-26 21:08:30 s_reload(): ifa_name=vboxnet2
I: 17-11-26 21:08:30 s_reload(): ifa_name=vboxnet3
I: 17-11-26 21:08:30 s_reload(): ifa_name=ipsec0
I: 17-11-26 21:08:30 s_reload(): ifa_name=ipsec0
I: 17-11-26 21:08:30 s_valid_flags(): flags=0xffff8051, ipv6=0
I: 17-11-26 21:08:30 s_reload(): ifa_name=ipsec0
I: 17-11-26 21:08:30 s_reload(): ifa_name=ipsec0
items in interface list: 1
ziflist: interfaces=1
 - name=en0 address=192.168.178.21 netmask=255.255.255.0 broadcast=192.168.178.255

@bluca
Copy link
Member

bluca commented Nov 26, 2017

It makes sense yes, and feel free to send a PR with that change.
Although I'm not sure what's wrong there - that interface clearly has a netmask of 255.255.255.0 like the other one.

On the other hand, its internal details are handled by Virtualbox's code in the kernel module, which is notoriously bad, so it might simply be a bug there.

@paddor
Copy link
Contributor Author

paddor commented Nov 26, 2017

Huh, seems like it. I just realized it only crashes while the VM using that adapter (Host-only Adapter) is running. I'll file a PR anyway. If there's no sa_family set, it simply shouldn't try to getnameinfo() from it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants