version 1.1, 2013/07/29 19:37:40
|
version 1.1.1.3, 2016/11/02 09:57:01
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley |
|
|
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
Line 49 void tftp_request(struct listener *listen, time_t now)
|
Line 49 void tftp_request(struct listener *listen, time_t now)
|
struct iovec iov; |
struct iovec iov; |
struct ifreq ifr; |
struct ifreq ifr; |
int is_err = 1, if_index = 0, mtu = 0; |
int is_err = 1, if_index = 0, mtu = 0; |
#ifdef HAVE_DHCP |
|
struct iname *tmp; |
struct iname *tmp; |
#endif |
|
struct tftp_transfer *transfer; |
struct tftp_transfer *transfer; |
int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */ |
int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */ |
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) |
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) |
Line 62 void tftp_request(struct listener *listen, time_t now)
|
Line 60 void tftp_request(struct listener *listen, time_t now)
|
char *prefix = daemon->tftp_prefix; |
char *prefix = daemon->tftp_prefix; |
struct tftp_prefix *pref; |
struct tftp_prefix *pref; |
struct all_addr addra; |
struct all_addr addra; |
| #ifdef HAVE_IPV6 |
| /* Can always get recvd interface for IPv6 */ |
| int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6; |
| #else |
| int check_dest = !option_bool(OPT_NOWILD); |
| #endif |
union { |
union { |
struct cmsghdr align; /* this ensures alignment */ |
struct cmsghdr align; /* this ensures alignment */ |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
Line 93 void tftp_request(struct listener *listen, time_t now)
|
Line 96 void tftp_request(struct listener *listen, time_t now)
|
|
|
if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2) |
if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2) |
return; |
return; |
| |
if (option_bool(OPT_NOWILD)) | /* Can always get recvd interface for IPv6 */ |
| if (!check_dest) |
{ |
{ |
if (listen->iface) |
if (listen->iface) |
{ |
{ |
addr = listen->iface->addr; |
addr = listen->iface->addr; |
mtu = listen->iface->mtu; |
|
name = listen->iface->name; |
name = listen->iface->name; |
|
mtu = listen->iface->mtu; |
|
if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu) |
|
mtu = daemon->tftp_mtu; |
} |
} |
else |
else |
{ |
{ |
Line 198 void tftp_request(struct listener *listen, time_t now)
|
Line 204 void tftp_request(struct listener *listen, time_t now)
|
addra.addr.addr6 = addr.in6.sin6_addr; |
addra.addr.addr6 = addr.in6.sin6_addr; |
#endif |
#endif |
|
|
if (!iface_check(listen->family, &addra, name, NULL)) | if (daemon->tftp_interfaces) |
{ |
{ |
if (!option_bool(OPT_CLEVERBIND)) | /* dedicated tftp interface list */ |
enumerate_interfaces(); | for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next) |
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name)) | if (tmp->name && wildcard_match(tmp->name, name)) |
| break; |
| |
| if (!tmp) |
return; |
return; |
} |
} |
| else |
| { |
| /* Do the same as DHCP */ |
| if (!iface_check(listen->family, &addra, name, NULL)) |
| { |
| if (!option_bool(OPT_CLEVERBIND)) |
| enumerate_interfaces(0); |
| if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) && |
| !label_exception(if_index, listen->family, &addra) ) |
| return; |
| } |
| |
#ifdef HAVE_DHCP |
#ifdef HAVE_DHCP |
/* allowed interfaces are the same as for DHCP */ | /* allowed interfaces are the same as for DHCP */ |
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) | for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) |
if (tmp->name && wildcard_match(tmp->name, name)) | if (tmp->name && wildcard_match(tmp->name, name)) |
return; | return; |
#endif |
#endif |
| } |
| |
strncpy(ifr.ifr_name, name, IF_NAMESIZE); |
strncpy(ifr.ifr_name, name, IF_NAMESIZE); |
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1) |
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1) |
mtu = ifr.ifr_mtu; | { |
| mtu = ifr.ifr_mtu; |
| if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu) |
| mtu = daemon->tftp_mtu; |
| } |
} |
} |
| |
| /* Failed to get interface mtu - can use configured value. */ |
| if (mtu == 0) |
| mtu = daemon->tftp_mtu; |
| |
if (name) |
if (name) |
{ |
{ |
/* check for per-interface prefix */ |
/* check for per-interface prefix */ |
Line 317 void tftp_request(struct listener *listen, time_t now)
|
Line 346 void tftp_request(struct listener *listen, time_t now)
|
{ |
{ |
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK)) |
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK)) |
{ |
{ |
|
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */ |
|
int overhead = (listen->family == AF_INET) ? 32 : 52; |
transfer->blocksize = atoi(opt); |
transfer->blocksize = atoi(opt); |
if (transfer->blocksize < 1) |
if (transfer->blocksize < 1) |
transfer->blocksize = 1; |
transfer->blocksize = 1; |
if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4) |
if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4) |
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4; |
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4; |
/* 32 bytes for IP, UDP and TFTP headers */ | if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead) |
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32) | transfer->blocksize = (unsigned)mtu - overhead; |
transfer->blocksize = (unsigned)mtu - 32; | |
transfer->opt_blocksize = 1; |
transfer->opt_blocksize = 1; |
transfer->block = 0; |
transfer->block = 0; |
} |
} |
Line 483 static struct tftp_file *check_tftp_fileperm(ssize_t *
|
Line 513 static struct tftp_file *check_tftp_fileperm(ssize_t *
|
return NULL; |
return NULL; |
} |
} |
|
|
void check_tftp_listeners(fd_set *rset, time_t now) | void check_tftp_listeners(time_t now) |
{ |
{ |
struct tftp_transfer *transfer, *tmp, **up; |
struct tftp_transfer *transfer, *tmp, **up; |
ssize_t len; |
ssize_t len; |
Line 499 void check_tftp_listeners(fd_set *rset, time_t now)
|
Line 529 void check_tftp_listeners(fd_set *rset, time_t now)
|
|
|
prettyprint_addr(&transfer->peer, daemon->addrbuff); |
prettyprint_addr(&transfer->peer, daemon->addrbuff); |
|
|
if (FD_ISSET(transfer->sockfd, rset)) | if (poll_check(transfer->sockfd, POLLIN)) |
{ |
{ |
/* we overwrote the buffer... */ |
/* we overwrote the buffer... */ |
daemon->srv_save = NULL; |
daemon->srv_save = NULL; |
Line 554 void check_tftp_listeners(fd_set *rset, time_t now)
|
Line 584 void check_tftp_listeners(fd_set *rset, time_t now)
|
} |
} |
/* don't complain about timeout when we're awaiting the last |
/* don't complain about timeout when we're awaiting the last |
ACK, some clients never send it */ |
ACK, some clients never send it */ |
else if (++transfer->backoff > 5 && len != 0) | else if (++transfer->backoff > 7 && len != 0) |
{ |
{ |
endcon = 1; |
endcon = 1; |
len = 0; |
len = 0; |