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