mirror of
https://github.com/ChronosX88/netsukuku.git
synced 2024-11-26 04:02:19 +00:00
298 lines
6.9 KiB
C
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;
|
|
}
|
|
|