-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
unix: fix wrong MAC of uv_interface_address #1375
unix: fix wrong MAC of uv_interface_address #1375
Conversation
Anyone to review this PR? /cc @cjihrig |
@santigimeno it seems failed? |
This won't fix #829 and nodejs/node#13581 because that was about EUI-64 MAC addresses and it almost certainly can't be the fix for nodejs/node#5629 because the file you changed is only used on the BSDs, not Linux. That aside, the fix looks okay but but you should be able to avoid duplicating |
For nodejs/node#13581, I think the wrong This PR won't fix other 2 issues, but I think it may fix nodejs/node#13581. |
The point stands though that bsd-ifaddrs.c is not used on Linux. |
One more time: https://ci.nodejs.org/view/libuv/job/libuv-test-commit/290/ |
sorry, I will update code later to fix linux. |
@bnoordhuis I've updated the code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit too much code duplication to my liking. Here is what you can do. Change:
static int uv__ifaddr_exclude(struct ifaddrs *ent) {
To:
static int uv__ifaddr_exclude(struct ifaddrs *ent, int skip_pf_packet) {
And update:
if (ent->ifa_addr->sa_family == PF_PACKET) return 1;
To:
if (ent->ifa_addr->sa_family == PF_PACKET) return skip_pf_packet;
And then update the call sites accordingly. Bonus points if you use a descriptive enum instead of a plain int.
@bnoordhuis But in bsd-ifaddr they are different. #elif defined(__NetBSD__) || defined(__OpenBSD__)
if (ent->ifa_addr->sa_family != PF_INET)
return 1;
#endif against ent->ifa_addr->sa_family != AF_LINK |
c204801
to
edd7e40
Compare
src/unix/bsd-ifaddrs.c
Outdated
@@ -31,7 +31,12 @@ | |||
#include <net/if_dl.h> | |||
#endif | |||
|
|||
static int uv__ifaddr_exclude(struct ifaddrs *ent) { | |||
typedef enum { | |||
UV__EXCLUDE_IFPHYS = 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two space indentation please.
@bnoordhuis I've updated the code. |
src/unix/bsd-ifaddrs.c
Outdated
typedef enum { | ||
UV__EXCLUDE_IFPHYS = 0, | ||
UV__EXCLUDE_IFADDR = 1 | ||
} uv__exclude_type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not wrong but you don't need to explicitly assign values. As well, I wouldn't use a typedef, it obscures the type. You use it in more than one file so you can move it to src/unix/internal.h to avoid the duplication.
src/unix/bsd-ifaddrs.c
Outdated
@@ -42,12 +47,13 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) { | |||
* devices. We're not interested in this information. | |||
*/ | |||
if (ent->ifa_addr->sa_family == AF_LINK) | |||
return 1; | |||
return !!(int)type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just return type;
(and consider renaming it to exclude_type
.)
src/unix/bsd-ifaddrs.c
Outdated
#elif defined(__NetBSD__) || defined(__OpenBSD__) | ||
if (ent->ifa_addr->sa_family != PF_INET) | ||
if (type == UV__EXCLUDE_IFADDR && ent->ifa_addr->sa_family != PF_INET) | ||
return 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can drop the check and just return !exclude_type;
or return exclude_type == UV__EXCLUDE_IFADDR;
.
src/unix/bsd-ifaddrs.c
Outdated
return 1; | ||
return type == UV__EXCLUDE_IFADDR ? 0 : (ent->ifa_addr->sa_family != AF_LINK); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Libuv house style generally doesn't use ternaries.
0e194c7
to
360accf
Compare
@bnoordhuis Updated. 👌 |
/ping @bnoordhuis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to add some checks to e.g. test/test-platform-output.c?
src/unix/bsd-ifaddrs.c
Outdated
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) | ||
return 1; | ||
if (ent->ifa_addr == NULL) | ||
return 1; | ||
/* | ||
* Just see whether sa_family equals to AF_LINK or not if exclude_type is | ||
* UV__EXCLUDE_IFPHYS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General style nit: please capitalize and punctuate comments.
* UV__EXCLUDE_IFPHYS | ||
*/ | ||
if (exclude_type == UV__EXCLUDE_IFPHYS) | ||
return (ent->ifa_addr->sa_family != AF_LINK); | ||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) | ||
/* | ||
* On BSD getifaddrs returns information related to the raw underlying |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you're assuming that AF_LINK is defined everywhere (and I believe it is), you could drop the #ifdef
and reduce this to:
return (exclude_type == UV__EXCLUDE_IFPHYS) ^ (ent->ifa_addr->sa_family == AF_LINK);
I think?
What about the NetBSD/OpenBSD code path? Should it take exclude_type
into account? Or just moved a few lines up, before the return
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If UV__EXCLUDE_IFPHYS
, then only returns (ent->ifa_addr->sa_family != AF_LINK)
on any system.
Otherwise, it depends on system. If it's OSX / FreeBSD / DragonFly then it depends on AF_LINK
, or it depends on PF_INET
.
src/unix/linux-core.c
Outdated
return 1; | ||
return 0; | ||
return exclude_type; | ||
return !exclude_type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/libuv/libuv/blob/v1.9.1/src/unix/linux-core.c#L901-L912 against https://github.com/libuv/libuv/blob/v1.9.1/src/unix/linux-core.c#L935-L939
if exclude_type
equals UV__EXCLUDE_IFPHYS
then return ent->ifa_addr->sa_family == PF_PACKET
, otherwise return ent->ifa_addr->sa_family != PF_PACKET
.
I'll add some test cases then. |
/ping @bnoordhuis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with comments and a question.
test/test-platform-output.c
Outdated
printf(" name: %s\n", interfaces[i].name); | ||
printf(" internal: %d\n", interfaces[i].is_internal); | ||
printf(" physical address: "); | ||
printf("%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
sprintf(ether, "%02x:%02x:%02x:%02x:%02x:%02x", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use snprintf() here?
test/test-platform-output.c
Outdated
(unsigned char)interfaces[i].phys_addr[0], | ||
(unsigned char)interfaces[i].phys_addr[1], | ||
(unsigned char)interfaces[i].phys_addr[2], | ||
(unsigned char)interfaces[i].phys_addr[3], | ||
(unsigned char)interfaces[i].phys_addr[4], | ||
(unsigned char)interfaces[i].phys_addr[5]); | ||
printf("%s\n", ether); | ||
|
||
if (strcmp(ether, "00:00:00:00:00:00") != 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why check if it's all zeroes?
test/test-platform-output.c
Outdated
|
||
if (interfaces[i].address.address4.sin_family == AF_INET) { | ||
uv_ip4_name(&interfaces[i].address.address4, buffer, sizeof(buffer)); | ||
} else if (interfaces[i].address.address4.sin_family == AF_INET6) { | ||
uv_ip6_name(&interfaces[i].address.address6, buffer, sizeof(buffer)); | ||
} | ||
|
||
printf(" address: %s\n", buffer); | ||
printf(" address: %s\n", buffer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whitespace change.
Tested and confirmed working. |
Let's see how the CI fares: https://ci.nodejs.org/view/libuv/job/libuv-test-commit/311/ EDIT: Still needs some work. Lots of red. |
Anyone has some better test solution? |
@bnoordhuis To be honest, I've no better idea than spawning a |
@XadillaX using |
@santigimeno All kinds of Linux distributions? By another way, |
AFAIK 2: enp3s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 70:4d:7b:3c:16:b0 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.116/24 brd 192.168.1.255 scope global dynamic enp3s0f1
valid_lft 2774sec preferred_lft 2774sec
inet6 fe80::4100:1991:751a:d1aa/64 scope link
valid_lft forever preferred_lft forever For now in Linux i've solved the issue shelling synchronously the command |
@libuv/collaborators How about we land this without the test? I don't think it's important enough to agonize endlessly over an unreliable test. |
+1 with @bnoordhuis |
👍 WRT the test, apart from the issue that making it work for every platform may not be easy, I think there's a problem in that the
|
Why don't we create a tap device with a self-defined hardware address? That last source code should work cross-platform (although not tested yet).
It is important for my goals to have proper mac address resolving, because i'm writing to raw sockets. Using the wrong MAC address disconnects the computer from the network my programs are running on (also how i discovered this bug myself). So, my goal is to use libuv as a shared library and therefor i need certain minimal guarantees. If we are allowed to create tap devices on the test systems, then this could work well, and i can create a test script for it. What platforms should be supported with
old wrong code:
|
@@ -145,6 +145,12 @@ enum { | |||
UV_LOOP_BLOCK_SIGPROF = 1 | |||
}; | |||
|
|||
/* flags of excluding ifaddr */ | |||
enum { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use a typedef?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@saghul I used to use typedef
. But I removed it later referred by #1375 (comment).
Agreed. |
/ping @bnoordhuis I've removed the test. |
src/unix/linux-core.c
Outdated
@@ -847,8 +847,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) { | |||
* devices. We're not interested in this information yet. | |||
*/ | |||
if (ent->ifa_addr->sa_family == PF_PACKET) | |||
return 1; | |||
return 0; | |||
return exclude_type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a bogus trailing space here.
/ping @bnoordhuis |
A general question about this function. Why do we care if a network device is running or up? Shouldn't we just be able to discover all available network devices?
I would say that we just make these flags parameters of the interface struct so the user can decide how to deal with inactive and down network devices. Or is this a cross-platform thing? |
@XadillaX the tests all succeeded (the failing ones weren't due to these changes). Can you finish your PR so it can be merged like squashing and a good commit message. |
@CurlyMoo I will rebase it after going back home, now i'm on a train. |
fix a wrong `if` in `uv_interface_address` about MAC. Fixes: nodejs/node#13581
d78164b
to
f34d7e2
Compare
/ping @CurlyMoo, /cc @bnoordhuis I've rebased the code. |
fix a wrong `if` in `uv_interface_address` about MAC. Fixes: nodejs/node#13581 PR-URL: #1375 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
It seems like this should also go into master, not just v1.x? (I haven’t tested it, but I was just reading the master code and thinking “how on earth is this supposed to work?”) |
No worries, we merge |
fix a wrong
if
inuv_interface_address
about MAC.Fixes: nodejs/node#13581
Refs: https://github.com/libuv/libuv/blob/v1.9.1/src/unix/freebsd.c#L418-L420
Refs: https://github.com/libuv/libuv/blob/v1.9.1/src/unix/darwin.c#L303-L305
Refs: ...