From: thad@public.BTR.COM (Thaddeus P. Floryan)
Newsgroups: comp.unix.questions
Subject: Re: recvfrom() problems
Date: 26 Jul 92 22:32:03 GMT
Organization: BTR Public Access UNIX, Mountain View CA

In article <1992Jul17.125731.1@hamp.hampshir> dhirmes@hamp.hampshire.edu writes:
>
>I'm writing a program using BSD socket interface.  I'm trying to 
>utilize the UDP (datagram) service, but when I run my programs, I
>get a "Bad Address" error.  I've tried several examples from tutorials,
> but I get the same error.  I'm working with SunOS 4.0.1 and some of
>the examples were written for Ultrix.  I was told there might be slight 
>differences in the TCP/IP structures used by BSD implementations. I'vewritten
>programs usinSOCK_STREAM which have worked fine, which adds to my
>confusion. Oh, and the error  only occurs when I attempt a recvfrom(),
>it appears to work when I use sendto().
>
>Can anyone help me out here?

The enclosed routine has functioned fine on every system upon which I've
tried it; it is a part of the "rsetclk" program I wrote for the 3B1 and
archived at ftp.uu.net and osu-cis (aka archive.cis.ohio-state.edu).

The systems upon which I know it works include SunOS 4.1.*, IRIX 4.0.*,
HP-UX 7.* and 8.*, 3B1, 3B2, CTIX 6.2.*, Mac A/UX 2.*, etc.

Thad Floryan [ thad@btr.com (OR) {decwrl, mips, fernwood}!btr!thad ]

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 07/26/1992 22:32 UTC by thad@thadlabs
# Source directory /usr/local/src/rsetclk
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   4772 -rw-r--r-- rhost_time.c
#
# ============= rhost_time.c ==============
if test -f 'rhost_time.c' -a X"$1" != X"-c"; then
	echo 'x - skipping rhost_time.c (File already exists)'
