Пример #1
0
/* {INET_PROPERTIES}.is_ipv6_available */
EIF_TYPED_VALUE F157_8694 (EIF_REFERENCE Current)
{
	GTCX
	char *l_feature_name = "is_ipv6_available";
	RTEX;
	EIF_BOOLEAN Result = ((EIF_BOOLEAN) 0);
	
	RTSN;
	RTDA;
	RTLD;
	
	RTLI(1);
	RTLR(0,Current);
	RTLU (SK_BOOL, &Result);
	RTLU (SK_REF, &Current);
	
	RTEAA(l_feature_name, 156, Current, 0, 0, 2264);
	RTSA(Dtype(Current));
	RTSC;
	RTME(Dtype(Current), 1);
	RTDBGEAA(156, Current, 2264);
	RTIV(Current, RTAL);Result = (EIF_BOOLEAN) EIF_TEST(en_ipv6_available());
	
	RTVI(Current, RTAL);
	RTRS;
	RTHOOK(1);
	RTDBGLE;
	RTMD(1);
	RTLE;
	RTLO(2);
	RTEE;
	{ EIF_TYPED_VALUE r; r.type = SK_BOOL; r.it_b = Result; return r; }
}
Пример #2
0
void en_socket_datagram_connect (EIF_INTEGER fd, EIF_INTEGER fd1, EIF_POINTER sockaddr) {

	SOCKETADDRESS* him;
	int family;
	EIF_INTEGER fdc = -1;
	int ipv6_supported;
	int connect_res;

	EIF_NET_INITIALIZE;

	ipv6_supported = en_ipv6_available();

	him = (SOCKETADDRESS*) sockaddr;
	family = him->him.sa_family; 

	if (family == AF_INET6 && !ipv6_supported) {
		eraise ("Protocol family not supported", EN_PROG);
		return;
	}
    	
	fdc = (family == AF_INET? fd: fd1);
	connect_res = connect(fdc, (struct sockaddr *)him, SOCKETADDRESS_LEN(him));
	if ( connect_res == -1) {
    		eraise("Unable to establish connection", EN_PROG);
	}
}
Пример #3
0
void en_socket_stream_create (EIF_INTEGER *a_fd, EIF_INTEGER *a_fd1) {
	SOCKET fd, fd1;

	EIF_NET_INITIALIZE;

	fd = check_socket_bounds(socket(AF_INET, SOCK_STREAM, 0));

	if (fd == INVALID_SOCKET) {
		*a_fd = -1;
		eif_net_check ((int)fd);
		return;
	} else {
			/* Set socket attribute so it is not passed to any child process */
		SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, FALSE);
		*a_fd = (EIF_INTEGER) fd;
	}
	if (en_ipv6_available()) {
		fd1 = check_socket_bounds(socket(AF_INET6, SOCK_STREAM, 0));
		if (fd1 == INVALID_SOCKET) {
			*a_fd = -1;
			*a_fd1 = -1;
			net_socket_close((int)fd);
			eif_net_check ((int)fd1);
			return;
		} else {
				/* Set socket attribute so it is not passed to any child process */
			SetHandleInformation((HANDLE)fd1, HANDLE_FLAG_INHERIT, FALSE);
			*a_fd1 = (EIF_INTEGER) fd1;
		}
	} else {
		*a_fd1 = -1;
	}
}
Пример #4
0
EIF_INTEGER en_socket_datagram_rcv_from (EIF_INTEGER fd, EIF_INTEGER fd1, EIF_INTEGER *a_last_fd, EIF_POINTER buf, EIF_INTEGER len, EIF_INTEGER flags, EIF_INTEGER timeout, SOCKETADDRESS *him) {

	int nsockets = 0;
	int fduse = 0;
	int result;
	int lenn = sizeof(SOCKETADDRESS);
	int ipv6_supported = en_ipv6_available();

	if (fd > 0) {
		nsockets++;
	}
	if (fd1 > 0) {
		nsockets++;
	}
    	if (nsockets == 2) { /* need to choose one of them */
		int ret, t = (timeout == 0) ? -1: timeout;
		ret = net_timeout2 (fd, fd1, t, &fduse);
		if (ret == 2) {
			fduse = check_last_fd (a_last_fd, fd, fd1);
		} else if (ret == 0) {
			if (ret == 0) {
				eraise("Receive timed out", EN_PROG);
			} else {
				eraise("Receive error", EN_PROG);
			}
			return -1;
		}

	} else if (!ipv6_supported) {
		fduse = fd;
	} else if (fd >= 0) {
		/* ipv6 supported: and this socket bound to an IPV6 only address */
		fduse = fd1;
	} else {
		/* ipv6 supported: and this socket bound to an IPV4 only address */
		fduse = fd;
	}

	if (timeout && nsockets == 1) {
		int ret;
		ret = net_timeout(fduse, timeout);
		if (ret <= 0) {
			if (ret == 0) {
				eraise("Receive timed out", EN_PROG);
			} else {
				eraise("Receive error", EN_PROG);
			}
			return -1;
		}
	}

	result = recvfrom ((SOCKET) fduse, (char *) buf, (int) len, (int) flags, (struct sockaddr *) him, &lenn);
	eif_net_check (result);
	
	return (EIF_INTEGER) result;
}
Пример #5
0
void en_socket_datagram_create (EIF_INTEGER *a_fd, EIF_INTEGER *a_fd1) {
	SOCKET fd, fd1;
	BOOL t = TRUE;
	DWORD x1, x2; /* ignored result codes */

	EIF_NET_INITIALIZE;
	fd = check_socket_bounds(socket (AF_INET, SOCK_DGRAM, 0));

	if (fd == INVALID_SOCKET) {
		*a_fd = -1;
		eif_net_check ((int)fd);
		return;
	} else {
			/* Set socket attribute so it is not passed to any child process */
		SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, FALSE);
		*a_fd = (EIF_INTEGER) fd;
		net_set_sock_opt((int) fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));
	}

	if (en_ipv6_available()) {
			/* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
			 * returns connection reset errors un connected UDP sockets (as well
			 * as connected sockets. The solution is to only enable this feature
			 * when the socket is connected */
		t = FALSE; 
		WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(BOOL),&x1,sizeof(x1),&x2,0,0);
		t = TRUE;
		fd1 = check_socket_bounds(socket (AF_INET6, SOCK_DGRAM, 0));
		if (fd1 == INVALID_SOCKET) {
			*a_fd = -1;
			*a_fd1 = -1;
			eif_net_check ((int)fd1);
			return;
		} else {
			net_set_sock_opt((int)fd1, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));
			t = FALSE;
			WSAIoctl(fd1,SIO_UDP_CONNRESET,&t,sizeof(BOOL),&x1,sizeof(x1),&x2,0,0);
			SetHandleInformation((HANDLE)fd1, HANDLE_FLAG_INHERIT, FALSE);
			*a_fd1 = (EIF_INTEGER) fd1;
		}
	} else {
		*a_fd1 = -1;
	}
}
Пример #6
0
void en_socket_stream_listen (EIF_INTEGER *a_fd, EIF_INTEGER *a_fd1, EIF_POINTER sockaddr, EIF_INTEGER count) {
	int fd, fd1;
	SOCKETADDRESS *addr;
	int ipv6_supported;
	int res;

	EIF_NET_INITIALIZE;

	addr = (SOCKETADDRESS*) sockaddr;
	ipv6_supported = en_ipv6_available();

	fd = *a_fd;

	if (addr->him.sa_family == AF_INET || NET_IN6ADDR_ISANY(&addr->him6) || NET_IN6ADDR_ISLOOPBACK(&addr->him6)) {
			/* listen on v4 */
		if ((res=listen(fd, count)) == -1) {
			eif_net_check(res);
		}
	} else {
		net_socket_close(fd);
		*a_fd = -1;
	}

	if (ipv6_supported) {
		fd1 = *a_fd1;
		if ((addr->him.sa_family == AF_INET6) || (addr->him4.sin_addr.s_addr == INADDR_ANY) || (addr->him4.sin_addr.s_addr == htonl (INADDR_LOOPBACK))) {
				/* listen on v6 */
			if ((res=listen(fd1, count)) == -1) {
				eif_net_check(res);
			}
		} else {
			net_socket_close(fd1);
			*a_fd1 = -1;
		}
	}
}
Пример #7
0
void en_socket_stream_bind (EIF_INTEGER *a_fd, EIF_INTEGER *a_fd1, EIF_INTEGER *a_local_port, EIF_POINTER sockaddr) {

	SOCKETADDRESS* him;
	int family;
	SOCKET fd, fd1;
	int ipv6_supported;
	int localport;
	int rv;

	EIF_NET_INITIALIZE;

	ipv6_supported = en_ipv6_available();

	him = (SOCKETADDRESS*) sockaddr;
	family = him->him.sa_family; 
	localport = ntohs (GET_PORT (him));

	fd = (SOCKET) *a_fd;
	fd1 = (SOCKET) *a_fd1;
	if (ipv6_supported) {
		struct ipv6bind v6bind;
		v6bind.addr = him;
		v6bind.ipv4_fd = fd;
		v6bind.ipv6_fd = fd1;
		rv = net_bindV6(&v6bind);
		if (rv != -1) {
				/* check if the fds have changed */
			if (v6bind.ipv4_fd != fd) {
				fd = v6bind.ipv4_fd;
				if (fd == INVALID_SOCKET) {
						/* socket is closed. */
					*a_fd = -1;
				} else {
						/* socket was re-created */
					*a_fd = (EIF_INTEGER) fd;
				}
			}
			if (v6bind.ipv6_fd != fd1) {
				fd1 = v6bind.ipv6_fd;
				if (fd1 == INVALID_SOCKET) {
						/* socket is closed. */
					*a_fd1 = -1;
				} else {
						/* socket was re-created */
					*a_fd1 = (EIF_INTEGER) fd1;
				}
			}
		}
	} else {
		rv = net_bind(fd, (struct sockaddr *)him, SOCKETADDRESS_LEN(him));
	}

	if (rv == -1) {	
		eraise("bind error", EN_PROG);
		return;
	}

		/* intialize the local port */
	if (localport == 0) {
			/* Now that we're a bound socket, let's extract the port number
			 * that the system chose for us and store it in the Socket object. */
		int len = SOCKETADDRESS_LEN(him);
		u_short port;
		fd = him->him.sa_family == AF_INET? fd: fd1;

		if ((rv=getsockname(fd, (struct sockaddr *)him, &len)) == -1) {
			eif_net_check(rv);
			return;
		}
		port = ntohs (GET_PORT (him));
		*a_local_port = port;
	} else {
		*a_local_port = localport;
	}
}
Пример #8
0
void en_socket_stream_connect (EIF_INTEGER *a_fd, EIF_INTEGER *a_fd1, EIF_INTEGER *a_local_port, EIF_POINTER sockaddr, EIF_INTEGER timeout, EIF_BOOLEAN is_blocking) {

	SOCKETADDRESS* him;
	int family;
	SOCKET fd, fd1 = INVALID_SOCKET;
	int ipv6_supported;
	int connect_res;

	EIF_NET_INITIALIZE;

	ipv6_supported = en_ipv6_available();

	fd = (SOCKET) *a_fd;
	if (ipv6_supported) {
		fd1 = *a_fd1;
	}

	him = (SOCKETADDRESS*) sockaddr;

	family = him->him.sa_family; 
	if (family == AF_INET6) {
		if (!ipv6_supported) {
			eraise ("Protocol family not supported", EN_PROG);
			return;
		} else {
			if (fd1 == -1) {
				eraise ("Destination unreachable", EN_PROG);
				return;
			}
				/* close the v4 socket, and set fd to be the v6 socket */
			*a_fd = (EIF_INTEGER) fd1;
			*a_fd1 = -1;
			net_socket_close(fd); 
			fd = fd1;
		}
	} else {
		if (fd1 != -1) {
				/* close the v6 socket */
			*a_fd1 = -1;
			net_socket_close(fd1); 
		}
		if (fd == INVALID_SOCKET) {
			eraise ("Destination unreachable", EN_PROG);
			return;
		} 
	}

	if (timeout <= 0) {
		connect_res = connect(fd, (struct sockaddr *) him, SOCKETADDRESS_LEN(him));
		if (connect_res == SOCKET_ERROR) {
			connect_res = WSAGetLastError();
			if ((connect_res == WSAEWOULDBLOCK) || (connect_res == WSAEINPROGRESS)) {
				connect_res = 0;
				errno = 0;
			}
		}
	} else {
		u_long optval;
		int optlen = sizeof(int);

			/* make socket non-blocking */
		if (is_blocking) {
			optval = 1;
			ioctlsocket( fd, FIONBIO, &optval );
		}

			/* initiate the connect */
		connect_res = connect(fd, (struct sockaddr *) him, SOCKETADDRESS_LEN(him));
		if (connect_res == SOCKET_ERROR) {
			if (WSAGetLastError() == WSAEWOULDBLOCK) {
				fd_set wr, ex;
				struct timeval t;

				FD_ZERO(&wr);
				FD_ZERO(&ex);
				FD_SET(fd, &wr);
				FD_SET(fd, &ex);
				t.tv_sec = timeout / 1000;
				t.tv_usec = (timeout % 1000) * 1000;

					/* Wait for timout, connection established or
					 * connection failed. */
				connect_res = select((int) fd+1, 0, &wr, &ex, &t);

				/* Timeout before connection is established/failed so
				 * we throw exception and shutdown input/output to prevent
				 * socket from being used.
				 * The socket should be closed immediately by the caller. */
				if (connect_res == 0) {
					shutdown( fd, SD_BOTH );
					if (is_blocking) {
							/* make socket blocking again - just in case */
						optval = 0;
						ioctlsocket( fd, FIONBIO, &optval );
					}
					eraise("connect timed out", EN_PROG);
					return;
				}

					/* We must now determine if the connection has been established
					 * or if it has failed. The logic here is designed to work around
					 * bug on Windows NT whereby using getsockopt to obtain the 
					 * last error (SO_ERROR) indicates there is no error. The workaround
					 * on NT is to allow winsock to be scheduled and this is done by
					 * yielding and retrying. As yielding is problematic in heavy
					 * load conditions we attempt up to 3 times to get the error reason. */
				if (!FD_ISSET(fd, &ex)) {
					connect_res = 0;
				} else {
					int retry;
					for (retry=0; retry<3; retry++) {
						net_get_sock_opt(fd, SOL_SOCKET, SO_ERROR, (char*)&connect_res, &optlen);
						if (connect_res) {
							break;
						}
						Sleep(0);
					}

					if (connect_res == 0) {
						eraise("Unable to establish connection", EN_PROG);
						return;
					}
				}
			}
		}

		if (is_blocking) {
				/* make socket blocking again */
			optval = 0;
			ioctlsocket(fd, FIONBIO, &optval);
		}
	}

	if (connect_res) {
		if (connect_res == WSAEADDRNOTAVAIL) {
			eraise("Address is invalid on local machine, or port is not valid on remote machine", EN_PROG);
		} else {
			eraise("Unable to establish connection", EN_PROG);
		}
		return;
	}

	*a_fd = (EIF_INTEGER) fd;

		/* we need to initialize the local port field if bind was called
		 * previously to the connect (by the client) then localport field
		 * will already be initialized. */
	if (*a_local_port == 0) {
			/* Now that we're a connected socket, let's extract the port number
			 * that the system chose for us and store it in the Socket object. */
		u_short port;
		int len = SOCKETADDRESS_LEN(him);
		if (getsockname(fd, (struct sockaddr *)him, &len) == -1) {
			if (WSAGetLastError() == WSAENOTSOCK) {
				eraise("Socket closed", EN_PROG);
			} else {
				eraise("getsockname failed", EN_PROG);
			}
			return;
		}
		port = ntohs (GET_PORT(him));
		*a_local_port = port;
	}
}