Annotation of tftpd/src/srv.c, revision 1.7.2.1
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.2.1 ! misho 6: * $Id: srv.c,v 1.7 2014/02/24 15:23:39 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));
1.7.2.1 ! misho 288: if (!RW && cli.opc == TFTP_OPC_WRQ) {
! 289: code = 2;
! 290: goto end;
! 291: }
1.4 misho 292: len = str_getString(RPACK_NEXT(pkt), rlen, &str);
1.1 misho 293: if (len == -1)
294: goto end;
295: else {
1.4 misho 296: strlcpy(cli.file, (char*) RPACK_NEXT(pkt), sizeof cli.file);
1.1 misho 297: rlen -= len;
1.4 misho 298: rpack_rnext(pkt, len);
1.1 misho 299: }
1.4 misho 300: len = str_getString((const u_char*) str, rlen, NULL);
1.1 misho 301: if (len == -1)
302: goto end;
303: else {
304: rlen -= len;
1.4 misho 305: rpack_rnext(pkt, len);
1.1 misho 306: if (!strcasecmp(str, TFTP_MODE_ASCII))
307: strlcpy(cli.mode, TFTP_MODE_ASCII, sizeof cli.mode);
308: else if (!strcasecmp(str, TFTP_MODE_OCTET))
309: strlcpy(cli.mode, TFTP_MODE_OCTET, sizeof cli.mode);
310: else if (!strcasecmp(str, TFTP_MODE_MAIL)) {
311: strlcpy(cli.mode, TFTP_MODE_MAIL, sizeof cli.mode);
1.5 misho 312: code = htons(4);
1.1 misho 313: goto end;
314: } else {
1.5 misho 315: code = htons(1);
1.1 misho 316: goto end;
317: }
318: }
319:
320: switch (cli.opc) {
321: case TFTP_OPC_RRQ:
322: code = O_RDONLY;
323: EVERBOSE(2, "RRQ:: file=%s mode=%s\n", cli.file, cli.mode);
324: break;
325: case TFTP_OPC_WRQ:
326: code = O_WRONLY | O_CREAT;
327: str = (char*) cfg_getAttribute(&cfg, "tftpd", "override");
328: if (!str || tolower(*str) != 'y')
329: code |= O_EXCL;
330: EVERBOSE(2, "WRQ:: file=%s mode=%s\n", cli.file, cli.mode);
331: break;
332: }
1.4 misho 333:
1.1 misho 334: cli.fd = open(cli.file, code, 0644);
335: if (cli.fd == -1) {
336: if (errno == EACCES)
1.5 misho 337: code = htons(2);
1.1 misho 338: else if (errno == ENFILE)
1.5 misho 339: code = htons(3);
1.1 misho 340: else if (errno == EEXIST)
1.5 misho 341: code = htons(6);
1.7 misho 342: else if (errno == ENOENT)
343: code = htons(1);
1.1 misho 344: else
1.5 misho 345: code = htons(0);
1.1 misho 346: ESYSERR(0);
347: goto end;
348: } else
349: cli.seq = 0;
350:
1.2 misho 351: schedEvent(TASK_ROOT(task), execProg, "request", 0, NULL, cli.opc);
352:
1.4 misho 353: if (!getOpts(pkt, rlen)) {
354: if (cli.tmp > TFTP_LOAD_MAX) {
355: if (rpack_resize(pkt, cli.tmp + 4))
356: ELIBERR(elwix);
357: else
358: cli.siz = cli.tmp;
359: }
360: if (cli.tout.tv_sec) {
361: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL,
362: timeoutSession, NULL);
363: schedTimer(TASK_ROOT(task), timeoutSession, NULL,
364: cli.tout, TASK_DATA(task), 0);
365: }
366: schedEvent(TASK_ROOT(task), txOack, NULL, TASK_FD(task),
367: TASK_DATA(task), 0);
368: } else if (cli.opc == TFTP_OPC_WRQ) {
1.1 misho 369: /* ack */
370: tftp->tftp_opc = htons(TFTP_OPC_ACK);
371: RPACK_REWIND(pkt);
372: rpack_uint16(pkt, NULL, 0);
373: rpack_uint16(pkt, &cli.seq, 0);
374:
375: schedEvent(TASK_ROOT(task), txPkt, NULL, TASK_FD(task),
376: TASK_DATA(task), RPACK_OFF(pkt));
377: } else
378: schedEvent(TASK_ROOT(task), txData, NULL, TASK_FD(task),
379: TASK_DATA(task), 0);
380:
381: cli.seq = 1; /* 1st ack */
382: taskExit(task, NULL);
383: end:
384: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
385: RPACK_REWIND(pkt);
386: rpack_uint16(pkt, NULL, 0);
387: rpack_uint16(pkt, &code, 0);
1.5 misho 388: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 389:
390: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
391: TASK_DATA(task), RPACK_OFF(pkt));
392: taskExit(task, NULL);
393: }
394:
395: static void *
396: ACK(sched_task_t *task)
397: {
398: rpack_t *pkt = TASK_DATA(task);
399: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
400: u_short code;
401:
402: ETRACE();
403:
404: RPACK_REWIND(pkt);
405: code = rpack_uint16(pkt, NULL, 0);
406: if (ntohs(code) != TFTP_OPC_ACK) {
1.5 misho 407: code = htons(5);
1.1 misho 408: goto end;
409: }
410:
411: code = rpack_uint16(pkt, NULL, 0);
412: if (ntohs(code) > cli.seq || (ntohs(code) < (cli.seq - 1))) {
1.5 misho 413: code = htons(5);
1.1 misho 414: goto end;
1.4 misho 415: } else if (ntohs(code) == cli.seq) {
416: /* check for rollover seq id */
417: if (cli.roll && cli.seq == USHRT_MAX)
1.5 misho 418: cli.seq = cli.roll - 1;
1.4 misho 419: else
420: cli.seq++;
421: }
1.1 misho 422:
423: EVERBOSE(3, "ACK:: seq=%hu; my new seq=%hu;", ntohs(code), cli.seq);
424:
425: if (!cli.close)
426: schedEvent(TASK_ROOT(task), txData, NULL, TASK_FD(task),
427: TASK_DATA(task), 0);
428: else {
1.2 misho 429: schedEvent(TASK_ROOT(task), execProg, "complete", 0, NULL, TFTP_OPC_RRQ);
1.1 misho 430: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL, timeoutSession, NULL);
1.4 misho 431: schedEvent(TASK_ROOT(task), timeoutSession, NULL, 0, TASK_DATA(task), 0);
1.1 misho 432: EVERBOSE(2, "Finish RRQ request");
433: }
434: taskExit(task, NULL);
435: end:
436: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
437: RPACK_REWIND(pkt);
438: rpack_uint16(pkt, NULL, 0);
439: rpack_uint16(pkt, &code, 0);
1.5 misho 440: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 441:
442: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
443: TASK_DATA(task), RPACK_OFF(pkt));
444: taskExit(task, NULL);
445: }
446:
447: static void *
448: DATA(sched_task_t *task)
449: {
450: rpack_t *pkt = TASK_DATA(task);
451: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
452: u_short code;
453: int len;
454:
455: ETRACE();
456:
457: RPACK_REWIND(pkt);
458: code = rpack_uint16(pkt, NULL, 0);
459: if (ntohs(code) != TFTP_OPC_DATA) {
1.5 misho 460: code = htons(5);
1.1 misho 461: goto end;
462: }
463:
464: code = rpack_uint16(pkt, NULL, 0);
465: if (ntohs(code) < cli.seq || ntohs(code) > cli.seq + 1) {
1.5 misho 466: code = htons(5);
1.1 misho 467: goto end;
468: } else
469: cli.seq = ntohs(code);
470:
1.4 misho 471: /* max file size check */
1.1 misho 472: len = TASK_DATLEN(task) - RPACK_OFF(pkt);
1.4 misho 473: if (cli.tsiz && cli.tsiz < cli.seq * cli.siz)
474: len = MIN(len, cli.tsiz - (cli.seq - 1) * cli.siz);
1.1 misho 475: if (len < cli.siz)
476: cli.close = 42; /* last received packet, should be close! */
477:
478: EVERBOSE(3, "DATA:: seq=%hu; len=%d", cli.seq, len);
479:
1.7 misho 480: if (!bf)
481: len = pwrite(cli.fd, RPACK_NEXT(pkt), len, (cli.seq - 1) * cli.siz);
482: else
483: len = bfwrite(cli.fd, RPACK_NEXT(pkt), len);
1.1 misho 484: if (len == -1) {
485: ESYSERR(0);
1.5 misho 486: code = htons(3);
1.1 misho 487: goto end;
488: } else {
489: rpack_rnext(pkt, len);
490: EVERBOSE(3, "Written to file %s %d bytes", cli.file, len);
491: }
492:
493: schedEvent(TASK_ROOT(task), txAck, NULL, TASK_FD(task), TASK_DATA(task), 0);
494: taskExit(task, NULL);
495: end:
496: tftp->tftp_opc = htons(TFTP_OPC_ERROR);
497: RPACK_REWIND(pkt);
498: rpack_uint16(pkt, NULL, 0);
499: rpack_uint16(pkt, &code, 0);
1.5 misho 500: rpack_rdata(pkt, errs[ntohs(code)].err_msg, strlen(errs[ntohs(code)].err_msg) + 1);
1.1 misho 501:
502: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
503: TASK_DATA(task), RPACK_OFF(pkt));
504: taskExit(task, NULL);
505: }
506:
507: void *
508: rxPkt(sched_task_t *task)
509: {
510: sockaddr_t sa;
511: socklen_t salen = sizeof sa;
512: int rlen;
513: rpack_t *pkt = TASK_DATA(task);
514: struct tftp_hdr *tftp = (struct tftp_hdr*) RPACK_BUF(pkt);
515: u_short code;
516:
517: ETRACE();
518:
519: memset(RPACK_BUF(pkt), 0, RPACK_LEN(pkt));
520: rlen = recvfrom(TASK_FD(task), RPACK_BUF(pkt), RPACK_LEN(pkt), 0, &sa.sa, &salen);
521: if (rlen == -1) {
522: ESYSERR(0);
523: goto end;
524: } else if (!cli.addr.sa.sa_len) {
525: cli.addr = sa;
1.4 misho 526: RPACK_REWIND(pkt);
1.1 misho 527: switch (ntohs(tftp->tftp_opc)) {
528: case TFTP_OPC_RRQ:
529: case TFTP_OPC_WRQ:
530: schedEvent(TASK_ROOT(task), RQ, NULL, TASK_FD(task),
531: TASK_DATA(task), rlen);
532: break;
533: case TFTP_OPC_ERROR:
534: default:
535: RPACK_REWIND(pkt);
536: code = htons(TFTP_OPC_ERROR);
537: rpack_uint16(pkt, &code, 0);
1.5 misho 538: code = htons(4);
1.1 misho 539: rpack_uint16(pkt, &code, 0);
540: rpack_rdata(pkt, errs[4].err_msg, strlen(errs[4].err_msg) + 1);
541:
542: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
543: TASK_DATA(task), RPACK_OFF(pkt));
544: goto end;
545: }
546: } else if (memcmp(&cli.addr, &sa, salen)) {
547: EERROR(LOG_WARNING, "Packet dropped!!!\n"
548: "Get frame from different address for this session");
549: goto end;
550: } else
551: switch (ntohs(tftp->tftp_opc)) {
552: case TFTP_OPC_ACK:
553: schedEvent(TASK_ROOT(task), ACK, NULL, TASK_FD(task),
554: TASK_DATA(task), rlen);
555: break;
556: case TFTP_OPC_DATA:
557: schedEvent(TASK_ROOT(task), DATA, NULL, TASK_FD(task),
558: TASK_DATA(task), rlen);
559: break;
560: case TFTP_OPC_OACK:
561: case TFTP_OPC_ERROR:
562: default:
563: RPACK_REWIND(pkt);
564: code = htons(TFTP_OPC_ERROR);
565: rpack_uint16(pkt, &code, 0);
1.5 misho 566: code = htons(4);
1.1 misho 567: rpack_uint16(pkt, &code, 0);
568: rpack_rdata(pkt, errs[4].err_msg, strlen(errs[4].err_msg) + 1);
569:
570: schedEvent(TASK_ROOT(task), txPkt, (void*) -1, TASK_FD(task),
571: TASK_DATA(task), RPACK_OFF(pkt));
572: goto end;
573: }
574:
575: schedCancelby(TASK_ROOT(task), taskTIMER, CRITERIA_CALL, timeoutSession, NULL);
1.4 misho 576: schedTimer(TASK_ROOT(task), timeoutSession, NULL,
577: cli.tout.tv_sec ? cli.tout : timeout, TASK_DATA(task), 0);
1.1 misho 578: end:
579: schedReadSelf(task);
580: taskExit(task, NULL);
581: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>