/* * ImapProxy - a caching IMAP proxy daemon * Copyright (C) 2002 Steven Van Acker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include /* socket_printf - sends something over a socket * arguments: * s - socket * fmt - format to use * ... - args */ void socket_printf(int s, char *fmt,...) { static char buf[8192]; int i; va_list v; va_start(v, fmt); i = vsnprintf(buf, sizeof(buf), fmt, v); write(s, buf, i); va_end(v); } /* resolve a hostname to an IP in long notation */ unsigned long my_resolve(char *name) { struct in_addr i; struct hostent *h; char *s; if (inet_aton(name, &i)) return i.s_addr; h = gethostbyname(name); if (h) return *((unsigned long *) (h->h_addr)); switch (h_errno) { case HOST_NOT_FOUND: s = "nonexistant host"; break; case NO_ADDRESS: s = "no IP for hostname"; break; case NO_RECOVERY: s = "fatal name server error"; break; case TRY_AGAIN: s = "try again later"; break; default: s = strerror(errno); break; } debug("my_resolve(\"%s\"): Unable to resolve %s: %s\n",name, name, s); return 0; } /* * setup_listener - sets a given socket to listen on a port, and returns that port * arguments: * ip - address to bind to * fd - socket fd * returns: * listening port on success * -1 on error */ int setup_listener(unsigned long ip,int fd,int port) { struct sockaddr_in local; int size = 0; int on = 1; local.sin_family = PF_INET; local.sin_addr.s_addr = ip; local.sin_port = port; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (bind(fd, (struct sockaddr *) &local, sizeof(struct sockaddr_in)) < 0) { debug("setup_listener(): bind() error (%m)\n"); return -1; } if (listen(fd, 1) < 0) { debug("setup_listener(): listen() error (%m)\n"); return -1; } size = sizeof(struct sockaddr_in); if(getsockname(fd, (struct sockaddr *) &local, &size)) { debug("setup_listener(): getsockname() error (%m)\n"); return -1; } return htons(local.sin_port); } /* nonblock_socket - creates a new socket and sets it to NONBLOCKING * returns: * socket fd on success * -1 on error */ int nonblock_socket() { int sockfd = 0; if((sockfd = socket(PF_INET,SOCK_STREAM,0))<0) { debug("nonblock_socket(): Couldn't create socket\n"); return -1; } if(fcntl(sockfd,F_SETFL,O_NONBLOCK)<0) { debug("nonblock_socket(): Couldn't set O_NONBLOCK\n"); return -1; } return sockfd; }