/*
* This function returns a socket file descriptor bound to the given port
*/
#if !defined(CMUIP) && !defined(NETLIB)
int
SOCKbind_to_port(port)
int port;
{
struct sockaddr_in serv_addr;
int reuseaddr = 1;
int sockfd;
#ifdef VMS_SERVER
union prvdef prvadr;
unsigned long int ON = -1;
if (port<1024) {
bzero((char *) &prvadr, sizeof(prvadr));
prvadr.prv$v_sysprv = 1;
if (SS$_NORMAL != (vaxc$errno = SYS$SETPRV (ON, &prvadr, 0, 0))) {
LOGGopher(-1,"Can't insure SYSPRV for bind to port %d, %s",
port, STRerror(vaxc$errno));
}
}
#endif
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
#ifndef VMS_SERVER
perror("server: can't open stream socket"), exit(-1);
#else
LOGGopher(-99,"fatal: can't open stream socket, %s",
vms_errno_string());
#endif
/** Bind our local address so that the client can send to us **/
/*
* This routine finds out the hostname of the server machine.
* It uses a couple of methods to find the fully qualified
* Domain name
*
* If gdchost is non NULL then use that paramater instead of
* the code in here.
*/
DNSname[0] = '\0';
/* Work out our fully-qualified name, for later use */
if (gethostname(DNSname, MAXHOSTNAMELEN) != 0) {
#ifndef VMS_SERVER
fprintf(stderr, "Cannot determine the name of this host\n");
exit(-1);
#else
LOGGopher(-99,"fatal: Cannot determine the name of this host");
#endif
}
/* Now, use gethostbyname to (hopefully) do a nameserver lookup */
hp = gethostbyname( DNSname);
/*
** If we got something, and the name is longer than hostname, then
** assume that it must the the fully-qualified hostname
*/
if ( hp!=NULL && strlen(hp->h_name) > strlen(DNSname) )
strncpy( DNSname, hp->h_name, MAXHOSTNAMELEN );
else
strcat(DNSname, backupdomain);
return(DNSname);
}
/*
* Tries to figure out what the currently connected port is.
*
* If it's a socket then it will return the port of the socket,
* if it isn't a socket then it returns -1.
*/
int
SOCKgetPort(fd)
int fd;
{
struct sockaddr_in serv_addr;
int length = sizeof(serv_addr);
/** Try to figure out the port we're running on. **/
/* SOCKconnect performs a connection to socket 'service' on host
* 'host'. Host can be a hostname or ip-address. If 'host' is null, the
* local host is assumed. The parameter full_hostname will, on return,
* contain the expanded hostname (if possible). Note that full_hostname is a
* pointer to a char *, and is allocated by connect_to_gopher()
*
* Errors: ErrSocket* defined in Sockets.h
*
*/
int
SOCKconnect(hostname, port)
char *hostname;
int port;
{
#if !defined(CMUIP) && !defined(NETLIB)
struct sockaddr_in Server;
struct hostent *HostPtr;
int sockfd = 0;
unsigned int ERRinet = -1;
#ifdef _CRAY
ERRinet = 0xFFFFFFFF; /* -1 doesn't sign extend on 64 bit machines */
#endif
/*** Find the hostname address ***/
if (hostname == NULL || *hostname == '\0')
return(ErrSocketNullHost);
/* SOCKaccept accepts a connection form some socket. *
* Errors: ErrSocket* defined in Sockets.h
*/
int
SOCKaccept(s, we)
int s;
struct sockaddr_in we;
{
int sockfd = 0;
int len = sizeof(struct sockaddr);
unsigned short tem;
tem = ntohs(we.sin_port);
Debugmsg("Here we go...\n");
if ((sockfd = accept(s, (struct sockaddr *) &we, &len)) < 0) {
return ErrSocketConnect;
}
close(s); /* Der Mohr hat seine Schuldigkeit getan */
return(sockfd);
}
/*
* SOCKnetnames -- return the network, subnet, and host names of
* our peer process for the Internet domain.
*
* Parameters: "sock" is our socket
* "host_name"
* is filled in by this routine with the
* corresponding ASCII names of our peer.
*
* if there doesn't exist a hostname in DNS etal,
* the IP# will be inserted for the host_name
*
* "ipnum" is filled in with the ascii IP#
*/
void
SOCKnetnames(sockfd, host_name, ipnum)
int sockfd;
char *host_name;
char *ipnum;
{
struct sockaddr_in sa;
int length;
struct hostent *hp;
length = sizeof(sa);
if (getpeername(sockfd, (struct sockaddr *)&sa, &length))
/** May fail if sockfd has been closed **/
#ifdef VMS_SERVER
{
LOGGopher(-2, "getpeername() failure: %s", vms_errno_string());
if (ipnum != NULL)
strcpy(ipnum,"Unknown");
if (host_name != NULL)
strcpy(host_name,"Unknown");
return;
}
#else
return;
#endif
if (ipnum != NULL)
strcpy(ipnum, inet_ntoa(sa.sin_addr));
if (host_name != NULL)
strcpy(host_name, inet_ntoa(sa.sin_addr));
#ifdef LOG_IP_ONLY
hp = NULL;
#else
hp = gethostbyaddr((char *) &sa.sin_addr,sizeof (sa.sin_addr), AF_INET);
#endif
#if defined(VMS_SERVER) && defined(MULTINET)
/*
* This turns the keepalive option on
* TGV recommended setting KEEPALIVE on the server, just in case
* we somehow got a socket locked in a CLOSE_WAIT state (shouldn't
* happen since we set REUSEADDR *before* we bind, but... it's
* sure a lot better than rebooting your VAX/AXP node to get the
* port back from a %MULTINET-F-EADDRINUSE error condition).
*/
void
SOCKkeepalive(sockfd, onoff)
int sockfd;
boolean onoff;
{
#if defined(SO_KEEPALIVE) && !defined(NO_KEEPALIVE)
int keepalive = onoff;
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepalive,
sizeof (keepalive)) < 0)
LOGGopher(-1,"warning: can't turn %s keepalive sockopt, %s",
onoff?"on":"off", vms_errno_string());
#endif
}
#endif