lib/eggdrop/socket.c File Reference

#include <eggdrop/eggdrop.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>

Go to the source code of this file.

Data Structures

struct  sockname_t

Defines

#define SHUT_RDWR   2
#define DO_IPV4

Functions

static int socket_name (sockname_t *name, const char *ipaddr, int port)
int socket_get_name (int sock, char **ip, int *port)
int socket_get_peer_name (int sock, char **peer_ip, int *peer_port)
int socket_get_error (int sock)
int socket_accept (int sock, char **peer_ip, int *peer_port)
int socket_create (const char *dest_ip, int dest_port, const char *src_ip, int src_port, int flags)
int socket_close (int sock)
int socket_set_nonblock (int sock, int value)
int socket_valid_ip (const char *ip)
int socket_ip_to_uint (const char *ip, unsigned int *longip)
int socket_ipv6_to_dots (const char *ip, char *dots)

Variables

static const char rcsid [] = "$Id: socket.c,v 1.14 2007-04-14 15:21:12 sven Exp $"


Define Documentation

#define DO_IPV4

Definition at line 41 of file socket.c.

#define SHUT_RDWR   2

Definition at line 35 of file socket.c.

Referenced by socket_close().


Function Documentation

int socket_accept ( int  sock,
char **  peer_ip,
int *  peer_port 
)

Definition at line 177 of file socket.c.

References sockname_t::addr, sockname_t::ipv4, NULL, and sockname_t::u.

Referenced by sockbuf_got_readable_server().

00178 {
00179   int newsock;
00180   sockname_t name;
00181   socklen_t len;
00182 
00183   *peer_ip = NULL;
00184   *peer_port = 0;
00185   memset(&name, 0, sizeof(name));
00186   len = sizeof(name.u);
00187   newsock = accept(sock, &name.u.addr, &len);
00188 #ifdef DO_IPV4
00189   if (len == sizeof(name.u.ipv4)) {
00190     *peer_ip = malloc(32);
00191     *peer_port = ntohs(name.u.ipv4.sin_port);
00192     inet_ntop(AF_INET, &name.u.ipv4.sin_addr, *peer_ip, 32);
00193   }
00194 #endif
00195 #ifdef DO_IPV6
00196   if (len == sizeof(name.u.ipv6)) {
00197     *peer_ip = malloc(128);
00198     *peer_port = ntohs(name.u.ipv6.sin6_port);
00199     if (IN6_IS_ADDR_V4MAPPED((&name.u.ipv6.sin6_addr))) {
00200       unsigned int ipv4part = 0;
00201       memcpy(&ipv4part, &name.u.ipv6.sin6_addr.s6_addr[12], 4);
00202       inet_ntop(AF_INET, &ipv4part, *peer_ip, 128);
00203     }
00204     else {
00205       inet_ntop(AF_INET6, &name.u.ipv6.sin6_addr, *peer_ip, 128);
00206     }
00207   }
00208 #endif
00209   return(newsock);
00210 }

int socket_close ( int  sock  ) 

Definition at line 276 of file socket.c.

References SHUT_RDWR.

Referenced by sockbuf_close(), and sockbuf_delete().

00277 {
00278   shutdown(sock, SHUT_RDWR);
00279   close(sock);
00280   return(0);
00281 }

int socket_create ( const char *  dest_ip,
int  dest_port,
const char *  src_ip,
int  src_port,
int  flags 
)

Definition at line 217 of file socket.c.

References sockname_t::addr, sockname_t::family, sockname_t::len, SOCKET_BIND, SOCKET_CLIENT, socket_name(), SOCKET_NONBLOCK, SOCKET_SERVER, socket_set_nonblock(), SOCKET_UDP, and sockname_t::u.

Referenced by connect_host_resolved(), egg_server(), and get_dns_idx().

00218 {
00219   char *passive[] = {"::", "0.0.0.0"};
00220   int sock = -1, pfamily, try;
00221   sockname_t dest_name, src_name;
00222 
00223   /* If no source ip address is given, try :: and 0.0.0.0 (passive). */
00224   for (try = 0; try < 2; try++) {
00225     /* Resolve the ip addresses. */
00226     socket_name(&dest_name, dest_ip ? dest_ip : passive[try], dest_port);
00227     socket_name(&src_name, src_ip ? src_ip : passive[try], src_port);
00228 
00229     if (src_ip || src_port) flags |= SOCKET_BIND;
00230 
00231     if (flags & SOCKET_CLIENT) pfamily = dest_name.family;
00232     else if (flags & SOCKET_SERVER) pfamily = src_name.family;
00233     else {
00234       errno = EADDRNOTAVAIL;
00235       return(-1);
00236     }
00237 
00238     /* Create the socket. */
00239     if (flags & SOCKET_UDP) sock = socket(pfamily, SOCK_DGRAM, 0);
00240     else sock = socket(pfamily, SOCK_STREAM, 0);
00241 
00242     if (sock >= 0) break;
00243   }
00244 
00245   if (sock < 0) return(-2);
00246 
00247   if (flags & SOCKET_NONBLOCK) socket_set_nonblock(sock, 1);
00248 
00249   /* Do the bind if necessary. */
00250   if (flags & (SOCKET_SERVER|SOCKET_BIND)) {
00251     int yes = 1;
00252 
00253     setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
00254     if (bind(sock, &src_name.u.addr, src_name.len) != 0) {
00255       close(sock);
00256       return(-3);
00257     }
00258     if (flags & SOCKET_SERVER) listen(sock, 50);
00259   }
00260 
00261   if (flags & SOCKET_CLIENT) {
00262     if (connect(sock, &dest_name.u.addr, dest_name.len) != 0) {
00263       if (errno != EINPROGRESS) {
00264         close(sock);
00265         return(-4);
00266       }
00267     }
00268   }
00269 
00270   errno = 0;
00271 
00272   /* Yay, we're done. */
00273   return(sock);
00274 }

int socket_get_error ( int  sock  ) 

Definition at line 164 of file socket.c.

Referenced by sockbuf_got_eof(), and sockbuf_got_writable_client().

00165 {
00166   int err;
00167   socklen_t size;
00168 
00169   if (sock < 0) return(0);
00170 
00171   size = sizeof(int);
00172   err = 0;
00173   getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &size);
00174   return(err);
00175 }

int socket_get_name ( int  sock,
char **  ip,
int *  port 
)

Definition at line 89 of file socket.c.

References sockname_t::addr, sockname_t::ipv4, NULL, and sockname_t::u.

Referenced by dcc_on_connect(), egg_server(), server_on_connect(), sockbuf_on_connect(), sockbuf_on_newclient(), and sockbuf_set_sock().

00090 {
00091   sockname_t name;
00092   socklen_t namelen;
00093 
00094   if (ip) *ip = NULL;
00095   if (port) *port = 0;
00096 
00097 #ifdef DO_IPV4
00098   namelen = sizeof(name.u.ipv4);
00099   if (!getsockname(sock, &name.u.addr, &namelen) && namelen == sizeof(name.u.ipv4)) {
00100     if (ip) {
00101       *ip = malloc(32);
00102       inet_ntop(AF_INET, &name.u.ipv4.sin_addr, *ip, 32);
00103     }
00104     if (port) *port = ntohs(name.u.ipv4.sin_port);
00105     return(0);
00106   }
00107 #endif
00108 #ifdef DO_IPV6
00109   namelen = sizeof(name.u.ipv6);
00110   if (!getsockname(sock, &name.u.addr, &namelen) && namelen == sizeof(name.u.ipv6)) {
00111     if (ip) {
00112       *ip = malloc(128);
00113       if (IN6_IS_ADDR_V4MAPPED((&name.u.ipv6.sin6_addr))) {
00114         unsigned int ipv4part = 0;
00115         memcpy(&ipv4part, &name.u.ipv6.sin6_addr.s6_addr[12], 4);
00116         inet_ntop(AF_INET, &ipv4part, *ip, 128);
00117       }
00118       else {
00119         inet_ntop(AF_INET6, &name.u.ipv6.sin6_addr, *ip, 128);
00120       }
00121     }
00122     if (port) *port = ntohs(name.u.ipv6.sin6_port);
00123     return(0);
00124   }
00125 #endif
00126 
00127   return(-1);
00128 }

int socket_get_peer_name ( int  sock,
char **  peer_ip,
int *  peer_port 
)

Definition at line 130 of file socket.c.

References sockname_t::addr, sockname_t::ipv4, NULL, and sockname_t::u.

Referenced by sockbuf_got_writable_client().

00131 {
00132   sockname_t name;
00133   socklen_t namelen;
00134 
00135   if (peer_ip) *peer_ip = NULL;
00136   if (peer_port) *peer_port = 0;
00137 
00138 #ifdef DO_IPV4
00139   namelen = sizeof(name.u.ipv4);
00140   if (!getpeername(sock, &name.u.addr, &namelen) && namelen == sizeof(name.u.ipv4)) {
00141     if (peer_ip) {
00142       *peer_ip = malloc(32);
00143       inet_ntop(AF_INET, &name.u.ipv4.sin_addr, *peer_ip, 32);
00144     }
00145     if (peer_port) *peer_port = ntohs(name.u.ipv4.sin_port);
00146     return(0);
00147   }
00148 #endif
00149 #ifdef DO_IPV6
00150   namelen = sizeof(name.u.ipv6);
00151   if (!getpeername(sock, &name.u.addr, &namelen) && namelen == sizeof(name.u.ipv6)) {
00152     if (peer_ip) {
00153       *peer_ip = malloc(128);
00154       inet_ntop(AF_INET6, &name.u.ipv6.sin6_addr, *peer_ip, 128);
00155     }
00156     if (peer_port) *peer_port = ntohs(name.u.ipv6.sin6_port);
00157     return(0);
00158   }
00159 #endif
00160 
00161   return(-1);
00162 }

int socket_ip_to_uint ( const char *  ip,
unsigned int *  longip 
)

Definition at line 306 of file socket.c.

Referenced by dcc_dns_callback().

00307 {
00308   struct in_addr addr;
00309 
00310   inet_pton(AF_INET, ip, &addr);
00311   *longip = htonl(addr.s_addr);
00312   return(0);
00313 }

int socket_ipv6_to_dots ( const char *  ip,
char *  dots 
)

Definition at line 317 of file socket.c.

Referenced by egg_dns_reverse().

00318 {
00319 #ifndef DO_IPV6
00320   dots[0] = 0;
00321   return(-1);
00322 #else
00323   struct in6_addr buf;
00324 
00325   dots[0] = 0;
00326   if (inet_pton(AF_INET6, ip, &buf) <= 0) return(-1);
00327   sprintf(dots, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x",
00328     buf.s6_addr[0] >> 4, buf.s6_addr[0] & 0xf,
00329     buf.s6_addr[1] >> 4, buf.s6_addr[1] & 0xf,
00330     buf.s6_addr[2] >> 4, buf.s6_addr[2] & 0xf,
00331     buf.s6_addr[3] >> 4, buf.s6_addr[3] & 0xf,
00332     buf.s6_addr[4] >> 4, buf.s6_addr[4] & 0xf,
00333     buf.s6_addr[5] >> 4, buf.s6_addr[5] & 0xf,
00334     buf.s6_addr[6] >> 4, buf.s6_addr[6] & 0xf,
00335     buf.s6_addr[7] >> 4, buf.s6_addr[7] & 0xf,
00336     buf.s6_addr[8] >> 4, buf.s6_addr[8] & 0xf,
00337     buf.s6_addr[9] >> 4, buf.s6_addr[9] & 0xf,
00338     buf.s6_addr[10] >> 4, buf.s6_addr[10] & 0xf,
00339     buf.s6_addr[11] >> 4, buf.s6_addr[11] & 0xf,
00340     buf.s6_addr[12] >> 4, buf.s6_addr[12] & 0xf,
00341     buf.s6_addr[13] >> 4, buf.s6_addr[13] & 0xf,
00342     buf.s6_addr[14] >> 4, buf.s6_addr[14] & 0xf,
00343     buf.s6_addr[15] >> 4, buf.s6_addr[15] & 0xf
00344   );
00345   return(0);
00346 #endif
00347 }

static int socket_name ( sockname_t name,
const char *  ipaddr,
int  port 
) [static]

Definition at line 57 of file socket.c.

References sockname_t::family, sockname_t::ipv4, sockname_t::len, and sockname_t::u.

Referenced by socket_create().

00058 {
00059   memset(name, 0, sizeof(*name));
00060 
00061 #ifdef DO_IPV4
00062   if (inet_pton(AF_INET, ipaddr, &name->u.ipv4.sin_addr) > 0) {
00063     name->len = sizeof(name->u.ipv4);
00064     name->family = PF_INET;
00065     name->u.ipv4.sin_port = htons(port);
00066     name->u.ipv4.sin_family = AF_INET;
00067     return(0);
00068   }
00069 #endif
00070 
00071 #ifdef DO_IPV6
00072   if (inet_pton(AF_INET6, ipaddr, &name->u.ipv6.sin6_addr) > 0) {
00073     name->len = sizeof(name->u.ipv6);
00074     name->family = PF_INET6;
00075     name->u.ipv6.sin6_port = htons(port);
00076     name->u.ipv6.sin6_family = AF_INET6;
00077     return(0);
00078   }
00079 #endif
00080 
00081   /* Invalid name? Then use passive. */
00082   name->len = sizeof(name->u.ipv4);
00083   name->family = PF_INET;
00084   name->u.ipv4.sin_port = htons(port);
00085   name->u.ipv4.sin_family = AF_INET;
00086   return(0);
00087 }

int socket_set_nonblock ( int  sock,
int  value 
)

Definition at line 283 of file socket.c.

Referenced by sockbuf_got_readable_server(), and socket_create().

00284 {
00285   int oldflags = fcntl(sock, F_GETFL, 0);
00286   if (oldflags == -1) return -1;
00287   if (value != 0) oldflags |= O_NONBLOCK;
00288   else oldflags &= ~O_NONBLOCK;
00289 
00290   return fcntl(sock, F_SETFL, oldflags);
00291 }

int socket_valid_ip ( const char *  ip  ) 

Definition at line 293 of file socket.c.

Referenced by egg_dns_lookup(), and egg_dns_reverse().

00294 {
00295   char buf[512];
00296 
00297 #ifdef DO_IPV6
00298   if (inet_pton(AF_INET6, ip, buf) > 0) return(1);
00299 #endif
00300 #ifdef DO_IPV4
00301   if (inet_pton(AF_INET, ip, buf) > 0) return(1);
00302 #endif
00303   return(0);
00304 }


Variable Documentation

const char rcsid[] = "$Id: socket.c,v 1.14 2007-04-14 15:21:12 sven Exp $" [static]

Definition at line 21 of file socket.c.


Generated on Sun Nov 30 18:43:34 2008 for eggdrop1.9 by  doxygen 1.5.6