3 Copyright (C) 2008 Lutz Mueller
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 /* this file is in the process of beeing ifdeffed to IPv6, but not completed yet
21 in the makefile_xxx add -DIPV6 in the CC compile flags
26 #define ADDR_TYPE AF_INET6
27 #define ICMP_TYPE IPPROTO_ICMPV6
29 #define ADDR_TYPE AF_INET
30 #define ICMP_TYPE IPPROTO_ICMP
39 #define fdopen win32_fdopen
41 #define gethostbyname2(A, B) gethostbyname(A)
43 #include <sys/types.h>
45 #include <sys/socket.h>
47 #include <sys/ioctl.h>
49 #include <netinet/in_systm.h>
50 #include <netinet/in.h>
51 #include <netinet/ip.h>
52 #include <netinet/ip_icmp.h>
53 #include <netinet/icmp6.h>
55 #include <arpa/inet.h>
61 #include <netinet/in_systm.h>
62 #define gethostbyname2(A, B) gethostbyname(A)
64 #define FIONREAD I_NREAD
74 #define INADDR_NONE (unsigned) -1
78 #define AF_UNIX PF_UNIX
83 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
88 #define MAX_PENDING_CONNECTS 128
89 #define NO_FLAGS_SET 0
93 #define close closesocket
95 #define SOCKET_ERROR -1
96 #define INVALID_SOCKET -1
100 #define ERR_INET_OPEN_SOCKET 1
101 #define ERR_INET_HOST_UNKNOWN 2
102 #define ERR_INET_INVALID_SERVICE 3
103 #define ERR_INET_CONNECT_FAILED 4
104 #define ERR_INET_ACCEPT 5
105 #define ERR_INET_CONNECTION_DROPPED 6
106 #define ERR_INET_CONNECTION_BROKEN 7
107 #define ERR_INET_READ 8
108 #define ERR_INET_WRITE 9
109 #define ERR_INET_CANNOT_BIND 10
110 #define ERR_INET_TOO_MUCH_SOCKETS 11
111 #define ERR_INET_LISTEN_FAILED 12
112 #define ERR_INET_BAD_FORMED_IP 13
113 #define ERR_INET_SELECT_FAILED 14
114 #define ERR_INET_PEEK_FAILED 15
115 #define ERR_INET_NOT_VALID_SOCKET 16
116 #define ERR_INET_TIMEOUT 17
117 #define MAX_NET_ERROR 17
119 #define isnum(A) ((A)>= '0' && (A) <= '9')
128 INET_SESSION
* netSessions
= NULL
;
130 int deleteInetSession(int sock
);
131 int getSocketFamily(int sock
);
134 #define READY_WRITE 1
138 extern int logTraffic
;
139 extern int noPromptMode
;
141 /* with MinGW gcc 3.4.5 not needed
147 int gettimeofday(struct timeval * tv, struct timezone * tz);
152 /********************** session functions *******************/
154 int createInetSession(int sock
, int family
)
156 INET_SESSION
* iSession
;
158 iSession
= (INET_SESSION
*)malloc(sizeof(INET_SESSION
));
160 iSession
->socket
= sock
;
161 iSession
->family
= family
;
163 if(netSessions
== NULL
)
165 netSessions
= iSession
;
166 iSession
->next
= NULL
;
170 iSession
->next
= netSessions
;
171 netSessions
= iSession
;
176 int deleteInetSession(int sock
)
178 INET_SESSION
* session
;
179 INET_SESSION
* previous
;
181 if(netSessions
== NULL
)
184 session
= previous
= netSessions
;
188 if(session
->socket
== sock
)
190 if(session
== netSessions
)
191 netSessions
= session
->next
;
193 previous
->next
= session
->next
;
194 free((char *)session
);
198 session
= session
->next
;
205 int getSocketFamily(int sock
)
207 INET_SESSION
* session
;
209 session
= netSessions
;
213 if(session
->socket
== sock
)
214 return(session
->family
);
215 session
= session
->next
;
221 /********************* user functions **************************/
224 CELL
* p_netClose(CELL
* params
)
228 getInteger(params
, &sock
);
229 deleteInetSession((int)sock
);
231 if(!getFlag(params
->next
))
232 shutdown(sock
, SHUT_RDWR
);
234 if(close((int)sock
) == SOCKET_ERROR
)
235 return(netError(ERR_INET_NOT_VALID_SOCKET
));
242 CELL
* p_netSessions(CELL
* params
)
244 INET_SESSION
* session
;
249 session
= netSessions
;
250 sList
= getCell(CELL_EXPRESSION
);
256 session
= session
->next
;
259 last
= stuffInteger(sPtr
->socket
);
260 sList
->contents
= (UINT
)last
;
264 last
->next
= stuffInteger(sPtr
->socket
);
274 /*********************************************************************/
276 CELL
* p_netService(CELL
* params
)
278 struct servent
* pSe
;
283 params
= getString(params
, &service
);
284 getString(params
, &protocol
);
286 if((pSe
= getservbyname(service
, protocol
)) == NULL
)
287 return(netError(ERR_INET_INVALID_SERVICE
));
289 port
= (int)ntohs(pSe
->s_port
);
292 return(stuffInteger((UINT
)port
));
296 CELL
* p_netConnect(CELL
* params
)
299 char * remoteHostName
;
302 char * protocol
= NULL
;
305 params
= getString(params
, &remoteHostName
);
307 if(params
== nilCell
)
309 if((sock
= netConnectLocal(remoteHostName
)) == SOCKET_ERROR
)
310 return(netError(errorIdx
));
312 return(stuffInteger((UINT
)sock
));
316 params
= getInteger(params
, &portNo
);
319 if(params
!= nilCell
)
321 params
= getString(params
, &protocol
);
322 *protocol
= toupper(*protocol
);
326 if(params
!= nilCell
)
327 getInteger(params
, &ttl
);
331 if((sock
= netConnect(remoteHostName
, (int)portNo
, type
, protocol
, (int)ttl
)) == SOCKET_ERROR
)
332 return(netError(errorIdx
));
334 createInetSession(sock
, AF_INET
);
337 return(stuffInteger((UINT
)sock
));
342 /* create local domain UNIX socket */
343 int netConnectLocal(char * path
)
346 struct sockaddr_un remote_sun
;
348 if((sock
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == SOCKET_ERROR
)
350 errorIdx
= ERR_INET_OPEN_SOCKET
;
351 return(SOCKET_ERROR
);
354 remote_sun
.sun_family
= AF_UNIX
;
355 strncpy(remote_sun
.sun_path
, path
, sizeof(remote_sun
.sun_path
) - 1);
356 remote_sun
.sun_path
[sizeof (remote_sun
.sun_path
) - 1] = '\0';
357 if (connect(sock
, (struct sockaddr
*)&remote_sun
, SUN_LEN(&remote_sun
)) == -1)
360 errorIdx
= ERR_INET_CONNECT_FAILED
;
361 return(SOCKET_ERROR
);
364 createInetSession(sock
, AF_UNIX
);
371 /* create internet socket */
372 int netConnect(char * remoteHostName
, int portNo
, int type
, char * prot
, int ttl
)
375 struct sockaddr_in6 dest_sin
;
376 struct in6_addr iaddr
;
378 struct sockaddr_in dest_sin
;
379 struct in_addr iaddr
;
381 struct hostent
* pHe
;
387 if((sock
= socket(ADDR_TYPE
, type
, 0)) == INVALID_SOCKET
)
389 errorIdx
= ERR_INET_OPEN_SOCKET
;
390 return(SOCKET_ERROR
);
393 if(prot
!= NULL
) if(*prot
== 'M' || *prot
== 'B')
395 memset(&iaddr
, 0, sizeof(iaddr
));
397 /* iaddr = IN6ADDR_ANY_INIT; */
400 iaddr
.s_addr
= INADDR_ANY
;
405 setsockopt(sock
, 0, IP_MULTICAST_IF
, (const void *)&iaddr
, sizeof(iaddr
));
407 setsockopt(sock
, 0, IP_MULTICAST_TTL
, (const void *)&opt
, sizeof(opt
));
413 setsockopt(sock
, SOL_SOCKET
, SO_BROADCAST
, (const void *)&opt
, sizeof(opt
));
417 if((pHe
= gethostbyname2(remoteHostName
, ADDR_TYPE
)) == NULL
)
419 errorIdx
= ERR_INET_HOST_UNKNOWN
;
420 return(SOCKET_ERROR
);
423 for(idx
= 0; ; idx
++)
426 memcpy((char *)&(dest_sin
.sin6_addr
), pHe
->h_addr_list
[idx
], pHe
->h_length
);
427 dest_sin
.sin6_port
= htons((u_short
)portNo
);
428 dest_sin
.sin6_family
= AF_INET6
;
430 memcpy((char *)&(dest_sin
.sin_addr
), pHe
->h_addr_list
[idx
], pHe
->h_length
);
431 dest_sin
.sin_port
= htons((u_short
)portNo
);
432 dest_sin
.sin_family
= AF_INET
;
433 memset(&(dest_sin
.sin_zero
), '\0', sizeof(dest_sin
.sin_zero
));
435 if(connect(sock
,(struct sockaddr
*)&dest_sin
, sizeof(dest_sin
)) == 0)
438 if(pHe
->h_addr_list
[idx
+1] != NULL
)
442 errorIdx
= ERR_INET_CONNECT_FAILED
;
443 return(SOCKET_ERROR
);
450 /********* should be called after listen/accept notification **********/
452 CELL
* p_netAccept(CELL
* params
)
457 getInteger(params
, &listenSock
);
459 if((sock
= netAccept((int)listenSock
)) == INVALID_SOCKET
)
460 return(netError(ERR_INET_ACCEPT
));
462 return(stuffInteger(sock
));
466 int netAccept(int listenSock
)
470 struct sockaddr_in6 dest_sin
;
472 struct sockaddr_in dest_sin
;
475 struct sockaddr_un dest_sun
;
479 family
= getSocketFamily(listenSock
);
482 if(family
== AF_UNIX
)
484 dest_slen
= sizeof(struct sockaddr_un
);
485 sock
= accept(listenSock
, (struct sockaddr
*) &dest_sun
, &dest_slen
);
491 dest_slen
= sizeof(struct sockaddr_in6
);
493 dest_slen
= sizeof(struct sockaddr_in
);
495 sock
= accept(listenSock
, (struct sockaddr
*) &dest_sin
, (void *)&dest_slen
);
498 if(sock
!= INVALID_SOCKET
)
500 createInetSession(sock
, family
);
508 /******************* returns remote IP and port number *************/
514 int getPeerName(int sock
, int peerLocalFlag
, char * IPaddress
)
516 socklen_t address_sin_len
;
518 struct sockaddr_in6 address_sin
;
520 struct sockaddr_in address_sin
;
523 if(getSocketFamily(sock
) == AF_UNIX
)
525 snprintf(IPaddress
, 6, "local");
530 address_sin_len
= sizeof(address_sin
);
531 if(peerLocalFlag
== LOCAL_INFO
)
534 (struct sockaddr
*)&address_sin
, (void *)&address_sin_len
)
541 (struct sockaddr
*)&address_sin
, (void *)&address_sin_len
)
546 /* return address IP number */
548 inet_ntop(AF_INET6
, &address_sin
.sin6_addr
, IPaddress
, 40);
549 return(ntohs(address_sin
.sin6_port
));
551 snprintf(IPaddress
, 16, inet_ntoa(address_sin
.sin_addr
));
552 return(ntohs(address_sin
.sin_port
));
557 CELL
* p_netLocal(CELL
* params
)
559 return(netPeerLocal(params
, LOCAL_INFO
));
562 CELL
* p_netPeer(CELL
* params
)
564 return(netPeerLocal(params
, PEER_INFO
));
568 CELL
* netPeerLocal(CELL
* params
, int peerLocalFlag
)
577 UINT addressPort
, sock
;
579 getInteger(params
, &sock
);
580 if((addressPort
= getPeerName((int)sock
, peerLocalFlag
, name
)) == SOCKET_ERROR
)
583 result
= getCell(CELL_EXPRESSION
);
584 result
->contents
= (UINT
)stuffString(name
);
585 cell
= (CELL
*)result
->contents
;
586 cell
->next
= stuffInteger((UINT
)addressPort
);
593 CELL
* p_netLookup(CELL
* params
)
596 struct sockaddr_in6 address
;
601 unsigned char chr
[4];
604 struct sockaddr_in address
;
606 struct hostent
* pHe
;
611 params
= getString(params
, &hostString
);
612 forceByName
= getFlag(params
);
614 /* get hostname from ip-number */
616 if((isDigit((unsigned char)*hostString
) || (hostString
[0] == ':')) && !forceByName
)
618 if(inet_pton(AF_INET6
, hostString
, &address
.sin6_addr
) == 0)
619 return(netError(ERR_INET_BAD_FORMED_IP
));
621 if((pHe
= gethostbyaddr(&address
.sin6_addr
, AF_INET6
, PF_INET6
)) == NULL
)
624 return(stuffString((char *)pHe
->h_name
));
627 if(isDigit((unsigned char)*hostString
) && !forceByName
)
629 if((ip
.no
= inet_addr(hostString
)) == INADDR_NONE
)
630 return(netError(ERR_INET_BAD_FORMED_IP
));
632 if((pHe
= gethostbyaddr((char *) &ip
.no
,4,PF_INET
)) == NULL
)
635 return(stuffString((char *)pHe
->h_name
));
639 /* get ip-number from hostname */
640 if((pHe
= gethostbyname2(hostString
, ADDR_TYPE
)) == NULL
)
644 memcpy((char *)&(address
.sin6_addr
), pHe
->h_addr_list
[0], pHe
->h_length
);
645 inet_ntop(AF_INET6
, &address
.sin6_addr
, IPaddress
, 40);
647 memcpy((char *)&(address
.sin_addr
), pHe
->h_addr_list
[0], pHe
->h_length
);
648 snprintf(IPaddress
, 16, inet_ntoa(address
.sin_addr
));
652 return(stuffString(IPaddress
));
655 CELL
* netReceive(int sock
, SYMBOL
* readSymbol
, size_t readSize
, CELL
* params
);
657 CELL
* p_netReceive(CELL
* params
)
663 params
= getInteger(params
, &sock
);
664 params
= getSymbol(params
, &readSymbol
);
665 params
= getInteger(params
, (UINT
*)&readSize
);
667 return(netReceive((int)sock
, readSymbol
, readSize
, params
));
670 CELL
* netReceive(int sock
, SYMBOL
* readSymbol
, size_t readSize
, CELL
* params
)
673 ssize_t bytesReceived
;
680 if(isProtected(readSymbol
->flags
))
681 return(errorProcExt2(ERR_SYMBOL_PROTECTED
, stuffSymbol(readSymbol
)));
683 memset(&netStream
, 0, sizeof(netStream
));
685 if(params
== nilCell
)
687 openStrStream(&netStream
, readSize
, 0);
689 bytesReceived
= recv(sock
, netStream
.buffer
, readSize
, NO_FLAGS_SET
);
693 getString(params
, &waitFor
);
694 openStrStream(&netStream
, MAX_LINE
, 0);
695 found
= bytesReceived
= 0;
696 length
= strlen(waitFor
);
697 while(bytesReceived
< (int)readSize
)
699 if(recv(sock
, &chr
, 1, NO_FLAGS_SET
) <= 0)
704 writeStreamChar(&netStream
, chr
);
705 if(++bytesReceived
< length
) continue;
706 if(strncmp(waitFor
, netStream
.ptr
- length
, length
) == 0)
715 if(bytesReceived
== 0 || found
== 0)
717 closeStrStream(&netStream
);
718 deleteInetSession(sock
);
720 return(netError(ERR_INET_CONNECTION_DROPPED
));
723 if(bytesReceived
== SOCKET_ERROR
)
725 closeStrStream(&netStream
);
726 deleteInetSession(sock
);
728 return(netError(ERR_INET_READ
));
731 cell
= stuffStringN(netStream
.buffer
, bytesReceived
);
732 closeStrStream(&netStream
);
734 deleteList((CELL
*)readSymbol
->contents
);
735 readSymbol
->contents
= (UINT
)cell
;
738 return(stuffInteger(bytesReceived
));
743 CELL
* netReceiveFrom(int sock
, size_t readSize
, int closeFlag
)
747 ssize_t bytesReceived
;
749 struct sockaddr_in6 remote_sin
;
751 struct sockaddr_in remote_sin
;
759 unsigned long remote_sin_len
;
761 socklen_t remote_sin_len
;
766 buffer
= (char *)allocMemory(readSize
+ 1);
767 remote_sin_len
= sizeof(remote_sin
);
768 memset(&remote_sin
, 0, sizeof(remote_sin
));
770 bytesReceived
= recvfrom(sock
, buffer
, readSize
, 0,
771 (struct sockaddr
*)&remote_sin
, &remote_sin_len
);
773 if(bytesReceived
== SOCKET_ERROR
)
777 return(netError(ERR_INET_READ
));
781 inet_ntop(AF_INET6
, &remote_sin
.sin6_addr
, IPaddress
, 40);
782 portNo
= ntohs(remote_sin
.sin6_port
);
784 snprintf(IPaddress
, 16, inet_ntoa(remote_sin
.sin_addr
));
785 portNo
= ntohs(remote_sin
.sin_port
);
789 cell
= result
= getCell(CELL_EXPRESSION
);
790 cell
->contents
= (UINT
)stuffStringN(buffer
, bytesReceived
);
791 cell
= (CELL
*)cell
->contents
;
792 cell
->next
= stuffString(IPaddress
);
793 ((CELL
*)cell
->next
)->next
= stuffInteger(portNo
);
797 if(closeFlag
) close(sock
);
804 CELL
* p_netReceiveUDP(CELL
* params
)
811 char * ifaddr
= NULL
;
813 params
= getInteger(params
, &portNo
);
814 params
= getInteger(params
, (UINT
*)&readSize
);
815 if(params
!= nilCell
)
817 params
= getInteger64(params
, &wait
);
818 if(params
!= nilCell
)
819 getString(params
, &ifaddr
);
822 if((sock
= netListenOrDatagram((int)portNo
, SOCK_DGRAM
, ifaddr
, NULL
)) == SOCKET_ERROR
)
825 /* if timeout parameter given wait for socket to be readable */
828 if((elapsed
= wait_ready(sock
, wait
, READY_READ
)) <= 0)
831 if(elapsed
== 0) return(netError(ERR_INET_TIMEOUT
));
832 else netError(ERR_INET_SELECT_FAILED
);
836 return(netReceiveFrom(sock
, readSize
, TRUE
));
840 CELL
* p_netReceiveFrom(CELL
* params
)
845 params
= getInteger(params
, &sock
);
846 getInteger(params
, (UINT
*)&readSize
);
848 return(netReceiveFrom((int)sock
, readSize
, FALSE
));
852 /**********************************************************************/
854 CELL
* p_netSend(CELL
* params
)
861 params
= getInteger(params
, &sock
);
862 params
= getStringSize(params
, &buffer
, &size
, TRUE
);
864 if(params
->type
!= CELL_NIL
)
866 getInteger(params
, (UINT
*)&size2
);
867 if(size2
< size
) size
= size2
;
870 if((bytesSent
= sendall((int)sock
, buffer
, size
)) == SOCKET_ERROR
)
872 deleteInetSession((int)sock
);
874 return(netError(ERR_INET_WRITE
));
878 return(stuffInteger(bytesSent
));
881 #define SEND_TO_UDP 0
882 #define SEND_TO_SOCK 1
884 CELL
* netSendTo(CELL
* params
, int type
)
889 struct sockaddr_in6 dest_sin
;
891 struct sockaddr_in dest_sin
;
893 struct hostent
* pHe
;
901 params
= getString(params
, &remoteHost
);
902 params
= getInteger(params
, &remotePort
);
903 params
= getStringSize(params
, &buffer
, &size
, TRUE
);
905 if((pHe
= gethostbyname2(remoteHost
, ADDR_TYPE
)) == NULL
)
906 return(netError(ERR_INET_HOST_UNKNOWN
));
908 if(type
== SEND_TO_UDP
) /* for 'net-send-udp' */
910 if((sock
= socket(ADDR_TYPE
, SOCK_DGRAM
, 0)) == INVALID_SOCKET
)
911 return(netError(ERR_INET_OPEN_SOCKET
));
914 setsockopt(sock
, SOL_SOCKET
, SO_BROADCAST
, (const void *)&one
, sizeof(one
));
916 else /* SEND_TO_SOCK , socket may or may not be UDP, for 'net-send-to' */
918 params
= getInteger(params
, &sock
);
922 memcpy((char *)&(dest_sin
.sin6_addr
), pHe
->h_addr_list
[0], pHe
->h_length
);
923 dest_sin
.sin6_port
= htons((u_short
)remotePort
);
924 dest_sin
.sin6_family
= AF_INET6
;
926 memcpy((char *)&(dest_sin
.sin_addr
), pHe
->h_addr_list
[0], pHe
->h_length
);
927 dest_sin
.sin_port
= htons((u_short
)remotePort
);
928 dest_sin
.sin_family
= AF_INET
;
929 memset(&(dest_sin
.sin_zero
), '\0', 8);
932 bytesSent
= sendto((int)sock
, buffer
, size
, NO_FLAGS_SET
,
933 (struct sockaddr
*)&dest_sin
, sizeof(dest_sin
));
935 if(type
== SEND_TO_UDP
) close((int)sock
);
937 if(bytesSent
== SOCKET_ERROR
)
938 return(netError(ERR_INET_WRITE
));
941 return(stuffInteger(bytesSent
));
945 CELL
* p_netSendUDP(CELL
* params
)
947 return(netSendTo(params
, SEND_TO_UDP
));
951 CELL
* p_netSendTo(CELL
* params
)
953 return(netSendTo(params
, SEND_TO_SOCK
));
957 /************************* listen **************************************/
959 CELL
* p_netListen(CELL
* params
)
962 char * ifAddr
= NULL
;
963 char * option
= NULL
;
964 char * mcAddr
= NULL
;
969 cell
= evaluateExpression(params
);
970 params
= params
->next
;
973 if(cell
->type
== CELL_STRING
)
975 if((sock
= netListenLocal((char *)cell
->contents
)) == SOCKET_ERROR
)
976 return(netError(errorIdx
));
978 return(stuffInteger((UINT
)sock
));
982 getIntegerExt(cell
, &portNo
, FALSE
);
984 if(params
!= nilCell
)
986 params
= getString(params
, &ifAddr
);
987 if(*ifAddr
== 0) ifAddr
= NULL
;
988 if(params
!= nilCell
)
990 params
= getString(params
, &option
);
991 if(*option
== 'u' || *option
== 'U')
993 else if(*option
== 'm' || *option
== 'M')
1003 if((sock
= netListenOrDatagram((int)portNo
, type
, ifAddr
, mcAddr
)) == SOCKET_ERROR
)
1006 return(stuffInteger(sock
));
1010 int netListenLocal(char * name
)
1013 struct sockaddr_un local_sun
;
1015 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1016 local_sun
.sun_family
= AF_UNIX
;
1017 strncpy(local_sun
.sun_path
, name
, sizeof(local_sun
.sun_path
) - 1);
1018 local_sun
.sun_path
[sizeof (local_sun
.sun_path
) - 1] = '\0';
1019 unlink(local_sun
.sun_path
);
1022 if(bind(sock
, (struct sockaddr
*)&local_sun
, sizeof(struct sockaddr_un
)) == -1)
1024 if(bind(sock
, (struct sockaddr
*)&local_sun
, SUN_LEN(&local_sun
)) != 0)
1028 errorIdx
= ERR_INET_CANNOT_BIND
;
1029 return(SOCKET_ERROR
);
1032 if(listen(sock
, MAX_PENDING_CONNECTS
) == SOCKET_ERROR
)
1035 errorIdx
= ERR_INET_LISTEN_FAILED
;
1036 return(SOCKET_ERROR
);
1039 createInetSession(sock
, AF_UNIX
);
1047 int netListenOrDatagram(int portNo
, int type
, char * ifAddr
, char * mcAddr
)
1053 struct sockaddr_in6 local_sin
;
1055 struct sockaddr_in local_sin
;
1057 struct hostent
* pHe
;
1058 struct ip_mreq mcast
;
1060 if((sock
= socket(ADDR_TYPE
, type
, 0)) == INVALID_SOCKET
)
1062 errorIdx
= ERR_INET_OPEN_SOCKET
;
1063 return SOCKET_ERROR
;
1066 memset(&local_sin
, 0, sizeof(local_sin
));
1068 if(ifAddr
!= NULL
&& *ifAddr
!= 0)
1070 if((pHe
= gethostbyname2(ifAddr
, ADDR_TYPE
)) == NULL
)
1072 errorIdx
= ERR_INET_HOST_UNKNOWN
;
1073 return(SOCKET_ERROR
);
1076 memcpy((char *)&(local_sin
.sin6_addr
), pHe
->h_addr_list
[0], pHe
->h_length
);
1080 local_sin
.sin6_addr
= in6addr_any
;
1083 memcpy((char *)&(local_sin
.sin_addr
), pHe
->h_addr_list
[0], pHe
->h_length
);
1086 local_sin
.sin_addr
.s_addr
= INADDR_ANY
;
1090 local_sin
.sin6_port
= htons((u_short
)portNo
);
1091 local_sin
.sin6_family
= AF_INET6
;
1093 local_sin
.sin_port
= htons((u_short
)portNo
);
1094 local_sin
.sin_family
= AF_INET
;
1097 setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, (const void*)&one
, sizeof(one
));
1099 if(bind(sock
, (struct sockaddr
*) &local_sin
, sizeof(local_sin
)) == SOCKET_ERROR
)
1102 errorIdx
= ERR_INET_CANNOT_BIND
;
1103 return(SOCKET_ERROR
);
1108 memset(&mcast
, 0, sizeof(mcast
));
1109 mcast
.imr_multiaddr
.s_addr
= inet_addr(mcAddr
);
1111 /* mcast.imr_interface.s_addr = IN6ADDR_ANY_INIT; */
1113 mcast
.imr_interface
.s_addr
= INADDR_ANY
;
1115 setsockopt(sock
, 0, IP_ADD_MEMBERSHIP
, (const void *)&mcast
, sizeof(mcast
));
1118 if(type
== SOCK_STREAM
)
1120 if(listen(sock
, MAX_PENDING_CONNECTS
) == SOCKET_ERROR
)
1123 errorIdx
= ERR_INET_LISTEN_FAILED
;
1124 return(SOCKET_ERROR
);
1128 createInetSession(sock
, AF_INET
);
1135 /* returns number of bytes ready to read */
1136 CELL
* p_netPeek(CELL
* params
)
1140 unsigned long result
;
1145 getInteger(params
, &sock
);
1147 if(ioctl((int)sock
, FIONREAD
, &result
) == SOCKET_ERROR
)
1148 return(netError(ERR_INET_PEEK_FAILED
));
1151 return(stuffInteger((UINT
)result
));
1162 /* checks a socket for readability/writeability */
1163 CELL
* p_netSelect(CELL
* params
)
1168 struct timeval timeOut
;
1171 SOCKLIST
* sockList
= NULL
;
1174 struct timeval
* tmvPtr
;
1178 FD_ZERO(&socketSet
);
1180 cell
= evaluateExpression(params
);
1181 if(isNumber(cell
->type
))
1182 getIntegerExt(cell
, (UINT
*)&value
, FALSE
);
1183 else if(isList(cell
->type
))
1185 cell
= (CELL
*)cell
->contents
;
1186 if(cell
== nilCell
) return(getCell(CELL_EXPRESSION
));
1187 sockList
= sockPtr
= allocMemory(sizeof(SOCKLIST
));
1188 sockPtr
->sock
= cell
->contents
;
1189 sockPtr
->next
= NULL
;
1190 FD_SET(sockPtr
->sock
, &socketSet
);
1192 while((cell
= cell
->next
) != nilCell
)
1194 sockPtr
->next
= allocMemory(sizeof(SOCKLIST
));
1195 sockPtr
= sockPtr
->next
;
1196 sockPtr
->sock
= cell
->contents
;
1197 sockPtr
->next
= NULL
;
1198 if(value
== FD_SETSIZE
)
1199 return(netError(ERR_INET_TOO_MUCH_SOCKETS
));
1201 FD_SET(sockPtr
->sock
, &socketSet
);
1204 else return(errorProcExt(ERR_LIST_OR_NUMBER_EXPECTED
, params
));
1206 params
= getString(params
->next
, &mode
);
1207 getInteger64(params
, &wait
);
1209 tmvPtr
= (wait
== -1) ? NULL
: &timeOut
;
1210 timeOut
.tv_sec
= wait
/1000000;
1211 timeOut
.tv_usec
= wait
- timeOut
.tv_sec
* 1000000;
1213 if(sockList
== NULL
)
1215 FD_SET((int)value
, &socketSet
);
1219 /* printf("%d %d %d\n", timeOut.tv_sec, timeOut.tv_usec, sizeof(timeOut.tv_sec)); */
1222 value
= select(FD_SETSIZE
, &socketSet
, NULL
, NULL
, tmvPtr
);
1223 else if(*mode
== 'w')
1224 value
= select(FD_SETSIZE
, NULL
, &socketSet
, NULL
, tmvPtr
);
1225 else if(*mode
== 'e')
1226 value
= select(FD_SETSIZE
, NULL
, NULL
, &socketSet
, tmvPtr
);
1230 if((sockPtr
= sockList
) == NULL
)
1232 if(value
== 0) return(nilCell
);
1233 else return(trueCell
);
1236 cell
= getCell(CELL_EXPRESSION
);
1237 while(sockPtr
!= NULL
)
1239 if(FD_ISSET(sockPtr
->sock
, &socketSet
))
1244 cell
->contents
= (UINT
)stuffInteger(sockPtr
->sock
);
1245 cell
= (CELL
*)cell
->contents
;
1249 cell
->next
= stuffInteger(sockPtr
->sock
);
1253 sockPtr
= sockPtr
->next
;
1258 if(list
== NULL
) return(cell
);
1262 netError(ERR_INET_SELECT_FAILED
);
1264 if(sockList
== NULL
) return(nilCell
);
1265 return(getCell(CELL_EXPRESSION
));
1268 extern char logFile
[];
1270 void writeLog(char * text
, int newLine
)
1275 handle
= open(logFile
, O_RDWR
| O_APPEND
| O_BINARY
| O_CREAT
, S_IREAD
| S_IWRITE
);
1277 handle
= open(logFile
, O_RDWR
| O_APPEND
| O_BINARY
| O_CREAT
,
1278 S_IRUSR
| S_IRGRP
| S_IROTH
| S_IWUSR
| S_IWGRP
| S_IWOTH
); /* rw-rw-rw */
1281 write(handle
, text
, strlen(text
));
1282 if(newLine
) write(handle
, &LINE_FEED
, strlen(LINE_FEED
));
1287 FILE * serverFD(int port
, char * domain
, int reconnect
)
1289 static int sock
, connection
;
1298 sock
= netListenOrDatagram(port
, SOCK_STREAM
, NULL
, NULL
);
1300 sock
= netListenLocal(domain
);
1302 sock
= netListenOrDatagram(port
, SOCK_STREAM
, NULL
, NULL
);
1305 if(sock
== SOCKET_ERROR
)
1307 snprintf(text
, 78, "newLISP v.%d listening on %s", version
, domain
);
1308 writeLog(text
, TRUE
);
1314 deleteInetSession(connection
);
1318 if((connection
= netAccept(sock
)) == SOCKET_ERROR
)
1321 createInetSession(connection
, (port
!= 0) ? AF_INET
: AF_UNIX
);
1324 getPeerName(connection
, PEER_INFO
, name
);
1326 snprintf(text
, 78, "Connected to %s on %s", name
, ctime(&t
));
1330 return(fdopen(connection
, "r+"));
1333 /******************************* distributed computing ***********************/
1335 #define MAX_BUFF 1024
1336 CELL
* netEvalError(int errNo
);
1349 void freeSessions(NETEVAL
* base
);
1351 CELL
* p_netEval(CELL
* params
)
1355 NETEVAL
* session
= NULL
;
1356 NETEVAL
* base
= NULL
;
1362 size_t size
, count
= 0;
1364 long timeOut
= MAX_LONG
;
1365 int start
, elapsed
= 0;
1368 CELL
* netEvalIdle
= NULL
;
1369 char buffer
[MAX_BUFF
];
1371 int rawMode
= FALSE
;
1372 int singleSession
= FALSE
;
1373 jmp_buf errorJumpSave
;
1375 int resultStackIdxSave
;
1377 list
= evaluateExpression(params
);
1378 if(list
->type
== CELL_STRING
)
1380 host
= (char *)list
->contents
;
1381 params
= getIntegerExt(params
->next
, &port
, TRUE
);
1382 params
= getStringSize(params
, &prog
, &size
, TRUE
);
1384 singleSession
= TRUE
;
1385 goto SINGLE_SESSION
;
1387 else if(list
->type
== CELL_EXPRESSION
)
1389 list
= (CELL
*)list
->contents
;
1390 params
= params
->next
;
1392 else return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, params
));
1395 if(!isList(list
->type
))
1396 return(errorProcExt(ERR_LIST_EXPECTED
, list
));
1397 cell
= (CELL
*)list
->contents
;
1399 /* get node parameters, since 8.9.8 evaluated */
1400 memcpy(errorJumpSave
, errorJump
, sizeof(jmp_buf));
1401 if((errNo
= setjmp(errorJump
)) != 0)
1403 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
1405 longjmp(errorJump
, errNo
);
1407 cell
= getStringSize(cell
, &host
, &size
, TRUE
);
1408 cell
= getInteger(cell
, &port
);
1409 cell
= getStringSize(cell
, &prog
, &size
, TRUE
);
1410 rawMode
= getFlag(cell
);
1412 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
1417 base
= session
= allocMemory(sizeof(NETEVAL
));
1418 memset(base
, 0, sizeof(NETEVAL
));
1422 session
->next
= allocMemory(sizeof(NETEVAL
));
1423 session
= session
->next
;
1424 memset(session
, 0, sizeof(NETEVAL
));
1429 sock
= netConnect(host
, (int)port
, SOCK_STREAM
, NULL
, 3);
1431 sock
= netConnectLocal(host
);
1433 sock
= netConnect(host
, (int)port
, SOCK_STREAM
, NULL
, 3);
1436 if(sock
== SOCKET_ERROR
)
1438 session
->result
= netEvalError(errorIdx
);
1439 goto CONTINUE_CREATE_SESSION
;
1442 session
->host
= host
;
1443 session
->port
= port
;
1444 session
->sock
= sock
;
1446 if( sendall(sock
, "[cmd]\n", 6) == SOCKET_ERROR
||
1447 sendall(sock
, prog
, size
) == SOCKET_ERROR
||
1448 sendall(sock
, "(exit)\n[/cmd]\n", 14) == SOCKET_ERROR
)
1451 session
->result
= netEvalError(ERR_INET_WRITE
);
1452 goto CONTINUE_CREATE_SESSION
;
1455 session
->netStream
= (void *)allocMemory(sizeof(STREAM
));
1456 memset(session
->netStream
, 0, sizeof(STREAM
));
1457 openStrStream(session
->netStream
, MAX_BUFF
, 0);
1458 /* prepend quote for evaluation */
1459 writeStreamChar(session
->netStream
, '\'');
1460 createInetSession(sock
, AF_INET
);
1462 CONTINUE_CREATE_SESSION
:
1464 if(list
!= nilCell
) goto CREATE_SESSION
;
1466 /* get timeout and optional handler symbol */
1468 if(params
!= nilCell
)
1469 params
= getInteger(params
, (UINT
*)&timeOut
);
1470 if(params
!= nilCell
)
1471 netEvalIdle
= params
;
1473 /* printf("timeout %d idle-loop %X\n", timeOut, netEvalIdle); */
1475 /* collect data from host in each active session */
1478 resultStackIdxSave
= resultStackIdx
;
1479 if( (netStream
= session
->netStream
) == NULL
)
1481 session
= session
->next
;
1482 if(session
== NULL
) session
= base
;
1486 start
= milliSecTime();
1490 cell
= getCell(CELL_EXPRESSION
);
1491 cell
->contents
= (UINT
)copyCell(netEvalIdle
);
1493 if(!evaluateExpressionSafe(cell
, &errNo
))
1496 longjmp(errorJump
, errNo
);
1501 ready
= wait_ready(session
->sock
, 100, READY_READ
);
1504 memset(buffer
, 0, MAX_BUFF
);
1505 bytes
= recv(session
->sock
, buffer
, MAX_BUFF
, NO_FLAGS_SET
);
1506 if(bytes
) writeStreamStr(netStream
, buffer
, bytes
);
1508 if(ready
< 0 || bytes
== 0 || elapsed
>= timeOut
)
1510 /* printf("count=%d ready=%d bytes=%d elapsed=%d\n", count, ready, bytes, elapsed); */
1511 if(elapsed
>= timeOut
) result
= copyCell(nilCell
);
1512 else if(rawMode
) /* get raw buffer without the quote */
1513 result
= stuffStringN(netStream
->buffer
+ 1, netStream
->position
- 1);
1516 makeStreamFromString(&evalStream
, netStream
->buffer
);
1517 memcpy(errorJumpSave
, errorJump
, sizeof(jmp_buf));
1518 if((errNo
= setjmp(errorJump
)) != 0)
1520 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
1522 longjmp(errorJump
, errNo
);
1524 result
= evaluateStream(&evalStream
, 0, TRUE
);
1525 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
1530 session
->result
= cell
= getCell(CELL_EXPRESSION
);
1531 cell
->contents
= (UINT
)stuffString(session
->host
);
1532 cell
= (CELL
*)cell
->contents
;
1533 cell
->next
= stuffInteger(session
->port
);
1535 cell
->next
= result
;
1538 session
->result
= result
;
1540 closeStrStream(netStream
);
1541 deleteInetSession(session
->sock
);
1542 close(session
->sock
);
1544 session
->netStream
= NULL
;
1548 list
= getCell(CELL_EXPRESSION
);
1549 list
->contents
= (UINT
)copyCell(netEvalIdle
);
1550 cell
= getCell(CELL_QUOTE
);
1551 cell
->contents
= (UINT
)session
->result
;
1552 ((CELL
*)list
->contents
)->next
= cell
;
1554 if(!evaluateExpressionSafe(list
, &errNo
))
1557 longjmp(errorJump
, errNo
);
1564 /* check for rollover at midnight */
1565 if(milliSecTime() >= start
)
1566 elapsed
+= milliSecTime() - start
;
1568 elapsed
+= milliSecTime();
1570 session
= session
->next
;
1571 if(session
== NULL
) session
= base
;
1573 cleanupResults(resultStackIdxSave
);
1576 /* free all sessions and configure result */
1580 if(netEvalIdle
== NULL
)
1585 result
= base
->result
;
1588 result
= getCell(CELL_EXPRESSION
);
1589 result
->contents
= (UINT
)base
->result
;
1590 cell
= base
->result
;
1595 cell
->next
= base
->result
;
1604 if(elapsed
> timeOut
)
1605 errorIdx
= ERR_INET_TIMEOUT
;
1607 if(netEvalIdle
== NULL
) return(result
);
1612 void freeSessions(NETEVAL
* base
)
1618 if(base
->netStream
!= NULL
)
1620 if(base
->result
!= NULL
)
1621 deleteList(base
->result
);
1622 closeStrStream(base
->netStream
);
1623 deleteInetSession(base
->sock
);
1625 free(base
->netStream
);
1626 base
->netStream
= NULL
;
1634 int sendall(int sock
, char * buffer
, int len
)
1639 while(bytesSend
< len
)
1641 if((n
= send(sock
, buffer
+ bytesSend
, len
- bytesSend
, NO_FLAGS_SET
)) == SOCKET_ERROR
)
1642 return(SOCKET_ERROR
);
1649 /*********************** error handling ***************************************/
1651 char * netErrorMsg
[] =
1654 "Cannot open socket",
1655 "Host name not known",
1656 "Not a valid service",
1657 "Connection failed",
1659 "Connection closed",
1660 "Connection broken",
1661 "Socket recv failed",
1662 "Socket send failed",
1663 "Cannot bind socket",
1664 "Too much sockets in net-select",
1669 "Not a valid socket",
1670 "Operation timed out"
1674 CELL
* netError(int errorNo
)
1680 CELL
* netEvalError(int errorNo
)
1683 return(p_netLastError(NULL
));
1686 CELL
* p_netLastError(CELL
* params
)
1691 if(errorIdx
== 0 || errorIdx
> MAX_NET_ERROR
) return(nilCell
);
1693 cell
= getCell(CELL_EXPRESSION
);
1694 cell
->contents
= (UINT
)stuffInteger(errorIdx
);
1695 snprintf(str
, 63, "ERR: %s", netErrorMsg
[errorIdx
]);
1696 ((CELL
*)cell
->contents
)->next
= stuffString(str
);
1706 CELL
* p_netPing(CELL
* params
)
1709 UINT maxwait
= 1000, listmode
= 0;
1713 address
= evaluateExpression(params
);
1714 if(address
->type
== CELL_EXPRESSION
)
1716 address
= (CELL
*)address
->contents
;
1719 else if(address
->type
!= CELL_STRING
)
1720 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, address
));
1722 params
= params
->next
;
1723 if(params
!= nilCell
)
1725 params
= getInteger(params
, &maxwait
);
1726 if(params
!= nilCell
)
1727 params
= getInteger(params
, &count
);
1728 flag
= getFlag(params
);
1731 return(ping(address
, (int)maxwait
, (int)listmode
, (int)count
, (int)flag
));
1735 /* datalen 56 + iplen 60 + icmplen 76 */
1736 #define PLEN 192 /* 192 or 64 ? */
1741 CELL
* ping(CELL
* address
, int maxwait
, int listmode
, int maxCount
, int flag
)
1745 char * hostaddr
= NULL
;
1747 unsigned char packet
[PLEN
];
1750 struct icmp6_hdr
*icp
= (struct icmp6_hdr
*) packet
;
1751 struct sockaddr_in6 whereto
;
1752 struct sockaddr_in6 from
;
1753 struct icmp6_filter filter
;
1756 struct sockaddr_in whereto
;
1757 struct sockaddr_in from
;
1758 struct icmp
*icp
= (struct icmp
*) packet
;
1762 unsigned long fromlen
;
1767 unsigned int fromlen
;
1771 int size
, ipNo
, startIp
= 0, endIp
= 0;
1772 int timeout
= 0, tdiff
;
1773 int sendCount
= 0, receiveCount
= 0, ping_sequence
= 0;
1775 struct timeval tv
, tp
;
1776 CELL
* result
= NULL
;
1780 if ((s
= socket(ADDR_TYPE
, SOCK_RAW
, ICMP_TYPE
)) < 0)
1781 return(netError(ERR_INET_OPEN_SOCKET
));
1784 ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY
, &filter
);
1785 setsockopt (s
, IPPROTO_ICMPV6
, ICMP6_FILTER
, &filter
, sizeof (filter
));
1787 /* setsockopt (s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &sockopt, sizeof (sockopt)); */
1790 gettimeofday(&tv
, NULL
);
1792 /* for each list-IP */
1793 while(address
!= nilCell
)
1796 if(address
->type
!= CELL_STRING
)
1798 shutdown(s
, SHUT_RDWR
);
1799 return(errorProcExt(ERR_STRING_EXPECTED
, address
));
1802 host
= (char *)address
->contents
;
1803 len
= address
->aux
- 1;
1806 if(strncmp(host
+ len
- 2, ".*", 2) == 0)
1814 startIp
= endIp
= 0;
1815 ptr
= host
+ len
- 1;
1816 while(isdigit((int)*ptr
)) --ptr
;
1819 endIp
= atoi(ptr
+ 1);
1821 while(isdigit((int)*ptr
)) --ptr
;
1824 startIp
= atoi(ptr
+ 1);
1825 len
= ptr
- host
+ 1;
1827 else endIp
= startIp
= 0;
1828 if(endIp
< startIp
) endIp
= startIp
;
1834 for(ipNo
= startIp
; ipNo
<= endIp
; ipNo
++)
1838 if(hostaddr
== NULL
) hostaddr
= alloca(len
+ 4);
1839 memcpy(hostaddr
, host
, len
);
1840 snprintf(hostaddr
+ len
, 4, "%d", ipNo
);
1845 /* target host address info */
1846 /* printf("->%s\n", hostaddr); */
1848 memset((char *)&whereto
, 0, sizeof(struct sockaddr_in6
));
1849 whereto
.sin6_family
= AF_INET6
;
1850 if(!(hp
= gethostbyname2(hostaddr
, AF_INET6
)))
1852 shutdown(s
, SHUT_RDWR
);
1853 return(netError(ERR_INET_HOST_UNKNOWN
));
1855 memcpy((char *)&(whereto
.sin6_addr
), hp
->h_addr_list
[0], hp
->h_length
);
1857 memset((char *)&whereto
, 0, sizeof(struct sockaddr_in
));
1858 whereto
.sin_family
= AF_INET
;
1859 if(!(hp
= gethostbyname2(hostaddr
, AF_INET
)))
1861 shutdown(s
, SHUT_RDWR
);
1862 return(netError(ERR_INET_HOST_UNKNOWN
));
1864 memcpy((void *)&whereto
.sin_addr
, hp
->h_addr
, hp
->h_length
);
1865 broadcast
= ((whereto
.sin_addr
.s_addr
& 0x000000ff) == 255);
1870 setsockopt(s
, SOL_SOCKET
, SO_BROADCAST
, (void *) &sockopt
, sizeof(sockopt
));
1874 memset(icp
, 0, PLEN
);
1876 icp
->icmp6_type
= ICMP6_ECHO_REQUEST
;
1877 icp
->icmp6_code
= 0;
1878 icp
->icmp6_cksum
= 0;
1879 icp
->icmp6_seq
= ping_sequence
;
1880 icp
->icmp6_id
= getpid() & 0xFFFF;
1881 gettimeofday((struct timeval
*)&icp
->icmp6_data8
[4], NULL
);
1883 sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
1884 setsockopt(s, SOL_RAW, IPV6_CHECKSUM, (char *)&sockopt, sizeof(sockopt));
1886 setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, (char *)&sockopt, sizeof(sockopt));
1890 icp
->icmp_type
= ICMP_ECHO
;
1892 icp
->icmp_cksum
= 0;
1893 icp
->icmp_seq
= ping_sequence
;
1894 icp
->icmp_id
= getpid() & 0xFFFF;
1895 gettimeofday((struct timeval
*)&icp
[1], NULL
);
1896 icp
->icmp_cksum
= in_cksum((unsigned short *) icp
, PLEN
);
1898 while(wait_ready(s
, 10000, READY_WRITE
) <= 0)
1900 gettimeofday(&tp
, NULL
);
1901 if((timeout
= (timediff(tp
, tv
) > maxwait
))) break;
1905 size
= sendto(s
, packet
, PLEN
, 0,(struct sockaddr
*)&whereto
, sizeof(struct sockaddr
));
1908 if(errno
== EHOSTUNREACH
|| errno
== EHOSTDOWN
)
1912 snprintf(buff
, 16, "errno: %d", errno
);
1914 memset(IPaddress
, 0, 40);
1915 inet_ntop(AF_INET6
, &whereto
.sin6_addr
, IPaddress
, 40);
1916 link
= addResult(&result
, link
,
1917 makePair(stuffString(IPaddress
), stuffString(buff
)));
1919 link
= addResult(&result
, link
,
1920 makePair(stuffString(inet_ntoa(whereto
.sin_addr
)), stuffString(buff
)));
1923 if( !(listmode
|| startIp
) ) break;
1926 shutdown(s
, SHUT_RDWR
);
1927 return(netError(ERR_INET_WRITE
));
1932 if(!listmode
) break;
1933 address
= address
->next
;
1936 /* wait for response(s) */
1937 if(maxCount
== 0) maxCount
= sendCount
;
1940 memset(packet
, 0, PLEN
);
1941 fromlen
= sizeof(from
);
1943 if(wait_ready(s
, 1000, READY_READ
) <= 0)
1945 gettimeofday(&tp
, NULL
);
1946 if((timeout
= (timediff(tp
, tv
) > maxwait
))) break;
1950 if ( (len
= recvfrom(s
, packet
, PLEN
, 0, (struct sockaddr
*)&from
, &fromlen
)) < 0)
1953 ip
= (struct ip
*) packet
;
1954 gettimeofday(&tp
, NULL
);
1956 icp
= (struct icmp6_hdr
*)packet
;
1957 if(icp
->icmp6_type
!= ICMP6_ECHO_REPLY
) continue;
1958 if(icp
->icmp6_id
!= (getpid() & 0xFFFF)) continue;
1959 tdiff
= timediff64(tp
, *(struct timeval
*)&icp
->icmp6_data8
[4]);
1961 icp
= (struct icmp
*)(packet
+ (ip
->ip_hl
<< 2));
1962 if(icp
->icmp_id
!= (getpid() & 0xFFFF)) continue;
1963 tdiff
= timediff64(tp
, *(struct timeval
*)&icp
[1]);
1967 inet_ntop(AF_INET6
, &from
.sin6_addr
, IPaddress
, 40);
1968 link
= addResult(&result
, link
,
1969 makePair(stuffString(IPaddress
), stuffInteger(tdiff
)));
1971 link
= addResult(&result
, link
,
1972 makePair(stuffString(inet_ntoa(from
.sin_addr
)), stuffInteger(tdiff
)));
1975 if(++receiveCount
== maxCount
) break;
1976 if( !(broadcast
|| listmode
|| startIp
) ) break;
1979 shutdown(s
, SHUT_RDWR
);
1981 if(timeout
) errorIdx
= ERR_INET_TIMEOUT
;
1983 return(result
== NULL
? getCell(CELL_EXPRESSION
) : result
);
1986 CELL
* addResult(CELL
* * result
, CELL
* cell
, CELL
* new)
1990 *result
= getCell(CELL_EXPRESSION
);
1991 ((CELL
*)(*result
))->contents
= (UINT
)new;
1999 CELL
* makePair(CELL
* left
, CELL
* right
)
2001 CELL
* cell
= getCell(CELL_EXPRESSION
);
2003 cell
->contents
= (UINT
)left
;
2009 int in_cksum(unsigned short * addr
, int len
)
2012 unsigned short *w
= addr
;
2013 unsigned short answer
;
2016 while( nleft
> 1 ) {
2023 *(unsigned char *)(&u
) = *(unsigned char *)w
;
2027 sum
= (sum
>> 16) + (sum
& 0xffff);
2033 #endif /* NET_PING */
2036 /* check socket for readability or error
2037 return 0 if the time limit expires or -1
2040 int wait_ready(int sock
, INT64 wait
, int mode
)
2042 struct timeval timeOut
;
2045 FD_ZERO(&socketSet
);
2046 FD_SET(sock
, &socketSet
);
2048 timeOut
.tv_sec
= wait
/1000000;
2049 timeOut
.tv_usec
= wait
- timeOut
.tv_sec
* 1000000;
2051 if(mode
== READY_READ
)
2052 return(select(FD_SETSIZE
, &socketSet
, NULL
, &socketSet
, &timeOut
));
2054 return(select(FD_SETSIZE
, NULL
, &socketSet
, &socketSet
, &timeOut
));
2058 /* ----------------------------- socket->filestream stuff for win32 ------------------------*/
2063 These functions use the FILE structure to store the raw file handle in '->_file' and
2064 set ->_flag to 0xFFFF, to identify this as a faked FILE structure.
2067 FILE * win32_fdopen(int handle
, const char * mode
)
2071 if((fPtr
= (FILE *)malloc(sizeof(FILE))) == NULL
)
2074 memset(fPtr
, 0, sizeof(FILE));
2078 fPtr
->_file
= handle
;
2079 fPtr
->_flag
= 0xFFFF;
2085 int win32_fclose(FILE * fPtr
)
2087 if(isSocketStream(fPtr
))
2088 return(close(getSocket(fPtr
)));
2091 return(fclose(fPtr
));
2095 /* for a full fprintf with format string and parameters
2096 see version previous to 9.0.2
2098 int win32_fprintf(FILE * fPtr
, char * buffer
)
2102 if(!isSocketStream(fPtr
))
2103 return(fprintf(fPtr
, buffer
));
2105 pSize
= strlen(buffer
);
2107 if((pSize
= sendall(getSocket(fPtr
), buffer
, pSize
)) == SOCKET_ERROR
)
2109 close(getSocket(fPtr
));
2116 int win32_fgetc(FILE * fPtr
)
2120 if(!isSocketStream(fPtr
))
2121 return(fgetc(fPtr
));
2123 if(recv(getSocket(fPtr
), &chr
, 1, NO_FLAGS_SET
) <= 0)
2125 close(getSocket(fPtr
));
2133 char * win32_fgets(char * buffer
, int size
, FILE * fPtr
)
2135 int bytesReceived
= 0;
2138 if(!isSocketStream(fPtr
))
2139 return(fgets(buffer
, size
- 1, fPtr
));
2141 while(bytesReceived
< size
)
2143 if(recv(getSocket(fPtr
), &chr
, 1, NO_FLAGS_SET
) <= 0)
2145 close(getSocket(fPtr
));
2149 *(buffer
+ bytesReceived
++) = chr
;
2151 if(chr
== '\n') break;
2154 *(buffer
+ bytesReceived
) = 0;