network.c revision 6a125dfb789cc44826e965987576fabb33425c01
/*
network.c : Network stuff with IPv6 support
Copyright (c) 1999-2002 Timo Sirainen
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "lib.h"
#include "network.h"
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#define LISTEN_BACKLOG 8
union sockaddr_union {
struct sockaddr_in sin;
#ifdef HAVE_IPV6
struct sockaddr_in6 sin6;
#endif
};
#ifdef HAVE_IPV6
#else
#endif
{
return 0;
#ifdef HAVE_IPV6
#endif
}
/* copy IP to sockaddr */
static inline void
{
#ifdef HAVE_IPV6
#else
#endif
return;
}
#ifdef HAVE_IPV6
else
#endif
}
static inline void
{
#ifdef HAVE_IPV6
else
#endif
}
{
#ifdef HAVE_IPV6
else
#endif
}
{
#ifdef HAVE_IPV6
#endif
}
static inline void close_save_errno(int fd)
{
}
/* Connect to socket with ip address */
{
union sockaddr_union so;
i_warning("net_connect_ip(): ip->family != my_ip->family");
}
/* create the socket */
if (fd == -1)
return -1;
/* set socket options */
/* set our own address */
/* failed, set it back to INADDR_ANY */
}
}
/* connect */
#ifndef WIN32
#else
#endif
{
return -1;
}
return fd;
}
int net_connect_unix(const char *path)
{
struct sockaddr_un sa;
/* too long path */
return -1;
}
/* create the socket */
if (fd == -1)
return -1;
/* connect */
return -1;
}
return fd;
}
/* Disconnect socket */
void net_disconnect(int fd)
{
i_error("net_disconnect() failed: %m");
}
/* Set socket blocking/nonblocking */
{
#ifdef HAVE_FCNTL
i_fatal("net_set_nonblock() failed: %m");
#endif
}
{
#ifdef TCP_CORK
#else
errno = ENOPROTOOPT;
return -1;
#endif
}
{
}
{
#ifdef HAVE_IPV6
#else
#endif
}
/* Listen for connections on a socket. if `my_ip' is NULL, listen in any
address. */
{
union sockaddr_union so;
/* create the socket */
#ifdef HAVE_IPV6
/* IPv6 is not supported by OS */
}
#endif
if (fd == -1)
return -1;
/* set socket options */
if (ret >= 0) {
/* get the actual port we started listen */
if (ret >= 0) {
/* start listening */
return fd;
}
}
/* error */
return -1;
}
int net_listen_unix(const char *path)
{
struct sockaddr_un sa;
int fd;
/* too long path */
return -1;
}
/* create the socket */
if (fd == -1)
return -1;
/* bind */
/* start listening */
return fd;
}
return -1;
}
/* Accept a connection on a socket */
{
union sockaddr_union so;
int ret;
if (ret < 0) {
return -2;
else
return -1;
}
return ret;
}
/* Read data from socket, return number of bytes read, -1 = error */
{
if (ret == 0) {
/* disconnected */
errno = 0;
return -2;
}
if (ret < 0) {
return 0;
/* treat as disconnection */
return -2;
}
}
return ret;
}
/* Transmit data, return number of bytes sent, -1 = error */
{
return 0;
return -2;
return ret;
}
/* Get IP addresses for host. ips contains ips_count of IPs, they don't need
to be free'd. Returns 0 = ok, others = error code for net_gethosterror() */
{
/* @UNSAFE */
#ifdef HAVE_IPV6
union sockaddr_union *so;
char hbuf[NI_MAXHOST];
int host_error;
#else
#endif
int count;
*ips_count = 0;
#ifdef HAVE_IPV6
/* save error to host_error for later use */
if (host_error != 0)
return host_error;
return 1;
/* get number of IPs */
count++;
count = 0;
}
#else
return h_errno;
/* get number of IPs */
count = 0;
count++;
while (count > 0) {
count--;
}
#endif
return 0;
}
{
union sockaddr_union so;
return -1;
return 0;
}
{
#ifdef HAVE_IPV6
return NULL;
#else
unsigned long ip4;
return NULL;
return t_strdup_printf("%lu.%lu.%lu.%lu",
(ip4 & 0x000000ff));
#endif
}
{
/* IPv6 */
#ifdef HAVE_IPV6
return -1;
#else
#endif
} else {
/* IPv4 */
return -1;
}
return 0;
}
/* Get socket error */
int net_geterror(int fd)
{
int data;
return -1;
return data;
}
/* get error of net_gethostname() */
const char *net_gethosterror(int error)
{
#ifdef HAVE_IPV6
if (error == 1) {
/* getnameinfo() failed */
}
return gai_strerror(error);
#else
switch (error) {
case HOST_NOT_FOUND:
return "Host not found";
case NO_ADDRESS:
return "No IP address found for name";
case NO_RECOVERY:
return "A non-recovable name server error occurred";
case TRY_AGAIN:
return "A temporary error on an authoritative name server";
}
/* unknown error */
return NULL;
#endif
}
/* return TRUE if host lookup failed because it didn't exist (ie. not
some error with name server) */
int net_hosterror_notfound(int error)
{
#ifdef HAVE_IPV6
#else
#endif
}
/* Get name of TCP service */
char *net_getservbyport(unsigned short port)
{
}
int is_ipv4_address(const char *addr)
{
while (*addr != '\0') {
return 0;
addr++;
}
return 1;
}
int is_ipv6_address(const char *addr)
{
while (*addr != '\0') {
return 0;
addr++;
}
return 1;
}