Back to index

courier  0.68.2
Functions
proxy.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>
#include <courierauthdebug.h>
#include "proxy.h"

Go to the source code of this file.

Functions

static int checkhostname (const char *host)
static int connect_host (struct proxyinfo *pi, const char *host)
int connect_proxy (struct proxyinfo *pi)
static int proxyconnect (struct proxyinfo *pi, int aftype, void *addr, size_t)
static int proxy_waitfd (int fd, int waitWrite, const char *hostnamebuf)
static int proxy_getch (int fd, struct proxybuf *pb)
int proxy_readline (int fd, struct proxybuf *pb, char *linebuf, size_t linebuflen, int imapmode)
int proxy_write (int fd, const char *hostname, const char *buf, size_t buf_len)
void proxyloop (int fd)

Function Documentation

static int checkhostname ( const char *  host) [static]

Definition at line 37 of file proxy.c.

{
       char hostbuf[256];
       const char *proxyhostname;

       if ((proxyhostname=getenv("PROXY_HOSTNAME")) != NULL)
       {
              if (strcmp(proxyhostname, host) == 0)
              {
                     courier_authdebug_printf("Proxy host %s is me, normal login.",
                                           host);
                     return -1;
              }
       }

       if (gethostname(hostbuf, sizeof(hostbuf)))
       {
              courier_authdebug_printf
                     ("gethostname failed: %s",
                      strerror(errno));
              return -1;
       }

       if (strcmp(hostbuf, host) == 0)
       {
              courier_authdebug_printf("Proxy host %s is me, normal login.",
                                    host);
              return -1;
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int connect_host ( struct proxyinfo pi,
const char *  host 
) [static]

Definition at line 168 of file proxy.c.

{
       struct hostent *he;
       int i;
       int fd;

       if (checkhostname(host))
              return (0);

       he=gethostbyname(host);

       if (he == NULL)
       {
              courier_authdebug_printf
                     ("gethostbyname on proxyhost %s failed.",
                      host);
              return (-1);
       }

       for (i=0; he->h_addr_list[i]; i++)
       {
              switch (he->h_addrtype) {
              case AF_INET:
                     {
                            struct sockaddr_in sin;

                            memset(&sin, 0, sizeof(sin));

                            sin.sin_family=AF_INET;

                            memcpy(&sin.sin_addr, he->h_addr_list[i],
                                   sizeof(sin.sin_addr));
                            sin.sin_port=htons(pi->port);

                            fd=proxyconnect(pi, PF_INET, &sin,
                                          sizeof(sin));
                     }
                     break;
#ifdef AF_INET6
              case AF_INET6:
                     {
                            struct sockaddr_in6 sin6;

                            memset(&sin6, 0, sizeof(sin6));

                            sin6.sin6_family=AF_INET6;

                            memcpy(&sin6.sin6_addr, he->h_addr_list[i],
                                   sizeof(sin6.sin6_addr));

                            sin6.sin6_port=htons(pi->port);
                            fd=proxyconnect(pi, PF_INET6, &sin6,
                                          sizeof(sin6));
                     }
                     break;
#endif
              default:
                     courier_authdebug_printf
                            ("Unknown address family type %d",
                             he->h_addrtype);
                     continue;
              }

              if (fd >= 0)
              {
                     if ((*pi->connected_func)(fd, host,
                                            pi->void_arg))
                     {
                            close(fd);
                            courier_authdebug_printf
                                   ("Failed: %s.", strerror(errno));
                            continue;
                     }
                     return fd;
              }
       }
       courier_authdebug_printf
              ("Connection to proxyhost %s failed.", host);
       return (-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connect_proxy ( struct proxyinfo pi)

Definition at line 71 of file proxy.c.

{
       char *h=strdup(pi->host);
       char *p, *q;
       int fd;

       if (!h)
       {
              courier_authdebug_printf("%s", strerror(errno));
              return -1;
       }

       for (p=h; *p;)
       {
              if (*p == ',')
              {
                     ++p;
                     continue;
              }

              for (q=p; *q; q++)
                     if (*q == ',')
                            break;
              if (*q)
                     *q++=0;

              fd=connect_host(pi, p);
              if (fd >= 0)
              {
                     free(h);
                     return fd;
              }
              p=q;
       }
       free(h);
       return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int proxy_getch ( int  fd,
struct proxybuf pb 
) [static]

Definition at line 401 of file proxy.c.

{
       if (pb->bufleft == 0)
       {
              int n;

              if (proxy_waitfd(fd, 0, "server"))
                     return -1;

              pb->bufptr=pb->buffer;

              n=read(fd, pb->buffer, sizeof(pb->buffer));

              if (n < 0)
              {
                     courier_authdebug_printf
                            ("Connection error: %s",
                             strerror(errno));
                     return -1;
              }

              if (n == 0)
              {
                     courier_authdebug_printf
                            ("Connection closed by remote host");
                     return -1;
              }

              pb->bufleft=(size_t)n;
       }
       --pb->bufleft;
       return ((int)(unsigned char)*pb->bufptr++);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_readline ( int  fd,
struct proxybuf pb,
char *  linebuf,
size_t  linebuflen,
int  imapmode 
)

Definition at line 435 of file proxy.c.

{
       size_t i;
       int ch;
       int prevch;

       i=0;

       ch=0;

       do
       {
              prevch=ch;

              ch=proxy_getch(fd, pb);

              if (ch < 0)
                     return -1;

              if (i < linebuflen)
                     linebuf[i++]=(char)ch;
       } while (ch != '\n' || (imapmode && prevch != '\r'));

       if (i)
              linebuf[--i]=0;

       if (i && linebuf[i-1] == '\r')
              linebuf[--i]=0;

       DPRINTF("Received: %s", linebuf);

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int proxy_waitfd ( int  fd,
int  waitWrite,
const char *  hostnamebuf 
) [static]

Definition at line 278 of file proxy.c.

{
       fd_set fds;
       struct timeval tv;

       FD_ZERO(&fds);
       FD_SET(fd, &fds);
       tv.tv_sec=30;
       tv.tv_usec=0;

       if (select(fd+1, waitWrite ? NULL:&fds,
                 waitWrite ? &fds:NULL, NULL, &tv) < 0)
       {
              courier_authdebug_printf
                     ("Select failed while waiting to connect to %s: %s",
                      hostnamebuf, strerror(errno));

              return -1;
       }

       if (!FD_ISSET(fd, &fds))
       {
              courier_authdebug_printf
                     ("Timeout connecting to %s", hostnamebuf);
              return -1;
       }

       return 0;
}

Here is the caller graph for this function:

int proxy_write ( int  fd,
const char *  hostname,
const char *  buf,
size_t  buf_len 
)

Definition at line 472 of file proxy.c.

{
       DPRINTF("Sending: %s", buf);

       while (buf_len)
       {
              int n;

              if (proxy_waitfd(fd, 1, hostname))
                     return -1;

              n=write(fd, buf, buf_len);

              if (n < 0)
              {
                     courier_authdebug_printf
                            ("Error sending to %s: %s",
                             hostname, strerror(errno));
                     return -1;
              }

              if (n == 0)
              {
                     courier_authdebug_printf
                            ("Connection close by %s", hostname);
                     return -1;
              }

              buf_len -= n;
              buf += n;
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int proxyconnect ( struct proxyinfo pi,
int  aftype,
void *  addr,
size_t  addrLen 
) [static]

Definition at line 309 of file proxy.c.

{
       int fd;
       char hostnamebuf[256];
       int errcode;
       socklen_t errcode_l;

       struct sockaddr *sa=(struct sockaddr *)addr;

       switch (sa->sa_family) {
       case AF_INET:
              {
                     struct sockaddr_in *sin=(struct sockaddr_in *)sa;

                     strcpy(hostnamebuf, inet_ntoa(sin->sin_addr));
              }
              break;

#ifdef AF_INET6
       case AF_INET6:
              {
                     struct sockaddr_in6 *sin6=
                            (struct sockaddr_in6 *)sa;

                     if (inet_ntop(AF_INET6, &sin6->sin6_addr,
                                  hostnamebuf,
                                  sizeof(hostnamebuf)) == NULL)
                            strcpy(hostnamebuf, "inet_ntop() failed");
              }
              break;
#endif
       }


       fd=socket(pf, SOCK_STREAM, 0);

       if (fd < 0)
       {
              courier_authdebug_printf("socket: %s", strerror(errno));
              return (-1);
       }

       if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0 ||
           fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
       {
              close(fd);
              courier_authdebug_printf("fcntl(socket): %s", strerror(errno));
       }

       if (connect(fd, addr, addrLen) == 0)
              return fd;

       if (errno != EINPROGRESS)
       {
              courier_authdebug_printf
                     ("Proxy connection to %s failed: %s",
                      hostnamebuf, strerror(errno));
              close(fd);
              return -1;
       }

       if (proxy_waitfd(fd, 1, hostnamebuf))
       {
              close(fd);
              return -1;
       }

       errcode_l=sizeof(errcode);

       if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &errcode_l) < 0)
       {
              courier_authdebug_printf
                     ("getsockopt failed: %s", strerror(errno));
              close(fd);
              return -1;
       }

       if (errcode)
       {
              courier_authdebug_printf
                     ("Proxy connection to %s failed: %s", hostnamebuf,
                      strerror(errcode));
              close(fd);
              return -1;
       }

       return fd;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void proxyloop ( int  fd)

Definition at line 621 of file proxy.c.

{
       char stdin_buf[BUFSIZ];
       char stdout_buf[BUFSIZ];

       char *stdin_ptr=NULL;
       char *stdout_ptr=NULL;
       size_t stdin_left=0;
       size_t stdout_left=0;
       int n;

       fd_set fdr, fdw;

       if (fcntl(0, F_SETFL, O_NONBLOCK) ||
           fcntl(1, F_SETFL, O_NONBLOCK))
       {
              courier_authdebug_printf("fcntl: %s",
                                    strerror(errno));
              return;
       }

       do
       {
              FD_ZERO(&fdr);
              FD_ZERO(&fdw);

              if (stdin_left == 0)
                     FD_SET(0, &fdr);
              else
                     FD_SET(fd, &fdw);

              if (stdout_left == 0)
                     FD_SET(fd, &fdr);
              else
                     FD_SET(1, &fdw);

              n=1;

              if (select(fd+1, &fdr, &fdw, NULL, NULL) < 0)
              {
                     courier_authdebug_printf("select: %s",
                                           strerror(errno));
                     continue;
              }

              if (stdin_left == 0)
              {
                     if (FD_ISSET(0, &fdr))
                     {
                            n=read(0, stdin_buf, sizeof(stdin_buf));

                            if (n > 0)
                            {
                                   stdin_ptr=stdin_buf;
                                   stdin_left=(size_t)n;
                            }
                     }
              }
              else if (FD_ISSET(fd, &fdw))
              {
                     n=write(fd, stdin_ptr, stdin_left);

                     if (n > 0)
                     {
                            stdin_ptr += n;
                            stdin_left -= n;
                     }
              }

              if (n > 0)
              {
                     if (stdout_left == 0)
                     {
                            if (FD_ISSET(fd, &fdr))
                            {
                                   n=read(fd, stdout_buf,
                                          sizeof(stdout_buf));
                            
                                   if (n > 0)
                                   {
                                          stdout_ptr=stdout_buf;
                                          stdout_left=(size_t)n;
                                   }
                            }
                     } else if (FD_ISSET(1, &fdw))
                     {
                            n=write(1, stdout_ptr, stdout_left);

                            if (n > 0)
                            {
                                   stdout_ptr += n;
                                   stdout_left -= n;
                            }
                     }
              }
       } while (n > 0);

       if (n < 0)
              courier_authdebug_printf("%s", strerror(errno));
}

Here is the caller graph for this function: