Tomato 1.28
[tomato.git] / release / src / router / dnsmasq / src / tftp.c
blob1f33eef003a776d6c52b5c2e562e7417a1e4d90b
1 /* dnsmasq is Copyright (c) 2000-2010 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 struct sockaddr_in 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 #if defined(HAVE_LINUX_NETWORK)
68 char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
69 #elif defined(HAVE_SOLARIS_NETWORK)
70 char control[CMSG_SPACE(sizeof(unsigned int))];
71 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
72 char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
73 #endif
74 } control_u;
76 msg.msg_controllen = sizeof(control_u);
77 msg.msg_control = control_u.control;
78 msg.msg_flags = 0;
79 msg.msg_name = &peer;
80 msg.msg_namelen = sizeof(peer);
81 msg.msg_iov = &iov;
82 msg.msg_iovlen = 1;
84 iov.iov_base = packet;
85 iov.iov_len = daemon->packet_buff_sz;
87 /* we overwrote the buffer... */
88 daemon->srv_save = NULL;
90 if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
91 return;
93 if (daemon->options & OPT_NOWILD)
95 addr = listen->iface->addr.in;
96 mtu = listen->iface->mtu;
97 name = listen->iface->name;
99 else
101 struct cmsghdr *cmptr;
102 int check;
103 struct interface_list *ir;
105 addr.sin_addr.s_addr = 0;
107 #if defined(HAVE_LINUX_NETWORK)
108 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
109 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
111 union {
112 unsigned char *c;
113 struct in_pktinfo *p;
114 } p;
115 p.c = CMSG_DATA(cmptr);
116 addr.sin_addr = p.p->ipi_spec_dst;
117 if_index = p.p->ipi_ifindex;
120 #elif defined(HAVE_SOLARIS_NETWORK)
121 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
123 union {
124 unsigned char *c;
125 struct in_addr *a;
126 unsigned int *i;
127 } p;
128 p.c = CMSG_DATA(cmptr);
129 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
130 addr.sin_addr = *(p.a);
131 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
132 if_index = *(p.i);
135 #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
136 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
138 union {
139 unsigned char *c;
140 struct in_addr *a;
141 struct sockaddr_dl *s;
142 } p;
143 p.c = CMSG_DATA(cmptr);
144 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
145 addr.sin_addr = *(p.a);
146 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
147 if_index = p.s->sdl_index;
150 #endif
152 if (!indextoname(listen->tftpfd, if_index, namebuff) ||
153 addr.sin_addr.s_addr == 0)
154 return;
156 name = namebuff;
157 check = iface_check(AF_INET, (struct all_addr *)&addr.sin_addr, name, &if_index);
159 /* wierd TFTP service override */
160 for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
161 if (strcmp(ir->interface, name) == 0)
162 break;
164 if (!ir)
166 if (!daemon->tftp_unlimited || !check)
167 return;
169 #ifdef HAVE_DHCP
170 /* allowed interfaces are the same as for DHCP */
171 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
172 if (tmp->name && (strcmp(tmp->name, name) == 0))
173 return;
174 #endif
177 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
178 if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
179 mtu = ifr.ifr_mtu;
182 /* check for per-interface prefix */
183 for (pref = daemon->if_prefix; pref; pref = pref->next)
184 if (strcmp(pref->interface, name) == 0)
185 prefix = pref->prefix;
187 /* wierd TFTP interfaces disable special options. */
188 for (ir = daemon->tftp_interfaces; ir; ir = ir->next)
189 if (strcmp(ir->interface, name) == 0)
190 special = 1;
192 addr.sin_port = htons(port);
193 addr.sin_family = AF_INET;
194 #ifdef HAVE_SOCKADDR_SA_LEN
195 addr.sin_len = sizeof(addr);
196 #endif
198 if (!(transfer = whine_malloc(sizeof(struct tftp_transfer))))
199 return;
201 if ((transfer->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
203 free(transfer);
204 return;
207 transfer->peer = peer;
208 transfer->timeout = now + 2;
209 transfer->backoff = 1;
210 transfer->block = 1;
211 transfer->blocksize = 512;
212 transfer->offset = 0;
213 transfer->file = NULL;
214 transfer->opt_blocksize = transfer->opt_transize = 0;
215 transfer->netascii = transfer->carrylf = 0;
217 /* if we have a nailed-down range, iterate until we find a free one. */
218 while (1)
220 if (bind(transfer->sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 ||
221 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
222 setsockopt(transfer->sockfd, SOL_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
223 #endif
224 !fix_fd(transfer->sockfd))
226 if (errno == EADDRINUSE && daemon->start_tftp_port != 0)
228 if (++port <= daemon->end_tftp_port)
230 addr.sin_port = htons(port);
231 continue;
233 my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
235 free_transfer(transfer);
236 return;
238 break;
241 p = packet + 2;
242 end = packet + len;
244 if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
245 !(filename = next(&p, end)) ||
246 !(mode = next(&p, end)) ||
247 (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
248 len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), inet_ntoa(peer.sin_addr));
249 else
251 if (strcasecmp(mode, "netascii") == 0)
252 transfer->netascii = 1;
254 while ((opt = next(&p, end)))
256 if (strcasecmp(opt, "blksize") == 0)
258 if ((opt = next(&p, end)) &&
259 (special || !(daemon->options & OPT_TFTP_NOBLOCK)))
261 transfer->blocksize = atoi(opt);
262 if (transfer->blocksize < 1)
263 transfer->blocksize = 1;
264 if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
265 transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
266 /* 32 bytes for IP, UDP and TFTP headers */
267 if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
268 transfer->blocksize = (unsigned)mtu - 32;
269 transfer->opt_blocksize = 1;
270 transfer->block = 0;
273 else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
275 transfer->opt_transize = 1;
276 transfer->block = 0;
280 /* cope with backslashes from windows boxen. */
281 while ((p = strchr(filename, '\\')))
282 *p = '/';
284 strcpy(daemon->namebuff, "/");
285 if (prefix)
287 if (prefix[0] == '/')
288 daemon->namebuff[0] = 0;
289 strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
290 if (prefix[strlen(prefix)-1] != '/')
291 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
293 if (!special && (daemon->options & OPT_TFTP_APREF))
295 size_t oldlen = strlen(daemon->namebuff);
296 struct stat statbuf;
298 strncat(daemon->namebuff, inet_ntoa(peer.sin_addr), (MAXDNAME-1) - strlen(daemon->namebuff));
299 strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
301 /* remove unique-directory if it doesn't exist */
302 if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
303 daemon->namebuff[oldlen] = 0;
306 /* Absolute pathnames OK if they match prefix */
307 if (filename[0] == '/')
309 if (strstr(filename, daemon->namebuff) == filename)
310 daemon->namebuff[0] = 0;
311 else
312 filename++;
315 else if (filename[0] == '/')
316 daemon->namebuff[0] = 0;
317 strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
319 /* check permissions and open file */
320 if ((transfer->file = check_tftp_fileperm(&len, prefix, special)))
322 if ((len = get_block(packet, transfer)) == -1)
323 len = tftp_err_oops(packet, daemon->namebuff);
324 else
325 is_err = 0;
329 while (sendto(transfer->sockfd, packet, len, 0,
330 (struct sockaddr *)&peer, sizeof(peer)) == -1 && errno == EINTR);
332 if (is_err)
333 free_transfer(transfer);
334 else
336 my_syslog(MS_TFTP | LOG_INFO, _("sent %s to %s"), daemon->namebuff, inet_ntoa(peer.sin_addr));
337 transfer->next = daemon->tftp_trans;
338 daemon->tftp_trans = transfer;
342 static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, int special)
344 char *packet = daemon->packet, *namebuff = daemon->namebuff;
345 struct tftp_file *file;
346 struct tftp_transfer *t;
347 uid_t uid = geteuid();
348 struct stat statbuf;
349 int fd = -1;
351 /* trick to ban moving out of the subtree */
352 if (prefix && strstr(namebuff, "/../"))
353 goto perm;
355 if ((fd = open(namebuff, O_RDONLY)) == -1)
357 if (errno == ENOENT)
359 *len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
360 return NULL;
362 else if (errno == EACCES)
363 goto perm;
364 else
365 goto oops;
368 /* stat the file descriptor to avoid stat->open races */
369 if (fstat(fd, &statbuf) == -1)
370 goto oops;
372 /* running as root, must be world-readable */
373 if (uid == 0)
375 if (!(statbuf.st_mode & S_IROTH))
376 goto perm;
378 /* in secure mode, must be owned by user running dnsmasq */
379 else if (!special && (daemon->options & OPT_TFTP_SECURE) && uid != statbuf.st_uid)
380 goto perm;
382 /* If we're doing many tranfers from the same file, only
383 open it once this saves lots of file descriptors
384 when mass-booting a big cluster, for instance.
385 Be conservative and only share when inode and name match
386 this keeps error messages sane. */
387 for (t = daemon->tftp_trans; t; t = t->next)
388 if (t->file->dev == statbuf.st_dev &&
389 t->file->inode == statbuf.st_ino &&
390 strcmp(t->file->filename, namebuff) == 0)
392 close(fd);
393 t->file->refcount++;
394 return t->file;
397 if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
399 errno = ENOMEM;
400 goto oops;
403 file->fd = fd;
404 file->size = statbuf.st_size;
405 file->dev = statbuf.st_dev;
406 file->inode = statbuf.st_ino;
407 file->refcount = 1;
408 strcpy(file->filename, namebuff);
409 return file;
411 perm:
412 errno = EACCES;
413 *len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
414 if (fd != -1)
415 close(fd);
416 return NULL;
418 oops:
419 *len = tftp_err_oops(packet, namebuff);
420 if (fd != -1)
421 close(fd);
422 return NULL;
425 void check_tftp_listeners(fd_set *rset, time_t now)
427 struct tftp_transfer *transfer, *tmp, **up;
428 ssize_t len;
430 struct ack {
431 unsigned short op, block;
432 } *mess = (struct ack *)daemon->packet;
434 /* Check for activity on any existing transfers */
435 for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
437 tmp = transfer->next;
439 if (FD_ISSET(transfer->sockfd, rset))
441 /* we overwrote the buffer... */
442 daemon->srv_save = NULL;
444 if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
446 if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block)
448 /* Got ack, ensure we take the (re)transmit path */
449 transfer->timeout = now;
450 transfer->backoff = 0;
451 if (transfer->block++ != 0)
452 transfer->offset += transfer->blocksize - transfer->expansion;
454 else if (ntohs(mess->op) == OP_ERR)
456 char *p = daemon->packet + sizeof(struct ack);
457 char *end = daemon->packet + len;
458 char *err = next(&p, end);
459 /* Sanitise error message */
460 if (!err)
461 err = "";
462 else
464 char *q, *r;
465 for (q = r = err; *r; r++)
466 if (isprint((int)*r))
467 *(q++) = *r;
468 *q = 0;
470 my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
471 (int)ntohs(mess->block), err,
472 inet_ntoa(transfer->peer.sin_addr));
474 /* Got err, ensure we take abort */
475 transfer->timeout = now;
476 transfer->backoff = 100;
481 if (difftime(now, transfer->timeout) >= 0.0)
483 int endcon = 0;
485 /* timeout, retransmit */
486 transfer->timeout += 1 + (1<<transfer->backoff);
488 /* we overwrote the buffer... */
489 daemon->srv_save = NULL;
491 if ((len = get_block(daemon->packet, transfer)) == -1)
493 len = tftp_err_oops(daemon->packet, transfer->file->filename);
494 endcon = 1;
496 else if (++transfer->backoff > 5)
498 /* don't complain about timeout when we're awaiting the last
499 ACK, some clients never send it */
500 if (len != 0)
501 my_syslog(MS_TFTP | LOG_ERR, _("failed sending %s to %s"),
502 transfer->file->filename, inet_ntoa(transfer->peer.sin_addr));
503 len = 0;
506 if (len != 0)
507 while(sendto(transfer->sockfd, daemon->packet, len, 0,
508 (struct sockaddr *)&transfer->peer, sizeof(transfer->peer)) == -1 && errno == EINTR);
510 if (endcon || len == 0)
512 /* unlink */
513 *up = tmp;
514 free_transfer(transfer);
515 continue;
519 up = &transfer->next;
523 static void free_transfer(struct tftp_transfer *transfer)
525 close(transfer->sockfd);
526 if (transfer->file && (--transfer->file->refcount) == 0)
528 close(transfer->file->fd);
529 free(transfer->file);
531 free(transfer);
534 static char *next(char **p, char *end)
536 char *ret = *p;
537 size_t len;
539 if (*(end-1) != 0 ||
540 *p == end ||
541 (len = strlen(ret)) == 0)
542 return NULL;
544 *p += len + 1;
545 return ret;
548 static ssize_t tftp_err(int err, char *packet, char *message, char *file)
550 struct errmess {
551 unsigned short op, err;
552 char message[];
553 } *mess = (struct errmess *)packet;
554 ssize_t ret = 4;
555 char *errstr = strerror(errno);
557 mess->op = htons(OP_ERR);
558 mess->err = htons(err);
559 ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
560 my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
562 return ret;
565 static ssize_t tftp_err_oops(char *packet, char *file)
567 return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), file);
570 /* return -1 for error, zero for done. */
571 static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
573 if (transfer->block == 0)
575 /* send OACK */
576 char *p;
577 struct oackmess {
578 unsigned short op;
579 char data[];
580 } *mess = (struct oackmess *)packet;
582 p = mess->data;
583 mess->op = htons(OP_OACK);
584 if (transfer->opt_blocksize)
586 p += (sprintf(p, "blksize") + 1);
587 p += (sprintf(p, "%d", transfer->blocksize) + 1);
589 if (transfer->opt_transize)
591 p += (sprintf(p,"tsize") + 1);
592 p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
595 return p - packet;
597 else
599 /* send data packet */
600 struct datamess {
601 unsigned short op, block;
602 unsigned char data[];
603 } *mess = (struct datamess *)packet;
605 size_t size = transfer->file->size - transfer->offset;
607 if (transfer->offset > transfer->file->size)
608 return 0; /* finished */
610 if (size > transfer->blocksize)
611 size = transfer->blocksize;
613 mess->op = htons(OP_DATA);
614 mess->block = htons((unsigned short)(transfer->block));
616 if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
617 !read_write(transfer->file->fd, mess->data, size, 1))
618 return -1;
620 transfer->expansion = 0;
622 /* Map '\n' to CR-LF in netascii mode */
623 if (transfer->netascii)
625 size_t i;
626 int newcarrylf;
628 for (i = 0, newcarrylf = 0; i < size; i++)
629 if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
631 if (size == transfer->blocksize)
633 transfer->expansion++;
634 if (i == size - 1)
635 newcarrylf = 1; /* don't expand LF again if it moves to the next block */
637 else
638 size++; /* room in this block */
640 /* make space and insert CR */
641 memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
642 mess->data[i] = '\r';
644 i++;
646 transfer->carrylf = newcarrylf;
650 return size + 4;
654 #endif