mtr icon indicating copy to clipboard operation
mtr copied to clipboard

Compiling under Cygwin result in error "`IN6_ADDR` not defined"

Open zcattacz opened this issue 3 years ago • 14 comments

gcc 10.2.0-1 make 4.3-1

Always receive Error IN6_ADDR not defined while make is processing probe.c

After a few greps, it turns out: IN6_ADDR is only defined in /usr/include/w32api/in6_addr.h as alias of in6_addr. But in6_addr is declared in both /usr/include/cygwin/in6.h and w32api/in6_addr.h together with a flag s6_addr.

in6.h is included priorior to in6_addr.h, and declares s6_addr in the first place, in6_addr.h check for flag s6_addr before any declaration. so IN6_ADDR and its poniters declared in in6_addr.h are always ignored.

Not sure how to fix this properly, so I just added a hack to the head of /usr/include/w32api/in6_addr.h before the s6_addr check.

#ifndef PIN6_ADDR
typedef struct in6_addr IN6_ADDR;
typedef struct in6_addr *PIN6_ADDR, *LPIN6_ADDR;

The compilition finished without exception, and the binary seems to work fine. Does this only happen to installtion ?

zcattacz avatar Jun 11 '21 09:06 zcattacz

And here I was going mad about this. Glad I am not the only one.

serialpotato avatar Jun 12 '21 06:06 serialpotato

I'm getting the same trying to compile 0.94 under Cygwin 64-bit / Windows 10.

I'd try the hack workaround but turns out I don't have a /usr/include/w32api/in6_addr.h , just in6addr.h, so not sure to add it. I'm not a C developer so on thin ice here as well.

I believe I have install all necessary depends with: setup-x86_64.exe --package-manager --wait --packages automake,pkg-config,make,gcc-core,libncurses-devel,libjansson-devel

First it gives some warnings on split.c:

