Annotation of tftpd/src/tftpd.c, revision 1.2.2.2
1.2 misho 1: /*************************************************************************
2: * (C) 2014 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.2.2.2 ! misho 6: * $Id: tftpd.c,v 1.2.2.1 2014/02/21 15:49:51 misho Exp $
1.2 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"
47: #include "srv.h"
48:
49:
50: intptr_t Kill;
51: struct tagCli cli;
52: cfg_root_t cfg;
53: sched_root_task_t *root;
1.2.2.2 ! misho 54: ait_val_t *bufIO;
1.1 misho 55: char szCfgName[PATH_MAX] = DEFAULT_CFGNAME;
56: struct timespec timeout = { DEFAULT_TIMEOUT, 0 };
57: extern char compiled[], compiledby[], compilehost[];
58:
59: const struct tagErr errs[9] = {
60: { 0, "Not defined" },
61: { 1, "File not found" },
62: { 2, "Access violation" },
63: { 3, "Disk full or allocation exceeded" },
64: { 4, "Illegal TFTP operation" },
65: { 5, "Unknown transfer ID" },
66: { 6, "File already exists" },
67: { 7, "No such user" },
68: { 8, "Option not supported" },
69: };
70:
71: static void
72: Usage()
73: {
74: printf( " -= TFTPd =- ELWIX extended TFTP service\n"
75: "=== %s === %s@%s ===\n\n"
76: " Syntax: TFTPd [options]\n\n"
77: "\t-c <config>\tConfig file [default=/etc/tftpd.conf]\n"
78: "\t-w\t\tSwitch to read-write mode [default=read-only]\n"
79: "\t-b\t\tRun into batch mode (default is daemon mode)\n"
1.2.2.1 misho 80: "\t-d\t\tDebug program\n"
1.1 misho 81: "\t-v\t\tVerbose (more -v, more verbosity ...)\n"
82: "\t-h\t\tThis help screen!\n"
83: "\n", compiled, compiledby, compilehost);
84: }
85:
86: static void *
87: sigHandler(sched_task_t *task)
88: {
89: int stat;
90: const char *str;
91:
92: switch (TASK_VAL(task)) {
93: case SIGHUP:
94: cfgUnloadConfig(&cfg);
95: if (cfgLoadConfig(szCfgName, &cfg)) {
96: ELIBERR(cfg);
97: Kill++;
98: } else
99: EVERBOSE(1, "Reloading config ...");
100:
101: str = cfg_getAttribute(&cfg, "tftpd", "timeout");
102: if (str)
103: timeout.tv_sec = strtol(str, NULL, 10);
1.2.2.2 ! misho 104:
! 105: ait_freeVar(&bufIO);
! 106: str = cfg_getAttribute(&cfg, "tftpd", "buf_io");
! 107: if (str) {
! 108: bufIO = ait_allocVar();
! 109: if (bufIO)
! 110: AIT_SET_BUFSIZ(bufIO, 0, strtol(str, NULL, 0));
! 111: }
1.1 misho 112: break;
113: case SIGINT:
114: case SIGTERM:
115: EVERBOSE(1, "Terminate service ...");
116: Kill++;
117: break;
118: case SIGCHLD:
119: while (waitpid(-1, &stat, WNOHANG) > 0);
120: break;
121: default:
122: EERROR(EINVAL, "Unknown signal #%lu?", TASK_VAL(task));
123: break;
124: }
125:
126: schedSignalSelf(task);
127: taskExit(task, NULL);
128: }
129:
130: int
131: main(int argc, char **argv)
132: {
133: char ch, m = 0, b = 0;
134: const char *str;
135: int fd, uid = 0, ret = 0;
136: struct passwd *pass;
137: pid_t pid;
138: sockaddr_t sa;
139: rpack_t *pkt = NULL;
140:
1.2.2.1 misho 141: while ((ch = getopt(argc, argv, "hvdbwc:")) != -1)
1.1 misho 142: switch (ch) {
143: case 'c':
144: strlcpy(szCfgName, optarg, sizeof szCfgName);
145: break;
146: case 'w':
147: m = 42; /* rw mode */
148: break;
149: case 'v':
150: e_incVerbose;
151: break;
1.2.2.1 misho 152: case 'd':
153: elwix_Debug |= ELWIX_DEBUG_TRACE;
154: break;
1.1 misho 155: case 'b':
156: b = 42;
157: break;
158: case 'h':
159: default:
160: Usage();
161: return 1;
162: }
163: argc -= optind;
164: argv += optind;
165:
166: openlog("TFTPd", LOG_PID | LOG_CONS, LOG_FTP);
167: if (cfgLoadConfig(szCfgName, &cfg)) {
168: ELIBERR(cfg);
169: return 2;
170: }
171:
172: str = cfg_getAttribute(&cfg, "tftpd", "user");
173: if (str) {
174: pass = getpwnam(str);
175: if (!pass) {
176: EERROR(EINVAL, "User %s not found!\n", str);
177: ret = 2;
178: goto end;
179: } else
180: uid = pass->pw_uid;
181: endpwent();
182: }
183:
184: if (!b) /* service mode */
185: switch ((pid = fork())) {
186: case -1:
187: ret = 3;
188: goto end;
189: case 0:
190: setsid();
191: chdir("/");
192:
193: fd = open(_PATH_DEVNULL, O_RDWR);
194: if (fd > 2) {
195: dup2(fd, STDIN_FILENO);
196: dup2(fd, STDOUT_FILENO);
197: dup2(fd, STDERR_FILENO);
198: close(fd);
199: }
200: EVERBOSE(1, "Welcome to the shadow-land!\n");
201: break;
202: default:
203: EVERBOSE(1, "Starting service with pid=%d ...\n", pid);
204: goto end;
205: }
206:
207: root = schedBegin();
208: if (!root) {
209: ELIBERR(sched);
210: ret = 3;
211: goto end;
212: }
213:
214: str = cfg_getAttribute(&cfg, "tftpd", "timeout");
215: if (str)
216: timeout.tv_sec = strtol(str, NULL, 10);
217:
218: str = cfg_getAttribute(&cfg, "tftpd", "port");
219: if (str)
220: fd = strtol(str, NULL, 10);
221: else
222: fd = 69;
223: str = cfg_getAttribute(&cfg, "tftpd", "bind");
224: e_gethostbyname(str ? str : "0.0.0.0", fd, &sa);
225: fd = socket(sa.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
226: if (fd == -1) {
227: ESYSERR(0);
228: ret = 4;
229: goto end;
230: }
231: if (bind(fd, &sa.sa, sa.sa.sa_len) == -1) {
232: ESYSERR(0);
233: close(fd);
234: ret = 4;
235: goto end;
236: }
237:
238: str = cfg_getAttribute(&cfg, "tftpd", "chroot");
239: if (str && chroot(str) == -1) {
240: ESYSERR(0);
241: close(fd);
242: ret = 3;
243: goto end;
244: } else {
245: setuid(uid);
246: str = cfg_getAttribute(&cfg, "tftpd", "dir");
247: if (str)
248: chdir(str);
249: }
250:
1.2.2.2 ! misho 251: str = cfg_getAttribute(&cfg, "tftpd", "buf_io");
! 252: if (str) {
! 253: bufIO = ait_allocVar();
! 254: if (bufIO)
! 255: AIT_SET_BUFSIZ(bufIO, 0, strtol(str, NULL, 0));
! 256: }
! 257:
1.1 misho 258: if (!(pkt = rpack_create(NULL, 0))) {
259: ELIBERR(elwix);
260: close(fd);
261: ret = 5;
262: goto end;
263: }
264: if (rpack_attach(pkt, TFTP_PKT_MAX)) {
265: ELIBERR(elwix);
266: close(fd);
267: ret = 5;
268: goto end;
269: }
270:
271: memset(&cli, 0, sizeof cli);
272: schedSignal(root, sigHandler, NULL, SIGHUP, NULL, 0);
273: schedSignal(root, sigHandler, NULL, SIGTERM, NULL, 0);
274: schedSignal(root, sigHandler, NULL, SIGINT, NULL, 0);
275: schedSignal(root, sigHandler, NULL, SIGCHLD, NULL, 0);
276: schedRead(root, rxPkt, NULL, fd, pkt, sizeof(rpack_t));
277: schedRun(root, &Kill);
278:
279: close(fd);
280: end:
281: schedEnd(&root);
282: rpack_detach(pkt);
283: rpack_destroy(&pkt);
1.2.2.2 ! misho 284: ait_freeVar(&bufIO);
1.1 misho 285: cfgUnloadConfig(&cfg);
286: closelog();
287: return ret;
288: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>