/************************************** * 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