39 |
#define _BSD_SOCKLEN_T_ |
#define _BSD_SOCKLEN_T_ |
40 |
#endif |
#endif |
41 |
|
|
42 |
|
#ifdef HAVE_NETINET_IN_H |
43 |
|
#include <netinet/in.h> |
44 |
|
#endif |
45 |
|
|
46 |
#ifdef HAVE_SYS_SOCKET_H |
#ifdef HAVE_SYS_SOCKET_H |
47 |
#include <sys/socket.h> |
#include <sys/socket.h> |
48 |
#endif |
#endif |
71 |
#include <netdb.h> |
#include <netdb.h> |
72 |
#endif |
#endif |
73 |
|
|
|
#ifdef HAVE_NETINET_IN_H |
|
|
#include <netinet/in.h> |
|
|
#endif |
|
|
|
|
74 |
#ifdef HAVE_SYS_TIME_H |
#ifdef HAVE_SYS_TIME_H |
75 |
#include <sys/time.h> |
#include <sys/time.h> |
76 |
#endif |
#endif |
87 |
#include <sys/filio.h> |
#include <sys/filio.h> |
88 |
#endif |
#endif |
89 |
|
|
90 |
|
#ifdef HAVE_NETINET_IP_H |
91 |
|
#include <netinet/ip.h> |
92 |
|
#endif |
93 |
|
|
94 |
|
#ifdef HAVE_NETINET_IP_ICMP_H |
95 |
|
#include <netinet/ip_icmp.h> |
96 |
|
#endif |
97 |
|
|
98 |
#ifdef HAVE_STRING_H |
#ifdef HAVE_STRING_H |
99 |
#include <string.h> |
#include <string.h> |
100 |
#endif |
#endif |
121 |
* General purpose Network and Socket methods. |
* General purpose Network and Socket methods. |
122 |
* |
* |
123 |
* @author Jan-Henrik Haukeland, <hauk@tildeslash.com> |
* @author Jan-Henrik Haukeland, <hauk@tildeslash.com> |
124 |
* @author Christian Hopp <chopp@iei.tu-clausthal.de> |
* @author Christian Hopp, <chopp@iei.tu-clausthal.de> |
125 |
|
* @author Martin Pala, <martin.pala@iol.cz> |
126 |
* |
* |
127 |
* @version \$Id$ |
* @version \$Id$ |
128 |
* |
* |
133 |
/* -------------------------------------------------------------- Prototypes */ |
/* -------------------------------------------------------------- Prototypes */ |
134 |
|
|
135 |
|
|
136 |
static int do_connect(int s, const struct sockaddr *addr, |
static int do_connect(int, const struct sockaddr *, socklen_t, int); |
137 |
socklen_t addrlen, int timeout); |
static unsigned short checksum_ip(unsigned char *, int); |
138 |
|
|
139 |
|
|
140 |
/* ------------------------------------------------------------------ Public */ |
/* ------------------------------------------------------------------ Public */ |
239 |
|
|
240 |
/** |
/** |
241 |
* Create a non-blocking socket against hostname:port with the given |
* Create a non-blocking socket against hostname:port with the given |
242 |
* protocol. The protocol should be either SOCK_STREAM or SOCK_DGRAM. |
* type. The type should be either SOCK_STREAM or SOCK_DGRAM. |
243 |
* @param hostname The host to open a socket at |
* @param hostname The host to open a socket at |
244 |
* @param port The port number to connect to |
* @param port The port number to connect to |
245 |
* @param protocol Socket protocol to use (SOCK_STREAM|SOCK_DGRAM) |
* @param type Socket type to use (SOCK_STREAM|SOCK_DGRAM) |
246 |
* @param timeout If not connected within timeout seconds abort and return -1 |
* @param timeout If not connected within timeout seconds abort and return -1 |
247 |
* @return The socket or -1 if an error occured. |
* @return The socket or -1 if an error occured. |
248 |
*/ |
*/ |
249 |
int create_socket(const char *hostname, int port, int protocol, int timeout) { |
int create_socket(const char *hostname, int port, int type, int timeout) { |
250 |
|
|
251 |
int s; |
int s; |
252 |
struct hostent *hp; |
struct hostent *hp; |
258 |
return -1; |
return -1; |
259 |
} |
} |
260 |
|
|
261 |
if((s= socket(AF_INET, protocol, 0)) < 0) { |
if((s= socket(AF_INET, type, 0)) < 0) { |
262 |
return -1; |
return -1; |
263 |
} |
} |
264 |
|
|
377 |
|
|
378 |
if(bindAddr) { |
if(bindAddr) { |
379 |
struct hostent *h= gethostbyname(bindAddr); |
struct hostent *h= gethostbyname(bindAddr); |
|
endhostent(); |
|
380 |
if(h==NULL) { |
if(h==NULL) { |
381 |
errno= h_errno; |
errno= h_errno; |
382 |
goto error; |
goto error; |
386 |
myaddr.sin_addr.s_addr= htonl(INADDR_ANY); |
myaddr.sin_addr.s_addr= htonl(INADDR_ANY); |
387 |
} |
} |
388 |
|
|
389 |
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(int)) < 0) |
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)) < 0) |
390 |
goto error; |
goto error; |
391 |
|
|
392 |
if(! set_noblock(s)) |
if(! set_noblock(s)) |
586 |
} |
} |
587 |
|
|
588 |
|
|
589 |
|
/** |
590 |
|
* Create a ICMP socket against hostname, send echo and wait for response. |
591 |
|
* @param hostname The host to open a socket at |
592 |
|
* @param timeout If response will not come within timeout seconds abort |
593 |
|
* @return TRUE on succes, FALSE on error |
594 |
|
*/ |
595 |
|
int icmp_echo(const char *hostname, int timeout) { |
596 |
|
|
597 |
|
struct hostent *hp; |
598 |
|
struct sockaddr_in sin; |
599 |
|
struct sockaddr_in sout; |
600 |
|
struct iphdr *iphdrin; |
601 |
|
struct icmphdr *icmphdrin= NULL; |
602 |
|
struct icmphdr *icmphdrout= NULL; |
603 |
|
struct timeval tv; |
604 |
|
size_t size; |
605 |
|
fd_set rset; |
606 |
|
int s; |
607 |
|
int n= 0; |
608 |
|
int rv= FALSE; |
609 |
|
unsigned ttl= 255; |
610 |
|
unsigned short mypid; |
611 |
|
char buf[STRLEN]; |
612 |
|
|
613 |
|
ASSERT(hostname); |
614 |
|
|
615 |
|
mypid= getpid(); |
616 |
|
|
617 |
|
if( (hp= gethostbyname(hostname)) == NULL ) |
618 |
|
return FALSE; |
619 |
|
|
620 |
|
if( (s= socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0 ) |
621 |
|
return FALSE; |
622 |
|
|
623 |
|
if( setsockopt(s, SOL_IP, IP_TTL, (char *)&ttl, sizeof(ttl)) < 0 ) |
624 |
|
goto error; |
625 |
|
|
626 |
|
icmphdrout= (struct icmphdr *)xmalloc(sizeof(struct icmphdr)); |
627 |
|
icmphdrout->type= ICMP_ECHO; |
628 |
|
icmphdrout->code= 0; |
629 |
|
icmphdrout->un.echo.id= mypid; |
630 |
|
icmphdrout->un.echo.sequence= 0; |
631 |
|
icmphdrout->checksum= checksum_ip((unsigned char *)icmphdrout, |
632 |
|
sizeof(struct icmphdr)); |
633 |
|
|
634 |
|
sout.sin_family= AF_INET; |
635 |
|
sout.sin_port= 0; |
636 |
|
memcpy(&sout.sin_addr, hp->h_addr, hp->h_length); |
637 |
|
|
638 |
|
sendto(s, (char *)icmphdrout, sizeof(struct icmphdr), 0, |
639 |
|
(struct sockaddr *)&sout, sizeof(struct sockaddr)); |
640 |
|
|
641 |
|
tv.tv_sec= timeout; |
642 |
|
tv.tv_usec= 0; |
643 |
|
|
644 |
|
do { |
645 |
|
|
646 |
|
FD_ZERO(&rset); |
647 |
|
FD_SET(s, &rset); |
648 |
|
|
649 |
|
do { |
650 |
|
n= select(s+1, &rset, NULL, NULL, &tv); |
651 |
|
} while(n == -1 && errno == EINTR); |
652 |
|
|
653 |
|
if(n <= 0) |
654 |
|
goto error; |
655 |
|
|
656 |
|
size= sizeof(struct sockaddr_in); |
657 |
|
|
658 |
|
if(recvfrom(s, buf, STRLEN, 0, (struct sockaddr *)&sin, &size) == -1) |
659 |
|
goto error; |
660 |
|
|
661 |
|
iphdrin= (struct iphdr *)buf; |
662 |
|
icmphdrin= (struct icmphdr *)(buf + iphdrin->ihl * 4); |
663 |
|
|
664 |
|
if( (icmphdrin->un.echo.id == mypid) && |
665 |
|
(icmphdrin->type == ICMP_ECHOREPLY) && |
666 |
|
(icmphdrin->un.echo.sequence == 0) ) { |
667 |
|
|
668 |
|
rv= TRUE; |
669 |
|
break; |
670 |
|
|
671 |
|
} |
672 |
|
|
673 |
|
} while(! ( (icmphdrin->un.echo.id == mypid) && |
674 |
|
(icmphdrin->type == ICMP_ECHOREPLY) && |
675 |
|
(icmphdrin->un.echo.sequence == 0) ) ); |
676 |
|
|
677 |
|
error: |
678 |
|
free(icmphdrout); |
679 |
|
close_socket(s); |
680 |
|
|
681 |
|
return rv; |
682 |
|
|
683 |
|
} |
684 |
|
|
685 |
|
|
686 |
/* ----------------------------------------------------------------- Private */ |
/* ----------------------------------------------------------------- Private */ |
687 |
|
|
688 |
|
|
700 |
error= 0; |
error= 0; |
701 |
|
|
702 |
if(0 > (n= connect(s, addr, addrlen))) |
if(0 > (n= connect(s, addr, addrlen))) |
703 |
if(errno != EINPROGRESS) |
if(errno != EINPROGRESS) |
704 |
return -1; |
return -1; |
705 |
|
|
706 |
FD_ZERO(&rset); |
FD_ZERO(&rset); |
707 |
FD_SET(s, &rset); |
FD_SET(s, &rset); |
718 |
if(FD_ISSET(s, &rset) || FD_ISSET(s, &wset)) { |
if(FD_ISSET(s, &rset) || FD_ISSET(s, &wset)) { |
719 |
int len= sizeof(error); |
int len= sizeof(error); |
720 |
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) |
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) |
|
return -1; |
|
|
} else |
|
721 |
return -1; |
return -1; |
722 |
|
} else |
723 |
|
return -1; |
724 |
|
|
725 |
if(error) { |
if(error) { |
726 |
errno= error; |
errno= error; |
731 |
|
|
732 |
} |
} |
733 |
|
|
734 |
|
|
735 |
|
/* |
736 |
|
* Compute Internet Checksum for "count" bytes beginning at location "addr". |
737 |
|
* Based on RFC1071. |
738 |
|
*/ |
739 |
|
static unsigned short checksum_ip(unsigned char *addr, int count) { |
740 |
|
|
741 |
|
register long sum= 0; |
742 |
|
|
743 |
|
while(count > 1) { |
744 |
|
sum += *((unsigned short *)addr)++; |
745 |
|
count -= 2; |
746 |
|
} |
747 |
|
|
748 |
|
/* Add left-over byte, if any */ |
749 |
|
if(count > 0) |
750 |
|
sum += *(unsigned char *)addr; |
751 |
|
|
752 |
|
/* Fold 32-bit sum to 16 bits */ |
753 |
|
while(sum >> 16) |
754 |
|
sum= (sum & 0xffff) + (sum >> 16); |
755 |
|
|
756 |
|
return ~sum; |
757 |
|
|
758 |
|
} |
759 |
|
|