Annotation of tftpd/src/srv.c, revision 1.7
1.6 misho 1: /*************************************************************************
2: * (C) 2014 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.7 ! misho 6: * $Id: srv.c,v 1.6.2.3 2014/02/24 14:38:47 misho Exp $
1.6 misho 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"
1.7 ! misho 48: #include "buf.h"
1.2 misho 49: #include "srv.h"
1.1 misho 50:
51:
52: static void *
53: timeoutSession(sched_task_t *task)
54: {
1.4 misho 55: rpack_t *pkt = TASK_DATA(task);
56:
1.1 misho 57: ETRACE();
58:
1.7 ! misho 59: if (bf)
! 60: flushBuffer(cli.fd);
! 61:
1.1 misho 62: /* drop session */
63: if (cli.fd > 2)
64: close(cli.fd);
1.4 misho 65: rpack_resize(pkt, TFTP_PKT_MAX);
1.1 misho 66: memset(&cli, 0, sizeof cli);
67:
68: taskExit(task, NULL);
69: }
70:
71: static void *
72: txPkt(sched_task_t *task)
73: {
74: int wlen;
75: rpack_t *pkt = TASK_DATA(task);
76: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
77:
78: ETRACE();
79:
80: wlen = sendto(TASK_FD(task), RPACK_BUF(pkt), TASK_DATLEN(task),
81: 0, &cli.addr.sa, cli.addr.sa.sa_len);
82: if (wlen == -1)
83: ESYSERR(0);
84: else if (wlen != TASK_DATLEN(task)) {
85: EERROR(EIO, "Sended %d bytes != packet %d bytes",
86: wlen, TASK_DATLEN(task));
1.2 misho 87: schedEvent(TASK_ROOT(task), execProg, "error", 0, NULL, TFTP_OPC_ERROR);
1.1 misho 88: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL,
89: timeoutSession, NULL);
1.4 misho 90: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 91: } else
92: EVERBOSE(2, "Sended %d bytes", wlen);
93: /* on error or argument, drop session */
94: if (TASK_ARG(task) == (void*) -1 || ntohs(tftp->tftp_opc) == TFTP_OPC_ERROR) {
1.2 misho 95: schedEvent(TASK_ROOT(task), execProg, "error", 0, NULL, TFTP_OPC_ERROR);
1.1 misho 96: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL,
97: timeoutSession, NULL);
1.4 misho 98: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 99: }
100:
101: taskExit(task, NULL);
102: }
103:
104: static void *
105: txData(sched_task_t *task)
106: {
107: rpack_t *pkt = TASK_DATA(task);
108: u_short code = 0, n = htons(TFTP_OPC_DATA);
109: int len;
110:
111: ETRACE();
112:
113: RPACK_REWIND(pkt);
114: rpack_uint16(pkt, &n, 0);
115: n = htons(cli.seq);
116: rpack_uint16(pkt, &n, 0);
117:
1.4 misho 118: /* max file size check */
119: if (cli.tsiz && cli.tsiz < cli.seq * cli.siz) {
120: len = cli.tsiz - (cli.seq - 1) * cli.siz;
121: cli.close = 42; /* last sended packet, should be close! */
122: } else
123: len = cli.siz;
124:
125: len = pread(cli.fd, RPACK_NEXT(pkt), len, (cli.seq - 1) * cli.siz);
1.1 misho 126: if (len == -1) {
127: ESYSERR(0);
1.5 misho 128: code = htons(3);
1.1 misho 129: goto end;
130: } else {
131: rpack_rnext(pkt, len);
132: EVERBOSE(3, "Read from file %s %d bytes", cli.file, len);
133: }
134:
135: if (cli.siz - len)
136: cli.close = 42; /* last sended packet, should be close! */
137:
138: schedEvent(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
139: TASK_DATA(task), RPACK_OFF(pkt));
140: taskExit(task, NULL);
141: end:
142: RPACK_REWIND(pkt);
143: n = htons(TFTP_OPC_ERROR);
144: rpack_uint16(pkt, &n, 0);
145: rpack_uint16(pkt, &code, 0);
1.5 misho 146: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 147:
148: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
149: TASK_DATA(task), RPACK_OFF(pkt));
150: taskExit(task, NULL);
151: }
152:
153: static void *
154: txAck(sched_task_t *task)
155: {
156: rpack_t *pkt = TASK_DATA(task);
157: u_short n = htons(TFTP_OPC_ACK);
158:
159: ETRACE();
160:
161: RPACK_REWIND(pkt);
162: rpack_uint16(pkt, &n, 0);
163: n = htons(cli.seq);
164: rpack_uint16(pkt, &n, 0);
165:
166: schedEvent(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
167: TASK_DATA(task), RPACK_OFF(pkt));
168:
169: if (cli.close) {
1.2 misho 170: schedEvent(TASK_ROOT(task), execProg, "complete", 0, NULL, TFTP_OPC_WRQ);
1.1 misho 171: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL, timeoutSession, NULL);
1.4 misho 172: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 173: EVERBOSE(2, "Finish WRQ request");
174: }
175: taskExit(task, NULL);
176: }
177:
1.3 misho 178: static int
1.4 misho 179: getOpts(rpack_t * __restrict pkt, int rlen)
1.3 misho 180: {
1.4 misho 181: char *opt, *val;
182: int len;
183:
184: if (!rlen)
1.3 misho 185: return -1;
186:
1.4 misho 187: do {
188: /* option */
189: len = str_getString(RPACK_NEXT(pkt), RPACK_REMAIN(pkt), NULL);
190: if (len == -1)
191: return -1;
192: else
193: rlen -= len;
194: opt = (char*) rpack_rnext(pkt, len);
195: if (!opt)
196: return -1;
197: EVERBOSE(7, "opt=%s rlen=%d", opt, rlen);
198: /* value */
199: len = str_getString(RPACK_NEXT(pkt), RPACK_REMAIN(pkt), NULL);
200: if (len == -1)
201: return -1;
202: else
203: rlen -= len;
204: val = (char*) rpack_rnext(pkt, len);
205: if (!val)
206: return -1;
207: EVERBOSE(7, "val=%s rlen=%d", val, rlen);
208:
209: if (!strcasecmp(opt, TFTP_OPT_BLKSIZE))
210: cli.tmp = strtol(val, NULL, 10);
211: else if (!strcasecmp(opt, TFTP_OPT_TSIZE))
212: cli.tsiz = strtoll(val, NULL, 10);
213: else if (!strcasecmp(opt, TFTP_OPT_TIMEOUT))
214: cli.tout.tv_sec = strtol(val, NULL, 10);
1.5 misho 215: else if (!strcasecmp(opt, TFTP_OPT_ROLLOVER)) {
1.4 misho 216: cli.roll = strtol(val, NULL, 10);
1.5 misho 217: cli.roll++;
218: }
1.4 misho 219: } while (rlen > 0);
220:
1.7 ! misho 221: EVERBOSE(4, "blksize=%u tsize=%llu timeout=%d rollover=%u",
! 222: cli.siz, cli.tsiz, (int) cli.tout.tv_sec, cli.roll - 1);
1.3 misho 223: return 0;
224: }
225:
1.1 misho 226: static void *
1.4 misho 227: txOack(sched_task_t *task)
228: {
229: rpack_t *pkt = TASK_DATA(task);
230: u_short n = htons(TFTP_OPC_OACK);
231: struct stat sb;
232: char szStr[STRSIZ];
233:
234: ETRACE();
235:
236: RPACK_REWIND(pkt);
237: rpack_uint16(pkt, &n, 0);
238:
239: /* if opcode is RRQ and tsize is 0 then we must return file size to client */
240: if (cli.opc == TFTP_OPC_RRQ && !cli.tsiz && stat(cli.file, &sb) != -1)
241: cli.tsiz = sb.st_size;
242:
243: if (cli.siz > TFTP_LOAD_MAX) {
244: memset(szStr, 0, sizeof szStr);
245: snprintf(szStr, sizeof szStr, "%u", cli.siz);
246: rpack_rdata(pkt, TFTP_OPT_BLKSIZE, strlen(TFTP_OPT_BLKSIZE) + 1);
247: rpack_rdata(pkt, szStr, strlen(szStr) + 1);
248: }
249: if (cli.tsiz) {
250: memset(szStr, 0, sizeof szStr);
251: snprintf(szStr, sizeof szStr, "%llu", cli.tsiz);
252: rpack_rdata(pkt, TFTP_OPT_TSIZE, strlen(TFTP_OPT_TSIZE) + 1);
253: rpack_rdata(pkt, szStr, strlen(szStr) + 1);
254: }
255: if (cli.tout.tv_sec) {
256: memset(szStr, 0, sizeof szStr);
1.7 ! misho 257: snprintf(szStr, sizeof szStr, "%d", (int) cli.tout.tv_sec);
1.4 misho 258: rpack_rdata(pkt, TFTP_OPT_TIMEOUT, strlen(TFTP_OPT_TIMEOUT) + 1);
259: rpack_rdata(pkt, szStr, strlen(szStr) + 1);
260: }
261: if (cli.roll) {
262: memset(szStr, 0, sizeof szStr);
1.5 misho 263: snprintf(szStr, sizeof szStr, "%u", cli.roll - 1);
1.4 misho 264: rpack_rdata(pkt, TFTP_OPT_ROLLOVER, strlen(TFTP_OPT_ROLLOVER) + 1);
265: rpack_rdata(pkt, szStr, strlen(szStr) + 1);
266: }
267:
1.7 ! misho 268: EVERBOSE(4, "blksize=%u tsize=%llu timeout=%d rollover=%u",
! 269: cli.siz, cli.tsiz, (int) cli.tout.tv_sec, cli.roll - 1);
1.5 misho 270: schedCallOnce(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
1.4 misho 271: TASK_DATA(task), RPACK_OFF(pkt));
272: taskExit(task, NULL);
273: }
274:
275: static void *
1.1 misho 276: RQ(sched_task_t *task)
277: {
278: rpack_t *pkt = TASK_DATA(task);
279: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
280: int len, rlen = TASK_DATLEN(task) - 2;
1.4 misho 281: char *str;
1.1 misho 282: u_short code = 0;
283:
284: ETRACE();
285:
286: cli.siz = TFTP_LOAD_MAX;
1.4 misho 287: cli.opc = ntohs(rpack_uint16(pkt, NULL, 0));
288: len = str_getString(RPACK_NEXT(pkt), rlen, &str);
1.1 misho 289: if (len == -1)
290: goto end;
291: else {
1.4 misho 292: strlcpy(cli.file, (char*) RPACK_NEXT(pkt), sizeof cli.file);
1.1 misho 293: rlen -= len;
1.4 misho 294: rpack_rnext(pkt, len);
1.1 misho 295: }
1.4 misho 296: len = str_getString((const u_char*) str, rlen, NULL);
1.1 misho 297: if (len == -1)
298: goto end;
299: else {
300: rlen -= len;
1.4 misho 301: rpack_rnext(pkt, len);
1.1 misho 302: if (!strcasecmp(str, TFTP_MODE_ASCII))
303: strlcpy(cli.mode, TFTP_MODE_ASCII, sizeof cli.mode);
304: else if (!strcasecmp(str, TFTP_MODE_OCTET))
305: strlcpy(cli.mode, TFTP_MODE_OCTET, sizeof cli.mode);
306: else if (!strcasecmp(str, TFTP_MODE_MAIL)) {
307: strlcpy(cli.mode, TFTP_MODE_MAIL, sizeof cli.mode);
1.5 misho 308: code = htons(4);
1.1 misho 309: goto end;
310: } else {
1.5 misho 311: code = htons(1);
1.1 misho 312: goto end;
313: }
314: }
315:
316: switch (cli.opc) {
317: case TFTP_OPC_RRQ:
318: code = O_RDONLY;
319: EVERBOSE(2, "RRQ:: file=%s mode=%s\n", cli.file, cli.mode);
320: break;
321: case TFTP_OPC_WRQ:
322: code = O_WRONLY | O_CREAT;
323: str = (char*) cfg_getAttribute(&cfg, "tftpd", "override");
324: if (!str || tolower(*str) != 'y')
325: code |= O_EXCL;
326: EVERBOSE(2, "WRQ:: file=%s mode=%s\n", cli.file, cli.mode);
327: break;
328: }
1.4 misho 329:
1.1 misho 330: cli.fd = open(cli.file, code, 0644);
331: if (cli.fd == -1) {
332: if (errno == EACCES)
1.5 misho 333: code = htons(2);
1.1 misho 334: else if (errno == ENFILE)
1.5 misho 335: code = htons(3);
1.1 misho 336: else if (errno == EEXIST)
1.5 misho 337: code = htons(6);
1.7 ! misho 338: else if (errno == ENOENT)
! 339: code = htons(1);
1.1 misho 340: else
1.5 misho 341: code = htons(0);
1.1 misho 342: ESYSERR(0);
343: goto end;
344: } else
345: cli.seq = 0;
346:
1.2 misho 347: schedEvent(TASK_ROOT(task), execProg, "request", 0, NULL, cli.opc);
348:
1.4 misho 349: if (!getOpts(pkt, rlen)) {
350: if (cli.tmp > TFTP_LOAD_MAX) {
351: if (rpack_resize(pkt, cli.tmp + 4))
352: ELIBERR(elwix);
353: else
354: cli.siz = cli.tmp;
355: }
356: if (cli.tout.tv_sec) {
357: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL,
358: timeoutSession, NULL);
359: schedTimer(TASK_ROOT(task), timeoutSession, NULL,
360: cli.tout, TASK_DATA(task), 0);
361: }
362: schedEvent(TASK_ROOT(task), txOack, NULL, TASK_FD(task),
363: TASK_DATA(task), 0);
364: } else if (cli.opc == TFTP_OPC_WRQ) {
1.1 misho 365: /* ack */
366: tftp->tftp_opc = htons(TFTP_OPC_ACK);
367: RPACK_REWIND(pkt);
368: rpack_uint16(pkt, NULL, 0);
369: rpack_uint16(pkt, &cli.seq, 0);
370:
371: schedEvent(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
372: TASK_DATA(task), RPACK_OFF(pkt));
373: } else
374: schedEvent(TASK_ROOT(task), txData, NULL, TASK_FD(task),
375: TASK_DATA(task), 0);
376:
377: cli.seq = 1; /* 1st ack */
378: taskExit(task, NULL);
379: end:
380: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
381: RPACK_REWIND(pkt);
382: rpack_uint16(pkt, NULL, 0);
383: rpack_uint16(pkt, &code, 0);
1.5 misho 384: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 385:
386: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
387: TASK_DATA(task), RPACK_OFF(pkt));
388: taskExit(task, NULL);
389: }
390:
391: static void *
392: ACK(sched_task_t *task)
393: {
394: rpack_t *pkt = TASK_DATA(task);
395: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
396: u_short code;
397:
398: ETRACE();
399:
400: RPACK_REWIND(pkt);
401: code = rpack_uint16(pkt, NULL, 0);
402: if (ntohs(code) != TFTP_OPC_ACK) {
1.5 misho 403: code = htons(5);
1.1 misho 404: goto end;
405: }
406:
407: code = rpack_uint16(pkt, NULL, 0);
408: if (ntohs(code) > cli.seq || (ntohs(code) < (cli.seq - 1))) {
1.5 misho 409: code = htons(5);
1.1 misho 410: goto end;
1.4 misho 411: } else if (ntohs(code) == cli.seq) {
412: /* check for rollover seq id */
413: if (cli.roll && cli.seq == USHRT_MAX)
1.5 misho 414: cli.seq = cli.roll - 1;
1.4 misho 415: else
416: cli.seq++;
417: }
1.1 misho 418:
419: EVERBOSE(3, "ACK:: seq=%hu; my new seq=%hu;", ntohs(code), cli.seq);
420:
421: if (!cli.close)
422: schedEvent(TASK_ROOT(task), txData, NULL, TASK_FD(task),
423: TASK_DATA(task), 0);
424: else {
1.2 misho 425: schedEvent(TASK_ROOT(task), execProg, "complete", 0, NULL, TFTP_OPC_RRQ);
1.1 misho 426: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL, timeoutSession, NULL);
1.4 misho 427: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 428: EVERBOSE(2, "Finish RRQ request");
429: }
430: taskExit(task, NULL);
431: end:
432: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
433: RPACK_REWIND(pkt);
434: rpack_uint16(pkt, NULL, 0);
435: rpack_uint16(pkt, &code, 0);
1.5 misho 436: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 437:
438: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
439: TASK_DATA(task), RPACK_OFF(pkt));
440: taskExit(task, NULL);
441: }
442:
443: static void *
444: DATA(sched_task_t *task)
445: {
446: rpack_t *pkt = TASK_DATA(task);
447: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
448: u_short code;
449: int len;
450:
451: ETRACE();
452:
453: RPACK_REWIND(pkt);
454: code = rpack_uint16(pkt, NULL, 0);
455: if (ntohs(code) != TFTP_OPC_DATA) {
1.5 misho 456: code = htons(5);
1.1 misho 457: goto end;
458: }
459:
460: code = rpack_uint16(pkt, NULL, 0);
461: if (ntohs(code) < cli.seq || ntohs(code) > cli.seq + 1) {
1.5 misho 462: code = htons(5);
1.1 misho 463: goto end;
464: } else
465: cli.seq = ntohs(code);
466:
1.4 misho 467: /* max file size check */
1.1 misho 468: len = TASK_DATLEN(task) - RPACK_OFF(pkt);
1.4 misho 469: if (cli.tsiz && cli.tsiz < cli.seq * cli.siz)
470: len = MIN(len, cli.tsiz - (cli.seq - 1) * cli.siz);
1.1 misho 471: if (len < cli.siz)
472: cli.close = 42; /* last received packet, should be close! */
473:
474: EVERBOSE(3, "DATA:: seq=%hu; len=%d", cli.seq, len);
475:
1.7 ! misho 476: if (!bf)
! 477: len = pwrite(cli.fd, RPACK_NEXT(pkt), len, (cli.seq - 1) * cli.siz);
! 478: else
! 479: len = bfwrite(cli.fd, RPACK_NEXT(pkt), len);
1.1 misho 480: if (len == -1) {
481: ESYSERR(0);
1.5 misho 482: code = htons(3);
1.1 misho 483: goto end;
484: } else {
485: rpack_rnext(pkt, len);
486: EVERBOSE(3, "Written to file %s %d bytes", cli.file, len);
487: }
488:
489: schedEvent(TASK_ROOT(task), txAck, NULL, TASK_FD(task), TASK_DATA(task), 0);
490: taskExit(task, NULL);
491: end:
492: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
493: RPACK_REWIND(pkt);
494: rpack_uint16(pkt, NULL, 0);
495: rpack_uint16(pkt, &code, 0);
1.5 misho 496: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 497:
498: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
499: TASK_DATA(task), RPACK_OFF(pkt));
500: taskExit(task, NULL);
501: }
502:
503: void *
504: rxPkt(sched_task_t *task)
505: {
506: sockaddr_t sa;
507: socklen_t salen = sizeof sa;
508: int rlen;
509: rpack_t *pkt = TASK_DATA(task);
510: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
511: u_short code;
512:
513: ETRACE();
514:
515: memset(RPACK_BUF(pkt), 0, RPACK_LEN(pkt));
516: rlen = recvfrom(TASK_FD(task), RPACK_BUF(pkt), RPACK_LEN(pkt), 0, &sa.sa, &salen);
517: if (rlen == -1) {
518: ESYSERR(0);
519: goto end;
520: } else if (!cli.addr.sa.sa_len) {
521: cli.addr = sa;
1.4 misho 522: RPACK_REWIND(pkt);
1.1 misho 523: switch (ntohs(tftp->tftp_opc)) {
524: case TFTP_OPC_RRQ:
525: case TFTP_OPC_WRQ:
526: schedEvent(TASK_ROOT(task), RQ, NULL, TASK_FD(task),
527: TASK_DATA(task), rlen);
528: break;
529: case TFTP_OPC_ERROR:
530: default:
531: RPACK_REWIND(pkt);
532: code = htons(TFTP_OPC_ERROR);
533: rpack_uint16(pkt, &code, 0);
1.5 misho 534: code = htons(4);
1.1 misho 535: rpack_uint16(pkt, &code, 0);
536: rpack_rdata(pkt, errs[4].err_msg, strlen(errs[4].err_msg) + 1);
537:
538: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
539: TASK_DATA(task), RPACK_OFF(pkt));
540: goto end;
541: }
542: } else if (memcmp(&cli.addr, &sa, salen)) {
543: EERROR(LOG_WARNING, "Packet dropped!!!\n"
544: "Get frame from different address for this session");
545: goto end;
546: } else
547: switch (ntohs(tftp->tftp_opc)) {
548: case TFTP_OPC_ACK:
549: schedEvent(TASK_ROOT(task), ACK, NULL, TASK_FD(task),
550: TASK_DATA(task), rlen);
551: break;
552: case TFTP_OPC_DATA:
553: schedEvent(TASK_ROOT(task), DATA, NULL, TASK_FD(task),
554: TASK_DATA(task), rlen);
555: break;
556: case TFTP_OPC_OACK:
557: case TFTP_OPC_ERROR:
558: default:
559: RPACK_REWIND(pkt);
560: code = htons(TFTP_OPC_ERROR);
561: rpack_uint16(pkt, &code, 0);
1.5 misho 562: code = htons(4);
1.1 misho 563: rpack_uint16(pkt, &code, 0);
564: rpack_rdata(pkt, errs[4].err_msg, strlen(errs[4].err_msg) + 1);
565:
566: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
567: TASK_DATA(task), RPACK_OFF(pkt));
568: goto end;
569: }
570:
571: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL, timeoutSession, NULL);
1.4 misho 572: schedTimer(TASK_ROOT(task), timeoutSession, NULL,
573: cli.tout.tv_sec ? cli.tout : timeout, TASK_DATA(task), 0);
1.1 misho 574: end:
575: schedReadSelf(task);
576: taskExit(task, NULL);
577: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>