network.c revision 0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 1999-2003 Timo Sirainen */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen# define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenint net_ip_compare(const struct ip_addr *ip1, const struct ip_addr *ip2)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen return memcmp(&ip1->ip, &ip2->ip, sizeof(ip1->ip)) == 0;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen/* copy IP to sockaddr */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstatic inline void
23b586b2cf5760527529f9963c04875c8566a24dTimo Sirainensin_set_ip(union sockaddr_union *so, const struct ip_addr *ip)
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen memcpy(&so->sin6.sin6_addr, &ip->ip, sizeof(ip->ip));
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstatic inline void
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainensin_get_ip(const union sockaddr_union *so, struct ip_addr *ip)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen memcpy(&ip->ip, &so->sin6.sin6_addr, sizeof(ip->ip));
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstatic inline void sin_set_port(union sockaddr_union *so, unsigned int port)
513b045d3cb2325250e74f0a92c144f9307eee44Timo Sirainen so->sin6.sin6_port = htons((unsigned short) port);
513b045d3cb2325250e74f0a92c144f9307eee44Timo Sirainen so->sin.sin_port = htons((unsigned short) port);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenstatic inline unsigned int sin_get_port(union sockaddr_union *so)
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen/* Connect to socket with ip address */
23b586b2cf5760527529f9963c04875c8566a24dTimo Sirainenint net_connect_ip(const struct ip_addr *ip, unsigned int port,
23b586b2cf5760527529f9963c04875c8566a24dTimo Sirainen if (my_ip != NULL && ip->family != my_ip->family) {
23b586b2cf5760527529f9963c04875c8566a24dTimo Sirainen i_warning("net_connect_ip(): ip->family != my_ip->family");
23b586b2cf5760527529f9963c04875c8566a24dTimo Sirainen /* create the socket */
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen /* set socket options */
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt));
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen /* set our own address */
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen if (bind(fd, &so.sa, SIZEOF_SOCKADDR(so)) == -1) {
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen /* failed, set it back to INADDR_ANY */
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen /* connect */
23b586b2cf5760527529f9963c04875c8566a24dTimo Sirainen ret = connect(fd, &so.sa, SIZEOF_SOCKADDR(so));
98fe03ecad7fcf0973584b9ab0b4dc4848881d56Timo Sirainen if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
23b586b2cf5760527529f9963c04875c8566a24dTimo Sirainen if (strocpy(sa.sun_path, path, sizeof(sa.sun_path)) < 0) {
23b586b2cf5760527529f9963c04875c8566a24dTimo Sirainen /* too long path */
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen /* create the socket */
dbf26a3ea43cd79fe88f01ec99c7d9440679b996Timo Sirainen /* connect */
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen ret = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen/* Disconnect socket */
98fe03ecad7fcf0973584b9ab0b4dc4848881d56Timo Sirainen/* Set socket blocking/nonblocking */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenvoid net_set_nonblock(int fd __attr_unused__, int nonblock __attr_unused__)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainenint net_set_cork(int fd __attr_unused__, int cork __attr_unused__)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen return setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork));
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen struct in_addr *in_ip = (struct in_addr *) &ip->ip;
98fe03ecad7fcf0973584b9ab0b4dc4848881d56Timo Sirainen/* Listen for connections on a socket. if `my_ip' is NULL, listen in any
98fe03ecad7fcf0973584b9ab0b4dc4848881d56Timo Sirainenint net_listen(const struct ip_addr *my_ip, unsigned int *port)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen /* create the socket */
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen fd = socket(so.sin.sin_family, SOCK_STREAM, 0);
#ifdef HAVE_IPV6
if (ret >= 0) {
if (ret >= 0) {
return fd;
int fd;
return fd;
int ret;
if (ret < 0) {
return ret;
if (ret == 0) {
errno = 0;
if (ret < 0) {
return ret;
return ret;
#ifdef HAVE_IPV6
int host_error;
int count;
*ips_count = 0;
#ifdef HAVE_IPV6
if (host_error != 0)
return host_error;
count++;
count = 0;
return h_errno;
count = 0;
count++;
while (count > 0) {
count--;
#ifdef HAVE_IPV6
return NULL;
unsigned long ip4;
return NULL;
#ifdef HAVE_IPV6
int data;
return data;
#ifdef HAVE_IPV6
switch (error) {
case HOST_NOT_FOUND:
case NO_ADDRESS:
case NO_RECOVERY:
case TRY_AGAIN:
return NULL;
#ifdef HAVE_IPV6
addr++;
addr++;