I'm trying to build on Windows, and I was eventually able to make static binaries with OpenSSL linked in. However I'm still having a problem with one bit of code. It fails to set the IP_PMTUDISC_DONT flag on the socket.
> uftpd.exe -D C:\xfertest\ -p 1044 -d -T c:\tmp
Error disabling MTU discovery: (10042) An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call.
Error leaving multicast group: (10038) An operation was attempted on something that is not a socket.
This is the code that is trying to set the flag on the socket in client_init.c:
#ifdef IP_MTU_DISCOVER{intmtuflag=IP_PMTUDISC_DONT;if(setsockopt(listener,IPPROTO_IP,IP_MTU_DISCOVER,&mtuflag,sizeof(mtuflag))==SOCKET_ERROR){sockerror(0,0,0,"Error disabling MTU discovery");closesocket(listener);exit(ERR_SOCKET);}}#endif
This is built on Windows Server 2016 with VS2017 community edition.
I have tried testing builds that don't include this flag, but they seem to have far worse performance (tons of NAKs), which maybe isn't a surprise if this causes fragmentation.
Can anyone think of why I can't setsockopt() on this? The listener is indeed a socket as created in the same file by listener = socket(family, SOCK_DGRAM, 0). I see other feedback on the internet claiming that some of these APIs may have changed through time. I will see if I can build on earlier VS and OS versions, but I am hoping someone who has hit this before can point out a clear path to a solution faster than I can.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
To fix the problem in the source code, I did these changes to client_init.c, proxy_init.c and server_init.c:
#ifdef IPV6_MTU_DISCOVER{intmtuflag=IP_PMTUDISC_DONT;if(setsockopt(listener,IPPROTO_IPV6,IPV6_MTU_DISCOVER,(char*)&mtuflag,sizeof(mtuflag))==SOCKET_ERROR){#ifdef WINDOWSif(WSAGetLastError()!=WSAENOPROTOOPT){#endifsockerror(0,0,0,"Error disabling MTU discovery");closesocket(listener);exit(ERR_SOCKET);#ifdef WINDOWS}#endif}}#endif#ifdef IP_MTU_DISCOVER{intmtuflag=IP_PMTUDISC_DONT;if(setsockopt(listener,IPPROTO_IP,IP_MTU_DISCOVER,(char*)&mtuflag,sizeof(mtuflag))==SOCKET_ERROR){#ifdef WINDOWSif(WSAGetLastError()!=WSAENOPROTOOPT){#endifsockerror(0,0,0,"Error disabling MTU discovery");closesocket(listener);exit(ERR_SOCKET);#ifdef WINDOWS}#endif}}#endif
The #ifdef WINDOWS blocks was added.
In addition, I fixed a problem related to the programs selecting UID on machines where the first network interface is missing an IP address, so the changed proxy_init.c and client_init.c noe loops through network interfaces, until a non-null UID may be extracted from the IP-address:
for (i = 0; i < interface_count; i++) {
if (m_interface[i].su.ss.ss_family == AF_INET6) {
uid = m_interface[i].su.sin6.sin6_addr.s6_addr[12] << 24;
uid |= m_interface[i].su.sin6.sin6_addr.s6_addr[13] << 16;
uid |= m_interface[i].su.sin6.sin6_addr.s6_addr[14] << 8;
uid |= m_interface[i].su.sin6.sin6_addr.s6_addr[15];
} else {
uid = m_interface[i].su.sin.sin_addr.s_addr;
}
// Break if found interface with IP address set
if (uid) break;
}
I'm trying to build on Windows, and I was eventually able to make static binaries with OpenSSL linked in. However I'm still having a problem with one bit of code. It fails to set the IP_PMTUDISC_DONT flag on the socket.
This is the code that is trying to set the flag on the socket in
client_init.c
:This is built on Windows Server 2016 with VS2017 community edition.
I have tried testing builds that don't include this flag, but they seem to have far worse performance (tons of NAKs), which maybe isn't a surprise if this causes fragmentation.
Can anyone think of why I can't setsockopt() on this? The listener is indeed a socket as created in the same file by
listener = socket(family, SOCK_DGRAM, 0)
. I see other feedback on the internet claiming that some of these APIs may have changed through time. I will see if I can build on earlier VS and OS versions, but I am hoping someone who has hit this before can point out a clear path to a solution faster than I can.The reason for the problem, is that the newer Windows SDKs has support for IP_MTU_DISCOVER and IPV6_MTU_DISCOVER, but the Windows you actually run the program on, misses the runtime support for the feature.
See more at https://stackoverflow.com/questions/49982697/why-cant-i-disable-mtu-discovery-on-windows-socket-ip-pmtudisc-dont-fails-to-s
To fix the problem in the source code, I did these changes to client_init.c, proxy_init.c and server_init.c:
The #ifdef WINDOWS blocks was added.
In addition, I fixed a problem related to the programs selecting UID on machines where the first network interface is missing an IP address, so the changed proxy_init.c and client_init.c noe loops through network interfaces, until a non-null UID may be extracted from the IP-address:
These fixes have been added to UFTP 4.9.8.