Annotation of tftpd/src/srv.c, revision 1.5.2.1
1.5.2.1 ! misho 1: /*************************************************************************
! 2: * (C) 2014 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
! 3: * by Michael Pounov <misho@elwix.org>
! 4: *
! 5: * $Author: misho $
! 6: * $Id: global.h,v 1.4 2014/01/29 14:16:53 misho Exp $
! 7: *
! 8: **************************************************************************
! 9: The ELWIX and AITNET software is distributed under the following
! 10: terms:
! 11:
! 12: All of the documentation and software included in the ELWIX and AITNET
! 13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
! 14:
! 15: Copyright 2004 - 2014
! 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
! 17:
! 18: Redistribution and use in source and binary forms, with or without
! 19: modification, are permitted provided that the following conditions
! 20: are met:
! 21: 1. Redistributions of source code must retain the above copyright
! 22: notice, this list of conditions and the following disclaimer.
! 23: 2. Redistributions in binary form must reproduce the above copyright
! 24: notice, this list of conditions and the following disclaimer in the
! 25: documentation and/or other materials provided with the distribution.
! 26: 3. All advertising materials mentioning features or use of this software
! 27: must display the following acknowledgement:
! 28: This product includes software developed by Michael Pounov <misho@elwix.org>
! 29: ELWIX - Embedded LightWeight unIX and its contributors.
! 30: 4. Neither the name of AITNET nor the names of its contributors
! 31: may be used to endorse or promote products derived from this software
! 32: without specific prior written permission.
! 33:
! 34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
! 35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 44: SUCH DAMAGE.
! 45: */
1.1 misho 46: #include "global.h"
1.2 misho 47: #include "exec.h"
48: #include "srv.h"
1.1 misho 49:
50:
51: static void *
52: timeoutSession(sched_task_t *task)
53: {
1.4 misho 54: rpack_t *pkt = TASK_DATA(task);
55:
1.1 misho 56: ETRACE();
57:
58: /* drop session */
59: if (cli.fd > 2)
60: close(cli.fd);
1.4 misho 61: rpack_resize(pkt, TFTP_PKT_MAX);
1.1 misho 62: memset(&cli, 0, sizeof cli);
63:
64: taskExit(task, NULL);
65: }
66:
67: static void *
68: txPkt(sched_task_t *task)
69: {
70: int wlen;
71: rpack_t *pkt = TASK_DATA(task);
72: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
73:
74: ETRACE();
75:
76: wlen = sendto(TASK_FD(task), RPACK_BUF(pkt), TASK_DATLEN(task),
77: 0, &cli.addr.sa, cli.addr.sa.sa_len);
78: if (wlen == -1)
79: ESYSERR(0);
80: else if (wlen != TASK_DATLEN(task)) {
81: EERROR(EIO, "Sended %d bytes != packet %d bytes",
82: wlen, TASK_DATLEN(task));
1.2 misho 83: schedEvent(TASK_ROOT(task), execProg, "error", 0, NULL, TFTP_OPC_ERROR);
1.1 misho 84: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL,
85: timeoutSession, NULL);
1.4 misho 86: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 87: } else
88: EVERBOSE(2, "Sended %d bytes", wlen);
89: /* on error or argument, drop session */
90: if (TASK_ARG(task) == (void*) -1 || ntohs(tftp->tftp_opc) == TFTP_OPC_ERROR) {
1.2 misho 91: schedEvent(TASK_ROOT(task), execProg, "error", 0, NULL, TFTP_OPC_ERROR);
1.1 misho 92: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL,
93: timeoutSession, NULL);
1.4 misho 94: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 95: }
96:
97: taskExit(task, NULL);
98: }
99:
100: static void *
101: txData(sched_task_t *task)
102: {
103: rpack_t *pkt = TASK_DATA(task);
104: u_short code = 0, n = htons(TFTP_OPC_DATA);
105: int len;
106:
107: ETRACE();
108:
109: RPACK_REWIND(pkt);
110: rpack_uint16(pkt, &n, 0);
111: n = htons(cli.seq);
112: rpack_uint16(pkt, &n, 0);
113:
1.4 misho 114: /* max file size check */
115: if (cli.tsiz && cli.tsiz < cli.seq * cli.siz) {
116: len = cli.tsiz - (cli.seq - 1) * cli.siz;
117: cli.close = 42; /* last sended packet, should be close! */
118: } else
119: len = cli.siz;
120:
121: len = pread(cli.fd, RPACK_NEXT(pkt), len, (cli.seq - 1) * cli.siz);
1.1 misho 122: if (len == -1) {
123: ESYSERR(0);
1.5 misho 124: code = htons(3);
1.1 misho 125: goto end;
126: } else {
127: rpack_rnext(pkt, len);
128: EVERBOSE(3, "Read from file %s %d bytes", cli.file, len);
129: }
130:
131: if (cli.siz - len)
132: cli.close = 42; /* last sended packet, should be close! */
133:
134: schedEvent(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
135: TASK_DATA(task), RPACK_OFF(pkt));
136: taskExit(task, NULL);
137: end:
138: RPACK_REWIND(pkt);
139: n = htons(TFTP_OPC_ERROR);
140: rpack_uint16(pkt, &n, 0);
141: rpack_uint16(pkt, &code, 0);
1.5 misho 142: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 143:
144: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
145: TASK_DATA(task), RPACK_OFF(pkt));
146: taskExit(task, NULL);
147: }
148:
149: static void *
150: txAck(sched_task_t *task)
151: {
152: rpack_t *pkt = TASK_DATA(task);
153: u_short n = htons(TFTP_OPC_ACK);
154:
155: ETRACE();
156:
157: RPACK_REWIND(pkt);
158: rpack_uint16(pkt, &n, 0);
159: n = htons(cli.seq);
160: rpack_uint16(pkt, &n, 0);
161:
162: schedEvent(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
163: TASK_DATA(task), RPACK_OFF(pkt));
164:
165: if (cli.close) {
1.2 misho 166: schedEvent(TASK_ROOT(task), execProg, "complete", 0, NULL, TFTP_OPC_WRQ);
1.1 misho 167: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL, timeoutSession, NULL);
1.4 misho 168: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 169: EVERBOSE(2, "Finish WRQ request");
170: }
171: taskExit(task, NULL);
172: }
173:
1.3 misho 174: static int
1.4 misho 175: getOpts(rpack_t * __restrict pkt, int rlen)
1.3 misho 176: {
1.4 misho 177: char *opt, *val;
178: int len;
179:
180: if (!rlen)
1.3 misho 181: return -1;
182:
1.4 misho 183: do {
184: /* option */
185: len = str_getString(RPACK_NEXT(pkt), RPACK_REMAIN(pkt), NULL);
186: if (len == -1)
187: return -1;
188: else
189: rlen -= len;
190: opt = (char*) rpack_rnext(pkt, len);
191: if (!opt)
192: return -1;
193: EVERBOSE(7, "opt=%s rlen=%d", opt, rlen);
194: /* value */
195: len = str_getString(RPACK_NEXT(pkt), RPACK_REMAIN(pkt), NULL);
196: if (len == -1)
197: return -1;
198: else
199: rlen -= len;
200: val = (char*) rpack_rnext(pkt, len);
201: if (!val)
202: return -1;
203: EVERBOSE(7, "val=%s rlen=%d", val, rlen);
204:
205: if (!strcasecmp(opt, TFTP_OPT_BLKSIZE))
206: cli.tmp = strtol(val, NULL, 10);
207: else if (!strcasecmp(opt, TFTP_OPT_TSIZE))
208: cli.tsiz = strtoll(val, NULL, 10);
209: else if (!strcasecmp(opt, TFTP_OPT_TIMEOUT))
210: cli.tout.tv_sec = strtol(val, NULL, 10);
1.5 misho 211: else if (!strcasecmp(opt, TFTP_OPT_ROLLOVER)) {
1.4 misho 212: cli.roll = strtol(val, NULL, 10);
1.5 misho 213: cli.roll++;
214: }
1.4 misho 215: } while (rlen > 0);
216:
217: EVERBOSE(4, "blksize=%u tsize=%llu timeout=%u rollover=%u",
1.5 misho 218: cli.siz, cli.tsiz, cli.tout.tv_sec, cli.roll - 1);
1.3 misho 219: return 0;
220: }
221:
1.1 misho 222: static void *
1.4 misho 223: txOack(sched_task_t *task)
224: {
225: rpack_t *pkt = TASK_DATA(task);
226: u_short n = htons(TFTP_OPC_OACK);
227: struct stat sb;
228: char szStr[STRSIZ];
229:
230: ETRACE();
231:
232: RPACK_REWIND(pkt);
233: rpack_uint16(pkt, &n, 0);
234:
235: /* if opcode is RRQ and tsize is 0 then we must return file size to client */
236: if (cli.opc == TFTP_OPC_RRQ && !cli.tsiz && stat(cli.file, &sb) != -1)
237: cli.tsiz = sb.st_size;
238:
239: if (cli.siz > TFTP_LOAD_MAX) {
240: memset(szStr, 0, sizeof szStr);
241: snprintf(szStr, sizeof szStr, "%u", cli.siz);
242: rpack_rdata(pkt, TFTP_OPT_BLKSIZE, strlen(TFTP_OPT_BLKSIZE) + 1);
243: rpack_rdata(pkt, szStr, strlen(szStr) + 1);
244: }
245: if (cli.tsiz) {
246: memset(szStr, 0, sizeof szStr);
247: snprintf(szStr, sizeof szStr, "%llu", cli.tsiz);
248: rpack_rdata(pkt, TFTP_OPT_TSIZE, strlen(TFTP_OPT_TSIZE) + 1);
249: rpack_rdata(pkt, szStr, strlen(szStr) + 1);
250: }
251: if (cli.tout.tv_sec) {
252: memset(szStr, 0, sizeof szStr);
253: snprintf(szStr, sizeof szStr, "%u", cli.tout.tv_sec);
254: rpack_rdata(pkt, TFTP_OPT_TIMEOUT, strlen(TFTP_OPT_TIMEOUT) + 1);
255: rpack_rdata(pkt, szStr, strlen(szStr) + 1);
256: }
257: if (cli.roll) {
258: memset(szStr, 0, sizeof szStr);
1.5 misho 259: snprintf(szStr, sizeof szStr, "%u", cli.roll - 1);
1.4 misho 260: rpack_rdata(pkt, TFTP_OPT_ROLLOVER, strlen(TFTP_OPT_ROLLOVER) + 1);
261: rpack_rdata(pkt, szStr, strlen(szStr) + 1);
262: }
263:
264: EVERBOSE(4, "blksize=%u tsize=%llu timeout=%u rollover=%u",
1.5 misho 265: cli.siz, cli.tsiz, cli.tout.tv_sec, cli.roll - 1);
266: schedCallOnce(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
1.4 misho 267: TASK_DATA(task), RPACK_OFF(pkt));
268: taskExit(task, NULL);
269: }
270:
271: static void *
1.1 misho 272: RQ(sched_task_t *task)
273: {
274: rpack_t *pkt = TASK_DATA(task);
275: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
276: int len, rlen = TASK_DATLEN(task) - 2;
1.4 misho 277: char *str;
1.1 misho 278: u_short code = 0;
279:
280: ETRACE();
281:
282: cli.siz = TFTP_LOAD_MAX;
1.4 misho 283: cli.opc = ntohs(rpack_uint16(pkt, NULL, 0));
284: len = str_getString(RPACK_NEXT(pkt), rlen, &str);
1.1 misho 285: if (len == -1)
286: goto end;
287: else {
1.4 misho 288: strlcpy(cli.file, (char*) RPACK_NEXT(pkt), sizeof cli.file);
1.1 misho 289: rlen -= len;
1.4 misho 290: rpack_rnext(pkt, len);
1.1 misho 291: }
1.4 misho 292: len = str_getString((const u_char*) str, rlen, NULL);
1.1 misho 293: if (len == -1)
294: goto end;
295: else {
296: rlen -= len;
1.4 misho 297: rpack_rnext(pkt, len);
1.1 misho 298: if (!strcasecmp(str, TFTP_MODE_ASCII))
299: strlcpy(cli.mode, TFTP_MODE_ASCII, sizeof cli.mode);
300: else if (!strcasecmp(str, TFTP_MODE_OCTET))
301: strlcpy(cli.mode, TFTP_MODE_OCTET, sizeof cli.mode);
302: else if (!strcasecmp(str, TFTP_MODE_MAIL)) {
303: strlcpy(cli.mode, TFTP_MODE_MAIL, sizeof cli.mode);
1.5 misho 304: code = htons(4);
1.1 misho 305: goto end;
306: } else {
1.5 misho 307: code = htons(1);
1.1 misho 308: goto end;
309: }
310: }
311:
312: switch (cli.opc) {
313: case TFTP_OPC_RRQ:
314: code = O_RDONLY;
315: EVERBOSE(2, "RRQ:: file=%s mode=%s\n", cli.file, cli.mode);
316: break;
317: case TFTP_OPC_WRQ:
318: code = O_WRONLY | O_CREAT;
319: str = (char*) cfg_getAttribute(&cfg, "tftpd", "override");
320: if (!str || tolower(*str) != 'y')
321: code |= O_EXCL;
322: EVERBOSE(2, "WRQ:: file=%s mode=%s\n", cli.file, cli.mode);
323: break;
324: }
1.4 misho 325:
1.1 misho 326: cli.fd = open(cli.file, code, 0644);
327: if (cli.fd == -1) {
328: if (errno == EACCES)
1.5 misho 329: code = htons(2);
1.1 misho 330: else if (errno == ENFILE)
1.5 misho 331: code = htons(3);
1.1 misho 332: else if (errno == EEXIST)
1.5 misho 333: code = htons(6);
1.1 misho 334: else
1.5 misho 335: code = htons(0);
1.1 misho 336: ESYSERR(0);
337: goto end;
338: } else
339: cli.seq = 0;
340:
1.2 misho 341: schedEvent(TASK_ROOT(task), execProg, "request", 0, NULL, cli.opc);
342:
1.4 misho 343: if (!getOpts(pkt, rlen)) {
344: if (cli.tmp > TFTP_LOAD_MAX) {
345: if (rpack_resize(pkt, cli.tmp + 4))
346: ELIBERR(elwix);
347: else
348: cli.siz = cli.tmp;
349: }
350: if (cli.tout.tv_sec) {
351: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL,
352: timeoutSession, NULL);
353: schedTimer(TASK_ROOT(task), timeoutSession, NULL,
354: cli.tout, TASK_DATA(task), 0);
355: }
356: schedEvent(TASK_ROOT(task), txOack, NULL, TASK_FD(task),
357: TASK_DATA(task), 0);
358: } else if (cli.opc == TFTP_OPC_WRQ) {
1.1 misho 359: /* ack */
360: tftp->tftp_opc = htons(TFTP_OPC_ACK);
361: RPACK_REWIND(pkt);
362: rpack_uint16(pkt, NULL, 0);
363: rpack_uint16(pkt, &cli.seq, 0);
364:
365: schedEvent(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
366: TASK_DATA(task), RPACK_OFF(pkt));
367: } else
368: schedEvent(TASK_ROOT(task), txData, NULL, TASK_FD(task),
369: TASK_DATA(task), 0);
370:
371: cli.seq = 1; /* 1st ack */
372: taskExit(task, NULL);
373: end:
374: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
375: RPACK_REWIND(pkt);
376: rpack_uint16(pkt, NULL, 0);
377: rpack_uint16(pkt, &code, 0);
1.5 misho 378: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 379:
380: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
381: TASK_DATA(task), RPACK_OFF(pkt));
382: taskExit(task, NULL);
383: }
384:
385: static void *
386: ACK(sched_task_t *task)
387: {
388: rpack_t *pkt = TASK_DATA(task);
389: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
390: u_short code;
391:
392: ETRACE();
393:
394: RPACK_REWIND(pkt);
395: code = rpack_uint16(pkt, NULL, 0);
396: if (ntohs(code) != TFTP_OPC_ACK) {
1.5 misho 397: code = htons(5);
1.1 misho 398: goto end;
399: }
400:
401: code = rpack_uint16(pkt, NULL, 0);
402: if (ntohs(code) > cli.seq || (ntohs(code) < (cli.seq - 1))) {
1.5 misho 403: code = htons(5);
1.1 misho 404: goto end;
1.4 misho 405: } else if (ntohs(code) == cli.seq) {
406: /* check for rollover seq id */
407: if (cli.roll && cli.seq == USHRT_MAX)
1.5 misho 408: cli.seq = cli.roll - 1;
1.4 misho 409: else
410: cli.seq++;
411: }
1.1 misho 412:
413: EVERBOSE(3, "ACK:: seq=%hu; my new seq=%hu;", ntohs(code), cli.seq);
414:
415: if (!cli.close)
416: schedEvent(TASK_ROOT(task), txData, NULL, TASK_FD(task),
417: TASK_DATA(task), 0);
418: else {
1.2 misho 419: schedEvent(TASK_ROOT(task), execProg, "complete", 0, NULL, TFTP_OPC_RRQ);
1.1 misho 420: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL, timeoutSession, NULL);
1.4 misho 421: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 422: EVERBOSE(2, "Finish RRQ request");
423: }
424: taskExit(task, NULL);
425: end:
426: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
427: RPACK_REWIND(pkt);
428: rpack_uint16(pkt, NULL, 0);
429: rpack_uint16(pkt, &code, 0);
1.5 misho 430: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 431:
432: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
433: TASK_DATA(task), RPACK_OFF(pkt));
434: taskExit(task, NULL);
435: }
436:
437: static void *
438: DATA(sched_task_t *task)
439: {
440: rpack_t *pkt = TASK_DATA(task);
441: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
442: u_short code;
443: int len;
444:
445: ETRACE();
446:
447: RPACK_REWIND(pkt);
448: code = rpack_uint16(pkt, NULL, 0);
449: if (ntohs(code) != TFTP_OPC_DATA) {
1.5 misho 450: code = htons(5);
1.1 misho 451: goto end;
452: }
453:
454: code = rpack_uint16(pkt, NULL, 0);
455: if (ntohs(code) < cli.seq || ntohs(code) > cli.seq + 1) {
1.5 misho 456: code = htons(5);
1.1 misho 457: goto end;
458: } else
459: cli.seq = ntohs(code);
460:
1.4 misho 461: /* max file size check */
1.1 misho 462: len = TASK_DATLEN(task) - RPACK_OFF(pkt);
1.4 misho 463: if (cli.tsiz && cli.tsiz < cli.seq * cli.siz)
464: len = MIN(len, cli.tsiz - (cli.seq - 1) * cli.siz);
1.1 misho 465: if (len < cli.siz)
466: cli.close = 42; /* last received packet, should be close! */
467:
468: EVERBOSE(3, "DATA:: seq=%hu; len=%d", cli.seq, len);
469:
470: len = pwrite(cli.fd, RPACK_NEXT(pkt), len, (cli.seq - 1) * cli.siz);
471: if (len == -1) {
472: ESYSERR(0);
1.5 misho 473: code = htons(3);
1.1 misho 474: goto end;
475: } else {
476: rpack_rnext(pkt, len);
477: EVERBOSE(3, "Written to file %s %d bytes", cli.file, len);
478: }
479:
480: schedEvent(TASK_ROOT(task), txAck, NULL, TASK_FD(task), TASK_DATA(task), 0);
481: taskExit(task, NULL);
482: end:
483: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
484: RPACK_REWIND(pkt);
485: rpack_uint16(pkt, NULL, 0);
486: rpack_uint16(pkt, &code, 0);
1.5 misho 487: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 488:
489: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
490: TASK_DATA(task), RPACK_OFF(pkt));
491: taskExit(task, NULL);
492: }
493:
494: void *
495: rxPkt(sched_task_t *task)
496: {
497: sockaddr_t sa;
498: socklen_t salen = sizeof sa;
499: int rlen;
500: rpack_t *pkt = TASK_DATA(task);
501: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
502: u_short code;
503:
504: ETRACE();
505:
506: memset(RPACK_BUF(pkt), 0, RPACK_LEN(pkt));
507: rlen = recvfrom(TASK_FD(task), RPACK_BUF(pkt), RPACK_LEN(pkt), 0, &sa.sa, &salen);
508: if (rlen == -1) {
509: ESYSERR(0);
510: goto end;
511: } else if (!cli.addr.sa.sa_len) {
512: cli.addr = sa;
1.4 misho 513: RPACK_REWIND(pkt);
1.1 misho 514: switch (ntohs(tftp->tftp_opc)) {
515: case TFTP_OPC_RRQ:
516: case TFTP_OPC_WRQ:
517: schedEvent(TASK_ROOT(task), RQ, NULL, TASK_FD(task),
518: TASK_DATA(task), rlen);
519: break;
520: case TFTP_OPC_ERROR:
521: default:
522: RPACK_REWIND(pkt);
523: code = htons(TFTP_OPC_ERROR);
524: rpack_uint16(pkt, &code, 0);
1.5 misho 525: code = htons(4);
1.1 misho 526: rpack_uint16(pkt, &code, 0);
527: rpack_rdata(pkt, errs[4].err_msg, strlen(errs[4].err_msg) + 1);
528:
529: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
530: TASK_DATA(task), RPACK_OFF(pkt));
531: goto end;
532: }
533: } else if (memcmp(&cli.addr, &sa, salen)) {
534: EERROR(LOG_WARNING, "Packet dropped!!!\n"
535: "Get frame from different address for this session");
536: goto end;
537: } else
538: switch (ntohs(tftp->tftp_opc)) {
539: case TFTP_OPC_ACK:
540: schedEvent(TASK_ROOT(task), ACK, NULL, TASK_FD(task),
541: TASK_DATA(task), rlen);
542: break;
543: case TFTP_OPC_DATA:
544: schedEvent(TASK_ROOT(task), DATA, NULL, TASK_FD(task),
545: TASK_DATA(task), rlen);
546: break;
547: case TFTP_OPC_OACK:
548: case TFTP_OPC_ERROR:
549: default:
550: RPACK_REWIND(pkt);
551: code = htons(TFTP_OPC_ERROR);
552: rpack_uint16(pkt, &code, 0);
1.5 misho 553: code = htons(4);
1.1 misho 554: rpack_uint16(pkt, &code, 0);
555: rpack_rdata(pkt, errs[4].err_msg, strlen(errs[4].err_msg) + 1);
556:
557: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
558: TASK_DATA(task), RPACK_OFF(pkt));
559: goto end;
560: }
561:
562: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL, timeoutSession, NULL);
1.4 misho 563: schedTimer(TASK_ROOT(task), timeoutSession, NULL,
564: cli.tout.tv_sec ? cli.tout : timeout, TASK_DATA(task), 0);
1.1 misho 565: end:
566: schedReadSelf(task);
567: taskExit(task, NULL);
568: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>