Dnsmasq: 2.60 update
[tomato.git] / release / src / router / dnsmasq / src / tftp.c
blob569adf92513e7c47ceef2d5e6559b2b687658f5a
1 /* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "dnsmasq.h"
19 #ifdef HAVE_TFTP
21 static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special);
22 static void free_transfer(struct tftp_transfer *transfer);
23 static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
24 static ssize_t tftp_err_oops(char *packet, char *file);
25 static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
26 static char *next(char **p, char *end);
28 #define OP_RRQ 1
29 #define OP_WRQ 2
30 #define OP_DATA 3
31 #define OP_ACK 4
32 #define OP_ERR 5
33 #define OP_OACK 6
35 #define ERR_NOTDEF 0
36 #define ERR_FNF 1
37 #define ERR_PERM 2
38 #define ERR_FULL 3
39 #define ERR_ILL 4
41 void tftp_request(struct listener *listen, time_t now)
43 ssize_t len;
44 char *packet = daemon->packet;
45 char *filename, *mode, *p, *end, *opt;
46 union mysockaddr addr, peer;
47 struct msghdr msg;
48 struct iovec iov;
49 struct ifreq ifr;
50 int is_err = 1, if_index = 0, mtu = 0, special = 0;
51 #ifdef HAVE_DHCP
52 struct iname *tmp;
53 #endif
54 struct tftp_transfer *transfer;
55 int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
56 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
57 int mtuflag = IP_PMTUDISC_DONT;
58 #endif
59 char namebuff[IF_NAMESIZE];
60 char *name;
61 char *prefix = daemon->tftp_prefix;
62 struct tftp_prefix *pref;
63 struct interface_list *ir;
65 union {
66 struct cmsghdr align; /* this ensures alignment */
67 #ifdef HAVE_IPV6
68 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
69 #endif
70 #if defined(HAVE_LINUX_NETWORK)
71 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
72 #elif defined(HAVE_SOLARIS_NETWORK)
73 char control[CMSG_SPACE(sizeof(unsigned int))];
74 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
75 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
76 #endif
77 } control_u;
79 msg.msg_controllen = sizeof(control_u);
80 msg.msg_control = control_u.control;
81 msg.msg_flags = 0;
82 msg.msg_name = &peer;
83 msg.msg_namelen = sizeof(peer);
84 msg.msg_iov = &iov;
85 msg.msg_iovlen = 1;
87 iov.iov_base = packet;
88 iov.iov_len = daemon->packet_buff_sz;
90 /* we overwrote the buffer... */
91 daemon->srv_save = NULL;
93 if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
94 return;
96 if (option_bool(OPT_NOWILD))
98 addr = listen->iface->addr;
99 mtu = listen->iface->mtu;
100 name = listen->iface->name;
102 else
104 struct cmsghdr *cmptr;
105 int check;
106 struct interface_list *ir;
108 if (msg.msg_controllen < sizeof(struct cmsghdr))
109 return;
111 addr.sa.sa_family = listen->family;
113 #if defined(HAVE_LINUX_NETWORK)
114 if (listen->family == AF_INET)
115 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
116 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
118 union {
119 unsigned char *c;
120 struct in_pktinfo *p;
121 } p;
122 p.c = CMSG_DATA(cmptr);
123 addr.in.sin_addr = p.p->ipi_spec_dst;
124 if_index = p.p->ipi_ifindex;
127 #elif defined(HAVE_SOLARIS_NETWORK)
128 if (listen->family == AF_INET)
129 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
131 union {
132 unsigned char *c;
133 struct in_addr *a;
134 unsigned int *i;
135 } p;
136 p.c = CMSG_DATA(cmptr);
137 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
138 addr.in.sin_addr = *(p.a);
139 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
140 if_index = *(p.i);
143 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
144 if (listen->family == AF_INET)
145 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
147 union {
148 unsigned char *c;
149 struct in_addr *a;
150 struct sockaddr_dl *s;
151 } p;
152 p.c = CMSG_DATA(cmptr);
153 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
154 addr.in.sin_addr = *(p.a);
155 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
156 if_index = p.s->sdl_index;
159 #endif
161 #ifdef HAVE_IPV6
162 if (listen->family == AF_INET6)
164 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
165 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
167 union {
168 unsigned char *c;
169 struct in6_pktinfo *p;
170 } p;
171 p.c = CMSG_DATA(cmptr);
173 addr.in6.sin6_addr = p.p->ipi6_addr;
174 if_index = p.p->ipi6_ifindex;
177 #endif
179 if (!indextoname(listen->tftpfd, if_index, namebuff))
180 return;
182 name = namebuff;
184 #ifdef HAVE_IPV6
185 if (listen->family == AF_INET6)
186 check = iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name);
187 else
188 #endif
189 check = iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name);
191 /* wierd TFTP service override */
192 for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
193 if (strcmp(ir->interface, name) == 0)
194 break;
196 if (!ir)
198 if (!daemon->tftp_unlimited || !check)
199 return;
201 #ifdef HAVE_DHCP
202 /* allowed interfaces are the same as for DHCP */
203 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
204 if (tmp->name && (strcmp(tmp->name, name) == 0))
205 return;
206 #endif
209 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
210 if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
211 mtu = ifr.ifr_mtu;
214 /* check for per-interface prefix */
215 for (pref = daemon->if_prefix; pref; pref = pref->next)
216 if (strcmp(pref->interface, name) == 0)
217 prefix = pref->prefix;
219 /* wierd TFTP interfaces disable special options. */
220 for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
221 if (strcmp(ir->interface, name) == 0)
222 special = 1;
224 if (listen->family == AF_INET)
226 addr.in.sin_port = htons(port);
227 #ifdef HAVE_SOCKADDR_SA_LEN
228 addr.in.sin_len = sizeof(addr.in);
229 #endif
231 #ifdef HAVE_IPV6
232 else
234 addr.in6.sin6_port = htons(port);
235 addr.in6.sin6_flowinfo = 0;
236 addr.in6.sin6_scope_id = 0;
237 #ifdef HAVE_SOCKADDR_SA_LEN
238 addr.in6.sin6_len = sizeof(addr.in6);
239 #endif
241 #endif
243 if (!(transfer = whine_malloc(sizeof(struct tftp_transfer))))
244 return;
246 if ((transfer->sockfd = socket(listen->family, SOCK_DGRAM, 0)) == -1)
248 free(transfer);
249 return;
252 transfer->peer = peer;
253 transfer->timeout = now + 2;
254 transfer->backoff = 1;
255 transfer->block = 1;
256 transfer->blocksize = 512;
257 transfer->offset = 0;
258 transfer->file = NULL;
259 transfer->opt_blocksize = transfer->opt_transize = 0;
260 transfer->netascii = transfer->carrylf = 0;
262 prettyprint_addr(&peer, daemon->addrbuff);
264 /* if we have a nailed-down range, iterate until we find a free one. */
265 while (1)
267 if (bind(transfer->sockfd, &addr.sa, sa_len(&addr)) == -1 ||
268 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
269 setsockopt(transfer->sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
270 #endif
271 !fix_fd(transfer->sockfd))
273 if (errno == EADDRINUSE && daemon->start_tftp_port != 0)
275 if (++port <= daemon->end_tftp_port)
277 if (listen->family == AF_INET)
278 addr.in.sin_port = htons(port);
279 #ifdef HAVE_IPV6
280 else
281 addr.in6.sin6_port = htons(port);
282 #endif
283 continue;
285 my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
287 free_transfer(transfer);
288 return;
290 break;
293 p = packet + 2;
294 end = packet + len;
296 if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
297 !(filename = next(&p, end)) ||
298 !(mode = next(&p, end)) ||
299 (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
300 len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff);
301 else
303 if (strcasecmp(mode, "netascii") == 0)
304 transfer->netascii = 1;
306 while ((opt = next(&p, end)))
308 if (strcasecmp(opt, "blksize") == 0)
310 if ((opt = next(&p, end)) &&
311 (special || !option_bool(OPT_TFTP_NOBLOCK)))
313 transfer->blocksize = atoi(opt);
314 if (transfer->blocksize < 1)
315 transfer->blocksize = 1;
316 if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
317 transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
318 /* 32 bytes for IP, UDP and TFTP headers */
319 if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
320 transfer->blocksize = (unsigned)mtu - 32;
321 transfer->opt_blocksize = 1;
322 transfer->block = 0;
325 else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
327 transfer->opt_transize = 1;
328 transfer->block = 0;
332 /* cope with backslashes from windows boxen. */
333 while ((p = strchr(filename, '\\')))
334 *p = '/';
336 strcpy(daemon->namebuff, "/");
337 if (prefix)
339 if (prefix[0] == '/')
340 daemon->namebuff[0] = 0;
341 strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
342 if (prefix[strlen(prefix)-1] != '/')
343 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
345 if (!special && option_bool(OPT_TFTP_APREF))
347 size_t oldlen = strlen(daemon->namebuff);
348 struct stat statbuf;
350 strncat(daemon->namebuff, daemon->addrbuff, (MAXDNAME-1) - strlen(daemon->namebuff));
351 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
353 /* remove unique-directory if it doesn't exist */
354 if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
355 daemon->namebuff[oldlen] = 0;
358 /* Absolute pathnames OK if they match prefix */
359 if (filename[0] == '/')
361 if (strstr(filename, daemon->namebuff) == filename)
362 daemon->namebuff[0] = 0;
363 else
364 filename++;
367 else if (filename[0] == '/')
368 daemon->namebuff[0] = 0;
369 strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
371 /* check permissions and open file */
372 if ((transfer->file = check_tftp_fileperm(&len, prefix, special)))
374 if ((len = get_block(packet, transfer)) == -1)
375 len = tftp_err_oops(packet, daemon->namebuff);
376 else
377 is_err = 0;
381 while (sendto(transfer->sockfd, packet, len, 0,
382 (struct sockaddr *)&peer, sizeof(peer)) == -1 && errno == EINTR);
384 if (is_err)
385 free_transfer(transfer);
386 else
388 transfer->next = daemon->tftp_trans;
389 daemon->tftp_trans = transfer;
393 static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special)
395 char *packet = daemon->packet, *namebuff = daemon->namebuff;
396 struct tftp_file *file;
397 struct tftp_transfer *t;
398 uid_t uid = geteuid();
399 struct stat statbuf;
400 int fd = -1;
402 /* trick to ban moving out of the subtree */
403 if (prefix && strstr(namebuff, "/../"))
404 goto perm;
406 if ((fd = open(namebuff, O_RDONLY)) == -1)
408 if (errno == ENOENT)
410 *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
411 return NULL;
413 else if (errno == EACCES)
414 goto perm;
415 else
416 goto oops;
419 /* stat the file descriptor to avoid stat->open races */
420 if (fstat(fd, &statbuf) == -1)
421 goto oops;
423 /* running as root, must be world-readable */
424 if (uid == 0)
426 if (!(statbuf.st_mode & S_IROTH))
427 goto perm;
429 /* in secure mode, must be owned by user running dnsmasq */
430 else if (!special && option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
431 goto perm;
433 /* If we're doing many tranfers from the same file, only
434 open it once this saves lots of file descriptors
435 when mass-booting a big cluster, for instance.
436 Be conservative and only share when inode and name match
437 this keeps error messages sane. */
438 for (t = daemon->tftp_trans; t; t = t->next)
439 if (t->file->dev == statbuf.st_dev &&
440 t->file->inode == statbuf.st_ino &&
441 strcmp(t->file->filename, namebuff) == 0)
443 close(fd);
444 t->file->refcount++;
445 return t->file;
448 if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
450 errno = ENOMEM;
451 goto oops;
454 file->fd = fd;
455 file->size = statbuf.st_size;
456 file->dev = statbuf.st_dev;
457 file->inode = statbuf.st_ino;
458 file->refcount = 1;
459 strcpy(file->filename, namebuff);
460 return file;
462 perm:
463 errno = EACCES;
464 *len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
465 if (fd != -1)
466 close(fd);
467 return NULL;
469 oops:
470 *len = tftp_err_oops(packet, namebuff);
471 if (fd != -1)
472 close(fd);
473 return NULL;
476 void check_tftp_listeners(fd_set *rset, time_t now)
478 struct tftp_transfer *transfer, *tmp, **up;
479 ssize_t len;
481 struct ack {
482 unsigned short op, block;
483 } *mess = (struct ack *)daemon->packet;
485 /* Check for activity on any existing transfers */
486 for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
488 tmp = transfer->next;
490 if (FD_ISSET(transfer->sockfd, rset))
492 /* we overwrote the buffer... */
493 daemon->srv_save = NULL;
495 prettyprint_addr(&transfer->peer, daemon->addrbuff);
497 if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
499 if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block)
501 /* Got ack, ensure we take the (re)transmit path */
502 transfer->timeout = now;
503 transfer->backoff = 0;
504 if (transfer->block++ != 0)
505 transfer->offset += transfer->blocksize - transfer->expansion;
507 else if (ntohs(mess->op) == OP_ERR)
509 char *p = daemon->packet + sizeof(struct ack);
510 char *end = daemon->packet + len;
511 char *err = next(&p, end);
513 /* Sanitise error message */
514 if (!err)
515 err = "";
516 else
518 unsigned char *q, *r;
519 for (q = r = (unsigned char *)err; *r; r++)
520 if (isprint(*r))
521 *(q++) = *r;
522 *q = 0;
525 my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
526 (int)ntohs(mess->block), err,
527 daemon->addrbuff);
529 /* Got err, ensure we take abort */
530 transfer->timeout = now;
531 transfer->backoff = 100;
536 if (difftime(now, transfer->timeout) >= 0.0)
538 int endcon = 0;
540 /* timeout, retransmit */
541 transfer->timeout += 1 + (1<<transfer->backoff);
543 /* we overwrote the buffer... */
544 daemon->srv_save = NULL;
546 if ((len = get_block(daemon->packet, transfer)) == -1)
548 len = tftp_err_oops(daemon->packet, transfer->file->filename);
549 endcon = 1;
551 else if (++transfer->backoff > 5)
553 /* don't complain about timeout when we're awaiting the last
554 ACK, some clients never send it */
555 if (len != 0)
557 my_syslog(MS_TFTP | LOG_ERR, _("failed sending %s to %s"),
558 transfer->file->filename, daemon->addrbuff);
559 len = 0;
560 endcon = 1;
564 if (len != 0)
565 while(sendto(transfer->sockfd, daemon->packet, len, 0,
566 (struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR);
568 if (endcon || len == 0)
570 if (!endcon)
571 my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), transfer->file->filename, daemon->addrbuff);
572 /* unlink */
573 *up = tmp;
574 free_transfer(transfer);
575 continue;
579 up = &transfer->next;
583 static void free_transfer(struct tftp_transfer *transfer)
585 close(transfer->sockfd);
586 if (transfer->file && (--transfer->file->refcount) == 0)
588 close(transfer->file->fd);
589 free(transfer->file);
591 free(transfer);
594 static char *next(char **p, char *end)
596 char *ret = *p;
597 size_t len;
599 if (*(end-1) != 0 ||
600 *p == end ||
601 (len = strlen(ret)) == 0)
602 return NULL;
604 *p += len + 1;
605 return ret;
608 static ssize_t tftp_err(int err, char *packet, char *message, char *file)
610 struct errmess {
611 unsigned short op, err;
612 char message[];
613 } *mess = (struct errmess *)packet;
614 ssize_t ret = 4;
615 char *errstr = strerror(errno);
617 mess->op = htons(OP_ERR);
618 mess->err = htons(err);
619 ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
620 my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
622 return ret;
625 static ssize_t tftp_err_oops(char *packet, char *file)
627 return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file);
630 /* return -1 for error, zero for done. */
631 static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
633 if (transfer->block == 0)
635 /* send OACK */
636 char *p;
637 struct oackmess {
638 unsigned short op;
639 char data[];
640 } *mess = (struct oackmess *)packet;
642 p = mess->data;
643 mess->op = htons(OP_OACK);
644 if (transfer->opt_blocksize)
646 p += (sprintf(p, "blksize") + 1);
647 p += (sprintf(p, "%d", transfer->blocksize) + 1);
649 if (transfer->opt_transize)
651 p += (sprintf(p,"tsize") + 1);
652 p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
655 return p - packet;
657 else
659 /* send data packet */
660 struct datamess {
661 unsigned short op, block;
662 unsigned char data[];
663 } *mess = (struct datamess *)packet;
665 size_t size = transfer->file->size - transfer->offset;
667 if (transfer->offset > transfer->file->size)
668 return 0; /* finished */
670 if (size > transfer->blocksize)
671 size = transfer->blocksize;
673 mess->op = htons(OP_DATA);
674 mess->block = htons((unsigned short)(transfer->block));
676 if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
677 !read_write(transfer->file->fd, mess->data, size, 1))
678 return -1;
680 transfer->expansion = 0;
682 /* Map '\n' to CR-LF in netascii mode */
683 if (transfer->netascii)
685 size_t i;
686 int newcarrylf;
688 for (i = 0, newcarrylf = 0; i < size; i++)
689 if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
691 transfer->expansion++;
693 if (size != transfer->blocksize)
694 size++; /* room in this block */
695 else if (i == size - 1)
696 newcarrylf = 1; /* don't expand LF again if it moves to the next block */
698 /* make space and insert CR */
699 memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
700 mess->data[i] = '\r';
702 i++;
704 transfer->carrylf = newcarrylf;
708 return size + 4;
712 #endif