"Fossies" - the Fresh Open Source Software Archive

Member "pidentd-3.0.19/src/request.c" (13 Jun 2004, 6145 Bytes) of package /linux/misc/old/pidentd-3.0.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "request.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** request.c - Handle an IDENT protocol request
    3 **
    4 ** Copyright (c) 1997 Peter Eriksson <pen@lysator.liu.se>
    5 **
    6 ** This program is free software; you can redistribute it and/or
    7 ** modify it as you wish - as long as you don't claim that you wrote
    8 ** it.
    9 **
   10 ** This program is distributed in the hope that it will be useful,
   11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   13 */
   14 
   15 #include "config.h"
   16 
   17 #include <stdio.h>
   18 #include <ctype.h>
   19 #include <errno.h>
   20 #include <syslog.h>
   21 #include <stdlib.h>
   22 #include <string.h>
   23 #ifdef HAVE_UNISTD_H
   24 #include <unistd.h>
   25 #endif
   26 
   27 #include "pidentd.h"
   28 
   29 int extensions_enabled = 0;
   30 int multiquery_enabled = 0;
   31 int request_timeout = 120;  /* 2 minutes */
   32 
   33 int requests_max = 0;
   34 int requests_cur;
   35 pthread_mutex_t requests_mtx;
   36 pthread_cond_t requests_cv;
   37 
   38 
   39 static int
   40 handle_request(int fd,
   41            char *buf,
   42            struct sockaddr_gen *remote_addr)
   43 {
   44     struct kernel *kp;
   45     int local_port, remote_port;
   46     socklen_t len;
   47     char *cmd, *bp;
   48     
   49     
   50     if (debug)
   51     fprintf(stderr, "handle_request: fd#%d: '%s'\n", fd, buf);
   52 
   53     if (sscanf(buf, " %d , %d", &local_port, &remote_port) == 2)
   54     {
   55     if (local_port < 1 || local_port > 65535 ||
   56         remote_port < 1 || remote_port > 65535)
   57     {
   58         send_error(fd,
   59                local_port, remote_port,
   60                "INVALID-PORT",
   61                remote_addr);
   62         return 0;
   63     }
   64     
   65     kp = kernel_alloc();
   66     kp->remote = *remote_addr;
   67     SGPORT(kp->remote) = htons(remote_port);
   68     
   69     len = sizeof(kp->local);
   70     if (s_getsockname(fd, (struct sockaddr *) &kp->local, &len) < 0)
   71     {
   72         syslog(LOG_ERR, "s_getsockname(%d): %m", fd);
   73         kernel_free(kp);
   74         return -1;
   75     }
   76     
   77     SGPORT(kp->local) = htons(local_port);
   78     
   79     kernel_query(kp);
   80 
   81     if (debug)
   82     {
   83         fprintf(stderr, "kernel_query, status = %d\n", kp->status);
   84         if (kp->status == 1)
   85         {
   86         if (kp->ruid != NO_UID)
   87             fprintf(stderr, "\truid = %ld\n", (long) kp->ruid);
   88         if (kp->euid != NO_UID)
   89             fprintf(stderr, "\teuid = %ld\n", (long) kp->euid);
   90         if (kp->pid != NO_PID)
   91             fprintf(stderr, "\tpid  = %ld\n", (long) kp->pid);
   92         if (kp->cmd)
   93             fprintf(stderr, "\tcmd  = %s\n", kp->cmd);
   94         if (kp->argv)
   95             fprintf(stderr, "\targv = %s\n", kp->argv);
   96         }
   97     }
   98     
   99     switch (kp->status)
  100     {
  101       case 1:
  102         send_result(fd, kp);
  103         break;
  104         
  105       case 0:
  106         send_error(fd,
  107                local_port, remote_port,
  108                "NO-USER",
  109                remote_addr);
  110         break;
  111         
  112       default:
  113         send_error(fd,
  114                local_port, remote_port,
  115                "UNKNOWN-ERROR",
  116                remote_addr);
  117     }
  118 
  119     kernel_free(kp);
  120     return 0;
  121     }
  122 
  123     if (extensions_enabled)
  124     {
  125     cmd = s_strtok_r(buf, " ", &bp);
  126     if (cmd == NULL)
  127         goto Fail;
  128     
  129     if (strcasecmp("version", cmd) == 0)
  130     {
  131         send_version(fd, remote_addr);
  132         return 0;
  133     }
  134     
  135     if (strcasecmp("quit", cmd) == 0)
  136         return -1;
  137     }
  138     
  139   Fail:
  140     send_error(fd, 0, 0, "UNKNOWN-ERROR", remote_addr);
  141     return -1;
  142 }
  143 
  144 
  145 static void
  146 timeout_handler(void *arg)
  147 {
  148     struct request *rp = (struct request *) arg;
  149 
  150     if (debug)
  151     fprintf(stderr, "timeout_handler(%08lx)\n", (unsigned long) arg);
  152 
  153     if (rp != NULL)
  154     shutdown(rp->fd, 2);
  155 }
  156 
  157 
  158 
  159 void *
  160 request_thread(void *vp)
  161 {
  162     struct request *rp = (struct request *) vp;
  163     struct timeout *tp = NULL;
  164     char buf[1024];
  165     size_t len;
  166     ssize_t got, pos;
  167 
  168 
  169 
  170     if (debug)
  171     fprintf(stderr, "request_thread: fd#%d: start\n", rp->fd);
  172 
  173     len = 0;
  174     pos = 0;
  175     if (request_timeout > 0)
  176     tp = timeout_create(request_timeout, timeout_handler, rp);
  177 
  178     do
  179     {
  180     if (len >= sizeof(buf)-1)
  181     {
  182         syslog(LOG_NOTICE,
  183            "request_thread: fd #%d: input buffer full: closing down",
  184            rp->fd);
  185         goto Exit;
  186     }
  187     
  188     got = s_read(rp->fd, buf+len, sizeof(buf)-len-1);
  189     if (got < 0)
  190     {
  191         syslog(LOG_ERR, "request_thread: read(%d, ..., %d) failed: %m",
  192            rp->fd, sizeof(buf)-len-1);
  193         goto Exit;
  194     }
  195 
  196     if (got == 0)
  197     {
  198         if (debug)
  199         fprintf(stderr, "s_read(%d, ...): returned 0\n", rp->fd);
  200         goto Exit;
  201     }
  202     
  203     len += got;
  204 
  205     /* Locate end of request line */
  206     while (pos < len && !(buf[pos] == '\n' || buf[pos] == '\r'))
  207         ++pos;
  208 
  209     if (pos < len || got == 0)
  210     {
  211         if (got > 0 || pos > 0)
  212         {
  213         buf[pos] = '\0';
  214         if (handle_request(rp->fd, buf, &rp->addr) != 0)
  215             goto Exit;
  216 
  217         if (!multiquery_enabled)
  218             goto Exit;
  219 
  220         if (tp)
  221             timeout_reset(tp, request_timeout);
  222 
  223         ++pos; /* Skip NUL */
  224         }
  225 
  226         /* Skip any additional SPC/CR/LF characters */
  227         while (pos < len && isspace((unsigned char) buf[pos]))
  228         ++pos;
  229         if (pos < len)
  230         memcpy(buf, buf+pos, len-pos);
  231         len = pos = (len-pos);
  232     }
  233     } while (got > 0);
  234     
  235   Exit:
  236     if (tp)
  237     timeout_cancel(tp);
  238     
  239     if (debug)
  240     fprintf(stderr, "request_thread: fd#%d: terminating\n", rp->fd);
  241     
  242     s_close(rp->fd);
  243     s_free(rp);
  244 
  245     if (requests_max > 0)
  246     {
  247     pthread_mutex_lock(&requests_mtx);
  248     if (requests_cur == requests_max)
  249         pthread_cond_signal(&requests_cv);
  250     
  251     requests_cur--;
  252     pthread_mutex_unlock(&requests_mtx);
  253     }
  254     return NULL;
  255 }
  256 
  257 
  258 
  259 
  260 int
  261 request_run(int fd, int nofork)
  262 {
  263     struct request *rip;
  264     pthread_t tid;
  265 
  266     
  267     rip = s_malloc(sizeof(*rip));
  268     rip->fd = fd;
  269 
  270     rip->addr_len = sizeof(rip->addr);
  271     if (s_getpeername(fd, (struct sockaddr *) &rip->addr, &rip->addr_len) < 0)
  272     {
  273     syslog(LOG_ERR, "s_getpeername(%d): %m", fd);
  274     s_free(rip);
  275     close(fd);
  276     return EXIT_FAILURE;
  277     }
  278 
  279     if (nofork)
  280     {
  281     request_thread(rip);
  282     return EXIT_SUCCESS;
  283     }
  284     else
  285     {
  286     if (requests_max > 0)
  287     {
  288         pthread_mutex_lock(&requests_mtx);
  289         while (requests_cur >= requests_max)
  290         pthread_cond_wait(&requests_cv, &requests_mtx);
  291         
  292         requests_cur++;
  293         pthread_mutex_unlock(&requests_mtx);
  294     }
  295     
  296     if (pthread_create(&tid,
  297                &cattr_detached,
  298                &request_thread, (void *) rip) < 0)
  299     {
  300         syslog(LOG_ERR, "pthread_create(request_thread) failed: %m");
  301         return EXIT_FAILURE;
  302     }
  303     }
  304 
  305     return EXIT_SUCCESS;
  306 }
  307 
  308 
  309 int
  310 request_init(void)
  311 {
  312     pthread_mutex_init(&requests_mtx, NULL);
  313     pthread_cond_init(&requests_cv, NULL);
  314     requests_cur = 0;
  315     
  316     return 0;
  317 }