else
echo 'x - extracting rhost_time.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'rhost_time.c' &&
X/****************************************************************************
X *	RHOST_TIME					           RHOST_TIME
X *
X * NAME
X *
X *	rhost_time - gets current time_t value from a remote host adjusted
X *		     to UNIX-style time.
X *
X * SYNOPSIS
X *
X *	time_t rhost_time(hostname, errptr)
X *
X *	char *hostname, *errptr
X *
X * DESCRIPTION
X *
X *	Returns the UNIX-style time from a remote host's inetd server.  Note
X *	the time returned by the inetd server is the number of seconds since
X *	midnight, Jan 1, 1900, in a timeval structure.  Since gettimeofday()
X *	returns the number of seconds since midnight, Jan 1, 1970, the value
X *	2208988800 seconds was added to gettimeofday(2)'s returned value and
X *	we have to make an adjustment to normal UNIX system time.  Note that
X *	the tv_usec value will always be zero.  For compilers that cannot
X *	handle such large numbers, 2208988800 is equivalent to 0x83AA7E80.
X *
X *	The returned value is compatible to that from time().  Note that since
X *	we cannot assume we're running on a "real" computer whose byte order
X *	is the same as network byte order, ntohl() is applied to the value
X *	retrieved from the remote host to accomodate "little endian" machines
X *	such as the DEC {VAX or Alpha} or Intel 80?86 platforms.
X *
X *	The hostname is a null-terminated string whose form may be anything
X *	normally used to reach that host (i.e. "host" or "host.domain.com").
X *
X * RETURN VALUES
X *
X *	On successful completion, rhost_time() returns the time as documented
X *	above.
X *
X *	On error, rhost_time() returns a -1, errno will be set, and a pointer
X *	to the error string will be returned via *errptr.
X *
X * BUGS
X *
X *	The return value for the error message points to a static data area
X *	whose content is potentially overwritten by each call to rhost_time.
X *
X * SEE ALSO
X *
X *	time(), stime()
X *	
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <sys/time.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <errno.h>
X
X#define SERVICE	"time"
X#define TIMEOUT 10		/* seconds to wait for reply from rhost */
X
Xextern	char			*sys_errlist[];	/* system error strings */
X
X	jmp_buf			 env;		/* used by timeout handler */
X	char			 errmsg[80];	/* text of error message */
X
Xtime_t
Xrhost_time(hostname, errptr)
X	char			*hostname;
X	char		       **errptr;
X{
X
X	int			 noanswer();
X
X	int			 s;
X	int			 n;
X	int			 len;
X	int			 status;
X	struct	timeval		 rtimebuf;
X	struct	hostent		*hp;
X	struct	servent		*sp;
X	struct	sockaddr_in	 sin;
X
X/*
X *	Get a datagram socket in the Internet domain
X */
X	s = socket(AF_INET, SOCK_DGRAM, 0);
X	if (s < 0) {
X	    sprintf(errmsg, "socket: %s\n", sys_errlist[errno]);
X	    *errptr = errmsg;
X	    return -1;
X	}
X/*
X *	Look up the port number of the service.
X */
X	sp = getservbyname(SERVICE, "udp");
X	if (sp == NULL) {
X	    errno = EINVAL;
X	    sprintf(errmsg, "%s/udp: unknown service\n", SERVICE);
X	    *errptr = errmsg;
X	    close(s);
X	    return -1;
X	}
X/*
X *	Look up the network number of the host on the command line
X */
X	hp = gethostbyname(hostname);
X	if (hp == NULL) {
X	    errno = EINVAL;
X	    sprintf(errmsg, "%s: host unknown\n", hostname);
X	    *errptr = errmsg;
X	    close(s);
X	    return -1;
X	}
X/*
X *	Build the address of the server on the remote machine
X */
X	sin.sin_family = AF_INET;
X	sin.sin_port   = sp->s_port;
X
X	bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
X/*
X *	Send a datagram to the server
X */
X	status = sendto(s, &rtimebuf, sizeof(rtimebuf), 0, &sin, sizeof(sin));
X	if (status < 0) {
X	    sprintf(errmsg, "sendto(%s): %s\n", hostname, sys_errlist[errno]);
X	    *errptr = errmsg;
X	    close(s);
X	    return -1;
X	}
X/*
X *	Enable timeout signal in case remote host is dead
X */
X	signal(SIGALRM, noanswer);
X	alarm(TIMEOUT);
X/*
X *	Test if we timed out waiting for remote host to respond; presume the
X *	remote host is down if so.
X */
X	status = setjmp(env);
X	if (status > 0) {
X	    errno = EHOSTDOWN;
X	    sprintf(errmsg, "timeout(%s): %s\n", hostname, sys_errlist[errno]);
X	    *errptr = errmsg;
X	    close(s);
X	    return -1;
X	}
X/*
X *	Receive a datagram back
X */
X	len = sizeof(sin);
X	n   = recvfrom(s, &rtimebuf, sizeof(rtimebuf), 0, &sin, &len);
X/*
X *	Disable timeout signal
X */
X	alarm(0);
X/*
X *	Test state of returned datagram
X */
X	if (n < 0) {
X	    sprintf(errmsg, "recvfrom(%s): %s", hostname, sys_errlist[errno]);
X	    *errptr = errmsg;
X	    close(s);
X	    return -1;
X	}
X/*
X *	Accomodate "little endian" architectures.
X */
X	rtimebuf.tv_sec = ntohl(rtimebuf.tv_sec);
X/*
X *	Adjust time with respect to the UNIX epoch of Jan. 1, 1970 00:00:00 GMT
X */
X	rtimebuf.tv_sec -= 2208988800L;
X/*
X *	Release socket
X */
X	close(s);
X
X	return rtimebuf.tv_sec;
X}
X
X/*
X *	rhost_time() timeout handler
X *
X */
Xnoanswer()
X{
X	longjmp(env, 1);
X}
SHAR_EOF
chmod 0644 rhost_time.c ||
echo 'restore of rhost_time.c failed'
Wc_c="`wc -c < 'rhost_time.c'`"
test 4772 -eq "$Wc_c" ||
	echo 'rhost_time.c: original size 4772, current size' "$Wc_c"
fi
exit 0