netsukuku/src/andns_net.c
Kirill Sotnikov f1761cad9a git repo init
2013-09-16 13:53:25 +04:00

298 lines
6.9 KiB
C

/**************************************
* AUTHOR: Federico Tomassini *
* Copyright (C) Federico Tomassini *
* Contact effetom@gmail.com *
***********************************************
******* BEGIN 4/2006 ********
*************************************************************************
* *
* 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. *
* *
************************************************************************/
#include "log.h"
#include "andns_net.h"
int idp_inet_ntop(int family,struct sockaddr *addr,char *buf,int buflen)
{
const char *res;
struct sockaddr_in *saddr;
struct sockaddr_in6 *saddr6;
switch(family) {
case AF_INET:
saddr=(struct sockaddr_in*)addr;
res=inet_ntop(family,(void*)(&(saddr->sin_addr)),buf,buflen);
break;
case AF_INET6:
saddr6=(struct sockaddr_in6*)addr;
res=inet_ntop(family,(void*)(&(saddr6->sin6_addr)),buf,buflen);
break;
default:
return -1;
}
if (!res)
return -1;
return 0;
}
/* Connection Layer */
int w_socket(int family,int type, int proto,int die)
{
int sk;
sk=socket(family,type,proto);
if (sk==-1) {
if (die)
fatal("w_socket: %s.",strerror(errno));
debug(DBG_NORMAL,"w_socket: %s.",strerror(errno));
return -1;
}
return sk;
}
int w_connect(struct addrinfo *ai,int die)
{
int sk,res;
sk=w_socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol,die);
res=connect(sk,ai->ai_addr,ai->ai_addrlen);
if (!res)
return sk;
if (die)
fatal("Unable to connect: %s.", strerror(errno));
debug(DBG_NORMAL,"w_connect: %s.",strerror(errno));
close(sk);
return -1;
}
int serial_connect(struct addrinfo *ai,int die)
{
int res;
struct addrinfo *temp;
temp=ai;
if (!temp) {
if (die)
fatal("Unable to connect: no host specified.");
debug(DBG_NORMAL,"serial_connect: no host specified.");
return -1;
}
do {
res=w_connect(temp,0);
temp=temp->ai_next;
} while (res==-1 && temp);
if (res==-1) {
if (die)
fatal("Unable to connect.");
debug(DBG_NORMAL,"serial_connect: unable to connect.");
return -1;
}
return res;
}
/*
* host_connect returns a connected socket to (host,port)
* endpoint. It is protocol independent.
* -1 on error.
*/
int host_connect(const char *host,uint16_t port,int type,int die)
{
int res;
char portstr[6];
struct addrinfo *ai,filter;
memset(&filter,0,sizeof(struct addrinfo));
filter.ai_socktype=type;
if (!host)
fatal("w_connect: malicious call.");
memset(portstr,0,6);
res=snprintf(portstr,6,"%d",port);
if (res<0 || res>=6) {
printf("Depousceve\n");
return -1;
}
res=getaddrinfo(host,portstr,&filter,&ai);
if (res!=0) {
printf("w_connect: error %s.\n",gai_strerror(errno));
return -1;
}
res=serial_connect(ai,die);
freeaddrinfo(ai);
return res;
}
int ai_connect(struct addrinfo *ai,int die,int free_ai)
{
int res;
res=serial_connect(ai,die);
if (free_ai)
freeaddrinfo(ai);
return res;
}
/* Communication Layer */
ssize_t w_send(int sk,const void *buf,size_t len,int die)
{
ssize_t ret;
ret=send(sk,buf,len,0);
if (ret!=len) {
if (die)
fatal("Unable to send(): %s.",strerror(errno));
debug(DBG_NORMAL,"w_send(): %s.",strerror(errno));
}
return ret;
}
ssize_t w_recv(int sk,void *buf,size_t len,int die)
{
ssize_t ret;
ret=recv(sk,buf,len,0);
if (ret<=0) {
if (die)
fatal("Unable to recv(): %s.",strerror(errno));
debug(DBG_INSANE,"w_recv(): %s.",strerror(errno));
}
return ret;
}
/*
* These two functions and the MACRO are
* almost VERBATIM copied from inet.c and inet.h.
* Functions by AlpT, Andrea Lo Pumo.
*/
#define MILLISEC_TO_TV(x,t) \
do{ \
(t).tv_sec=(x)/1000; \
(t).tv_usec=((x) - ((x)/1000)*1000)*1000; \
}while(0)
ssize_t w_send_timeout(int s,const void *buf,size_t len,int die,int timeout)
{
struct timeval timeout_t;
fd_set fdset;
int ret;
MILLISEC_TO_TV(timeout*1000, timeout_t);
FD_ZERO(&fdset);
FD_SET(s, &fdset);
ret = select(s+1, &fdset, NULL, NULL, &timeout_t);
if (ret == -1) {
if (die)
fatal("send(): select error.");
debug(DBG_NORMAL,"send(): select error.");
return ret;
}
if(FD_ISSET(s, &fdset))
return w_send(s, buf, len, die);
return -1;
}
ssize_t w_recv_timeout(int s,void *buf,size_t len,int die,int timeout)
{
struct timeval timeout_t;
fd_set fdset;
int ret;
MILLISEC_TO_TV(timeout*1000, timeout_t);
FD_ZERO(&fdset);
FD_SET(s, &fdset);
ret = select(s+1, NULL, &fdset, NULL, &timeout_t);
if (ret == -1) {
if (die)
fatal("recv(): select error.");
debug(DBG_NORMAL,"recv(): select error.");
return ret;
}
if(FD_ISSET(s, &fdset))
return w_recv(s, buf, len, die);
return -1;
}
/* Dialog Layer */
/* "Botta e risposta" */
ssize_t hn_send_recv_close(const char *host,uint16_t port,int type,void *buf,
size_t buflen,void *anbuf,size_t anlen,int die,int timeout)
{
ssize_t ret;
int res;
res=host_connect(host,port,type,die);
if (res==-1)
return -1;
if (timeout)
ret=w_send_timeout(res,buf,buflen,die,timeout);
else
ret=w_send(res,buf,buflen,die);
if (ret==-1)
return -2;
if (timeout)
ret=w_recv_timeout(res,anbuf,anlen,die,timeout);
else
ret=w_recv(res,anbuf,anlen,die);
if (ret==-1)
return -3;
close(res);
return ret;
}
/* "Botta e risposta" */
ssize_t ai_send_recv_close(struct addrinfo *ai,void *buf,size_t buflen,
void *anbuf,size_t anlen,int die,int free_ai,int timeout)
{
ssize_t ret;
int res;
res=ai_connect(ai,die,free_ai);
if (res==-1)
return -1;
if (timeout)
ret=w_send_timeout(res,buf,buflen,die,timeout);
else
ret=w_send(res,buf,buflen,die);
if (ret==-1)
return -2;
if (timeout)
ret=w_recv_timeout(res,anbuf,anlen,die,timeout);
else
ret=w_recv(res,anbuf,anlen,die);
if (ret==-1)
return -3;
close(res);
return ret;
}
void char_print(char *buf, int len)
{
int i,count=0;
printf("Printing %d bytes\n",len);
for (i=0;i<len;i++) {
printf("%02X ", (unsigned char)(buf[i]));
count++;
if ((count%16)==0) printf("\n");
}
printf("\n");
return;
}