Annotation of tftpd/src/tftpd.c, revision 1.1.1.1

1.1       misho       1: #include "global.h"
                      2: #include "srv.h"
                      3: 
                      4: 
                      5: intptr_t Kill;
                      6: struct tagCli cli;
                      7: cfg_root_t cfg;
                      8: sched_root_task_t *root;
                      9: char szCfgName[PATH_MAX] = DEFAULT_CFGNAME;
                     10: struct timespec timeout = { DEFAULT_TIMEOUT, 0 };
                     11: extern char compiled[], compiledby[], compilehost[];
                     12: 
                     13: const struct tagErr errs[9] = {
                     14:        { 0, "Not defined" }, 
                     15:        { 1, "File not found" }, 
                     16:        { 2, "Access violation" }, 
                     17:        { 3, "Disk full or allocation exceeded" }, 
                     18:        { 4, "Illegal TFTP operation" }, 
                     19:        { 5, "Unknown transfer ID" }, 
                     20:        { 6, "File already exists" }, 
                     21:        { 7, "No such user" }, 
                     22:        { 8, "Option not supported" }, 
                     23: };
                     24: 
                     25: static void
                     26: Usage()
                     27: {
                     28:        printf( " -= TFTPd =- ELWIX extended TFTP service\n"
                     29:                "=== %s === %s@%s ===\n\n"
                     30:                " Syntax: TFTPd [options]\n\n"
                     31:                "\t-c <config>\tConfig file [default=/etc/tftpd.conf]\n"
                     32:                "\t-w\t\tSwitch to read-write mode [default=read-only]\n"
                     33:                "\t-b\t\tRun into batch mode (default is daemon mode)\n"
                     34:                "\t-v\t\tVerbose (more -v, more verbosity ...)\n"
                     35:                "\t-h\t\tThis help screen!\n"
                     36:                "\n", compiled, compiledby, compilehost);
                     37: }
                     38: 
                     39: static void *
                     40: sigHandler(sched_task_t *task)
                     41: {
                     42:        int stat;
                     43:        const char *str;
                     44: 
                     45:        switch (TASK_VAL(task)) {
                     46:                case SIGHUP:
                     47:                        cfgUnloadConfig(&cfg);
                     48:                        if (cfgLoadConfig(szCfgName, &cfg)) {
                     49:                                ELIBERR(cfg);
                     50:                                Kill++;
                     51:                        } else
                     52:                                EVERBOSE(1, "Reloading config ...");
                     53: 
                     54:                        str = cfg_getAttribute(&cfg, "tftpd", "timeout");
                     55:                        if (str)
                     56:                                timeout.tv_sec = strtol(str, NULL, 10);
                     57:                        break;
                     58:                case SIGINT:
                     59:                case SIGTERM:
                     60:                        EVERBOSE(1, "Terminate service ...");
                     61:                        Kill++;
                     62:                        break;
                     63:                case SIGCHLD:
                     64:                        while (waitpid(-1, &stat, WNOHANG) > 0);
                     65:                        break;
                     66:                default:
                     67:                        EERROR(EINVAL, "Unknown signal #%lu?", TASK_VAL(task));
                     68:                        break;
                     69:        }
                     70: 
                     71:        schedSignalSelf(task);
                     72:        taskExit(task, NULL);
                     73: }
                     74: 
                     75: int
                     76: main(int argc, char **argv)
                     77: {
                     78:        char ch, m = 0, b = 0;
                     79:        const char *str;
                     80:        int fd, uid = 0, ret = 0;
                     81:        struct passwd *pass;
                     82:        pid_t pid;
                     83:        sockaddr_t sa;
                     84:        rpack_t *pkt = NULL;
                     85: 
                     86:        while ((ch = getopt(argc, argv, "hvbwc:")) != -1)
                     87:                switch (ch) {
                     88:                        case 'c':
                     89:                                strlcpy(szCfgName, optarg, sizeof szCfgName);
                     90:                                break;
                     91:                        case 'w':
                     92:                                m = 42; /* rw mode */
                     93:                                break;
                     94:                        case 'v':
                     95:                                e_incVerbose;
                     96:                                break;
                     97:                        case 'b':
                     98:                                b = 42;
                     99:                                break;
                    100:                        case 'h':
                    101:                        default:
                    102:                                Usage();
                    103:                                return 1;
                    104:                }
                    105:        argc -= optind;
                    106:        argv += optind;
                    107: 
                    108:        openlog("TFTPd", LOG_PID | LOG_CONS, LOG_FTP);
                    109:        if (cfgLoadConfig(szCfgName, &cfg)) {
                    110:                ELIBERR(cfg);
                    111:                return 2;
                    112:        }
                    113: 
                    114:        str = cfg_getAttribute(&cfg, "tftpd", "user");
                    115:        if (str) {
                    116:                pass = getpwnam(str);
                    117:                if (!pass) {
                    118:                        EERROR(EINVAL, "User %s not found!\n", str);
                    119:                        ret = 2;
                    120:                        goto end;
                    121:                } else
                    122:                        uid = pass->pw_uid;
                    123:                endpwent();
                    124:        }
                    125: 
                    126:        if (!b) /* service mode */
                    127:                switch ((pid = fork())) {
                    128:                        case -1:
                    129:                                ret = 3;
                    130:                                goto end;
                    131:                        case 0:
                    132:                                setsid();
                    133:                                chdir("/");
                    134: 
                    135:                                fd = open(_PATH_DEVNULL, O_RDWR);
                    136:                                if (fd > 2) {
                    137:                                        dup2(fd, STDIN_FILENO);
                    138:                                        dup2(fd, STDOUT_FILENO);
                    139:                                        dup2(fd, STDERR_FILENO);
                    140:                                        close(fd);
                    141:                                }
                    142:                                EVERBOSE(1, "Welcome to the shadow-land!\n");
                    143:                                break;
                    144:                        default:
                    145:                                EVERBOSE(1, "Starting service with pid=%d ...\n", pid);
                    146:                                goto end;
                    147:                }
                    148: 
                    149:        root = schedBegin();
                    150:        if (!root) {
                    151:                ELIBERR(sched);
                    152:                ret = 3;
                    153:                goto end;
                    154:        }
                    155: 
                    156:        str = cfg_getAttribute(&cfg, "tftpd", "timeout");
                    157:        if (str)
                    158:                timeout.tv_sec = strtol(str, NULL, 10);
                    159: 
                    160:        str = cfg_getAttribute(&cfg, "tftpd", "port");
                    161:        if (str)
                    162:                fd = strtol(str, NULL, 10);
                    163:        else
                    164:                fd = 69;
                    165:        str = cfg_getAttribute(&cfg, "tftpd", "bind");
                    166:        e_gethostbyname(str ? str : "0.0.0.0", fd, &sa);
                    167:        fd = socket(sa.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
                    168:        if (fd == -1) {
                    169:                ESYSERR(0);
                    170:                ret = 4;
                    171:                goto end;
                    172:        }
                    173:        if (bind(fd, &sa.sa, sa.sa.sa_len) == -1) {
                    174:                ESYSERR(0);
                    175:                close(fd);
                    176:                ret = 4;
                    177:                goto end;
                    178:        }
                    179: 
                    180:        str = cfg_getAttribute(&cfg, "tftpd", "chroot");
                    181:        if (str && chroot(str) == -1) {
                    182:                ESYSERR(0);
                    183:                close(fd);
                    184:                ret = 3;
                    185:                goto end;
                    186:        } else {
                    187:                setuid(uid);
                    188:                str = cfg_getAttribute(&cfg, "tftpd", "dir");
                    189:                if (str)
                    190:                        chdir(str);
                    191:        }
                    192: 
                    193:        if (!(pkt = rpack_create(NULL, 0))) {
                    194:                ELIBERR(elwix);
                    195:                close(fd);
                    196:                ret = 5;
                    197:                goto end;
                    198:        }
                    199:        if (rpack_attach(pkt, TFTP_PKT_MAX)) {
                    200:                ELIBERR(elwix);
                    201:                close(fd);
                    202:                ret = 5;
                    203:                goto end;
                    204:        }
                    205: 
                    206:        memset(&cli, 0, sizeof cli);
                    207:        schedSignal(root, sigHandler, NULL, SIGHUP, NULL, 0);
                    208:        schedSignal(root, sigHandler, NULL, SIGTERM, NULL, 0);
                    209:        schedSignal(root, sigHandler, NULL, SIGINT, NULL, 0);
                    210:        schedSignal(root, sigHandler, NULL, SIGCHLD, NULL, 0);
                    211:        schedRead(root, rxPkt, NULL, fd, pkt, sizeof(rpack_t));
                    212:        schedRun(root, &Kill);
                    213: 
                    214:        close(fd);
                    215: end:
                    216:        schedEnd(&root);
                    217:        rpack_detach(pkt);
                    218:        rpack_destroy(&pkt);
                    219:        cfgUnloadConfig(&cfg);
                    220:        closelog();
                    221:        return ret;
                    222: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>