[BACK]Return to bgplg.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / bgplg

Annotation of src/usr.bin/bgplg/bgplg.c, Revision 1.1

1.1     ! reyk        1: /*     $OpenBSD$       */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2005, 2006 Reyk Floeter <reyk@vantronix.net>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: #include <sys/stat.h>
        !            20: #include <sys/types.h>
        !            21: #include <sys/param.h>
        !            22:
        !            23: #include <stdio.h>
        !            24: #include <stdlib.h>
        !            25: #include <signal.h>
        !            26: #include <string.h>
        !            27: #include <unistd.h>
        !            28: #include <ctype.h>
        !            29: #include <errno.h>
        !            30: #include <fcntl.h>
        !            31:
        !            32: #include "bgplg.h"
        !            33:
        !            34: #define INC_STYLE      "/conf/bgplg.css"
        !            35: #define INC_HEAD       "/conf/bgplg.head"
        !            36: #define INC_FOOT       "/conf/bgplg.foot"
        !            37:
        !            38: #define BGPDSOCK       "/logs/bgpd.rsock"
        !            39: #define BGPCTL         "/bin/bgpctl", "-s", BGPDSOCK
        !            40: #define PING           "/bin/ping"
        !            41: #define TRACEROUTE     "/bin/traceroute"
        !            42:
        !            43: static struct cmd cmds[] = CMDS;
        !            44:
        !            45: char            *lg_getenv(const char *, int *);
        !            46: void             lg_urldecode(char *);
        !            47: char           **lg_arg2argv(char *, int *);
        !            48: char           **lg_argextra(char **, int, struct cmd *);
        !            49: char            *lg_getarg(const char *, char *, int);
        !            50: int              lg_incl(const char *);
        !            51:
        !            52: void
        !            53: lg_urldecode(char *str)
        !            54: {
        !            55:        size_t i, c, len;
        !            56:        char code[3];
        !            57:        long result;
        !            58:
        !            59:        if (str && *str) {
        !            60:                len = strlen(str);
        !            61:                i = c = 0;
        !            62:                while (i < len) {
        !            63:                        if (str[i] == '%' && i <= (len - 2)) {
        !            64:                                if (isxdigit(str[i + 1]) &&
        !            65:                                    isxdigit(str[i + 2])) {
        !            66:                                        code[0] = str[i + 1];
        !            67:                                        code[1] = str[i + 2];
        !            68:                                        code[2] = 0;
        !            69:                                        result = strtol(code, NULL, 16);
        !            70:                                        /* Replace NUL chars with a space */
        !            71:                                        if (result == 0)
        !            72:                                                result = ' ';
        !            73:                                        str[c++] = result;
        !            74:                                        i += 3;
        !            75:                                } else {
        !            76:                                        str[c++] = '%';
        !            77:                                        i++;
        !            78:                                }
        !            79:                        } else if (str[i] == '+') {
        !            80:                                str[i] = ' ';
        !            81:                        } else {
        !            82:                                if (c != i)
        !            83:                                        str[c] = str[i];
        !            84:                                c++;
        !            85:                                i++;
        !            86:                        }
        !            87:                }
        !            88:                str[c] = 0x0;
        !            89:        }
        !            90: }
        !            91:
        !            92: char *
        !            93: lg_getenv(const char *name, int *lenp)
        !            94: {
        !            95:        size_t len;
        !            96:        u_int i;
        !            97:        char *ptr;
        !            98:
        !            99:        if ((ptr = getenv(name)) == NULL)
        !           100:                return (NULL);
        !           101:
        !           102:        lg_urldecode(ptr);
        !           103:
        !           104:        if (!(len = strlen(ptr)))
        !           105:                return (NULL);
        !           106:
        !           107:        if (lenp != NULL)
        !           108:                *lenp = len;
        !           109:
        !           110: #define allowed_in_string(_x)                                           \
        !           111:         ((isalnum(_x) || isprint(_x)) &&                               \
        !           112:         (_x != '%' && _x != '\\' && _x != ';' && _x != '|'))
        !           113:
        !           114:        for (i = 0; i < len; i++) {
        !           115:                if (!allowed_in_string(ptr[i])) {
        !           116:                        printf("invalid character in input\n");
        !           117:                        return (NULL);
        !           118:                }
        !           119:                if (ptr[i] == '&')
        !           120:                        ptr[i] = '\0';
        !           121:        }
        !           122:
        !           123:        return (ptr);
        !           124: }
        !           125:
        !           126: char *
        !           127: lg_getarg(const char *name, char *arg, int len)
        !           128: {
        !           129:        char *ptr = arg;
        !           130:        size_t namelen, ptrlen;
        !           131:        int i;
        !           132:
        !           133:        namelen = strlen(name);
        !           134:
        !           135:        for (i = 0; i < len; i++) {
        !           136:                if (arg[i] == '\0')
        !           137:                        continue;
        !           138:                ptr = arg + i;
        !           139:                ptrlen = strlen(ptr);
        !           140:                if (namelen >= ptrlen)
        !           141:                        continue;
        !           142:                if (strncmp(name, ptr, namelen) == 0)
        !           143:                        return (ptr + namelen);
        !           144:        }
        !           145:
        !           146:        return (NULL);
        !           147: }
        !           148:
        !           149: char **
        !           150: lg_arg2argv(char *arg, int *argc)
        !           151: {
        !           152:        char **argv, *ptr = arg;
        !           153:        size_t len;
        !           154:        u_int i, c = 1;
        !           155:
        !           156:        len = strlen(arg);
        !           157:
        !           158:        /* Count elements */
        !           159:        for (i = 0; i < (len - 1); i++) {
        !           160:                if (isspace(arg[i])) {
        !           161:                        /* filter out additional options */
        !           162:                        if (arg[i + 1] == '-') {
        !           163:                                printf("invalid input\n");
        !           164:                                return (NULL);
        !           165:                        }
        !           166:                        arg[i] = '\0';
        !           167:                        c++;
        !           168:                }
        !           169:        }
        !           170:
        !           171:        /* Generate array */
        !           172:        if ((argv = calloc(c + 1, sizeof(char *))) == NULL) {
        !           173:                printf("fatal error: %s\n", strerror(errno));
        !           174:                return (NULL);
        !           175:        }
        !           176:
        !           177:        argv[c] = NULL;
        !           178:        *argc = c;
        !           179:
        !           180:        /* Fill array */
        !           181:        for (i = c = 0; i < (len - 1); i++) {
        !           182:                if (arg[i] == '\0' || i == 0) {
        !           183:                        if (i != 0)
        !           184:                                ptr = &arg[i + 1];
        !           185:                        argv[c++] = ptr;
        !           186:                }
        !           187:        }
        !           188:
        !           189:        return (argv);
        !           190: }
        !           191:
        !           192: char **
        !           193: lg_argextra(char **argv, int argc, struct cmd *cmdp)
        !           194: {
        !           195:        char **new_argv;
        !           196:        int i, c = 0;
        !           197:
        !           198:        /* Count elements */
        !           199:        for (i = 0; cmdp->earg[i] != NULL; i++)
        !           200:                c++;
        !           201:
        !           202:        /* Generate array */
        !           203:        if ((new_argv = calloc(c + argc + 1, sizeof(char *))) == NULL) {
        !           204:                printf("fatal error: %s\n", strerror(errno));
        !           205:                return (NULL);
        !           206:        }
        !           207:
        !           208:        /* Fill array */
        !           209:        for (i = c = 0; cmdp->earg[i] != NULL; i++)
        !           210:                new_argv[c++] = cmdp->earg[i];
        !           211:
        !           212:        /* Append old array */
        !           213:        for (i = 0; i < argc; i++)
        !           214:                new_argv[c++] = argv[i];
        !           215:
        !           216:        new_argv[c] = NULL;
        !           217:
        !           218:        if (argv != NULL)
        !           219:                free(argv);
        !           220:
        !           221:        return (new_argv);
        !           222: }
        !           223:
        !           224: int
        !           225: lg_incl(const char *file)
        !           226: {
        !           227:        char buf[BUFSIZ];
        !           228:        int fd, len;
        !           229:
        !           230:        if ((fd = open(file, O_RDONLY)) == -1)
        !           231:                return (errno);
        !           232:
        !           233:        do {
        !           234:                len = read(fd, buf, sizeof(buf));
        !           235:                fwrite(buf, len, 1, stdout);
        !           236:        } while(len == BUFSIZ);
        !           237:
        !           238:        return (0);
        !           239: }
        !           240:
        !           241: int
        !           242: main(void)
        !           243: {
        !           244:        char *query, *self, *cmd = NULL, *req;
        !           245:        char **argv = NULL;
        !           246:        char myname[MAXHOSTNAMELEN];
        !           247:        int ret = 1, argc = 0, query_length = 0;
        !           248:        struct stat st;
        !           249:        u_int i;
        !           250:        struct cmd *cmdp = NULL;
        !           251:
        !           252:        printf("Content-Type: text/html\n"
        !           253:            "Cache-Control: no-cache\n\n"
        !           254:            "<html>\n"
        !           255:            "<head>\n"
        !           256:            "<title>bgplg</title>\n");
        !           257:        if (stat(INC_STYLE, &st) == 0) {
        !           258:                printf("<style type='text/css'><!--\n");
        !           259:                lg_incl(INC_STYLE);
        !           260:                printf("--></style>\n");
        !           261:        }
        !           262:        if (stat(INC_HEAD, &st) != 0 || lg_incl(INC_HEAD) != 0) {
        !           263:                printf("</head>\n"
        !           264:                    "<body>\n");
        !           265:        }
        !           266:
        !           267:        if (gethostname(myname, sizeof(myname)) != 0)
        !           268:                goto err;
        !           269:
        !           270:        printf("<h1>%s: %s</h1>\n", NAME, myname);
        !           271:        printf("<h2>%s</h2>\n", BRIEF);
        !           272:
        !           273:        /* print a form with possible options */
        !           274:        if ((self = lg_getenv("SCRIPT_NAME", NULL)) == NULL) {
        !           275:                printf("fatal error: invalid request\n");
        !           276:                goto err;
        !           277:        }
        !           278:        if ((query = lg_getenv("QUERY_STRING", &query_length)) != NULL)
        !           279:                cmd = lg_getarg("cmd=", query, query_length);
        !           280:        printf("<form action='%s'>\n"
        !           281:            "<select name='cmd'>\n",
        !           282:            self);
        !           283:        for (i = 0; cmds[i].name != NULL; i++) {
        !           284:                if (!lg_checkperm(&cmds[i]))
        !           285:                        continue;
        !           286:
        !           287:                if (cmd != NULL && strcmp(cmd, cmds[i].name) == 0)
        !           288:                        printf("<option value='%s' selected='selected'>%s"
        !           289:                            "</option>\n",
        !           290:                            cmds[i].name, cmds[i].name);
        !           291:                else
        !           292:                        printf("<option value='%s'>%s</option>\n",
        !           293:                            cmds[i].name, cmds[i].name);
        !           294:        }
        !           295:        printf("</select>\n"
        !           296:            "<input type='text' name='req'/>\n"
        !           297:            "<input type='submit' value='submit'/>\n"
        !           298:            "</form>\n"
        !           299:            "<pre>\n");
        !           300:        fflush(stdout);
        !           301:
        !           302: #ifdef DEBUG
        !           303:        if (close(2) == -1 || dup2(1, 2) == -1)
        !           304: #else
        !           305:        if (close(2) == -1)
        !           306: #endif
        !           307:        {
        !           308:                printf("fatal error: %s\n", strerror(errno));
        !           309:                goto err;
        !           310:        }
        !           311:
        !           312:        if (query == NULL)
        !           313:                goto err;
        !           314:        if (cmd == NULL) {
        !           315:                printf("unspecified command\n");
        !           316:                goto err;
        !           317:        }
        !           318:        if ((req = lg_getarg("req=", query, query_length)) != NULL) {
        !           319:                /* Could be NULL */
        !           320:                argv = lg_arg2argv(req, &argc);
        !           321:        }
        !           322:
        !           323:        for (i = 0; cmds[i].name != NULL; i++) {
        !           324:                if (strcmp(cmd, cmds[i].name) == 0) {
        !           325:                        cmdp = &cmds[i];
        !           326:                        break;
        !           327:                }
        !           328:        }
        !           329:
        !           330:        if (cmdp == NULL) {
        !           331:                printf("invalid command: %s\n", cmd);
        !           332:                goto err;
        !           333:        }
        !           334:        if (argc > cmdp->maxargs) {
        !           335:                printf("superfluous argument(s): %s %s\n",
        !           336:                    cmd, cmdp->args ? cmdp->args : "");
        !           337:                goto err;
        !           338:        }
        !           339:        if (argc < cmdp->minargs) {
        !           340:                printf("missing argument(s): %s %s\n", cmd, cmdp->args);
        !           341:                goto err;
        !           342:        }
        !           343:
        !           344:        if (cmdp->func != NULL) {
        !           345:                ret = cmdp->func(cmds, argv);
        !           346:        } else {
        !           347:                if ((argv = lg_argextra(argv, argc, cmdp)) == NULL)
        !           348:                        goto err;
        !           349:                ret = lg_exec(cmdp->earg[0], argv);
        !           350:        }
        !           351:        if (ret != 0)
        !           352:                printf("\nfailed%s\n", ret == 127 ? ": file not found" : ".");
        !           353:        else
        !           354:                printf("\nsuccess.\n");
        !           355:
        !           356:  err:
        !           357:        fflush(stdout);
        !           358:
        !           359:        if (argv != NULL);
        !           360:                free(argv);
        !           361:
        !           362:        printf("</pre>\n");
        !           363:
        !           364:        if (stat(INC_FOOT, &st) != 0 || lg_incl(INC_FOOT) != 0)
        !           365:                printf("<hr/>\n");
        !           366:
        !           367:        printf("<div class='footer'>\n"
        !           368:            "<small>%s - %s<br/>Copyright (c) %s</small>\n"
        !           369:            "</div>\n"
        !           370:            "</body>\n"
        !           371:            "</html>\n", NAME, BRIEF, COPYRIGHT);
        !           372:
        !           373:        return (ret);
        !           374: }