src/test: Remove "sock".
Now available via HaikuPorts if needed.
This commit is contained in:
@@ -24,6 +24,5 @@ SubInclude HAIKU_TOP src tests system network icmp ;
|
||||
SubInclude HAIKU_TOP src tests system network ipv6 ;
|
||||
SubInclude HAIKU_TOP src tests system network multicast ;
|
||||
SubInclude HAIKU_TOP src tests system network posixnet ;
|
||||
SubInclude HAIKU_TOP src tests system network sock ;
|
||||
SubInclude HAIKU_TOP src tests system network tcp_shell ;
|
||||
SubInclude HAIKU_TOP src tests system network tcptester ;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
SubDir HAIKU_TOP src tests system network sock ;
|
||||
|
||||
UseHeaders $(SUBDIR) : true ;
|
||||
|
||||
SimpleTest sock :
|
||||
buffers.c cliopen.c crlf.c error.c looptcp.c
|
||||
loopudp.c main.c multicast.c pattern.c servopen.c
|
||||
sleepus.c sockopts.c sourceroute.c sourcetcp.c
|
||||
sourceudp.c sinktcp.c sinkudp.c tellwait.c write.c writen.c
|
||||
: $(TARGET_NETWORK_LIBS)
|
||||
;
|
||||
@@ -1,49 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*- */
|
||||
#ifndef ADDRINFO_H
|
||||
#define ADDRINFO_H
|
||||
|
||||
/*
|
||||
* Everything here really belongs in <netdb.h>.
|
||||
* These defines are separate for now, to avoid having to modify the
|
||||
* system's header.
|
||||
*/
|
||||
|
||||
struct addrinfo {
|
||||
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
|
||||
int ai_family; /* PF_xxx */
|
||||
int ai_socktype; /* SOCK_xxx */
|
||||
int ai_protocol; /* IPPROTO_xxx for IPv4 and IPv6 */
|
||||
size_t ai_addrlen; /* length of ai_addr */
|
||||
char *ai_canonname; /* canonical name for host */
|
||||
struct sockaddr *ai_addr; /* binary address */
|
||||
struct addrinfo *ai_next; /* next structure in linked list */
|
||||
};
|
||||
|
||||
/* following for getaddrinfo() */
|
||||
#define AI_PASSIVE 1 /* socket is intended for bind() + listen() */
|
||||
#define AI_CANONNAME 2 /* return canonical name */
|
||||
|
||||
/* following for getnameinfo() */
|
||||
#define NI_MAXHOST 1025 /* max hostname returned */
|
||||
#define NI_MAXSERV 32 /* max service name returned */
|
||||
|
||||
#define NI_NOFQDN 1 /* do not return FQDN */
|
||||
#define NI_NUMERICHOST 2 /* return numeric form of hostname */
|
||||
#define NI_NAMEREQD 4 /* return error if hostname not found */
|
||||
#define NI_NUMERICSERV 8 /* return numeric form of service name */
|
||||
#define NI_DGRAM 16 /* datagram service for getservbyname() */
|
||||
|
||||
/* error returns */
|
||||
#define EAI_ADDRFAMILY 1 /* address family for host not supported */
|
||||
#define EAI_AGAIN 2 /* temporary failure in name resolution */
|
||||
#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
|
||||
#define EAI_FAIL 4 /* non-recoverable fail in name resolution */
|
||||
#define EAI_FAMILY 5 /* ai_family not supported */
|
||||
#define EAI_MEMORY 6 /* memory allocation failure */
|
||||
#define EAI_NODATA 7 /* no address associated with host */
|
||||
#define EAI_NONAME 8 /* host nor service provided, or not known */
|
||||
#define EAI_SERVICE 9 /* service not supported for ai_socktype */
|
||||
#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
|
||||
#define EAI_SYSTEM 11 /* system error returned in errno */
|
||||
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include <sock.h>
|
||||
|
||||
void buffers(int sockfd)
|
||||
{
|
||||
int n;
|
||||
socklen_t optlen;
|
||||
|
||||
/* Allocate the read and write buffers. */
|
||||
|
||||
if (rbuf == NULL) {
|
||||
if ( (rbuf = malloc(readlen)) == NULL)
|
||||
err_sys("malloc error for read buffer");
|
||||
}
|
||||
|
||||
if (wbuf == NULL) {
|
||||
if ( (wbuf = malloc(writelen)) == NULL)
|
||||
err_sys("malloc error for write buffer");
|
||||
}
|
||||
|
||||
/* Set the socket send and receive buffer sizes (if specified).
|
||||
The receive buffer size is tied to TCP's advertised window. */
|
||||
|
||||
if (rcvbuflen) {
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuflen,
|
||||
sizeof(rcvbuflen)) < 0)
|
||||
err_sys("SO_RCVBUF setsockopt error");
|
||||
|
||||
optlen = sizeof(n);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, &optlen) < 0)
|
||||
err_sys("SO_RCVBUF getsockopt error");
|
||||
if (n != rcvbuflen)
|
||||
err_quit("error: requested rcvbuflen = %d, resulting SO_RCVBUF = %d", rcvbuflen, n);
|
||||
if (verbose)
|
||||
fprintf(stderr, "SO_RCVBUF = %d\n", n);
|
||||
}
|
||||
|
||||
if (sndbuflen) {
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sndbuflen,
|
||||
sizeof(sndbuflen)) < 0)
|
||||
err_sys("SO_SNDBUF setsockopt error");
|
||||
|
||||
optlen = sizeof(n);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &n, &optlen) < 0)
|
||||
err_sys("SO_SNDBUF getsockopt error");
|
||||
if (n != sndbuflen)
|
||||
err_quit("error: requested sndbuflen = %d, resulting SO_SNDBUF = %d", sndbuflen, n);
|
||||
if (verbose)
|
||||
fprintf(stderr, "SO_SNDBUF = %d\n", n);
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
int cliopen(char *host, char *port)
|
||||
{
|
||||
int fd, i, on;
|
||||
char *protocol;
|
||||
struct in_addr inaddr;
|
||||
struct servent *sp;
|
||||
struct hostent *hp;
|
||||
|
||||
protocol = udp ? "udp" : "tcp";
|
||||
|
||||
/* initialize socket address structure */
|
||||
bzero(&servaddr, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
|
||||
/* see if "port" is a service name or number */
|
||||
if ( (i = atoi(port)) == 0) {
|
||||
if ( (sp = getservbyname(port, protocol)) == NULL)
|
||||
err_quit("getservbyname() error for: %s/%s", port, protocol);
|
||||
|
||||
servaddr.sin_port = sp->s_port;
|
||||
} else
|
||||
servaddr.sin_port = htons(i);
|
||||
|
||||
/*
|
||||
* First try to convert the host name as a dotted-decimal number.
|
||||
* Only if that fails do we call gethostbyname().
|
||||
*/
|
||||
|
||||
if (inet_aton(host, &inaddr) == 1)
|
||||
servaddr.sin_addr = inaddr; /* it's dotted-decimal */
|
||||
else if ( (hp = gethostbyname(host)) != NULL)
|
||||
bcopy(hp->h_addr, &servaddr.sin_addr, hp->h_length);
|
||||
else
|
||||
err_quit("invalid hostname: %s", host);
|
||||
|
||||
if ( (fd = socket(AF_INET, udp ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
|
||||
err_sys("socket() error");
|
||||
|
||||
if (reuseaddr) {
|
||||
on = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
|
||||
err_sys("setsockopt of SO_REUSEADDR error");
|
||||
}
|
||||
|
||||
#ifdef SO_REUSEPORT
|
||||
if (reuseport) {
|
||||
on = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof (on)) < 0)
|
||||
err_sys("setsockopt of SO_REUSEPORT error");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* User can specify port number for client to bind. Only real use
|
||||
* is to see a TCP connection initiated by both ends at the same time.
|
||||
* Also, if UDP is being used, we specifically call bind() to assign
|
||||
* an ephemeral port to the socket.
|
||||
* Also, for experimentation, client can also set local IP address
|
||||
* (and port) using -l option. Allow localip[] to be set but bindport
|
||||
* to be 0.
|
||||
*/
|
||||
|
||||
if (bindport != 0 || localip[0] != 0 || udp) {
|
||||
bzero(&cliaddr, sizeof(cliaddr));
|
||||
cliaddr.sin_family = AF_INET;
|
||||
cliaddr.sin_port = htons(bindport); /* can be 0 */
|
||||
if (localip[0] != 0) {
|
||||
if (inet_aton(localip, &cliaddr.sin_addr) == 0)
|
||||
err_quit("invalid IP address: %s", localip);
|
||||
} else
|
||||
cliaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)) < 0)
|
||||
err_sys("bind() error");
|
||||
}
|
||||
|
||||
/* Need to allocate buffers before connect(), since they can affect
|
||||
* TCP options (window scale, etc.).
|
||||
*/
|
||||
|
||||
buffers(fd);
|
||||
sockopts(fd, 0); /* may also want to set SO_DEBUG */
|
||||
|
||||
/*
|
||||
* Connect to the server. Required for TCP, optional for UDP.
|
||||
*/
|
||||
|
||||
if (udp == 0 || connectudp) {
|
||||
for ( ; ; ) {
|
||||
if (connect(fd, (struct sockaddr *) &servaddr, sizeof(servaddr))
|
||||
== 0)
|
||||
break; /* all OK */
|
||||
if (errno == EINTR) /* can happen with SIGIO */
|
||||
continue;
|
||||
if (errno == EISCONN) /* can happen with SIGIO */
|
||||
break;
|
||||
err_sys("connect() error");
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
/* Call getsockname() to find local address bound to socket:
|
||||
TCP ephemeral port was assigned by connect() or bind();
|
||||
UDP ephemeral port was assigned by bind(). */
|
||||
i = sizeof(cliaddr);
|
||||
if (getsockname(fd, (struct sockaddr *) &cliaddr, &i) < 0)
|
||||
err_sys("getsockname() error");
|
||||
|
||||
/* Can't do one fprintf() since inet_ntoa() stores
|
||||
the result in a static location. */
|
||||
fprintf(stderr, "connected on %s.%d ",
|
||||
INET_NTOA(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
|
||||
fprintf(stderr, "to %s.%d\n",
|
||||
INET_NTOA(servaddr.sin_addr), ntohs(servaddr.sin_port));
|
||||
}
|
||||
|
||||
sockopts(fd, 1); /* some options get set after connect() */
|
||||
|
||||
return(fd);
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
/* config.h. Generated by configure. */
|
||||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
/* Define the following if you have the corresponding header */
|
||||
/* #undef CPU_VENDOR_OS */
|
||||
/* #undef HAVE_NETCONFIG_H */ /* <netconfig.h> */
|
||||
/* #undef HAVE_NETDIR_H */ /* <netdir.h> */
|
||||
/* #undef HAVE_POLL_H */ /* <poll.h> */
|
||||
/* #undef HAVE_PTHREAD_H */ /* <pthread.h> */
|
||||
/* #undef HAVE_STRINGS_H */ /* <strings.h> */
|
||||
/* #undef HAVE_SYS_FILIO_H */ /* <sys/filio.h> */
|
||||
/* #undef HAVE_SYS_IOCTL_H */ /* <sys/ioctl.h> */
|
||||
/* #undef HAVE_SYS_SELECT_H */ /* <sys/select.h> */
|
||||
/* #undef HAVE_SYS_SOCKIO_H */ /* <sys/sockio.h> */
|
||||
/* #undef HAVE_SYS_SYSCTL_H */ /* <sys/sysctl.h> */
|
||||
/* #undef HAVE_SYS_TIME_H */ /* <sys/time.h> */
|
||||
/* #undef HAVE_SYS_TYPES_H */ /* <sys/types.> */
|
||||
|
||||
/* Define the following to the appropriate datatype, if necessary */
|
||||
/* #undef int8_t */ /* <sys/types.h> */
|
||||
/* #undef int16_t */ /* <sys/types.h> */
|
||||
/* #undef int32_t */ /* <sys/types.h> */
|
||||
/* #undef u_int8_t */ /* <sys/types.h> */
|
||||
/* #undef u_int16_t */ /* <sys/types.h> */
|
||||
/* #undef u_int32_t */ /* <sys/types.h> */
|
||||
/* #undef DEBUG */
|
||||
|
||||
/* #undef HAVE_ADDRINFO_STRUCT */ /* <netdb.h> */
|
||||
#define HAVE_MSGHDR_MSG_CONTROL
|
||||
#define HAVE_ADDRINFO_PROTO 1
|
||||
|
||||
/* struct addrinfo is defined */
|
||||
#define HAVE_ADDRINFO_STRUCT
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `nsl' library (-lnsl). */
|
||||
#define HAVE_LIBNSL 1
|
||||
|
||||
/* Define to 1 if you have the `socket' library (-lsocket). */
|
||||
/* #undef HAVE_LIBSOCKET */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* struct msghdr has msg_control field */
|
||||
#define HAVE_MSGHDR_MSG_CONTROL
|
||||
|
||||
/* Define to 1 if you have the <netconfig.h> header file. */
|
||||
/* #undef HAVE_NETCONFIG_H */
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#define HAVE_NETDB_H 1
|
||||
|
||||
/* Define to 1 if you have the <netdir.h> header file. */
|
||||
/* #undef HAVE_NETDIR_H */
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#define HAVE_POLL_H 1
|
||||
|
||||
/* Define to 1 if you have the <pthread.h> header file. */
|
||||
#define HAVE_PTHREAD_H 1
|
||||
|
||||
/* Define to 1 if you have the `setlinebuf' function. */
|
||||
#define HAVE_SETLINEBUF 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#define HAVE_STRDUP 1
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <stropts.h> header file. */
|
||||
#define HAVE_STROPTS_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/filio.h> header file. */
|
||||
/* #undef HAVE_SYS_FILIO_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#define HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#define HAVE_SYS_PARAM_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#define HAVE_SYS_SELECT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/sockio.h> header file. */
|
||||
#define HAVE_SYS_SOCKIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/sysctl.h> header file. */
|
||||
#define HAVE_SYS_SYSCTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
#define HAVE_SYS_UIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||
#define HAVE_SYS_UN_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#define HAVE_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "sock"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||
#define RETSIGTYPE void
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.3"
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
/* #undef WORDS_BIGENDIAN */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
@@ -1,51 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
/* Convert newline to return/newline. */
|
||||
|
||||
int
|
||||
crlf_add(char *dst, int dstsize, const char *src, int lenin)
|
||||
{
|
||||
int lenout;
|
||||
char c;
|
||||
|
||||
if ( (lenout = lenin) > dstsize)
|
||||
err_quit("crlf_add: destination not big enough");
|
||||
|
||||
for ( ; lenin > 0; lenin--) {
|
||||
if ( (c = *src++) == '\n') {
|
||||
if (++lenout >= dstsize)
|
||||
err_quit("crlf_add: destination not big enough");
|
||||
*dst++ = '\r';
|
||||
}
|
||||
*dst++ = c;
|
||||
}
|
||||
|
||||
return(lenout);
|
||||
}
|
||||
|
||||
int
|
||||
crlf_strip(char *dst, int dstsize, const char *src, int lenin)
|
||||
{
|
||||
int lenout;
|
||||
char c;
|
||||
|
||||
for (lenout = 0; lenin > 0; lenin--) {
|
||||
if ( (c = *src++) != '\r') {
|
||||
if (++lenout >= dstsize)
|
||||
err_quit("crlf_strip: destination not big enough");
|
||||
*dst++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
return(lenout);
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*- */
|
||||
#include <errno.h> /* for definition of errno */
|
||||
#include <stdarg.h> /* ANSI C header file */
|
||||
#include "ourhdr.h"
|
||||
|
||||
static void err_doit(int, const char *, va_list);
|
||||
|
||||
char *pname = NULL; /* caller can set this from argv[0] */
|
||||
|
||||
/* Nonfatal error related to a system call.
|
||||
* Print a message and return. */
|
||||
|
||||
void
|
||||
/* $f err_ret $ */
|
||||
err_ret(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
err_doit(1, fmt, ap);
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fatal error related to a system call.
|
||||
* Print a message and terminate. */
|
||||
|
||||
void
|
||||
/* $f err_sys $ */
|
||||
err_sys(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
err_doit(1, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Fatal error related to a system call.
|
||||
* Print a message, dump core, and terminate. */
|
||||
|
||||
void
|
||||
/* $f err_dump $ */
|
||||
err_dump(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
err_doit(1, fmt, ap);
|
||||
va_end(ap);
|
||||
abort(); /* dump core and terminate */
|
||||
exit(1); /* shouldn't get here */
|
||||
}
|
||||
|
||||
/* Nonfatal error unrelated to a system call.
|
||||
* Print a message and return. */
|
||||
|
||||
void
|
||||
/* $f err_msg $ */
|
||||
err_msg(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
err_doit(0, fmt, ap);
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fatal error unrelated to a system call.
|
||||
* Print a message and terminate. */
|
||||
|
||||
void
|
||||
/* $f err_quit $ */
|
||||
err_quit(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
err_doit(0, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Print a message and return to caller.
|
||||
* Caller specifies "errnoflag". */
|
||||
|
||||
static void
|
||||
err_doit(int errnoflag, const char *fmt, va_list ap)
|
||||
{
|
||||
int errno_save;
|
||||
char buf[MAXLINE];
|
||||
|
||||
errno_save = errno; /* value caller might want printed */
|
||||
vsprintf(buf, fmt, ap);
|
||||
if (errnoflag)
|
||||
sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
|
||||
strcat(buf, "\n");
|
||||
fflush(stdout); /* in case stdout and stderr are the same */
|
||||
fputs(buf, stderr);
|
||||
fflush(stderr); /* SunOS 4.1.* doesn't grok NULL argument */
|
||||
return;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*- */
|
||||
#ifndef GLOBAL_H
|
||||
#define GLOBAL_H
|
||||
|
||||
#include "config.h" /* configuration options for current OS */
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifndef HAVE_ADDRINFO_STRUCT
|
||||
#include "addrinfo.h"
|
||||
#endif
|
||||
|
||||
/* Older resolvers do not have gethostbyname2() */
|
||||
#ifndef HAVE_GETHOSTBYNAME2
|
||||
#define gethostbyname2(host,family) gethostbyname((host))
|
||||
#endif
|
||||
|
||||
/* This avoids a warning with glibc compilation */
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
|
||||
/* Miscellaneous constants */
|
||||
#define MAXLINE 4096 /* max text line length */
|
||||
#define MAXSOCKADDR 128 /* max socket address structure size */
|
||||
#define BUFFSIZE 8192 /* buffer size for reads and writes */
|
||||
|
||||
/* stdin and stdout file descriptors */
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,101 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
/* Copy everything from stdin to "sockfd",
|
||||
* and everything from "sockfd" to stdout. */
|
||||
|
||||
void loop_tcp(int sockfd)
|
||||
{
|
||||
int maxfdp1, nread, ntowrite, stdineof, flags;
|
||||
fd_set rset;
|
||||
|
||||
if (pauseinit)
|
||||
sleep_us(pauseinit*1000); /* intended for server */
|
||||
|
||||
flags = 0;
|
||||
stdineof = 0;
|
||||
FD_ZERO(&rset);
|
||||
maxfdp1 = sockfd + 1; /* check descriptors [0..sockfd] */
|
||||
|
||||
for ( ; ; ) {
|
||||
if (stdineof == 0)
|
||||
FD_SET(STDIN_FILENO, &rset);
|
||||
FD_SET(sockfd, &rset);
|
||||
|
||||
if (select(maxfdp1, &rset, NULL, NULL, NULL) < 0)
|
||||
err_sys("select error");
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &rset)) {
|
||||
/* data to read on stdin */
|
||||
if ( (nread = read(STDIN_FILENO, rbuf, readlen)) < 0)
|
||||
err_sys("read error from stdin");
|
||||
else if (nread == 0) {
|
||||
/* EOF on stdin */
|
||||
if (halfclose) {
|
||||
if (shutdown(sockfd, SHUT_WR) < 0)
|
||||
err_sys("shutdown() error");
|
||||
|
||||
FD_CLR(STDIN_FILENO, &rset);
|
||||
stdineof = 1; /* don't read stdin anymore */
|
||||
continue; /* back to select() */
|
||||
}
|
||||
break; /* default: stdin EOF -> done */
|
||||
}
|
||||
|
||||
if (crlf) {
|
||||
ntowrite = crlf_add(wbuf, writelen, rbuf, nread);
|
||||
if (dowrite(sockfd, wbuf, ntowrite) != ntowrite)
|
||||
err_sys("write error");
|
||||
} else {
|
||||
if (dowrite(sockfd, rbuf, nread) != nread)
|
||||
err_sys("write error");
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(sockfd, &rset)) {
|
||||
/* data to read from socket */
|
||||
/* msgpeek = 0 or MSG_PEEK */
|
||||
flags = msgpeek;
|
||||
oncemore:
|
||||
if ( (nread = recv(sockfd, rbuf, readlen, flags)) < 0)
|
||||
err_sys("recv error");
|
||||
else if (nread == 0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "connection closed by peer\n");
|
||||
break; /* EOF, terminate */
|
||||
}
|
||||
|
||||
if (crlf) {
|
||||
ntowrite = crlf_strip(wbuf, writelen, rbuf, nread);
|
||||
if (writen(STDOUT_FILENO, wbuf, ntowrite) != ntowrite)
|
||||
err_sys("writen error to stdout");
|
||||
} else {
|
||||
if (writen(STDOUT_FILENO, rbuf, nread) != nread)
|
||||
err_sys("writen error to stdout");
|
||||
}
|
||||
|
||||
if (flags != 0) {
|
||||
flags = 0; /* no infinite loop */
|
||||
goto oncemore; /* read the message again */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pauseclose) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "pausing before close\n");
|
||||
sleep_us(pauseclose*1000);
|
||||
}
|
||||
|
||||
if (close(sockfd) < 0)
|
||||
err_sys("close error"); /* since SO_LINGER may be set */
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "sock.h"
|
||||
|
||||
/* Copy everything from stdin to "sockfd",
|
||||
* and everything from "sockfd" to stdout. */
|
||||
|
||||
void
|
||||
loop_udp(int sockfd)
|
||||
{
|
||||
int maxfdp1, nread, ntowrite, stdineof, clilen, servlen, flags;
|
||||
fd_set rset;
|
||||
struct sockaddr_in cliaddr; /* for UDP server */
|
||||
struct sockaddr_in servaddr; /* for UDP client */
|
||||
|
||||
#ifdef HAVE_MSGHDR_MSG_CONTROL
|
||||
struct iovec iov[1];
|
||||
struct msghdr msg;
|
||||
|
||||
#ifdef IP_RECVDSTADDR /* 4.3BSD Reno and later */
|
||||
static struct cmsghdr *cmptr = NULL; /* malloc'ed */
|
||||
struct in_addr dstinaddr; /* for UDP server */
|
||||
#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(struct in_addr))
|
||||
#endif /* IP_RECVDSTADDR */
|
||||
|
||||
#endif /* MSG_TRUNC */
|
||||
|
||||
if (pauseinit)
|
||||
sleep_us(pauseinit*1000); /* intended for server */
|
||||
|
||||
flags = 0;
|
||||
stdineof = 0;
|
||||
FD_ZERO(&rset);
|
||||
maxfdp1 = sockfd + 1; /* check descriptors [0..sockfd] */
|
||||
|
||||
/* If UDP client issues connect(), recv() and write() are used.
|
||||
Server is harder since cannot issue connect(). We use recvfrom()
|
||||
or recvmsg(), depending on OS. */
|
||||
|
||||
for ( ; ; ) {
|
||||
if (stdineof == 0)
|
||||
FD_SET(STDIN_FILENO, &rset);
|
||||
FD_SET(sockfd, &rset);
|
||||
|
||||
if (select(maxfdp1, &rset, NULL, NULL, NULL) < 0)
|
||||
err_sys("select error");
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &rset)) {
|
||||
/* data to read on stdin */
|
||||
if ( (nread = read(STDIN_FILENO, rbuf, readlen)) < 0)
|
||||
err_sys("read error from stdin");
|
||||
else if (nread == 0) {
|
||||
/* EOF on stdin */
|
||||
if (halfclose) {
|
||||
if (shutdown(sockfd, SHUT_WR) < 0)
|
||||
err_sys("shutdown() error");
|
||||
|
||||
FD_CLR(STDIN_FILENO, &rset);
|
||||
stdineof = 1; /* don't read stdin anymore */
|
||||
continue; /* back to select() */
|
||||
}
|
||||
break; /* default: stdin EOF -> done */
|
||||
}
|
||||
|
||||
if (crlf) {
|
||||
ntowrite = crlf_add(wbuf, writelen, rbuf, nread);
|
||||
if (connectudp) {
|
||||
if (write(sockfd, wbuf, ntowrite) != ntowrite)
|
||||
err_sys("write error");
|
||||
} else {
|
||||
if (sendto(sockfd, wbuf, ntowrite, 0,
|
||||
(struct sockaddr *) &servaddr, sizeof(servaddr))
|
||||
!= ntowrite)
|
||||
err_sys("sendto error");
|
||||
}
|
||||
} else {
|
||||
if (connectudp) {
|
||||
if (write(sockfd, rbuf, nread) != nread)
|
||||
err_sys("write error");
|
||||
} else {
|
||||
if (sendto(sockfd, rbuf, nread, 0,
|
||||
(struct sockaddr *) &servaddr, sizeof(servaddr))
|
||||
!= nread)
|
||||
err_sys("sendto error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(sockfd, &rset)) {
|
||||
/* data to read from socket */
|
||||
if (server) {
|
||||
clilen = sizeof(cliaddr);
|
||||
#ifndef MSG_TRUNC /* vanilla BSD sockets */
|
||||
nread = recvfrom(sockfd, rbuf, readlen, 0,
|
||||
(struct sockaddr *) &cliaddr, &clilen);
|
||||
|
||||
#else /* 4.3BSD Reno and later; use recvmsg() to get at MSG_TRUNC flag */
|
||||
/* Also lets us get at control information (destination address) */
|
||||
|
||||
iov[0].iov_base = rbuf;
|
||||
iov[0].iov_len = readlen;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_name = (caddr_t) &cliaddr;
|
||||
msg.msg_namelen = clilen;
|
||||
|
||||
#ifdef IP_RECVDSTADDR
|
||||
if (cmptr == NULL && (cmptr = malloc(CONTROLLEN)) == NULL)
|
||||
err_sys("malloc error for control buffer");
|
||||
|
||||
msg.msg_control = (caddr_t) cmptr; /* for dest address */
|
||||
msg.msg_controllen = CONTROLLEN;
|
||||
#else
|
||||
msg.msg_control = (caddr_t) 0; /* no ancillary data */
|
||||
msg.msg_controllen = 0;
|
||||
#endif /* IP_RECVDSTADDR */
|
||||
msg.msg_flags = 0; /* flags returned here */
|
||||
|
||||
nread = recvmsg(sockfd, &msg, 0);
|
||||
#endif /* HAVE_MSGHDR_MSG_CONTROL */
|
||||
if (nread < 0)
|
||||
err_sys("datagram receive error");
|
||||
|
||||
if (verbose) {
|
||||
printf("from %s", INET_NTOA(cliaddr.sin_addr));
|
||||
#ifdef HAVE_MSGHDR_MSG_CONTROL
|
||||
#ifdef IP_RECVDSTADDR
|
||||
if (recvdstaddr) {
|
||||
if (cmptr->cmsg_len != CONTROLLEN)
|
||||
err_quit("control length (%d) != %d",
|
||||
cmptr->cmsg_len, CONTROLLEN);
|
||||
if (cmptr->cmsg_level != IPPROTO_IP)
|
||||
err_quit("control level != IPPROTO_IP");
|
||||
if (cmptr->cmsg_type != IP_RECVDSTADDR)
|
||||
err_quit("control type != IP_RECVDSTADDR");
|
||||
bcopy(CMSG_DATA(cmptr), &dstinaddr,
|
||||
sizeof(struct in_addr));
|
||||
bzero(cmptr, CONTROLLEN);
|
||||
|
||||
printf(", to %s", INET_NTOA(dstinaddr));
|
||||
}
|
||||
#endif /* IP_RECVDSTADDR */
|
||||
#endif /* HAVE_MSGHDR_MSG_CONTROL */
|
||||
printf(": ");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
#ifdef MSG_TRUNC
|
||||
if (msg.msg_flags & MSG_TRUNC)
|
||||
printf("(datagram truncated)\n");
|
||||
#endif
|
||||
|
||||
} else if (connectudp) {
|
||||
/* msgpeek = 0 or MSG_PEEK */
|
||||
flags = msgpeek;
|
||||
oncemore:
|
||||
if ( (nread = recv(sockfd, rbuf, readlen, flags)) < 0)
|
||||
err_sys("recv error");
|
||||
else if (nread == 0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "connection closed by peer\n");
|
||||
break; /* EOF, terminate */
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Must use recvfrom() for unconnected UDP client */
|
||||
servlen = sizeof(servaddr);
|
||||
nread = recvfrom(sockfd, rbuf, readlen, 0,
|
||||
(struct sockaddr *) &servaddr, &servlen);
|
||||
if (nread < 0)
|
||||
err_sys("datagram recvfrom() error");
|
||||
|
||||
if (verbose) {
|
||||
printf("from %s", INET_NTOA(servaddr.sin_addr));
|
||||
printf(": ");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
if (crlf) {
|
||||
ntowrite = crlf_strip(wbuf, writelen, rbuf, nread);
|
||||
if (writen(STDOUT_FILENO, wbuf, ntowrite) != ntowrite)
|
||||
err_sys("writen error to stdout");
|
||||
} else {
|
||||
if (writen(STDOUT_FILENO, rbuf, nread) != nread)
|
||||
err_sys("writen error to stdout");
|
||||
}
|
||||
|
||||
if (flags != 0) {
|
||||
flags = 0; /* no infinite loop */
|
||||
goto oncemore; /* read the message again */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pauseclose) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "pausing before close\n");
|
||||
sleep_us(pauseclose*1000);
|
||||
}
|
||||
|
||||
if (close(sockfd) < 0)
|
||||
err_sys("close error"); /* since SO_LINGER may be set */
|
||||
}
|
||||
@@ -1,447 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include "sock.h"
|
||||
|
||||
char *host; /* hostname or dotted-decimal string */
|
||||
char *port;
|
||||
|
||||
/* DefinE global variables */
|
||||
int bindport; /* 0 or TCP or UDP port number to bind */
|
||||
/* set by -b or -l options */
|
||||
int broadcast; /* SO_BROADCAST */
|
||||
int cbreak; /* set terminal to cbreak mode */
|
||||
int chunkwrite; /* write in small chunks; not all-at-once */
|
||||
int client = 1; /* acting as client is the default */
|
||||
int connectudp = 1; /* connect UDP client */
|
||||
int crlf; /* convert newline to CR/LF & vice versa */
|
||||
int debug; /* SO_DEBUG */
|
||||
int dofork; /* concurrent server, do a fork() */
|
||||
int dontroute; /* SO_DONTROUTE */
|
||||
char foreignip[32]; /* foreign IP address, dotted-decimal string */
|
||||
int foreignport; /* foreign port number */
|
||||
int halfclose; /* TCP half close option */
|
||||
int ignorewerr; /* true if write() errors should be ignored */
|
||||
int iptos = -1; /* IP_TOS opton */
|
||||
int ipttl = -1; /* IP_TTL opton */
|
||||
char joinip[32]; /* multicast IP address, dotted-decimal string */
|
||||
int keepalive; /* SO_KEEPALIVE */
|
||||
long linger = -1; /* 0 or positive turns on option */
|
||||
int listenq = 5; /* listen queue for TCP Server */
|
||||
char localip[32]; /* local IP address, dotted-decimal string */
|
||||
int maxseg; /* TCP_MAXSEG */
|
||||
int mcastttl; /* multicast TTL */
|
||||
int msgpeek; /* MSG_PEEK */
|
||||
int nodelay; /* TCP_NODELAY (Nagle algorithm) */
|
||||
int nbuf = 1024; /* number of buffers to write (sink mode) */
|
||||
int onesbcast; /* set IP_ONESBCAST for 255.255.255.255 bcasts */
|
||||
int pauseclose; /* #ms to sleep after recv FIN, before close */
|
||||
int pauseinit; /* #ms to sleep before first read */
|
||||
int pauselisten; /* #ms to sleep after listen() */
|
||||
int pauserw; /* #ms to sleep before each read or write */
|
||||
int reuseaddr; /* SO_REUSEADDR */
|
||||
int reuseport; /* SO_REUSEPORT */
|
||||
int readlen = 1024; /* default read length for socket */
|
||||
int writelen = 1024; /* default write length for socket */
|
||||
int recvdstaddr; /* IP_RECVDSTADDR option */
|
||||
int rcvbuflen; /* size for SO_RCVBUF */
|
||||
int sndbuflen; /* size for SO_SNDBUF */
|
||||
long rcvtimeo; /* SO_RCVTIMEO */
|
||||
long sndtimeo; /* SO_SNDTIMEO */
|
||||
int sroute_cnt; /* count of #IP addresses in route */
|
||||
char *rbuf; /* pointer that is malloc'ed */
|
||||
char *wbuf; /* pointer that is malloc'ed */
|
||||
int server; /* to act as server requires -s option */
|
||||
int sigio; /* send SIGIO */
|
||||
int sourcesink; /* source/sink mode */
|
||||
int udp; /* use UDP instead of TCP */
|
||||
int urgwrite; /* write urgent byte after this write */
|
||||
int verbose; /* each -v increments this by 1 */
|
||||
int usewritev; /* use writev() instead of write() */
|
||||
|
||||
struct sockaddr_in cliaddr, servaddr;
|
||||
|
||||
static void usage(const char *);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int c, fd;
|
||||
char *ptr;
|
||||
|
||||
if (argc < 2)
|
||||
usage("");
|
||||
|
||||
opterr = 0; /* don't want getopt() writing to stderr */
|
||||
while ( (c = getopt(argc, argv, "2b:cf:g:hij:kl:n:op:q:r:st:uvw:x:y:ABCDEFG:H:IJ:KL:NO:P:Q:R:S:TU:VWX:YZ")) != -1) {
|
||||
switch (c) {
|
||||
#ifdef IP_ONESBCAST
|
||||
case '2': /* use 255.255.255.255 as broadcast address */
|
||||
onesbcast = 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'b':
|
||||
bindport = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'c': /* convert newline to CR/LF & vice versa */
|
||||
crlf = 1;
|
||||
break;
|
||||
|
||||
case 'f': /* foreign IP address and port#: a.b.c.d.p */
|
||||
if ( (ptr = strrchr(optarg, '.')) == NULL)
|
||||
usage("invalid -f option");
|
||||
|
||||
*ptr++ = 0; /* null replaces final period */
|
||||
foreignport = atoi(ptr); /* port number */
|
||||
strcpy(foreignip, optarg); /* save dotted-decimal IP */
|
||||
break;
|
||||
|
||||
case 'g': /* loose source route */
|
||||
sroute_doopt(0, optarg);
|
||||
break;
|
||||
|
||||
case 'h': /* TCP half-close option */
|
||||
halfclose = 1;
|
||||
break;
|
||||
|
||||
case 'i': /* source/sink option */
|
||||
sourcesink = 1;
|
||||
break;
|
||||
|
||||
#ifdef IP_ADD_MEMBERSHIP
|
||||
case 'j': /* join multicast group a.b.c.d */
|
||||
strcpy(joinip, optarg); /* save dotted-decimal IP */
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'k': /* chunk-write option */
|
||||
chunkwrite = 1;
|
||||
break;
|
||||
|
||||
case 'l': /* local IP address and port#: a.b.c.d.p */
|
||||
if ( (ptr = strrchr(optarg, '.')) == NULL)
|
||||
usage("invalid -l option");
|
||||
|
||||
*ptr++ = 0; /* null replaces final period */
|
||||
bindport = atoi(ptr); /* port number */
|
||||
strcpy(localip, optarg); /* save dotted-decimal IP */
|
||||
break;
|
||||
|
||||
case 'n': /* number of buffers to write */
|
||||
nbuf = atol(optarg);
|
||||
break;
|
||||
|
||||
case 'o': /* do not connect UDP client */
|
||||
connectudp = 0;
|
||||
break;
|
||||
|
||||
case 'p': /* pause before each read or write */
|
||||
pauserw = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'q': /* listen queue for TCP server */
|
||||
listenq = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'r': /* read() length */
|
||||
readlen = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 's': /* server */
|
||||
server = 1;
|
||||
client = 0;
|
||||
break;
|
||||
|
||||
#ifdef IP_MULTICAST_TTL
|
||||
case 't': /* IP_MULTICAST_TTL */
|
||||
mcastttl = atoi(optarg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'u': /* use UDP instead of TCP */
|
||||
udp = 1;
|
||||
break;
|
||||
|
||||
case 'v': /* output what's going on */
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'w': /* write() length */
|
||||
writelen = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'x': /* SO_RCVTIMEO socket option */
|
||||
rcvtimeo = atol(optarg);
|
||||
break;
|
||||
|
||||
case 'y': /* SO_SNDTIMEO socket option */
|
||||
sndtimeo = atol(optarg);
|
||||
break;
|
||||
|
||||
case 'A': /* SO_REUSEADDR socket option */
|
||||
reuseaddr = 1;
|
||||
break;
|
||||
|
||||
case 'B': /* SO_BROADCAST socket option */
|
||||
broadcast = 1;
|
||||
break;
|
||||
|
||||
case 'C': /* set standard input to cbreak mode */
|
||||
cbreak = 1;
|
||||
break;
|
||||
|
||||
case 'D': /* SO_DEBUG socket option */
|
||||
debug = 1;
|
||||
break;
|
||||
|
||||
case 'E': /* IP_RECVDSTADDR socket option */
|
||||
recvdstaddr = 1;
|
||||
break;
|
||||
|
||||
case 'F': /* concurrent server, do a fork() */
|
||||
dofork = 1;
|
||||
break;
|
||||
|
||||
case 'G': /* strict source route */
|
||||
sroute_doopt(1, optarg);
|
||||
break;
|
||||
|
||||
#ifdef IP_TOS
|
||||
case 'H': /* IP_TOS socket option */
|
||||
iptos = atoi(optarg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'I': /* SIGIO signal */
|
||||
sigio = 1;
|
||||
break;
|
||||
|
||||
#ifdef IP_TTL
|
||||
case 'J': /* IP_TTL socket option */
|
||||
ipttl = atoi(optarg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'K': /* SO_KEEPALIVE socket option */
|
||||
keepalive = 1;
|
||||
break;
|
||||
|
||||
case 'L': /* SO_LINGER socket option */
|
||||
linger = atol(optarg);
|
||||
break;
|
||||
|
||||
case 'N': /* SO_NODELAY socket option */
|
||||
nodelay = 1;
|
||||
break;
|
||||
|
||||
case 'O': /* pause before listen(), before first accept() */
|
||||
pauselisten = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'P': /* pause before first read() */
|
||||
pauseinit = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'Q': /* pause after receiving FIN, but before close() */
|
||||
pauseclose = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'R': /* SO_RCVBUF socket option */
|
||||
rcvbuflen = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'S': /* SO_SNDBUF socket option */
|
||||
sndbuflen = atoi(optarg);
|
||||
break;
|
||||
|
||||
#ifdef SO_REUSEPORT
|
||||
case 'T': /* SO_REUSEPORT socket option */
|
||||
reuseport = 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'U': /* when to write urgent byte */
|
||||
urgwrite = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'V': /* use writev() instead of write() */
|
||||
usewritev = 1;
|
||||
chunkwrite = 1; /* implies this option too */
|
||||
break;
|
||||
|
||||
case 'W': /* ignore write errors */
|
||||
ignorewerr = 1;
|
||||
break;
|
||||
|
||||
case 'X': /* TCP maximum segment size option */
|
||||
maxseg = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'Y': /* SO_DONTROUTE socket option */
|
||||
dontroute = 1;
|
||||
break;
|
||||
|
||||
case 'Z': /* MSG_PEEK option */
|
||||
msgpeek = MSG_PEEK;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
usage("unrecognized option");
|
||||
}
|
||||
}
|
||||
|
||||
/* check for options that don't make sense */
|
||||
if (udp && halfclose)
|
||||
usage("can't specify -h and -u");
|
||||
if (udp && debug)
|
||||
usage("can't specify -D and -u");
|
||||
if (udp && linger >= 0)
|
||||
usage("can't specify -L and -u");
|
||||
if (udp && nodelay)
|
||||
usage("can't specify -N and -u");
|
||||
#ifdef notdef
|
||||
if (udp == 0 && broadcast)
|
||||
usage("can't specify -B with TCP");
|
||||
#endif
|
||||
if (udp == 0 && foreignip[0] != 0)
|
||||
usage("can't specify -f with TCP");
|
||||
|
||||
if (client) {
|
||||
if (optind != argc-2)
|
||||
usage("missing <hostname> and/or <port>");
|
||||
host = argv[optind];
|
||||
port = argv[optind+1];
|
||||
|
||||
} else {
|
||||
/* If server specifies host and port, then local address is
|
||||
bound to the "host" argument, instead of being wildcarded. */
|
||||
if (optind == argc-2) {
|
||||
host = argv[optind];
|
||||
port = argv[optind+1];
|
||||
} else if (optind == argc-1) {
|
||||
host = NULL;
|
||||
port = argv[optind];
|
||||
} else
|
||||
usage("missing <port>");
|
||||
}
|
||||
|
||||
if (client)
|
||||
fd = cliopen(host, port);
|
||||
else
|
||||
fd = servopen(host, port);
|
||||
|
||||
if (sourcesink) { /* ignore stdin/stdout */
|
||||
if (client) {
|
||||
if (udp)
|
||||
source_udp(fd);
|
||||
else
|
||||
source_tcp(fd);
|
||||
} else {
|
||||
if (udp)
|
||||
sink_udp(fd);
|
||||
else
|
||||
sink_tcp(fd);
|
||||
}
|
||||
|
||||
} else { /* copy stdin/stdout to/from socket */
|
||||
if (udp)
|
||||
loop_udp(fd);
|
||||
else
|
||||
loop_tcp(fd);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(const char *msg)
|
||||
{
|
||||
err_msg(
|
||||
"usage: sock [ options ] <host> <port> (for client; default)\n"
|
||||
" sock [ options ] -s [ <IPaddr> ] <port> (for server)\n"
|
||||
" sock [ options ] -i <host> <port> (for \"source\" client)\n"
|
||||
" sock [ options ] -i -s [ <IPaddr> ] <port> (for \"sink\" server)\n"
|
||||
"options: -b n bind n as client's local port number\n"
|
||||
" -c convert newline to CR/LF & vice versa\n"
|
||||
" -f a.b.c.d.p foreign IP address = a.b.c.d, foreign port# = p\n"
|
||||
" -g a.b.c.d loose source route\n"
|
||||
" -h issue TCP half close on standard input EOF\n"
|
||||
" -i \"source\" data to socket, \"sink\" data from socket (w/-s)\n"
|
||||
#ifdef IP_ADD_MEMBERSHIP
|
||||
" -j a.b.c.d join multicast group\n"
|
||||
#endif
|
||||
" -k write or writev in chunks\n"
|
||||
" -l a.b.c.d.p client's local IP address = a.b.c.d, local port# = p\n"
|
||||
" -n n #buffers to write for \"source\" client (default 1024)\n"
|
||||
" -o do NOT connect UDP client\n"
|
||||
" -p n #ms to pause before each read or write (source/sink)\n"
|
||||
" -q n size of listen queue for TCP server (default 5)\n"
|
||||
" -r n #bytes per read() for \"sink\" server (default 1024)\n"
|
||||
" -s operate as server instead of client\n"
|
||||
#ifdef IP_MULTICAST_TTL
|
||||
" -t n set multicast ttl\n"
|
||||
#endif
|
||||
" -u use UDP instead of TCP\n"
|
||||
" -v verbose\n"
|
||||
" -w n #bytes per write() for \"source\" client (default 1024)\n"
|
||||
" -x n #ms for SO_RCVTIMEO (receive timeout)\n"
|
||||
" -y n #ms for SO_SNDTIMEO (send timeout)\n"
|
||||
" -A SO_REUSEADDR option\n"
|
||||
" -B SO_BROADCAST option\n"
|
||||
" -C set terminal to cbreak mode\n"
|
||||
" -D SO_DEBUG option\n"
|
||||
" -E IP_RECVDSTADDR option\n"
|
||||
" -F fork after connection accepted (TCP concurrent server)\n"
|
||||
" -G a.b.c.d strict source route\n"
|
||||
#ifdef IP_TOS
|
||||
" -H n IP_TOS option (16=min del, 8=max thru, 4=max rel, 2=min$)\n"
|
||||
#endif
|
||||
" -I SIGIO signal\n"
|
||||
#ifdef IP_TTL
|
||||
" -J n IP_TTL option\n"
|
||||
#endif
|
||||
" -K SO_KEEPALIVE option\n"
|
||||
" -L n SO_LINGER option, n = linger time\n"
|
||||
" -N TCP_NODELAY option\n"
|
||||
" -O n #ms to pause after listen, but before first accept\n"
|
||||
" -P n #ms to pause before first read or write (source/sink)\n"
|
||||
" -Q n #ms to pause after receiving FIN, but before close\n"
|
||||
" -R n SO_RCVBUF option\n"
|
||||
" -S n SO_SNDBUF option\n"
|
||||
#ifdef SO_REUSEPORT
|
||||
" -T SO_REUSEPORT option\n"
|
||||
#endif
|
||||
" -U n enter urgent mode before write number n (source only)\n"
|
||||
" -V use writev() instead of write(); enables -k too\n"
|
||||
" -W ignore write errors for sink client\n"
|
||||
" -X n TCP_MAXSEG option (set MSS)\n"
|
||||
" -Y SO_DONTROUTE option\n"
|
||||
" -Z MSG_PEEK\n"
|
||||
#ifdef IP_ONESBCAST
|
||||
" -2 IP_ONESBCAST option (255.255.255.255 for broadcast\n"
|
||||
#endif
|
||||
);
|
||||
|
||||
if (msg[0] != 0)
|
||||
err_quit("%s", msg);
|
||||
exit(1);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
void
|
||||
join_mcast(int fd, struct sockaddr_in *sin)
|
||||
{
|
||||
#ifdef IP_ADD_MEMBERSHIP /* only include if host supports mcasting */
|
||||
u_long inaddr;
|
||||
struct ip_mreq mreq;
|
||||
|
||||
inaddr = sin->sin_addr.s_addr;
|
||||
if (IN_MULTICAST(inaddr) == 0)
|
||||
return; /* not a multicast address */
|
||||
|
||||
mreq.imr_multiaddr.s_addr = inaddr;
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY); /* need way to change */
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
|
||||
sizeof(mreq)) == -1 )
|
||||
err_sys("IP_ADD_MEMBERSHIP error");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "multicast group joined\n");
|
||||
#endif /* IP_ADD_MEMBERSHIP */
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*- */
|
||||
/* Our own header, to be included *after* all standard system headers */
|
||||
|
||||
#ifndef __ourhdr_h
|
||||
#define __ourhdr_h
|
||||
|
||||
#include <sys/types.h> /* required for some of our prototypes */
|
||||
#include <stdio.h> /* for convenience */
|
||||
#include <stdlib.h> /* for convenience */
|
||||
#include <string.h> /* for convenience */
|
||||
#include <unistd.h> /* for convenience */
|
||||
|
||||
#ifdef notdef /* delete for systems that don't define this (SunOS 4.x) */
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
|
||||
#ifdef notdef /* delete if <stdlib.h> doesn't define these for getopt() */
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
#endif
|
||||
|
||||
#ifdef notdef /* delete if send() not supported (DEC OSF/1) */
|
||||
#define send(a,b,c,d) sendto((a), (b), (c), (d), (struct sockaddr *) NULL, 0)
|
||||
#endif
|
||||
|
||||
#define MAXLINE 4096 /* max line length */
|
||||
|
||||
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
|
||||
/* default file access permissions for new files */
|
||||
#define DIR_MODE (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
|
||||
/* default permissions for new directories */
|
||||
|
||||
typedef void Sigfunc(int); /* for signal handlers */
|
||||
|
||||
/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
|
||||
#if defined(SIG_IGN) && !defined(SIG_ERR)
|
||||
#define SIG_ERR ((Sigfunc *)-1)
|
||||
#endif
|
||||
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
/* prototypes for our own functions */
|
||||
char *path_alloc(int *); /* {Prog pathalloc} */
|
||||
int open_max(void); /* {Prog openmax} */
|
||||
void clr_fl(int, int); /* {Prog setfl} */
|
||||
void set_fl(int, int); /* {Prog setfl} */
|
||||
void pr_exit(int); /* {Prog prexit} */
|
||||
void pr_mask(const char *); /* {Prog prmask} */
|
||||
Sigfunc *signal_intr(int, Sigfunc *);/* {Prog signal_intr_function} */
|
||||
|
||||
int tty_cbreak(int); /* {Prog raw} */
|
||||
int tty_raw(int); /* {Prog raw} */
|
||||
int tty_reset(int); /* {Prog raw} */
|
||||
void tty_atexit(void); /* {Prog raw} */
|
||||
#ifdef ECHO /* only if <termios.h> has been included */
|
||||
struct termios *tty_termios(void); /* {Prog raw} */
|
||||
#endif
|
||||
|
||||
void sleep_us(unsigned int); /* {Ex sleepus} */
|
||||
ssize_t readn(int, void *, size_t);/* {Prog readn} */
|
||||
ssize_t writen(int, const void *, size_t);/* {Prog writen} */
|
||||
int daemon_init(void); /* {Prog daemoninit} */
|
||||
|
||||
int s_pipe(int *); /* {Progs svr4_spipe bsd_spipe} */
|
||||
int recv_fd(int, ssize_t (*func)(int, const void *, size_t));
|
||||
/* {Progs recvfd_svr4 recvfd_43bsd} */
|
||||
int send_fd(int, int); /* {Progs sendfd_svr4 sendfd_43bsd} */
|
||||
int send_err(int, int, const char *);/* {Prog senderr} */
|
||||
int serv_listen(const char *); /* {Progs servlisten_svr4 servlisten_44bsd} */
|
||||
int serv_accept(int, uid_t *); /* {Progs servaccept_svr4 servaccept_44bsd} */
|
||||
int cli_conn(const char *); /* {Progs cliconn_svr4 cliconn_44bsd} */
|
||||
int buf_args(char *, int (*func)(int, char **));
|
||||
/* {Prog bufargs} */
|
||||
|
||||
int ptym_open(char *); /* {Progs ptyopen_svr4 ptyopen_44bsd} */
|
||||
int ptys_open(int, char *); /* {Progs ptyopen_svr4 ptyopen_44bsd} */
|
||||
#ifdef TIOCGWINSZ
|
||||
pid_t pty_fork(int *, char *, const struct termios *,
|
||||
const struct winsize *); /* {Prog ptyfork} */
|
||||
#endif
|
||||
|
||||
int lock_reg(int, int, int, off_t, int, off_t);
|
||||
/* {Prog lockreg} */
|
||||
#define read_lock(fd, offset, whence, len) \
|
||||
lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)
|
||||
#define readw_lock(fd, offset, whence, len) \
|
||||
lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len)
|
||||
#define write_lock(fd, offset, whence, len) \
|
||||
lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)
|
||||
#define writew_lock(fd, offset, whence, len) \
|
||||
lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len)
|
||||
#define un_lock(fd, offset, whence, len) \
|
||||
lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len)
|
||||
|
||||
pid_t lock_test(int, int, off_t, int, off_t);
|
||||
/* {Prog locktest} */
|
||||
|
||||
#define is_readlock(fd, offset, whence, len) \
|
||||
lock_test(fd, F_RDLCK, offset, whence, len)
|
||||
#define is_writelock(fd, offset, whence, len) \
|
||||
lock_test(fd, F_WRLCK, offset, whence, len)
|
||||
|
||||
void err_dump(const char *, ...); /* {App misc_source} */
|
||||
void err_msg(const char *, ...);
|
||||
void err_quit(const char *, ...);
|
||||
void err_ret(const char *, ...);
|
||||
void err_sys(const char *, ...);
|
||||
|
||||
void log_msg(const char *, ...); /* {App misc_source} */
|
||||
void log_open(const char *, int, int);
|
||||
void log_quit(const char *, ...);
|
||||
void log_ret(const char *, ...);
|
||||
void log_sys(const char *, ...);
|
||||
|
||||
void TELL_WAIT(void); /* parent/child from {Sec race_conditions} */
|
||||
void TELL_PARENT(pid_t);
|
||||
void TELL_CHILD(pid_t);
|
||||
void WAIT_PARENT(void);
|
||||
void WAIT_CHILD(void);
|
||||
|
||||
#endif /* __ourhdr_h */
|
||||
@@ -1,25 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "sock.h"
|
||||
#include <ctype.h>
|
||||
|
||||
void
|
||||
pattern(char *ptr, int len)
|
||||
{
|
||||
char c;
|
||||
|
||||
c = 0;
|
||||
while(len-- > 0) {
|
||||
while(isprint((c & 0x7F)) == 0)
|
||||
c++; /* skip over nonprinting characters */
|
||||
*ptr++ = (c++ & 0x7F);
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "sock.h"
|
||||
|
||||
int
|
||||
servopen(char *host, char *port)
|
||||
{
|
||||
int fd, newfd, i, on, pid;
|
||||
char *protocol;
|
||||
struct in_addr inaddr;
|
||||
struct servent *sp;
|
||||
|
||||
protocol = udp ? "udp" : "tcp";
|
||||
|
||||
/* Initialize the socket address structure */
|
||||
bzero(&servaddr, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
|
||||
/* Caller normally wildcards the local Internet address, meaning
|
||||
a connection will be accepted on any connected interface.
|
||||
We only allow an IP address for the "host", not a name. */
|
||||
if (host == NULL)
|
||||
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
|
||||
else {
|
||||
if (inet_aton(host, &inaddr) == 0)
|
||||
err_quit("invalid host name for server: %s", host);
|
||||
servaddr.sin_addr = inaddr;
|
||||
}
|
||||
|
||||
/* See if "port" is a service name or number */
|
||||
if ( (i = atoi(port)) == 0) {
|
||||
if ( (sp = getservbyname(port, protocol)) == NULL)
|
||||
err_ret("getservbyname() error for: %s/%s", port, protocol);
|
||||
|
||||
servaddr.sin_port = sp->s_port;
|
||||
} else
|
||||
servaddr.sin_port = htons(i);
|
||||
|
||||
if ( (fd = socket(AF_INET, udp ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
|
||||
err_sys("socket() error");
|
||||
|
||||
if (reuseaddr) {
|
||||
on = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
||||
err_sys("setsockopt of SO_REUSEADDR error");
|
||||
}
|
||||
|
||||
#ifdef SO_REUSEPORT
|
||||
if (reuseport) {
|
||||
on = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
|
||||
err_sys("setsockopt of SO_REUSEPORT error");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Bind our well-known port so the client can connect to us. */
|
||||
if (bind(fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
|
||||
err_sys("can't bind local address");
|
||||
|
||||
join_mcast(fd, &servaddr);
|
||||
|
||||
if (udp) {
|
||||
buffers(fd);
|
||||
|
||||
if (foreignip[0] != 0) { /* connect to foreignip/port# */
|
||||
bzero(&cliaddr, sizeof(cliaddr));
|
||||
if (inet_aton(foreignip, &cliaddr.sin_addr) == 0)
|
||||
err_quit("invalid IP address: %s", foreignip);
|
||||
cliaddr.sin_family = AF_INET;
|
||||
cliaddr.sin_port = htons(foreignport);
|
||||
/* connect() for datagram socket doesn't appear to allow
|
||||
wildcarding of either IP address or port number */
|
||||
|
||||
if (connect(fd, (struct sockaddr *) &cliaddr, sizeof(cliaddr))
|
||||
< 0)
|
||||
err_sys("connect() error");
|
||||
|
||||
}
|
||||
|
||||
sockopts(fd, 1);
|
||||
|
||||
return(fd); /* nothing else to do */
|
||||
}
|
||||
|
||||
buffers(fd); /* may set receive buffer size; must do here to get
|
||||
correct window advertised on SYN */
|
||||
sockopts(fd, 0); /* only set some socket options for fd */
|
||||
|
||||
listen(fd, listenq);
|
||||
|
||||
if (pauselisten)
|
||||
sleep_us(pauselisten*1000); /* lets connection queue build up */
|
||||
|
||||
if (dofork)
|
||||
TELL_WAIT(); /* initialize synchronization primitives */
|
||||
|
||||
for ( ; ; ) {
|
||||
i = sizeof(cliaddr);
|
||||
if ( (newfd = accept(fd, (struct sockaddr *) &cliaddr, &i)) < 0)
|
||||
err_sys("accept() error");
|
||||
|
||||
if (dofork) {
|
||||
if ( (pid = fork()) < 0)
|
||||
err_sys("fork error");
|
||||
|
||||
if (pid > 0) {
|
||||
close(newfd); /* parent closes connected socket */
|
||||
WAIT_CHILD(); /* wait for child to output to terminal */
|
||||
continue; /* and back to for(;;) for another accept() */
|
||||
} else {
|
||||
close(fd); /* child closes listening socket */
|
||||
}
|
||||
}
|
||||
|
||||
/* child (or iterative server) continues here */
|
||||
if (verbose) {
|
||||
/* Call getsockname() to find local address bound to socket:
|
||||
local internet address is now determined (if multihomed). */
|
||||
i = sizeof(servaddr);
|
||||
if (getsockname(newfd, (struct sockaddr *) &servaddr, &i) < 0)
|
||||
err_sys("getsockname() error");
|
||||
|
||||
/* Can't do one fprintf() since inet_ntoa() stores
|
||||
the result in a static location. */
|
||||
fprintf(stderr, "connection on %s.%d ",
|
||||
INET_NTOA(servaddr.sin_addr), ntohs(servaddr.sin_port));
|
||||
fprintf(stderr, "from %s.%d\n",
|
||||
INET_NTOA(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
|
||||
}
|
||||
|
||||
buffers(newfd); /* setsockopt() again, in case it didn't propagate
|
||||
from listening socket to connected socket */
|
||||
sockopts(newfd, 1); /* can set all socket options for this socket */
|
||||
|
||||
if (dofork)
|
||||
TELL_PARENT(getppid()); /* tell parent we're done with terminal */
|
||||
|
||||
return(newfd);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sock.h"
|
||||
|
||||
void
|
||||
sink_tcp(int sockfd)
|
||||
{
|
||||
int n, flags;
|
||||
|
||||
if (pauseinit)
|
||||
sleep_us(pauseinit*1000);
|
||||
|
||||
for ( ; ; ) { /* read until peer closes connection; -n opt ignored */
|
||||
/* msgpeek = 0 or MSG_PEEK */
|
||||
flags = msgpeek;
|
||||
oncemore:
|
||||
if ( (n = recv(sockfd, rbuf, readlen, flags)) < 0) {
|
||||
err_sys("recv error");
|
||||
|
||||
} else if (n == 0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "connection closed by peer\n");
|
||||
break;
|
||||
|
||||
#ifdef notdef /* following not possible with TCP */
|
||||
} else if (n != readlen)
|
||||
err_quit("read returned %d, expected %d", n, readlen);
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "received %d bytes%s\n", n,
|
||||
(flags == MSG_PEEK) ? " (MSG_PEEK)" : "");
|
||||
|
||||
if (pauserw)
|
||||
sleep_us(pauserw*1000);
|
||||
|
||||
if (flags != 0) {
|
||||
flags = 0; /* no infinite loop */
|
||||
goto oncemore; /* read the message again */
|
||||
}
|
||||
}
|
||||
|
||||
if (pauseclose) { /* pausing here puts peer into FIN_WAIT_2 */
|
||||
if (verbose)
|
||||
fprintf(stderr, "pausing before close\n");
|
||||
sleep_us(pauseclose*1000);
|
||||
}
|
||||
|
||||
if (close(sockfd) < 0)
|
||||
err_sys("close error"); /* since SO_LINGER may be set */
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sock.h"
|
||||
|
||||
void
|
||||
sink_udp(int sockfd) /* TODO: use recvfrom ?? */
|
||||
{
|
||||
int n, flags;
|
||||
|
||||
if (pauseinit)
|
||||
sleep_us(pauseinit*1000);
|
||||
|
||||
for ( ; ; ) { /* read until peer closes connection; -n opt ignored */
|
||||
/* msgpeek = 0 or MSG_PEEK */
|
||||
flags = msgpeek;
|
||||
oncemore:
|
||||
if ( (n = recv(sockfd, rbuf, readlen, flags)) < 0) {
|
||||
err_sys("recv error");
|
||||
|
||||
} else if (n == 0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "connection closed by peer\n");
|
||||
break;
|
||||
|
||||
#ifdef notdef /* following not possible with TCP */
|
||||
} else if (n != readlen)
|
||||
err_quit("read returned %d, expected %d", n, readlen);
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stderr, "received %d bytes%s\n", n,
|
||||
(flags == MSG_PEEK) ? " (MSG_PEEK)" : "");
|
||||
if (verbose > 1) {
|
||||
fprintf(stderr, "printing %d bytes\n", n);
|
||||
rbuf[n] = 0; /* make certain it's null terminated */
|
||||
fprintf(stderr, "SDAP header: %lx\n", *((long *) rbuf));
|
||||
fprintf(stderr, "next long: %lx\n", *((long *) rbuf+4));
|
||||
fputs(&rbuf[8], stderr);
|
||||
}
|
||||
}
|
||||
|
||||
if (pauserw)
|
||||
sleep_us(pauserw*1000);
|
||||
|
||||
if (flags != 0) {
|
||||
flags = 0; /* avoid infinite loop */
|
||||
goto oncemore; /* read the message again */
|
||||
}
|
||||
}
|
||||
|
||||
if (pauseclose) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "pausing before close\n");
|
||||
sleep_us(pauseclose*1000);
|
||||
}
|
||||
|
||||
if (close(sockfd) < 0)
|
||||
err_sys("close error");
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*- */
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include "ourhdr.h"
|
||||
|
||||
void
|
||||
sleep_us(unsigned int nusecs)
|
||||
{
|
||||
struct timeval tval;
|
||||
|
||||
for ( ; ; ) {
|
||||
tval.tv_sec = nusecs / 1000000;
|
||||
tval.tv_usec = nusecs % 1000000;
|
||||
if (select(0, NULL, NULL, NULL, &tval) == 0)
|
||||
break; /* all OK */
|
||||
/*
|
||||
* Note than on an interrupted system call (i.e, SIGIO) there's not
|
||||
* much we can do, since the timeval{} isn't updated with the time
|
||||
* remaining. We could obtain the clock time before the call, and
|
||||
* then obtain the clock time here, subtracting them to determine
|
||||
* how long select() blocked before it was interrupted, but that
|
||||
* seems like too much work :-)
|
||||
*/
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
err_sys("sleep_us: select error");
|
||||
}
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h" /* configuration options for current OS */
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ADDRINFO_STRUCT
|
||||
#include "addrinfo.h"
|
||||
#endif
|
||||
|
||||
#include <sys/uio.h>
|
||||
#ifdef __bsdi__
|
||||
#include <machine/endian.h> /* required before tcp.h, for BYTE_ORDER */
|
||||
#endif
|
||||
#include <netinet/tcp.h> /* TCP_NODELAY */
|
||||
#include <netdb.h> /* getservbyname(), gethostbyname() */
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
||||
/* Older resolvers do not have gethostbyname2() */
|
||||
#ifndef HAVE_GETHOSTBYNAME2
|
||||
#define gethostbyname2(host,family) gethostbyname((host))
|
||||
#endif
|
||||
|
||||
/* This avoids a warning with glibc compilation */
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
|
||||
/* Miscellaneous constants */
|
||||
#define MAXLINE 4096 /* max text line length */
|
||||
#define MAXSOCKADDR 128 /* max socket address structure size */
|
||||
#define BUFFSIZE 8192 /* buffer size for reads and writes */
|
||||
|
||||
/* stdin and stdout file descriptors */
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
/* declare global variables */
|
||||
extern int bindport;
|
||||
extern int broadcast;
|
||||
extern int cbreak;
|
||||
extern int chunkwrite;
|
||||
extern int client;
|
||||
extern int connectudp;
|
||||
extern int crlf;
|
||||
extern int debug;
|
||||
extern int dofork;
|
||||
extern int dontroute;
|
||||
extern char foreignip[];
|
||||
extern int foreignport;
|
||||
extern int halfclose;
|
||||
extern int ignorewerr;
|
||||
extern int iptos;
|
||||
extern int ipttl;
|
||||
extern char joinip[];
|
||||
extern int keepalive;
|
||||
extern long linger;
|
||||
extern int listenq;
|
||||
extern char localip[];
|
||||
extern int maxseg;
|
||||
extern int mcastttl;
|
||||
extern int msgpeek;
|
||||
extern int nodelay;
|
||||
extern int nbuf;
|
||||
extern int onesbcast;
|
||||
extern int pauseclose;
|
||||
extern int pauseinit;
|
||||
extern int pauselisten;
|
||||
extern int pauserw;
|
||||
extern int reuseaddr;
|
||||
extern int reuseport;
|
||||
extern int readlen;
|
||||
extern int writelen;
|
||||
extern int recvdstaddr;
|
||||
extern int rcvbuflen;
|
||||
extern int sndbuflen;
|
||||
extern long rcvtimeo;
|
||||
extern long sndtimeo;
|
||||
extern char *rbuf;
|
||||
extern char *wbuf;
|
||||
extern int server;
|
||||
extern int sigio;
|
||||
extern int sourcesink;
|
||||
extern int sroute_cnt;
|
||||
extern int udp;
|
||||
extern int urgwrite;
|
||||
extern int verbose;
|
||||
extern int usewritev;
|
||||
|
||||
extern struct sockaddr_in cliaddr, servaddr;
|
||||
|
||||
/* Earlier versions of gcc under SunOS 4.x have problems passing arguments
|
||||
that are structs (as opposed to pointers to structs). This shows up
|
||||
with inet_ntoa, whose argument is a "struct in_addr". */
|
||||
|
||||
#if defined(sun) && defined(__GNUC__) && defined(GCC_STRUCT_PROBLEM)
|
||||
#define INET_NTOA(foo) inet_ntoa(&foo)
|
||||
#else
|
||||
#define INET_NTOA(foo) inet_ntoa(foo)
|
||||
#endif
|
||||
|
||||
/* function prototypes */
|
||||
void buffers(int);
|
||||
int cliopen(char *, char *);
|
||||
int crlf_add(char *, int, const char *, int);
|
||||
int crlf_strip(char *, int, const char *, int);
|
||||
void join_mcast(int, struct sockaddr_in *);
|
||||
void loop_tcp(int);
|
||||
void loop_udp(int);
|
||||
void pattern(char *, int);
|
||||
int servopen(char *, char *);
|
||||
void sink_tcp(int);
|
||||
void sink_udp(int);
|
||||
void source_tcp(int);
|
||||
void source_udp(int);
|
||||
void sroute_doopt(int, char *);
|
||||
void sroute_set(int);
|
||||
void sleep_us(unsigned int);
|
||||
void sockopts(int, int);
|
||||
ssize_t dowrite(int, const void *, size_t);
|
||||
|
||||
void TELL_WAIT(void);
|
||||
void TELL_PARENT(pid_t);
|
||||
void WAIT_PARENT(void);
|
||||
void TELL_CHILD(pid_t);
|
||||
void WAIT_CHILD(void);
|
||||
|
||||
void err_dump(const char *, ...);
|
||||
void err_msg(const char *, ...);
|
||||
void err_quit(const char *, ...);
|
||||
void err_ret(const char *, ...);
|
||||
void err_sys(const char *, ...);
|
||||
|
||||
ssize_t writen(int, const void *, size_t);
|
||||
@@ -1,374 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include "sock.h"
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef FIOASYNC
|
||||
static void sigio_func(int);
|
||||
|
||||
static void
|
||||
sigio_func(int signo)
|
||||
{
|
||||
fprintf(stderr, "SIGIO\n");
|
||||
/* shouldn't printf from a signal handler ... */
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
sockopts(int sockfd, int doall)
|
||||
{
|
||||
int option;
|
||||
unsigned optlen;
|
||||
struct linger ling;
|
||||
struct timeval timer;
|
||||
|
||||
/* "doall" is 0 for a server's listening socket (i.e., before
|
||||
accept() has returned.) Some socket options such as SO_KEEPALIVE
|
||||
don't make sense at this point, while others like SO_DEBUG do. */
|
||||
|
||||
if (debug) {
|
||||
option = 1;
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_DEBUG,
|
||||
&option, sizeof(option)) < 0)
|
||||
err_sys("SO_DEBUG setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_DEBUG,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("SO_DEBUG getsockopt error");
|
||||
if (option == 0)
|
||||
err_quit("SO_DEBUG not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "SO_DEBUG set\n");
|
||||
}
|
||||
|
||||
if (dontroute) {
|
||||
option = 1;
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE,
|
||||
&option, sizeof(option)) < 0)
|
||||
err_sys("SO_DONTROUTE setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("SO_DONTROUTE getsockopt error");
|
||||
if (option == 0)
|
||||
err_quit("SO_DONTROUTE not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "SO_DONTROUTE set\n");
|
||||
}
|
||||
|
||||
#ifdef IP_TOS
|
||||
if (iptos != -1 && doall == 0) {
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_TOS,
|
||||
&iptos, sizeof(iptos)) < 0)
|
||||
err_sys("IP_TOS setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, IPPROTO_IP, IP_TOS,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("IP_TOS getsockopt error");
|
||||
if (option != iptos)
|
||||
err_quit("IP_TOS not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "IP_TOS set to %d\n", iptos);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IP_TTL
|
||||
if (ipttl != -1 && doall == 0) {
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_TTL,
|
||||
&ipttl, sizeof(ipttl)) < 0)
|
||||
err_sys("IP_TTL setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, IPPROTO_IP, IP_TTL,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("IP_TTL getsockopt error");
|
||||
if (option != ipttl)
|
||||
err_quit("IP_TTL not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "IP_TTL set to %d\n", ipttl);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (maxseg && udp == 0) {
|
||||
/* Need to set MSS for server before connection established */
|
||||
/* Beware: some kernels do not let the process set this socket
|
||||
option; others only let it be decreased. */
|
||||
if (setsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG,
|
||||
&maxseg, sizeof(maxseg)) < 0)
|
||||
err_sys("TCP_MAXSEG setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("TCP_MAXSEG getsockopt error");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "TCP_MAXSEG = %d\n", option);
|
||||
}
|
||||
|
||||
if (sroute_cnt > 0)
|
||||
sroute_set(sockfd);
|
||||
|
||||
if (broadcast) {
|
||||
option = 1;
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
|
||||
&option, sizeof(option)) < 0)
|
||||
err_sys("SO_BROADCAST setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("SO_BROADCAST getsockopt error");
|
||||
if (option == 0)
|
||||
err_quit("SO_BROADCAST not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "SO_BROADCAST set\n");
|
||||
|
||||
#ifdef IP_ONESBCAST
|
||||
if (onesbcast) {
|
||||
option = 1;
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_ONESBCAST,
|
||||
&option, sizeof(option)) < 0)
|
||||
err_sys("IP_ONESBCAST setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, IPPROTO_IP, IP_ONESBCAST,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("IP_ONESBCAST getsockopt error");
|
||||
if (option == 0)
|
||||
err_quit("IP_ONESBCAST not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "IP_ONESBCAST set\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef IP_ADD_MEMBERSHIP
|
||||
if (joinip[0]) {
|
||||
struct ip_mreq join;
|
||||
|
||||
if (inet_aton(joinip, &join.imr_multiaddr) == 0)
|
||||
err_quit("invalid multicast address: %s", joinip);
|
||||
join.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&join, sizeof(join)) < 0)
|
||||
err_sys("IP_ADD_MEMBERSHIP setsockopt error");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "IP_ADD_MEMBERSHIP set\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IP_MULTICAST_TTL
|
||||
if (mcastttl) {
|
||||
u_char ttl = mcastttl;
|
||||
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
&ttl, sizeof(ttl)) < 0)
|
||||
err_sys("IP_MULTICAST_TTL setsockopt error");
|
||||
|
||||
optlen = sizeof(ttl);
|
||||
if (getsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
&ttl, &optlen) < 0)
|
||||
err_sys("IP_MULTICAST_TTL getsockopt error");
|
||||
if (ttl != mcastttl)
|
||||
err_quit("IP_MULTICAST_TTL not set (%d)", ttl);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "IP_MULTICAST_TTL set to %d\n", ttl);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (keepalive && doall && udp == 0) {
|
||||
option = 1;
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
|
||||
&option, sizeof(option)) < 0)
|
||||
err_sys("SO_KEEPALIVE setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("SO_KEEPALIVE getsockopt error");
|
||||
if (option == 0)
|
||||
err_quit("SO_KEEPALIVE not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "SO_KEEPALIVE set\n");
|
||||
}
|
||||
|
||||
if (nodelay && doall && udp == 0) {
|
||||
option = 1;
|
||||
if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
|
||||
&option, sizeof(option)) < 0)
|
||||
err_sys("TCP_NODELAY setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("TCP_NODELAY getsockopt error");
|
||||
if (option == 0)
|
||||
err_quit("TCP_NODELAY not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "TCP_NODELAY set\n");
|
||||
}
|
||||
|
||||
if (doall && verbose && udp == 0) { /* just print MSS if verbose */
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("TCP_MAXSEG getsockopt error");
|
||||
|
||||
fprintf(stderr, "TCP_MAXSEG = %d\n", option);
|
||||
}
|
||||
|
||||
if (linger >= 0 && doall && udp == 0) {
|
||||
ling.l_onoff = 1;
|
||||
ling.l_linger = linger; /* 0 for abortive disconnect */
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
|
||||
&ling, sizeof(ling)) < 0)
|
||||
err_sys("SO_LINGER setsockopt error");
|
||||
|
||||
ling.l_onoff = 0;
|
||||
ling.l_linger = -1;
|
||||
optlen = sizeof(struct linger);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_LINGER,
|
||||
&ling, &optlen) < 0)
|
||||
err_sys("SO_LINGER getsockopt error");
|
||||
if (ling.l_onoff == 0 || ling.l_linger != linger)
|
||||
err_quit("SO_LINGER not set (%d, %d)", ling.l_onoff, ling.l_linger);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "linger %s, time = %d\n",
|
||||
ling.l_onoff ? "on" : "off", ling.l_linger);
|
||||
}
|
||||
|
||||
if (doall && rcvtimeo) {
|
||||
#ifdef SO_RCVTIMEO
|
||||
/* User specifies millisec, must convert to sec/usec */
|
||||
timer.tv_sec = rcvtimeo / 1000;
|
||||
timer.tv_usec = (rcvtimeo % 1000) * 1000;
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,
|
||||
&timer, sizeof(timer)) < 0)
|
||||
err_sys("SO_RCVTIMEO setsockopt error");
|
||||
|
||||
timer.tv_sec = timer.tv_usec = 0;
|
||||
optlen = sizeof(timer);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,
|
||||
&timer, &optlen) < 0)
|
||||
err_sys("SO_RCVTIMEO getsockopt error");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "SO_RCVTIMEO: %ld.%06ld\n",
|
||||
timer.tv_sec, timer.tv_usec);
|
||||
#else
|
||||
fprintf(stderr, "warning: SO_RCVTIMEO not supported by host\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (doall && sndtimeo) {
|
||||
#ifdef SO_SNDTIMEO
|
||||
/* User specifies millisec, must convert to sec/usec */
|
||||
timer.tv_sec = sndtimeo / 1000;
|
||||
timer.tv_usec = (sndtimeo % 1000) * 1000;
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO,
|
||||
&timer, sizeof(timer)) < 0)
|
||||
err_sys("SO_SNDTIMEO setsockopt error");
|
||||
|
||||
timer.tv_sec = timer.tv_usec = 0;
|
||||
optlen = sizeof(timer);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO,
|
||||
&timer, &optlen) < 0)
|
||||
err_sys("SO_SNDTIMEO getsockopt error");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "SO_SNDTIMEO: %ld.%06ld\n",
|
||||
timer.tv_sec, timer.tv_usec);
|
||||
#else
|
||||
fprintf(stderr, "warning: SO_SNDTIMEO not supported by host\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (recvdstaddr && udp) {
|
||||
#ifdef IP_RECVDSTADDR
|
||||
option = 1;
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR,
|
||||
&option, sizeof(option)) < 0)
|
||||
err_sys("IP_RECVDSTADDR setsockopt error");
|
||||
|
||||
option = 0;
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("IP_RECVDSTADDR getsockopt error");
|
||||
if (option == 0)
|
||||
err_quit("IP_RECVDSTADDR not set (%d)", option);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "IP_RECVDSTADDR set\n");
|
||||
#else
|
||||
fprintf(stderr, "warning: IP_RECVDSTADDR not supported by host\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sigio) {
|
||||
#ifdef FIOASYNC
|
||||
/*
|
||||
* Should be able to set this with fcntl(O_ASYNC) or fcntl(FASYNC),
|
||||
* but some systems (AIX?) only do it with ioctl().
|
||||
*
|
||||
* Need to set this for listening socket and for connected socket.
|
||||
*/
|
||||
signal(SIGIO, sigio_func);
|
||||
|
||||
if (fcntl(sockfd, F_SETOWN, getpid()) < 0)
|
||||
err_sys("fcntl F_SETOWN error");
|
||||
|
||||
option = 1;
|
||||
if (ioctl(sockfd, FIOASYNC, (char *) &option) < 0)
|
||||
err_sys("ioctl FIOASYNC error");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "FIOASYNC set\n");
|
||||
#else
|
||||
fprintf(stderr, "warning: FIOASYNC not supported by host\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sock.h"
|
||||
#include <netinet/ip.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/*
|
||||
* There is a fundamental limit of 9 IP addresses in a source route.
|
||||
* But we allocate sroute_opt[44] with room for 10 IP addresses (and
|
||||
* the 3-byte source route type/len/offset) because with the BSD
|
||||
* IP_OPTIONS socket option we can specify up to 9 addresses, followed
|
||||
* by the destination address. The in_pcbopts() function in the kernel
|
||||
* then takes the final address in the list (the destination) and moves
|
||||
* it to the front, as shown in Figure 9.33 of "TCP/IP Illustrated,
|
||||
* Volume 2". Also note that this destination address that we pass as
|
||||
* the final IP address in our array overrides the destination address
|
||||
* of the sendto() (Figure 9.28 of Volume 2).
|
||||
*/
|
||||
|
||||
u_char sroute_opt[44]; /* some implementations require this to be
|
||||
on a 4-byte boundary */
|
||||
u_char *optr; /* pointer into options being formed */
|
||||
|
||||
/*
|
||||
* Process either the -g (loose) or -G (strict) command-line option,
|
||||
* specifying one hop in a source route.
|
||||
* Either option can be specified up to 9 times.
|
||||
* With IPv4 the entire source route is either loose or strict, but we
|
||||
* set the source route type field based on the first option encountered,
|
||||
* either -g or -G.
|
||||
*/
|
||||
|
||||
void
|
||||
sroute_doopt(int strict, char *argptr)
|
||||
{
|
||||
struct in_addr inaddr;
|
||||
struct hostent *hp;
|
||||
|
||||
if (sroute_cnt >= 9)
|
||||
err_quit("too many source routes with: %s", argptr);
|
||||
|
||||
if (sroute_cnt == 0) { /* first one */
|
||||
bzero(sroute_opt, sizeof(sroute_opt));
|
||||
optr = sroute_opt;
|
||||
*optr++ = strict ? IPOPT_SSRR : IPOPT_LSRR;
|
||||
optr++; /* we fill in the total length later */
|
||||
*optr++ = 4; /* ptr to first source-route address */
|
||||
}
|
||||
|
||||
if (inet_aton(argptr, &inaddr) == 1) {
|
||||
bcopy(&inaddr, optr, sizeof(u_long)); /* dotted decimal */
|
||||
if (verbose)
|
||||
fprintf(stderr, "source route to %s\n", inet_ntoa(inaddr));
|
||||
} else if ( (hp = gethostbyname(argptr)) != NULL) {
|
||||
bcopy(hp->h_addr, optr, sizeof(u_long));/* hostname */
|
||||
if (verbose)
|
||||
fprintf(stderr, "source route to %s\n",
|
||||
inet_ntoa(*((struct in_addr *) hp->h_addr)));
|
||||
} else
|
||||
err_quit("unknown host: %s\n", argptr);
|
||||
|
||||
optr += sizeof(u_long); /* for next IP addr in list */
|
||||
sroute_cnt++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the actual source route with the IP_OPTIONS socket option.
|
||||
* This function is called if srouce_cnt is nonzero.
|
||||
* The final destination goes at the end of the list of IP addresses.
|
||||
*/
|
||||
|
||||
void
|
||||
sroute_set(int sockfd)
|
||||
{
|
||||
sroute_cnt++; /* account for destination */
|
||||
sroute_opt[1] = 3 + (sroute_cnt * 4); /* total length, incl. destination */
|
||||
|
||||
/* destination must be stored as final entry */
|
||||
bcopy(&servaddr.sin_addr, optr, sizeof(u_long));
|
||||
optr += sizeof(u_long);
|
||||
if (verbose) {
|
||||
fprintf(stderr, "source route to %s\n", inet_ntoa(servaddr.sin_addr));
|
||||
fprintf(stderr, "source route size %d bytes\n", sroute_opt[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* The number of bytes that we pass to setsockopt() must be a multiple
|
||||
* of 4. Since the buffer was initialized to 0, this leaves an EOL
|
||||
* following the final IP address.
|
||||
* For optimization we could put a NOP before the 3-byte type/len/offset
|
||||
* field, which would then align all the IP addresses on 4-byte boundaries,
|
||||
* but the source routing code is not exactly in the fast path of most
|
||||
* routers.
|
||||
*/
|
||||
while ((optr - sroute_opt) & 3)
|
||||
optr++;
|
||||
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_OPTIONS,
|
||||
sroute_opt, optr - sroute_opt) < 0)
|
||||
err_sys("setsockopt error for IP_OPTIONS");
|
||||
|
||||
sroute_cnt = 0; /* don't call this function again */
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sock.h"
|
||||
|
||||
void
|
||||
source_tcp(int sockfd)
|
||||
{
|
||||
int i, n, option;
|
||||
socklen_t optlen;
|
||||
char oob;
|
||||
|
||||
pattern(wbuf, writelen); /* fill send buffer with a pattern */
|
||||
|
||||
if (pauseinit)
|
||||
sleep_us(pauseinit*1000);
|
||||
|
||||
for (i = 1; i <= nbuf; i++) {
|
||||
if (urgwrite == i) {
|
||||
oob = urgwrite;
|
||||
if ( (n = send(sockfd, &oob, 1, MSG_OOB)) != 1)
|
||||
err_sys("send of MSG_OOB returned %d, expected %d",
|
||||
n, writelen);
|
||||
if (verbose)
|
||||
fprintf(stderr, "wrote %d byte of urgent data\n", n);
|
||||
}
|
||||
|
||||
if ( (n = write(sockfd, wbuf, writelen)) != writelen) {
|
||||
if (ignorewerr) {
|
||||
err_ret("write returned %d, expected %d", n, writelen);
|
||||
/* also call getsockopt() to clear so_error */
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("SO_ERROR getsockopt error");
|
||||
} else
|
||||
err_sys("write returned %d, expected %d", n, writelen);
|
||||
|
||||
} else if (verbose)
|
||||
fprintf(stderr, "wrote %d bytes\n", n);
|
||||
|
||||
if (pauserw)
|
||||
sleep_us(pauserw*1000);
|
||||
}
|
||||
|
||||
if (pauseclose) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "pausing before close\n");
|
||||
sleep_us(pauseclose*1000);
|
||||
}
|
||||
|
||||
if (close(sockfd) < 0)
|
||||
err_sys("close error"); /* since SO_LINGER may be set */
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sock.h"
|
||||
|
||||
void
|
||||
source_udp(int sockfd) /* TODO: use sendto ?? */
|
||||
{
|
||||
int i, n, option;
|
||||
socklen_t optlen;
|
||||
|
||||
pattern(wbuf, writelen); /* fill send buffer with a pattern */
|
||||
|
||||
if (pauseinit)
|
||||
sleep_us(pauseinit*1000);
|
||||
|
||||
for (i = 1; i <= nbuf; i++) {
|
||||
if (connectudp) {
|
||||
if ( (n = write(sockfd, wbuf, writelen)) != writelen) {
|
||||
if (ignorewerr) {
|
||||
err_ret("write returned %d, expected %d", n, writelen);
|
||||
/* also call getsockopt() to clear so_error */
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("SO_ERROR getsockopt error");
|
||||
} else
|
||||
err_sys("write returned %d, expected %d", n, writelen);
|
||||
}
|
||||
} else {
|
||||
if ( (n = sendto(sockfd, wbuf, writelen, 0,
|
||||
(struct sockaddr *) &servaddr,
|
||||
sizeof(struct sockaddr))) != writelen) {
|
||||
if (ignorewerr) {
|
||||
err_ret("sendto returned %d, expected %d", n, writelen);
|
||||
/* also call getsockopt() to clear so_error */
|
||||
optlen = sizeof(option);
|
||||
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
||||
&option, &optlen) < 0)
|
||||
err_sys("SO_ERROR getsockopt error");
|
||||
} else
|
||||
err_sys("sendto returned %d, expected %d", n, writelen);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "wrote %d bytes\n", n);
|
||||
|
||||
if (pauserw)
|
||||
sleep_us(pauserw*1000);
|
||||
}
|
||||
|
||||
if (pauseclose) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "pausing before close\n");
|
||||
sleep_us(pauseclose*1000);
|
||||
}
|
||||
|
||||
if (close(sockfd) < 0)
|
||||
err_sys("close error"); /* since SO_LINGER may be set */
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*- */
|
||||
#include <signal.h>
|
||||
#include "ourhdr.h"
|
||||
|
||||
static volatile sig_atomic_t sigflag;
|
||||
/* set nonzero by signal handler */
|
||||
static sigset_t newmask, oldmask, zeromask;
|
||||
|
||||
static void
|
||||
sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
|
||||
{
|
||||
sigflag = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
TELL_WAIT()
|
||||
{
|
||||
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
|
||||
err_sys("signal(SIGINT) error");
|
||||
if (signal(SIGUSR2, sig_usr) == SIG_ERR)
|
||||
err_sys("signal(SIGQUIT) error");
|
||||
|
||||
sigemptyset(&zeromask);
|
||||
|
||||
sigemptyset(&newmask);
|
||||
sigaddset(&newmask, SIGUSR1);
|
||||
sigaddset(&newmask, SIGUSR2);
|
||||
/* block SIGUSR1 and SIGUSR2, and save current signal mask */
|
||||
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
|
||||
err_sys("SIG_BLOCK error");
|
||||
}
|
||||
|
||||
void
|
||||
TELL_PARENT(pid_t pid)
|
||||
{
|
||||
kill(pid, SIGUSR2); /* tell parent we're done */
|
||||
}
|
||||
|
||||
void
|
||||
WAIT_PARENT(void)
|
||||
{
|
||||
while (sigflag == 0)
|
||||
sigsuspend(&zeromask); /* and wait for parent */
|
||||
|
||||
sigflag = 0;
|
||||
/* reset signal mask to original value */
|
||||
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
|
||||
err_sys("SIG_SETMASK error");
|
||||
}
|
||||
|
||||
void
|
||||
TELL_CHILD(pid_t pid)
|
||||
{
|
||||
kill(pid, SIGUSR1); /* tell child we're done */
|
||||
}
|
||||
|
||||
void
|
||||
WAIT_CHILD(void)
|
||||
{
|
||||
while (sigflag == 0)
|
||||
sigsuspend(&zeromask); /* and wait for child */
|
||||
|
||||
sigflag = 0;
|
||||
/* reset signal mask to original value */
|
||||
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
|
||||
err_sys("SIG_SETMASK error");
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*-
|
||||
*
|
||||
* Copyright (c) 1993 W. Richard Stevens. All rights reserved.
|
||||
* Permission to use or modify this software and its documentation only for
|
||||
* educational purposes and without fee is hereby granted, provided that
|
||||
* the above copyright notice appear in all copies. The author makes no
|
||||
* representations about the suitability of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
#ifndef UIO_MAXIOV
|
||||
#define UIO_MAXIOV 16 /* we assume this; may not be true? */
|
||||
#endif
|
||||
|
||||
ssize_t
|
||||
dowrite(int fd, const void *vptr, size_t nbytes)
|
||||
{
|
||||
struct iovec iov[UIO_MAXIOV];
|
||||
const char *ptr;
|
||||
int chunksize, i, n, nleft, nwritten, ntotal;
|
||||
|
||||
if (chunkwrite == 0 && usewritev == 0)
|
||||
return(write(fd, vptr, nbytes)); /* common case */
|
||||
|
||||
/*
|
||||
* Figure out what sized chunks to write.
|
||||
* Try to use UIO_MAXIOV chunks.
|
||||
*/
|
||||
|
||||
chunksize = nbytes / UIO_MAXIOV;
|
||||
if (chunksize <= 0)
|
||||
chunksize = 1;
|
||||
else if ((nbytes % UIO_MAXIOV) != 0)
|
||||
chunksize++;
|
||||
|
||||
ptr = vptr;
|
||||
nleft = nbytes;
|
||||
for (i = 0; i < UIO_MAXIOV; i++)
|
||||
{
|
||||
iov[i].iov_base = (void *) ptr;
|
||||
n = (nleft >= chunksize) ? chunksize : nleft;
|
||||
iov[i].iov_len = n;
|
||||
if (verbose)
|
||||
fprintf(stderr, "iov[%2d].iov_base = %x, iov[%2d].iov_len = %d\n",
|
||||
i, (u_int32_t) iov[i].iov_base, i, (int) iov[i].iov_len);
|
||||
ptr += n;
|
||||
if ((nleft -= n) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == UIO_MAXIOV)
|
||||
err_quit("i == UIO_MAXIOV");
|
||||
|
||||
if (usewritev)
|
||||
return(writev(fd, iov, i+1));
|
||||
else {
|
||||
ntotal = 0;
|
||||
for (n = 0; n <= i; n++) {
|
||||
nwritten = write(fd, iov[n].iov_base, iov[n].iov_len);
|
||||
if (nwritten != (int) iov[n].iov_len)
|
||||
return(-1);
|
||||
ntotal += nwritten;
|
||||
}
|
||||
return(ntotal);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/* -*- c-basic-offset: 8; -*- */
|
||||
/* include writen */
|
||||
#include "sock.h"
|
||||
|
||||
ssize_t /* Write "n" bytes to a descriptor. */
|
||||
writen(int fd, const void *vptr, size_t n)
|
||||
{
|
||||
size_t nleft;
|
||||
ssize_t nwritten;
|
||||
const char *ptr;
|
||||
|
||||
ptr = vptr;
|
||||
nleft = n;
|
||||
while (nleft > 0) {
|
||||
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
|
||||
if (errno == EINTR)
|
||||
nwritten = 0; /* and call write() again */
|
||||
else
|
||||
return(-1); /* error */
|
||||
}
|
||||
|
||||
nleft -= nwritten;
|
||||
ptr += nwritten;
|
||||
}
|
||||
return(n);
|
||||
}
|
||||
/* end writen */
|
||||
|
||||
Reference in New Issue
Block a user