Annotation of embedaddon/dnsmasq/src/tftp.c, revision 1.1.1.5
1.1.1.5 ! misho 1: /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
1.1 misho 2:
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.
7:
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.
12:
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/>.
15: */
16:
17: #include "dnsmasq.h"
18:
19: #ifdef HAVE_TFTP
20:
1.1.1.4 misho 21: static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len);
1.1.1.5 ! misho 22: static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, char *client);
1.1 misho 23: static void free_transfer(struct tftp_transfer *transfer);
1.1.1.5 ! misho 24: static ssize_t tftp_err(int err, char *packet, char *message, char *file, char *arg2);
! 25: static ssize_t tftp_err_oops(char *packet, const char *file);
1.1 misho 26: static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
27: static char *next(char **p, char *end);
28: static void sanitise(char *buf);
29:
30: #define OP_RRQ 1
31: #define OP_WRQ 2
32: #define OP_DATA 3
33: #define OP_ACK 4
34: #define OP_ERR 5
35: #define OP_OACK 6
36:
37: #define ERR_NOTDEF 0
38: #define ERR_FNF 1
39: #define ERR_PERM 2
40: #define ERR_FULL 3
41: #define ERR_ILL 4
1.1.1.5 ! misho 42: #define ERR_TID 5
1.1 misho 43:
44: void tftp_request(struct listener *listen, time_t now)
45: {
46: ssize_t len;
47: char *packet = daemon->packet;
48: char *filename, *mode, *p, *end, *opt;
49: union mysockaddr addr, peer;
50: struct msghdr msg;
51: struct iovec iov;
52: struct ifreq ifr;
53: int is_err = 1, if_index = 0, mtu = 0;
54: struct iname *tmp;
1.1.1.4 misho 55: struct tftp_transfer *transfer = NULL, **up;
1.1 misho 56: int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
57: #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
58: int mtuflag = IP_PMTUDISC_DONT;
59: #endif
60: char namebuff[IF_NAMESIZE];
61: char *name = NULL;
62: char *prefix = daemon->tftp_prefix;
63: struct tftp_prefix *pref;
1.1.1.4 misho 64: union all_addr addra;
65: int family = listen->addr.sa.sa_family;
1.1.1.2 misho 66: /* Can always get recvd interface for IPv6 */
1.1.1.4 misho 67: int check_dest = !option_bool(OPT_NOWILD) || family == AF_INET6;
1.1 misho 68: union {
69: struct cmsghdr align; /* this ensures alignment */
70: char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
71: #if defined(HAVE_LINUX_NETWORK)
72: char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
73: #elif defined(HAVE_SOLARIS_NETWORK)
1.1.1.4 misho 74: char control[CMSG_SPACE(sizeof(struct in_addr)) +
75: CMSG_SPACE(sizeof(unsigned int))];
1.1 misho 76: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
1.1.1.4 misho 77: char control[CMSG_SPACE(sizeof(struct in_addr)) +
78: CMSG_SPACE(sizeof(struct sockaddr_dl))];
1.1 misho 79: #endif
80: } control_u;
81:
82: msg.msg_controllen = sizeof(control_u);
83: msg.msg_control = control_u.control;
84: msg.msg_flags = 0;
85: msg.msg_name = &peer;
86: msg.msg_namelen = sizeof(peer);
87: msg.msg_iov = &iov;
88: msg.msg_iovlen = 1;
89:
90: iov.iov_base = packet;
91: iov.iov_len = daemon->packet_buff_sz;
92:
93: /* we overwrote the buffer... */
94: daemon->srv_save = NULL;
95:
96: if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
97: return;
1.1.1.2 misho 98:
1.1.1.5 ! misho 99: #ifdef HAVE_DUMPFILE
! 100: dump_packet_udp(DUMP_TFTP, (void *)packet, len, (union mysockaddr *)&peer, NULL, listen->tftpfd);
! 101: #endif
! 102:
1.1.1.2 misho 103: /* Can always get recvd interface for IPv6 */
104: if (!check_dest)
1.1 misho 105: {
106: if (listen->iface)
107: {
108: addr = listen->iface->addr;
109: name = listen->iface->name;
1.1.1.3 misho 110: mtu = listen->iface->mtu;
111: if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
112: mtu = daemon->tftp_mtu;
1.1 misho 113: }
114: else
115: {
116: /* we're listening on an address that doesn't appear on an interface,
117: ask the kernel what the socket is bound to */
118: socklen_t tcp_len = sizeof(union mysockaddr);
119: if (getsockname(listen->tftpfd, (struct sockaddr *)&addr, &tcp_len) == -1)
120: return;
121: }
122: }
123: else
124: {
125: struct cmsghdr *cmptr;
126:
127: if (msg.msg_controllen < sizeof(struct cmsghdr))
128: return;
129:
1.1.1.4 misho 130: addr.sa.sa_family = family;
1.1 misho 131:
132: #if defined(HAVE_LINUX_NETWORK)
1.1.1.4 misho 133: if (family == AF_INET)
1.1 misho 134: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
135: if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
136: {
137: union {
138: unsigned char *c;
139: struct in_pktinfo *p;
140: } p;
141: p.c = CMSG_DATA(cmptr);
142: addr.in.sin_addr = p.p->ipi_spec_dst;
143: if_index = p.p->ipi_ifindex;
144: }
145:
146: #elif defined(HAVE_SOLARIS_NETWORK)
1.1.1.4 misho 147: if (family == AF_INET)
1.1 misho 148: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
149: {
150: union {
151: unsigned char *c;
152: struct in_addr *a;
153: unsigned int *i;
154: } p;
155: p.c = CMSG_DATA(cmptr);
156: if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
157: addr.in.sin_addr = *(p.a);
158: else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
159: if_index = *(p.i);
160: }
161:
162: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
1.1.1.4 misho 163: if (family == AF_INET)
1.1 misho 164: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
165: {
166: union {
167: unsigned char *c;
168: struct in_addr *a;
169: struct sockaddr_dl *s;
170: } p;
171: p.c = CMSG_DATA(cmptr);
172: if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
173: addr.in.sin_addr = *(p.a);
174: else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
175: if_index = p.s->sdl_index;
176: }
177:
178: #endif
179:
1.1.1.4 misho 180: if (family == AF_INET6)
1.1 misho 181: {
182: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
183: if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
184: {
185: union {
186: unsigned char *c;
187: struct in6_pktinfo *p;
188: } p;
189: p.c = CMSG_DATA(cmptr);
190:
191: addr.in6.sin6_addr = p.p->ipi6_addr;
192: if_index = p.p->ipi6_ifindex;
193: }
194: }
195:
196: if (!indextoname(listen->tftpfd, if_index, namebuff))
197: return;
198:
199: name = namebuff;
200:
1.1.1.4 misho 201: addra.addr4 = addr.in.sin_addr;
1.1 misho 202:
1.1.1.4 misho 203: if (family == AF_INET6)
204: addra.addr6 = addr.in6.sin6_addr;
1.1 misho 205:
1.1.1.2 misho 206: if (daemon->tftp_interfaces)
1.1 misho 207: {
1.1.1.2 misho 208: /* dedicated tftp interface list */
209: for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
210: if (tmp->name && wildcard_match(tmp->name, name))
211: break;
212:
213: if (!tmp)
1.1 misho 214: return;
215: }
1.1.1.2 misho 216: else
217: {
218: /* Do the same as DHCP */
1.1.1.4 misho 219: if (!iface_check(family, &addra, name, NULL))
1.1.1.2 misho 220: {
221: if (!option_bool(OPT_CLEVERBIND))
222: enumerate_interfaces(0);
1.1.1.4 misho 223: if (!loopback_exception(listen->tftpfd, family, &addra, name) &&
224: !label_exception(if_index, family, &addra))
1.1.1.2 misho 225: return;
226: }
227:
1.1 misho 228: #ifdef HAVE_DHCP
1.1.1.2 misho 229: /* allowed interfaces are the same as for DHCP */
230: for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
231: if (tmp->name && wildcard_match(tmp->name, name))
232: return;
1.1 misho 233: #endif
1.1.1.2 misho 234: }
235:
1.1.1.4 misho 236: safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
1.1 misho 237: if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
1.1.1.3 misho 238: {
239: mtu = ifr.ifr_mtu;
240: if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
241: mtu = daemon->tftp_mtu;
242: }
1.1 misho 243: }
1.1.1.3 misho 244:
245: /* Failed to get interface mtu - can use configured value. */
246: if (mtu == 0)
247: mtu = daemon->tftp_mtu;
248:
1.1.1.4 misho 249: /* data transfer via server listening socket */
250: if (option_bool(OPT_SINGLE_PORT))
251: {
252: int tftp_cnt;
253:
254: for (tftp_cnt = 0, transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; up = &transfer->next, transfer = transfer->next)
255: {
256: tftp_cnt++;
257:
258: if (sockaddr_isequal(&peer, &transfer->peer))
259: {
260: if (ntohs(*((unsigned short *)packet)) == OP_RRQ)
261: {
262: /* Handle repeated RRQ or abandoned transfer from same host and port
263: by unlinking and reusing the struct transfer. */
264: *up = transfer->next;
265: break;
266: }
267: else
268: {
269: handle_tftp(now, transfer, len);
270: return;
271: }
272: }
273: }
274:
275: /* Enforce simultaneous transfer limit. In non-single-port mode
276: this is doene by not listening on the server socket when
277: too many transfers are in progress. */
278: if (!transfer && tftp_cnt >= daemon->tftp_max)
279: return;
280: }
281:
1.1 misho 282: if (name)
283: {
284: /* check for per-interface prefix */
285: for (pref = daemon->if_prefix; pref; pref = pref->next)
286: if (strcmp(pref->interface, name) == 0)
287: prefix = pref->prefix;
288: }
289:
1.1.1.4 misho 290: if (family == AF_INET)
1.1 misho 291: {
292: addr.in.sin_port = htons(port);
293: #ifdef HAVE_SOCKADDR_SA_LEN
294: addr.in.sin_len = sizeof(addr.in);
295: #endif
296: }
297: else
298: {
299: addr.in6.sin6_port = htons(port);
300: addr.in6.sin6_flowinfo = 0;
301: addr.in6.sin6_scope_id = 0;
302: #ifdef HAVE_SOCKADDR_SA_LEN
303: addr.in6.sin6_len = sizeof(addr.in6);
304: #endif
305: }
306:
1.1.1.4 misho 307: /* May reuse struct transfer from abandoned transfer in single port mode. */
308: if (!transfer && !(transfer = whine_malloc(sizeof(struct tftp_transfer))))
1.1 misho 309: return;
310:
1.1.1.4 misho 311: if (option_bool(OPT_SINGLE_PORT))
312: transfer->sockfd = listen->tftpfd;
313: else if ((transfer->sockfd = socket(family, SOCK_DGRAM, 0)) == -1)
1.1 misho 314: {
315: free(transfer);
316: return;
317: }
318:
319: transfer->peer = peer;
1.1.1.4 misho 320: transfer->source = addra;
321: transfer->if_index = if_index;
1.1 misho 322: transfer->timeout = now + 2;
323: transfer->backoff = 1;
324: transfer->block = 1;
325: transfer->blocksize = 512;
326: transfer->offset = 0;
327: transfer->file = NULL;
328: transfer->opt_blocksize = transfer->opt_transize = 0;
329: transfer->netascii = transfer->carrylf = 0;
330:
1.1.1.4 misho 331: (void)prettyprint_addr(&peer, daemon->addrbuff);
1.1 misho 332:
333: /* if we have a nailed-down range, iterate until we find a free one. */
1.1.1.4 misho 334: while (!option_bool(OPT_SINGLE_PORT))
1.1 misho 335: {
336: if (bind(transfer->sockfd, &addr.sa, sa_len(&addr)) == -1 ||
337: #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
338: setsockopt(transfer->sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &mtuflag, sizeof(mtuflag)) == -1 ||
339: #endif
340: !fix_fd(transfer->sockfd))
341: {
342: if (errno == EADDRINUSE && daemon->start_tftp_port != 0)
343: {
344: if (++port <= daemon->end_tftp_port)
345: {
1.1.1.4 misho 346: if (family == AF_INET)
1.1 misho 347: addr.in.sin_port = htons(port);
348: else
1.1.1.4 misho 349: addr.in6.sin6_port = htons(port);
350:
1.1 misho 351: continue;
352: }
353: my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
354: }
355: free_transfer(transfer);
356: return;
357: }
358: break;
359: }
360:
361: p = packet + 2;
362: end = packet + len;
1.1.1.4 misho 363:
1.1 misho 364: if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
365: !(filename = next(&p, end)) ||
366: !(mode = next(&p, end)) ||
367: (strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
368: {
1.1.1.5 ! misho 369: len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff, NULL);
1.1 misho 370: is_err = 1;
371: }
372: else
373: {
374: if (strcasecmp(mode, "netascii") == 0)
375: transfer->netascii = 1;
376:
377: while ((opt = next(&p, end)))
378: {
379: if (strcasecmp(opt, "blksize") == 0)
380: {
381: if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
382: {
1.1.1.3 misho 383: /* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
1.1.1.4 misho 384: int overhead = (family == AF_INET) ? 32 : 52;
1.1 misho 385: transfer->blocksize = atoi(opt);
386: if (transfer->blocksize < 1)
387: transfer->blocksize = 1;
388: if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
389: transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
1.1.1.3 misho 390: if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead)
391: transfer->blocksize = (unsigned)mtu - overhead;
1.1 misho 392: transfer->opt_blocksize = 1;
393: transfer->block = 0;
394: }
395: }
396: else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
397: {
398: transfer->opt_transize = 1;
399: transfer->block = 0;
400: }
401: }
402:
403: /* cope with backslashes from windows boxen. */
404: for (p = filename; *p; p++)
405: if (*p == '\\')
406: *p = '/';
407: else if (option_bool(OPT_TFTP_LC))
1.1.1.5 ! misho 408: *p = tolower((unsigned char)*p);
1.1 misho 409:
410: strcpy(daemon->namebuff, "/");
411: if (prefix)
412: {
413: if (prefix[0] == '/')
414: daemon->namebuff[0] = 0;
415: strncat(daemon->namebuff, prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
416: if (prefix[strlen(prefix)-1] != '/')
417: strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
418:
1.1.1.4 misho 419: if (option_bool(OPT_TFTP_APREF_IP))
1.1 misho 420: {
421: size_t oldlen = strlen(daemon->namebuff);
422: struct stat statbuf;
423:
424: strncat(daemon->namebuff, daemon->addrbuff, (MAXDNAME-1) - strlen(daemon->namebuff));
425: strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
426:
427: /* remove unique-directory if it doesn't exist */
428: if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
429: daemon->namebuff[oldlen] = 0;
430: }
1.1.1.4 misho 431:
432: if (option_bool(OPT_TFTP_APREF_MAC))
433: {
434: unsigned char *macaddr = NULL;
435: unsigned char macbuf[DHCP_CHADDR_MAX];
436:
437: #ifdef HAVE_DHCP
438: if (daemon->dhcp && peer.sa.sa_family == AF_INET)
439: {
440: /* Check if the client IP is in our lease database */
441: struct dhcp_lease *lease = lease_find_by_addr(peer.in.sin_addr);
442: if (lease && lease->hwaddr_type == ARPHRD_ETHER && lease->hwaddr_len == ETHER_ADDR_LEN)
443: macaddr = lease->hwaddr;
444: }
445: #endif
446:
447: /* If no luck, try to find in ARP table. This only works if client is in same (V)LAN */
448: if (!macaddr && find_mac(&peer, macbuf, 1, now) > 0)
449: macaddr = macbuf;
450:
451: if (macaddr)
452: {
453: size_t oldlen = strlen(daemon->namebuff);
454: struct stat statbuf;
455:
456: snprintf(daemon->namebuff + oldlen, (MAXDNAME-1) - oldlen, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x/",
457: macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
458:
459: /* remove unique-directory if it doesn't exist */
460: if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
461: daemon->namebuff[oldlen] = 0;
462: }
463: }
464:
1.1 misho 465: /* Absolute pathnames OK if they match prefix */
466: if (filename[0] == '/')
467: {
468: if (strstr(filename, daemon->namebuff) == filename)
469: daemon->namebuff[0] = 0;
470: else
471: filename++;
472: }
473: }
474: else if (filename[0] == '/')
475: daemon->namebuff[0] = 0;
476: strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
1.1.1.4 misho 477:
1.1 misho 478: /* check permissions and open file */
1.1.1.5 ! misho 479: if ((transfer->file = check_tftp_fileperm(&len, prefix, daemon->addrbuff)))
1.1 misho 480: {
481: if ((len = get_block(packet, transfer)) == -1)
482: len = tftp_err_oops(packet, daemon->namebuff);
483: else
484: is_err = 0;
485: }
486: }
1.1.1.4 misho 487:
488: send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), packet, len, &peer, &addra, if_index);
1.1.1.5 ! misho 489:
! 490: #ifdef HAVE_DUMPFILE
! 491: dump_packet_udp(DUMP_TFTP, (void *)packet, len, NULL, (union mysockaddr *)&peer, transfer->sockfd);
! 492: #endif
1.1 misho 493:
494: if (is_err)
495: free_transfer(transfer);
496: else
497: {
498: transfer->next = daemon->tftp_trans;
499: daemon->tftp_trans = transfer;
500: }
501: }
502:
1.1.1.5 ! misho 503: static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, char *client)
1.1 misho 504: {
505: char *packet = daemon->packet, *namebuff = daemon->namebuff;
506: struct tftp_file *file;
507: struct tftp_transfer *t;
508: uid_t uid = geteuid();
509: struct stat statbuf;
510: int fd = -1;
511:
512: /* trick to ban moving out of the subtree */
513: if (prefix && strstr(namebuff, "/../"))
514: goto perm;
515:
516: if ((fd = open(namebuff, O_RDONLY)) == -1)
517: {
518: if (errno == ENOENT)
519: {
1.1.1.5 ! misho 520: *len = tftp_err(ERR_FNF, packet, _("file %s not found for %s"), namebuff, client);
1.1 misho 521: return NULL;
522: }
523: else if (errno == EACCES)
524: goto perm;
525: else
526: goto oops;
527: }
528:
529: /* stat the file descriptor to avoid stat->open races */
530: if (fstat(fd, &statbuf) == -1)
531: goto oops;
532:
533: /* running as root, must be world-readable */
534: if (uid == 0)
535: {
536: if (!(statbuf.st_mode & S_IROTH))
537: goto perm;
538: }
539: /* in secure mode, must be owned by user running dnsmasq */
540: else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
541: goto perm;
542:
1.1.1.4 misho 543: /* If we're doing many transfers from the same file, only
1.1 misho 544: open it once this saves lots of file descriptors
545: when mass-booting a big cluster, for instance.
546: Be conservative and only share when inode and name match
547: this keeps error messages sane. */
548: for (t = daemon->tftp_trans; t; t = t->next)
549: if (t->file->dev == statbuf.st_dev &&
550: t->file->inode == statbuf.st_ino &&
551: strcmp(t->file->filename, namebuff) == 0)
552: {
553: close(fd);
554: t->file->refcount++;
555: return t->file;
556: }
557:
558: if (!(file = whine_malloc(sizeof(struct tftp_file) + strlen(namebuff) + 1)))
559: {
560: errno = ENOMEM;
561: goto oops;
562: }
563:
564: file->fd = fd;
565: file->size = statbuf.st_size;
566: file->dev = statbuf.st_dev;
567: file->inode = statbuf.st_ino;
568: file->refcount = 1;
569: strcpy(file->filename, namebuff);
570: return file;
571:
572: perm:
1.1.1.5 ! misho 573: *len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff, strerror(EACCES));
1.1 misho 574: if (fd != -1)
575: close(fd);
576: return NULL;
577:
578: oops:
579: *len = tftp_err_oops(packet, namebuff);
580: if (fd != -1)
581: close(fd);
582: return NULL;
583: }
584:
1.1.1.3 misho 585: void check_tftp_listeners(time_t now)
1.1 misho 586: {
587: struct tftp_transfer *transfer, *tmp, **up;
588:
1.1.1.4 misho 589: /* In single port mode, all packets come via port 69 and tftp_request() */
590: if (!option_bool(OPT_SINGLE_PORT))
591: for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1.1.1.3 misho 592: if (poll_check(transfer->sockfd, POLLIN))
1.1 misho 593: {
1.1.1.5 ! misho 594: union mysockaddr peer;
! 595: socklen_t addr_len = sizeof(union mysockaddr);
! 596: ssize_t len;
! 597:
1.1 misho 598: /* we overwrote the buffer... */
599: daemon->srv_save = NULL;
1.1.1.4 misho 600:
1.1.1.5 ! misho 601: if ((len = recvfrom(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0, &peer.sa, &addr_len)) > 0)
! 602: {
! 603: if (sockaddr_isequal(&peer, &transfer->peer))
! 604: handle_tftp(now, transfer, len);
! 605: else
! 606: {
! 607: /* Wrong source address. See rfc1350 para 4. */
! 608: prettyprint_addr(&peer, daemon->addrbuff);
! 609: len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff, NULL);
! 610: while(retry_send(sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer))));
! 611:
! 612: #ifdef HAVE_DUMPFILE
! 613: dump_packet_udp(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&peer, transfer->sockfd);
! 614: #endif
! 615: }
! 616: }
! 617: }
! 618:
1.1.1.4 misho 619: for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
620: {
621: tmp = transfer->next;
1.1 misho 622:
623: if (difftime(now, transfer->timeout) >= 0.0)
624: {
625: int endcon = 0;
1.1.1.4 misho 626: ssize_t len;
1.1 misho 627:
628: /* timeout, retransmit */
1.1.1.4 misho 629: transfer->timeout += 1 + (1<<(transfer->backoff/2));
1.1 misho 630:
631: /* we overwrote the buffer... */
632: daemon->srv_save = NULL;
1.1.1.5 ! misho 633:
1.1 misho 634: if ((len = get_block(daemon->packet, transfer)) == -1)
635: {
636: len = tftp_err_oops(daemon->packet, transfer->file->filename);
637: endcon = 1;
638: }
1.1.1.4 misho 639: else if (++transfer->backoff > 7)
1.1 misho 640: {
1.1.1.4 misho 641: /* don't complain about timeout when we're awaiting the last
642: ACK, some clients never send it */
643: if ((unsigned)len == transfer->blocksize + 4)
644: endcon = 1;
1.1 misho 645: len = 0;
646: }
647:
648: if (len != 0)
1.1.1.5 ! misho 649: {
! 650: send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len,
! 651: &transfer->peer, &transfer->source, transfer->if_index);
! 652: #ifdef HAVE_DUMPFILE
! 653: dump_packet_udp(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&transfer->peer, transfer->sockfd);
! 654: #endif
! 655: }
! 656:
1.1 misho 657: if (endcon || len == 0)
658: {
659: strcpy(daemon->namebuff, transfer->file->filename);
660: sanitise(daemon->namebuff);
1.1.1.4 misho 661: (void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
1.1 misho 662: my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
663: /* unlink */
664: *up = tmp;
665: if (endcon)
666: free_transfer(transfer);
667: else
668: {
669: /* put on queue to be sent to script and deleted */
670: transfer->next = daemon->tftp_done_trans;
671: daemon->tftp_done_trans = transfer;
672: }
673: continue;
674: }
675: }
676:
677: up = &transfer->next;
678: }
679: }
1.1.1.4 misho 680:
681: /* packet in daemon->packet as this is called. */
682: static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len)
683: {
684: struct ack {
685: unsigned short op, block;
686: } *mess = (struct ack *)daemon->packet;
687:
688: if (len >= (ssize_t)sizeof(struct ack))
689: {
690: if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block)
691: {
692: /* Got ack, ensure we take the (re)transmit path */
693: transfer->timeout = now;
694: transfer->backoff = 0;
695: if (transfer->block++ != 0)
696: transfer->offset += transfer->blocksize - transfer->expansion;
697: }
698: else if (ntohs(mess->op) == OP_ERR)
699: {
700: char *p = daemon->packet + sizeof(struct ack);
701: char *end = daemon->packet + len;
702: char *err = next(&p, end);
703:
704: (void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
705:
706: /* Sanitise error message */
707: if (!err)
708: err = "";
709: else
710: sanitise(err);
711:
712: my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
713: (int)ntohs(mess->block), err,
714: daemon->addrbuff);
715:
716: /* Got err, ensure we take abort */
717: transfer->timeout = now;
718: transfer->backoff = 100;
719: }
720: }
721: }
1.1 misho 722:
723: static void free_transfer(struct tftp_transfer *transfer)
724: {
1.1.1.4 misho 725: if (!option_bool(OPT_SINGLE_PORT))
726: close(transfer->sockfd);
727:
1.1 misho 728: if (transfer->file && (--transfer->file->refcount) == 0)
729: {
730: close(transfer->file->fd);
731: free(transfer->file);
732: }
1.1.1.4 misho 733:
1.1 misho 734: free(transfer);
735: }
736:
737: static char *next(char **p, char *end)
738: {
739: char *ret = *p;
740: size_t len;
741:
742: if (*(end-1) != 0 ||
743: *p == end ||
744: (len = strlen(ret)) == 0)
745: return NULL;
746:
747: *p += len + 1;
748: return ret;
749: }
750:
751: static void sanitise(char *buf)
752: {
753: unsigned char *q, *r;
754: for (q = r = (unsigned char *)buf; *r; r++)
755: if (isprint((int)*r))
756: *(q++) = *r;
757: *q = 0;
758:
759: }
760:
1.1.1.4 misho 761: #define MAXMESSAGE 500 /* limit to make packet < 512 bytes and definitely smaller than buffer */
1.1.1.5 ! misho 762: static ssize_t tftp_err(int err, char *packet, char *message, char *file, char *arg2)
1.1 misho 763: {
764: struct errmess {
765: unsigned short op, err;
766: char message[];
767: } *mess = (struct errmess *)packet;
1.1.1.4 misho 768: ssize_t len, ret = 4;
1.1.1.5 ! misho 769:
1.1.1.4 misho 770: memset(packet, 0, daemon->packet_buff_sz);
1.1.1.5 ! misho 771: if (file)
! 772: sanitise(file);
1.1.1.4 misho 773:
1.1 misho 774: mess->op = htons(OP_ERR);
775: mess->err = htons(err);
1.1.1.5 ! misho 776: len = snprintf(mess->message, MAXMESSAGE, message, file, arg2);
1.1.1.4 misho 777: ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
778:
1.1.1.5 ! misho 779: if (err != ERR_FNF || !option_bool(OPT_QUIET_TFTP))
! 780: my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
1.1 misho 781:
782: return ret;
783: }
784:
1.1.1.5 ! misho 785: static ssize_t tftp_err_oops(char *packet, const char *file)
1.1 misho 786: {
787: /* May have >1 refs to file, so potentially mangle a copy of the name */
1.1.1.5 ! misho 788: if (file != daemon->namebuff)
! 789: strcpy(daemon->namebuff, file);
! 790: return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), daemon->namebuff, strerror(errno));
1.1 misho 791: }
792:
793: /* return -1 for error, zero for done. */
794: static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
795: {
1.1.1.4 misho 796: memset(packet, 0, daemon->packet_buff_sz);
797:
1.1 misho 798: if (transfer->block == 0)
799: {
800: /* send OACK */
801: char *p;
802: struct oackmess {
803: unsigned short op;
804: char data[];
805: } *mess = (struct oackmess *)packet;
806:
807: p = mess->data;
808: mess->op = htons(OP_OACK);
809: if (transfer->opt_blocksize)
810: {
811: p += (sprintf(p, "blksize") + 1);
1.1.1.4 misho 812: p += (sprintf(p, "%u", transfer->blocksize) + 1);
1.1 misho 813: }
814: if (transfer->opt_transize)
815: {
816: p += (sprintf(p,"tsize") + 1);
817: p += (sprintf(p, "%u", (unsigned int)transfer->file->size) + 1);
818: }
819:
820: return p - packet;
821: }
822: else
823: {
824: /* send data packet */
825: struct datamess {
826: unsigned short op, block;
827: unsigned char data[];
828: } *mess = (struct datamess *)packet;
829:
830: size_t size = transfer->file->size - transfer->offset;
831:
832: if (transfer->offset > transfer->file->size)
833: return 0; /* finished */
834:
835: if (size > transfer->blocksize)
836: size = transfer->blocksize;
837:
838: mess->op = htons(OP_DATA);
839: mess->block = htons((unsigned short)(transfer->block));
840:
841: if (lseek(transfer->file->fd, transfer->offset, SEEK_SET) == (off_t)-1 ||
842: !read_write(transfer->file->fd, mess->data, size, 1))
843: return -1;
844:
845: transfer->expansion = 0;
846:
847: /* Map '\n' to CR-LF in netascii mode */
848: if (transfer->netascii)
849: {
850: size_t i;
851: int newcarrylf;
852:
853: for (i = 0, newcarrylf = 0; i < size; i++)
854: if (mess->data[i] == '\n' && ( i != 0 || !transfer->carrylf))
855: {
856: transfer->expansion++;
857:
858: if (size != transfer->blocksize)
859: size++; /* room in this block */
860: else if (i == size - 1)
861: newcarrylf = 1; /* don't expand LF again if it moves to the next block */
862:
863: /* make space and insert CR */
864: memmove(&mess->data[i+1], &mess->data[i], size - (i + 1));
865: mess->data[i] = '\r';
866:
867: i++;
868: }
869: transfer->carrylf = newcarrylf;
870:
871: }
872:
873: return size + 4;
874: }
875: }
876:
877:
878: int do_tftp_script_run(void)
879: {
880: struct tftp_transfer *transfer;
881:
882: if ((transfer = daemon->tftp_done_trans))
883: {
884: daemon->tftp_done_trans = transfer->next;
885: #ifdef HAVE_SCRIPT
886: queue_tftp(transfer->file->size, transfer->file->filename, &transfer->peer);
887: #endif
888: free_transfer(transfer);
889: return 1;
890: }
891:
892: return 0;
893: }
894: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>