ui/split.c: In function ‘split_redraw’:
ui/split.c:105:52: warning: ‘%d’ directive output may be truncated writing between 1 and 11 bytes into a region of size between 0 and 255 [-Wformat-truncation=]
  105 |             snprintf(newLine, sizeof(newLine), "%s %d %d %d %d %d %d",
      |                                                    ^~
ui/split.c:105:48: note: directive argument in the range [-2147483, 2147483]
  105 |             snprintf(newLine, sizeof(newLine), "%s %d %d %d %d %d %d",
      |                                                ^~~~~~~~~~~~~~~~~~~~~~
ui/split.c:105:48: note: directive argument in the range [-2147483, 2147483]
ui/split.c:105:48: note: directive argument in the range [-2147483, 2147483]
ui/split.c:105:13: note: ‘snprintf’ output between 13 and 319 bytes into a destination of size 256
  105 |             snprintf(newLine, sizeof(newLine), "%s %d %d %d %d %d %d",
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  106 |                      name, net_loss(at), net_returned(at), net_xmit(at),
      |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  107 |                      net_best(at) / 1000, net_avg(at) / 1000,
      |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  108 |                      net_worst(at) / 1000);
      |                      ~~~~~~~~~~~~~~~~~~~~~
In file included from ui/split.c:37:
In function ‘xstrncpy’,
    inlined from ‘split_redraw’ at ui/split.c:121:13:
ui/utils.h:42:5: warning: ‘strncpy’ output may be truncated copying 255 bytes from a string of length 255 [-Wstringop-truncation]
   42 |     strncpy(dest, src, n - 1);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~

Then errors on mprapi.h (so not actually in6_addr.h):

/usr/include/w32api/mprapi.h:240:5: error: unknown type name ‘IN6_ADDR’
  240 |     IN6_ADDR                ipv6addrDns;
      |     ^~~~~~~~
/usr/include/w32api/mprapi.h:241:5: error: unknown type name ‘IN6_ADDR’
  241 |     IN6_ADDR                ipv6addrDnsAlt;
      |     ^~~~~~~~
/usr/include/w32api/mprapi.h:242:5: error: unknown type name ‘IN6_ADDR’
  242 |     IN6_ADDR *              ipv6addr;
      |     ^~~~~~~~
/usr/include/w32api/mprapi.h:703:3: error: unknown type name ‘IN6_ADDR’
  703 |   IN6_ADDR *lpdwIpv6Address,
      |   ^~~~~~~~
/usr/include/w32api/mprapi.h:710:3: error: unknown type name ‘IN6_ADDR’
  710 |   IN6_ADDR *lpdwIpv6Address
      |   ^~~~~~~~
/usr/include/w32api/mprapi.h:929:77: error: unknown type name ‘IN6_ADDR’
  929 | typedef DWORD (APIENTRY * PMPRADMINGETIPV6ADDRESSFORUSER)(WCHAR *, WCHAR *, IN6_ADDR *, WINBOOL *);
      |                                                                             ^~~~~~~~
/usr/include/w32api/mprapi.h:930:81: error: unknown type name ‘IN6_ADDR’
  930 | typedef VOID  (APIENTRY * PMPRADMINRELEASEIPV6ADDRESSFORUSER)(WCHAR *, WCHAR *, IN6_ADDR *);
      |                                                                                 ^~~~~~~~
/usr/include/w32api/mprapi.h:942:3: error: unknown type name ‘PMPRADMINGETIPV6ADDRESSFORUSER’
  942 |   PMPRADMINGETIPV6ADDRESSFORUSER          lpfnMprAdminGetIpv6AddressForUser;
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/w32api/mprapi.h:943:3: error: unknown type name ‘PMPRADMINRELEASEIPV6ADDRESSFORUSER’
  943 |   PMPRADMINRELEASEIPV6ADDRESSFORUSER      lpfnMprAdminReleaseIpV6AddressForUser;
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Full paste here: https://pastebin.com/yuB4rwU7

Pathduck avatar Jul 06 '21 17:07 Pathduck

does adding

#include <in6addr.h>

to ui/mtr.h help?

krisl avatar Jul 07 '21 05:07 krisl

Use a tool like "grep" under unix-os-es to search for the missing define in your development toolchain.

I tried looking for your missing define here on LInux but it wasn't found. On closer inspection, the error is thrown in YOUR includes, i.e. the missing define is NOT in the mtr sources anywhere, but your include files seem to be using a macro that is not defined. It is probably defined in another header, that you're supposed to include before the one that called this one.

rewolff avatar Jul 07 '21 09:07 rewolff

@krisl

does adding

#include <in6addr.h>

to ui/mtr.h help?

I just tried that - it errors earlier with this:

make[1]: Entering directory '/cygdrive/g/dev/mtr'
  CC       ui/mtr-mtr.o
  CC       ui/mtr-net.o
In file included from ui/mtr.h:24,
                 from ui/net.c:36:
/usr/include/w32api/_bsd_types.h:30:27: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘__ms_u_long’
   30 | typedef unsigned __LONG32 u_long;
      |                           ^~~~~~
In file included from /usr/include/cygwin/in.h:274,
                 from /usr/include/netinet/in.h:12,
                 from /usr/include/netdb.h:65,
                 from ui/mtr.h:26,
                 from ui/net.c:36:
/usr/include/cygwin/in6.h:73:8: error: redefinition of ‘struct in6_addr’
   73 | struct in6_addr
      |        ^~~~~~~~
In file included from ui/mtr.h:24,
                 from ui/net.c:36:
/usr/include/w32api/in6addr.h:17:16: note: originally defined here
   17 | typedef struct in6_addr {
      |                ^~~~~~~~
make[1]: *** [Makefile:944: ui/mtr-net.o] Error 1
make[1]: Leaving directory '/cygdrive/g/dev/mtr'
make: *** [Makefile:672: all] Error 2

@rewolff I'll be happy to try anything, but I'm not a developer, I'm able to compile basic stuff under Cygwin but once I hit snags like this I'm lost on what to do. But willing to learn.

I know it sucks trying to debug someone elses's setup, but this is pretty much a vanilla Cygwin install. But maybe I will try to just do a clean install from base to see if it helps.

Edit: Did a clean install of Cygwin 64-bit, also tried adding mingw64-i686-gcc. Maybe I need to use 32-bit? 😕

Pathduck avatar Jul 07 '21 10:07 Pathduck

@Pathduck - I have the same issue you are having where /usr/include/w32api/in6_addr.h is not present on my system. Instead of adding the below definitions to that file like @zcattacz suggests, I added it with a closing #endif pragma in /usr/include/cygwin/in6.h after the struct in6_addr definition.

So this code snippet:

#ifndef PIN6_ADDR
typedef struct in6_addr IN6_ADDR;
typedef struct in6_addr *PIN6_ADDR, *LPIN6_ADDR;

Became this code in /usr/include/cygwin/in6.h, given with context here since you say you are not familiar with C:

// Find these lines, but don't touch/change them:
struct in6_addr
{
  union
    {
      uint8_t     __s6_addr[16];
      uint16_t    __s6_addr16[8];
      uint32_t    __s6_addr32[4];
    } __u6;
#define s6_addr         __u6.__s6_addr
#define s6_addr16       __u6.__s6_addr16
#define s6_addr32       __u6.__s6_addr32
};

// Add these lines
#ifndef PIN6_ADDR
typedef struct in6_addr IN6_ADDR;
typedef struct in6_addr *PIN6_ADDR, *LPIN6_ADDR;
#endif /* PIN6_ADDR */

After this, I was able to run ./bootstrap && ./configure && make in my mtr-0.94 source directory successfully. I got some (expected) warnings about strncopy, but both mtr.exe and mtr-packet.exe were built and seem to work just fine.

casnix avatar Jul 08 '21 14:07 casnix

@casnix Brilliant, that worked beautifully! Thank you so much! 👍

I still got the same warnings as before but everything seems fine otherwise 😄

Pathduck avatar Jul 08 '21 19:07 Pathduck

@casnix Thank you so much - works for me too :)

Does anybody know if it's possibe to get mtr working in cmd or PowerShell, i.e. without an xterm?

sphr2k avatar Jul 08 '21 19:07 sphr2k

@sphr2k

Does anybody know if it's possibe to get mtr working in cmd or PowerShell, i.e. without an xterm?

It seems to work fine here in Cmder (https://cmder.net) which is cmd so it should be fine as long as it's on the %PATH%. Oh and you certainly don't need an xterm, I use MinTTY under Cygwin.

"Nothin' to it but to do it" as they say ;)

Pathduck avatar Jul 08 '21 19:07 Pathduck

It seems to work fine here in Cmder (https://cmder.net) which is cmd so it should be fine as long as it's on the %PATH%. Oh and you certainly don't need an xterm, I use MinTTY under Cygwin.

Sorry, I phrased that unclearly. I'm trying to get mtr to run outside a Cygwin environment, i.e. I copied mtr.exe and its dependencies (cygwin1.dll, cygncursesw-10.dll etc.) to a directory and tried to run it in cmd and PowerShell, which results in the following error:

Error opening terminal: xterm-256color.

I think this is due to the usage of ncurses.

sphr2k avatar Jul 09 '21 16:07 sphr2k

@sphr2k Oh yeah I think you'll have a lot of dependecy issues trying that. It might work though, if you get all the dependencies copied. Best to just have \cygwin\bin \cygwin\usr\sbin on the %path%

I checked with Process Explorer, it seems to load at least:

d:\bin\cygwin\bin\cygncursesw-10.dll
d:\bin\cygwin\bin\cygjansson-4.dll
d:\bin\cygwin\bin\cygwin1.dll 

Pathduck avatar Jul 09 '21 19:07 Pathduck

@Pathduck Yep, those are the dependencies I identified as well. Still, mtr throws "Error opening terminal ..."

sphr2k avatar Jul 09 '21 20:07 sphr2k

It seems to work fine here in cmd. Maybe you have the term variable set in Cmd which should be unnecessary?

image

You should probably open a separate issue about this?

Pathduck avatar Jul 09 '21 20:07 Pathduck

I'm not sure how it's working for Pathduck. With a hint from https://github.com/traviscross/mtr/issues/299#issuecomment-485856941, I ended up doing something like this:

$ out="/cygdrive/c/Users/$USER/mtr"
$ mkdir -p "$out/"{terminfo/78,bin}
$ cp mtr/mtr{,-packet}.exe "$out/bin/"
$ cp /bin/cyg{win,ncursesw-10,jansson-4}.dll "$out/bin/"
$ cp /usr/share/terminfo/78/xterm-256color  "$out/terminfo/78/"

And a slightly simplified version of Matt's batch script:

@echo off
set "PATH=%~dp0\bin;%PATH%"
set "TERMINFO=%~dp0\terminfo"
mtr.exe %*

half-duplex avatar Aug 02 '21 23:08 half-duplex