AI_CANONNAME is only relevant when the resulting official name is used, which is not the case in tftpd for the address to bind to. Also AI_ADDRCONFIG isn't helpful. This flag is good for sockets used to connect(2) somewhere. But for listening sockets it makes tftpd fail to start when -a 0.0.0.0:69 is passed and no network device is up yet.
This addresses Debian bug https://bugs.debian.org/771441 --- common/tftpsubs.c | 4 ++-- common/tftpsubs.h | 2 +- tftp/main.c | 9 ++++++--- tftpd/tftpd.c | 6 ++++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/common/tftpsubs.c b/common/tftpsubs.c index 8c999f66eed8..344c74b3d78c 100644 --- a/common/tftpsubs.c +++ b/common/tftpsubs.c @@ -300,7 +300,7 @@ int pick_port_bind(int sockfd, union sock_addr *myaddr, } int -set_sock_addr(char *host,union sock_addr *s, char **name) +set_sock_addr(char *host, union sock_addr *s, char **name, int ai_flags) { struct addrinfo *addrResult; struct addrinfo hints; @@ -308,7 +308,7 @@ set_sock_addr(char *host,union sock_addr *s, char **name) memset(&hints, 0, sizeof(hints)); hints.ai_family = s->sa.sa_family; - hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; + hints.ai_flags = ai_flags; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; err = getaddrinfo(strip_address(host), NULL, &hints, &addrResult); diff --git a/common/tftpsubs.h b/common/tftpsubs.h index b3a3bf3c95e1..0edda03a514c 100644 --- a/common/tftpsubs.h +++ b/common/tftpsubs.h @@ -98,7 +98,7 @@ static inline int sa_set_port(union sock_addr *s, u_short port) return 0; } -int set_sock_addr(char *, union sock_addr *, char **); +int set_sock_addr(char *, union sock_addr *, char **, int); struct tftphdr; diff --git a/tftp/main.c b/tftp/main.c index b2f90593ed31..4aebe630af1e 100644 --- a/tftp/main.c +++ b/tftp/main.c @@ -414,7 +414,8 @@ void setpeer(int argc, char *argv[]) } peeraddr.sa.sa_family = ai_fam; - err = set_sock_addr(argv[1], &peeraddr, &hostname); + err = set_sock_addr(argv[1], &peeraddr, &hostname, + AI_CANONNAME | AI_ADDRCONFIG); if (err) { printf("Error: %s\n", gai_strerror(err)); printf("%s: unknown host\n", argv[1]); @@ -557,7 +558,8 @@ void put(int argc, char *argv[]) targ = strchr(cp, ':'); *targ++ = 0; peeraddr.sa.sa_family = ai_fam; - err = set_sock_addr(cp, &peeraddr,&hostname); + err = set_sock_addr(cp, &peeraddr, &hostname, + AI_CANONNAME | AI_ADDRCONFIG); if (err) { printf("Error: %s\n", gai_strerror(err)); printf("%s: unknown host\n", argv[1]); @@ -648,7 +650,8 @@ void get(int argc, char *argv[]) *src++ = 0; peeraddr.sa.sa_family = ai_fam; - err = set_sock_addr(argv[n], &peeraddr, &hostname); + err = set_sock_addr(argv[n], &peeraddr, &hostname, + AI_CANONNAME | AI_ADDRCONFIG); if (err) { printf("Warning: %s\n", gai_strerror(err)); printf("%s: unknown host\n", argv[1]); diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c index 364e7d2303e0..db22426edbb9 100644 --- a/tftpd/tftpd.c +++ b/tftpd/tftpd.c @@ -638,7 +638,8 @@ int main(int argc, char **argv) if (fd4 >= 0) { bindaddr4.sin_family = AF_INET; err = set_sock_addr(address, - (union sock_addr *)&bindaddr4, NULL); + (union sock_addr *)&bindaddr4, NULL, + AI_PASSIVE); if (err) { syslog(LOG_ERR, "cannot resolve local IPv4 bind address: %s, %s", @@ -650,7 +651,8 @@ int main(int argc, char **argv) if (fd6 >= 0) { bindaddr6.sin6_family = AF_INET6; err = set_sock_addr(address, - (union sock_addr *)&bindaddr6, NULL); + (union sock_addr *)&bindaddr6, NULL, + AI_PASSIVE); if (err) { if (fd4 >= 0) { syslog(LOG_ERR, -- 2.11.0