For what it's worth, throwing a dumb retry around the bind call worked for me (along with adding the LanmanServer dependency in the Windows service manager). I don't know that it's suitable for general use, but here's what I did:
in tftpd_main.c:
#define TFTP_MAX_BIND_RETRIES 5
static SOCKET TftpBindLocalInterface (void)
{
int retryBind = 0;
int retries = 0;
.
.
.
// It's possible for the service to start before all network interfaces
// are available, even if it has dependencies on LanmanServer and LanmanWorkstation.
// So retry WSAEADDRNOTAVAIL bind errors a few times.
do
{
// bind the socket to the active interface
Rc = bind(sListenSocket, res->ai_addr, res->ai_addrlen);
if (Rc == INVALID_SOCKET)
{
char szAddr[MAXLEN_IPv6]="unknown", szServ[NI_MAXSERV]="unknown";
int KeepLastError = GetLastError();
// retrieve localhost and port
getnameinfo ( res->ai_addr, res->ai_addrlen,
szAddr, sizeof szAddr,
szServ, sizeof szServ,
NI_NUMERICHOST | AI_NUMERICSERV );
SetLastError (KeepLastError); // getnameinfo has reset LastError !
// 3 causes : access violation, socket already bound, bind on an address
switch (GetLastError ())
{
case WSAEADDRNOTAVAIL : // 10049
SVC_ERROR ("Error %d\n%s\n\n"
"Tftpd32 tried to bind the %s port\n"
"to the interface %s\nwhich is not available for this host\n"
"Either remove the %s service or suppress %s interface assignation",
GetLastError (), LastErrorText (),
"tftp", sSettings.szTftpLocalIP, "tftp", sSettings.szTftpLocalIP);
retries++;
if ( retries<= TFTP_MAX_BIND_RETRIES )
{
Sleep(1000);
retryBind = 1;
}
break;
case WSAEINVAL :
case WSAEADDRINUSE :
SVC_ERROR ("Error %d\n%s\n\n"
"Tftpd32 can not bind the %s port\n"
"an application is already listening on this port",
GetLastError (), LastErrorText (),
"tftp" );
break;
default :
SVC_ERROR ("Bind error %d\n%s",
GetLastError (), LastErrorText () );
break;
} // switch error type
if (!retryBind)
{
closesocket (sListenSocket);
LogToMonitor ("bind port to %s port %s failed\n", szAddr, szServ);
}
}
} while (retryBind);
and in service_stuff.c, I bumped up the wait hint value for good measure:
if (!ReportStatusToSCMgr(
SERVICE_START_PENDING, // service state
NO_ERROR, // exit code
8000)) // wait hint
Edited by AHenry, 17 July 2015 - 08:23 PM.