aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorHartmut Brandt <harti@FreeBSD.org>2003-10-29 10:26:38 +0000
committerHartmut Brandt <harti@FreeBSD.org>2003-10-29 10:26:38 +0000
commitf0be771edd415413f7ae84904f5a9e557fbb482e (patch)
tree5db9c1ad9af901c6d3e5e609afebb74d97e805f7 /contrib
parente869973eeca47c8777b3ffec6f8e5afb1949aed7 (diff)
downloadsrc-f0be771edd415413f7ae84904f5a9e557fbb482e.tar.gz
src-f0be771edd415413f7ae84904f5a9e557fbb482e.zip
Virgin import of the NgATM SSCOP tool v0.9.vendor/ngatm/0.9
Notes
Notes: svn path=/vendor/ngatm/dist/; revision=121663 svn path=/vendor/ngatm/0.9/; revision=121665; tag=vendor/ngatm/0.9
Diffstat (limited to 'contrib')
-rw-r--r--contrib/ngatm/sscop/common.c431
-rw-r--r--contrib/ngatm/sscop/common.h72
-rw-r--r--contrib/ngatm/sscop/sscop.1169
-rw-r--r--contrib/ngatm/sscop/sscop_main.c435
4 files changed, 1107 insertions, 0 deletions
diff --git a/contrib/ngatm/sscop/common.c b/contrib/ngatm/sscop/common.c
new file mode 100644
index 000000000000..f1b918076f2c
--- /dev/null
+++ b/contrib/ngatm/sscop/common.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Author: Harti Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/sscop/common.c,v 1.3 2003/09/19 13:10:35 hbb Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <err.h>
+#include <isc/eventlib.h>
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscop.h>
+#include "common.h"
+
+struct timer {
+ evTimerID id;
+ struct sscop *sscop;
+ void (*func)(void *);
+};
+
+int useframe;
+int sscopframe;
+u_int sscop_vflag;
+int sscop_fd;
+int user_fd;
+int loose;
+int user_out_fd;
+u_int verbose;
+evContext evctx;
+evFileID sscop_h;
+evFileID user_h;
+
+/*
+ * This function get's called from sscop to put out verbose messages
+ */
+void
+sscop_verbose(struct sscop *sscop __unused, void *u __unused,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+void
+verb(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+/*
+ * Dump a buffer in hex to stderr.
+ */
+void
+dump_buf(const char *w, const u_char *buf, size_t len)
+{
+ u_int i;
+
+ fprintf(stderr, "%s %zu: ", w, len);
+ for(i = 0; i < len; i++) {
+ if (i % 4 == 0 && i != 0)
+ fprintf(stderr, " ");
+ fprintf(stderr, "%02x", *buf++);
+ }
+ fprintf(stderr, "\n");
+}
+
+/*
+ * SSCOP file descriptor is ready. Allocate and read one message
+ * and dispatch a signal.
+ */
+struct uni_msg *
+proto_msgin(int fd __unused)
+{
+ struct uni_msg *m = NULL;
+ ssize_t size;
+ u_int32_t flen;
+ u_int got;
+
+ if (sscopframe) {
+ if ((size = read(sscop_fd, &flen, 4)) == -1)
+ err(1, "error reading frame hdr");
+ if (size == 0) {
+ got = 0;
+ goto eof;
+ }
+ if (size != 4)
+ errx(1, "short frame header: %zd", size);
+ if ((m = uni_msg_alloc(flen)) == NULL)
+ err(1, NULL);
+ for (got = 0; got < flen; got += (size_t)size) {
+ size = read(sscop_fd, m->b_rptr + got, flen - got);
+ if (size == -1)
+ err(1, "error reading frame");
+ if (size == 0) {
+ got = 0;
+ break;
+ }
+ }
+
+ } else {
+ if ((m = uni_msg_alloc(MAXMSG)) == NULL)
+ err(1, NULL);
+ if ((size = read(sscop_fd, m->b_rptr, MAXMSG)) == -1)
+ err(1, "error reading message");
+ got = size;
+ }
+
+ if (got == 0) {
+ eof:
+ evDeselectFD(evctx, sscop_h);
+ (void)close(sscop_fd);
+ sscop_fd = -1;
+ if (m != NULL)
+ uni_msg_destroy(m);
+ VERBOSE(("EOF on sscop file descriptor"));
+ return (NULL);
+ }
+ m->b_wptr = m->b_rptr + got;
+
+ if(verbose & 0x0002)
+ dump_buf("SSCOP INPUT", m->b_rptr, got);
+
+ return (m);
+}
+
+/*
+ * User file descriptor ready - read a message
+ */
+struct uni_msg *
+user_msgin(int fd __unused)
+{
+ struct uni_msg *m = NULL;
+ ssize_t size;
+ u_int32_t flen;
+ u_int got;
+
+ if (useframe) {
+ if ((size = read(user_fd, &flen, 4)) == -1)
+ err(1, "error reading frame hdr");
+ if (size == 0) {
+ got = 0;
+ goto eof;
+ }
+ if (size != 4)
+ errx(1, "short frame header: %zd", size);
+ if ((m = uni_msg_alloc(flen)) == NULL)
+ err(1, NULL);
+ for (got = 0; got < flen; got++) {
+ size = read(user_fd, m->b_rptr + got, flen - got);
+ if (size == -1)
+ err(1, "error reading frame");
+ if (size == 0) {
+ got = 0;
+ break;
+ }
+ got += (size_t)size;
+ }
+
+ } else {
+ if ((m = uni_msg_alloc(MAXMSG)) == NULL)
+ err(1, NULL);
+ if ((size = read(user_fd, m->b_rptr, MAXMSG)) == -1)
+ err(1, "error reading message");
+ got = size;
+ }
+
+ if (size == 0) {
+ eof:
+ evDeselectFD(evctx, user_h);
+ if (m != NULL)
+ uni_msg_destroy(m);
+ VERBOSE(("EOF on user connection"));
+ return (NULL);
+ }
+ m->b_wptr = m->b_rptr + size;
+
+ return (m);
+}
+
+/*
+ * Write message to the SSCOP file descriptor.
+ * Here we have a problem: we should have a means to check how much space
+ * we have. If the pipe is full, we could declare the lower layer busy and
+ * drop the message. However, how do we know, when a message will fit?
+ * Selecting for WRITE doesn't help, because it will return even if a single
+ * byte can be written. For this reason, we switch the file descriptor to
+ * blocking mode, and hope everything is fast enough to not timeout us.
+ * Alternatively we could just drop the message. Using kevent would help here.
+ */
+void
+proto_msgout(struct uni_msg *m)
+{
+ struct iovec iov[2];
+ u_int32_t flen;
+ ssize_t size;
+ static int sent;
+ int fl;
+
+ if (verbose & 0x0002)
+ dump_buf("send", m->b_rptr, uni_msg_len(m));
+ if (loose > 0 && (sent++ % loose) == loose - 1) {
+ VERBOSE(("loosing message"));
+ uni_msg_destroy(m);
+ return;
+ }
+
+ flen = uni_msg_len(m);
+
+ iov[0].iov_len = sscopframe ? 4 : 0;
+ iov[0].iov_base = (caddr_t)&flen;
+ iov[1].iov_len = uni_msg_len(m);
+ iov[1].iov_base = m->b_rptr;
+
+ if ((fl = fcntl(sscop_fd, F_GETFL, 0)) == -1)
+ err(1, "cannot get flags for sscop fd");
+ fl &= ~O_NONBLOCK;
+ if (fcntl(sscop_fd, F_SETFL, fl) == -1)
+ err(1, "cannot set flags for sscop fd");
+
+ if ((size = writev(sscop_fd, iov, 2)) == -1)
+ err(1, "write sscop");
+ if ((size_t)size != iov[0].iov_len + iov[1].iov_len)
+ err(1, "short sscop write %zu %zu %zd",
+ iov[0].iov_len, iov[1].iov_len, size);
+
+ fl |= O_NONBLOCK;
+ if (fcntl(sscop_fd, F_SETFL, fl) == -1)
+ err(1, "cannot restore flags for sscop fd");
+
+ uni_msg_destroy(m);
+}
+
+/*
+ * output a message to the user
+ */
+void
+user_msgout(struct uni_msg *m)
+{
+ struct iovec iov[2];
+ u_int32_t flen;
+ ssize_t size;
+
+ flen = uni_msg_len(m);
+
+ iov[0].iov_len = useframe ? 4 : 0;
+ iov[0].iov_base = (caddr_t)&flen;
+ iov[1].iov_len = uni_msg_len(m);
+ iov[1].iov_base = m->b_rptr;
+
+ if ((size = writev(user_out_fd, iov, 2)) == -1)
+ err(1, "write sscop");
+ if ((size_t)size != iov[0].iov_len + iov[1].iov_len)
+ errx(1, "short sscop write");
+
+ uni_msg_destroy(m);
+}
+
+void
+parse_param(struct sscop_param *param, u_int *pmask, int opt, char *arg)
+{
+ u_int val;
+ char *end, *p;
+
+ if(opt == 'b') {
+ param->flags |= SSCOP_ROBUST;
+ *pmask |= SSCOP_SET_ROBUST;
+ return;
+ }
+ if(opt == 'x') {
+ param->flags |= SSCOP_POLLREX;
+ *pmask |= SSCOP_SET_POLLREX;
+ return;
+ }
+ if(opt == 'W') {
+ val = (u_int)strtoul(optarg, &end, 0);
+
+ if(*end != '\0')
+ errx(1, "bad number to -W '%s'", optarg);
+ if(val >= (1 << 24) - 1)
+ errx(1, "window too large: 0x%x", val);
+ param->mr = val;
+ *pmask |= SSCOP_SET_MR;
+ return;
+ }
+
+ if((p = strchr(arg, '=')) == NULL)
+ errx(1, "need '=' in argument to -%c", opt);
+ *p++ = 0;
+ if(*p == 0)
+ errx(1, "argument to -%c %s empty", opt, arg);
+ val = strtoul(p, &end, 0);
+ if(*end != 0)
+ errx(1, "bad number in -%c %s=%s", opt, arg, p);
+
+ if(opt == 't') {
+ if(strcmp(arg, "cc") == 0) {
+ param->timer_cc = val;
+ *pmask |= SSCOP_SET_TCC;
+ } else if(strcmp(arg, "poll") == 0) {
+ param->timer_poll = val;
+ *pmask |= SSCOP_SET_TPOLL;
+ } else if(strcmp(arg, "ka") == 0) {
+ param->timer_keep_alive = val;
+ *pmask |= SSCOP_SET_TKA;
+ } else if(strcmp(arg, "nr") == 0) {
+ param->timer_no_response = val;
+ *pmask |= SSCOP_SET_TNR;
+ } else if(strcmp(arg, "idle") == 0) {
+ param->timer_idle = val;
+ *pmask |= SSCOP_SET_TIDLE;
+ } else
+ errx(1, "bad timer name '%s'", arg);
+ return;
+ }
+
+ if(opt == 'a') {
+ if(strcmp(arg, "j") == 0) {
+ param->maxj = val;
+ *pmask |= SSCOP_SET_MAXJ;
+ } else if(strcmp(arg, "k") == 0) {
+ param->maxk = val;
+ *pmask |= SSCOP_SET_MAXK;
+ } else if(strcmp(arg, "cc") == 0) {
+ param->maxcc = val;
+ *pmask |= SSCOP_SET_MAXCC;
+ } else if(strcmp(arg, "pd") == 0) {
+ param->maxpd = val;
+ *pmask |= SSCOP_SET_MAXPD;
+ } else if(strcmp(arg, "stat") == 0) {
+ param->maxstat = val;
+ *pmask |= SSCOP_SET_MAXSTAT;
+ } else
+ errx(1, "bad parameter '%s'", arg);
+ return;
+ }
+
+ verb("bad flag");
+ abort();
+}
+
+static void
+tfunc(evContext ctx __unused, void *uap, struct timespec due __unused,
+ struct timespec inter __unused)
+{
+ struct timer *t = uap;
+
+ t->func(t->sscop);
+ free(t);
+}
+
+/*
+ * Start a timer
+ */
+void *
+sscop_start_timer(struct sscop *sscop, void *arg __unused, u_int msec,
+ void (*func)(void *))
+{
+ struct timer *t;
+ struct timespec due;
+
+ if ((t = malloc(sizeof(*t))) == NULL)
+ err(1, NULL);
+ t->sscop = sscop;
+ t->func = func;
+
+ due = evAddTime(evNowTime(),
+ evConsTime((time_t)msec/1000, (long)(msec%1000)*1000));
+
+ if (evSetTimer(evctx, tfunc, t, due, evConsTime(0, 0), &t->id))
+ err(1, "cannot start timer");
+
+ return (t);
+}
+
+/*
+ * Stop a timer
+ */
+void
+sscop_stop_timer(struct sscop *sscop __unused, void *arg __unused, void *tp)
+{
+ struct timer *t = tp;
+
+ evClearTimer(evctx, t->id);
+ free(t);
+}
diff --git a/contrib/ngatm/sscop/common.h b/contrib/ngatm/sscop/common.h
new file mode 100644
index 000000000000..c4b02b8619f9
--- /dev/null
+++ b/contrib/ngatm/sscop/common.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Author: Harti Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/sscop/common.h,v 1.3 2003/09/19 13:10:35 hbb Exp $
+ *
+ * Common declaration for the SAAL programs.
+ */
+#ifndef _SAAL_COMMON_H_
+#define _SAAL_COMMON_H_
+
+/*
+ * Writes to a pipe must be in messages (if we don't use framing).
+ * It is not clear, what is the maximum message size for this. It seems
+ * to be PIPE_BUF, but be conservative.
+ */
+#define MAXUSRMSG 4096
+#define MAXMSG (MAXUSRMSG+4)
+
+extern int useframe; /* use frame functions */
+extern int sscopframe; /* use sscop framing */
+extern u_int sscop_vflag; /* be talkative */
+extern int sscop_fd; /* file descriptor for SSCOP protocol */
+extern int user_fd; /* file descriptor for USER */
+extern int loose; /* loose messages */
+extern int user_out_fd; /* file descriptor for output to user */
+extern u_int verbose; /* talk to me */
+extern evContext evctx;
+extern evFileID sscop_h;
+extern evFileID user_h;
+
+void dump_buf(const char *, const u_char *, size_t);
+struct uni_msg *proto_msgin(int);
+struct uni_msg *user_msgin(int);
+void proto_msgout(struct uni_msg *);
+void user_msgout(struct uni_msg *);
+void parse_param(struct sscop_param *, u_int *, int, char *);
+
+void verb(const char *, ...) __printflike(1, 2);
+
+void sscop_verbose(struct sscop *, void *, const char *, ...)
+ __printflike(3, 4);
+void *sscop_start_timer(struct sscop *, void *, u_int, void (*)(void *));
+void sscop_stop_timer(struct sscop *, void *, void *);
+
+#define VERBOSE(P) do { if (verbose & 0x0001) verb P; } while(0)
+
+#endif /* _SAAL_COMMON_H_ */
diff --git a/contrib/ngatm/sscop/sscop.1 b/contrib/ngatm/sscop/sscop.1
new file mode 100644
index 000000000000..db718b37516b
--- /dev/null
+++ b/contrib/ngatm/sscop/sscop.1
@@ -0,0 +1,169 @@
+.\"
+.\" Copyright (c) 2001-2003
+.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Author: Harti Brandt <harti@freebsd.org>
+.\"
+.\" $Begemot: libunimsg/sscop/sscop.1,v 1.2 2003/08/21 16:01:08 hbb Exp $
+.\"
+.Dd October 28, 2003
+.Dt SSCOP 1
+.Os
+.Sh NAME
+.Nm sscop
+.Nd "SSCOP transport protocol"
+.Sh SYNOPSIS
+.Nm
+.Op Fl Fbefhirwx3
+.Op Fl V Ar X
+.Op Fl W Ar N
+.Op Fl a Ar p Ns Li = Ns Ar v
+.Op Fl l Ar N
+.Op Fl t Ar t Ns Li = Ns Ar m
+.Op Fl v Ar X
+.Sh DESCRIPTION
+The
+.Nm
+tool implements the Q.2110 transport protocol.
+Normally the program reads from standard input and sends this input over
+the SSCOP protocol on the standard output file descriptor. This means, that
+the standard output file descriptor should be connected in read-write mode.
+The program takes the
+following arguments:
+.Bl -tag -width ".It Fl a Ar p Ns Li = Ns Ar v"
+.It Fl F
+Use frameing on the SSCOP connection (see the
+.Fl f
+option).
+.It Fl V Ar X
+Set the verbose flag to the hex value
+.Ar X .
+.It Fl W Ar N
+Set the initial SSCOP window to
+.Ar N .
+.It Fl a Ar p Ns Li = Ns Ar v
+Set SSCOP parameter
+.Ar p
+to the value
+.Ar v .
+The following parameters may be set:
+.Bl -tag -width ".It Li stat Ns = Ns Ar N"
+.It Li j Ns = Ns Ar N
+Set the maximum SSCOP-UU data size to
+.Ar N
+octets.
+.It Li k Ns = Ns Ar N
+Set the maximum SSCOP SDU data size to
+.Ar N
+octets.
+.It Li cc Ns = Ns Ar N
+Set the parameter
+.Li MaxCC
+(maximum number of connection control message re-transmissions) to
+the value
+.Ar N .
+.It Li pd Ns = Ns Ar N
+Set the parameter
+.Li MaxPD
+(maximum acceptable number of outstanding unacknowledged SD PDUs before
+sending a POLL) to the value
+.Ar N .
+.It Li stat Ns = Ns Ar N
+Set the parameter
+.Li MaxSTAT
+(maximum number of elements placed in a STAT PDU) to the value
+.Ar N .
+.El
+.It Fl b
+Enable the ATM-Forum SSCOP robustness enhancement.
+.It Fl e
+Exit when there is an end of file condition on the input file or the
+SSCOP indicates a release confirmation.
+.It Fl f
+Use the framing protocol for communication over the SSCOP link. See
+.Xr frame l
+(libbegemot) for framing.
+.It Fl h
+Print a short help information and exit.
+.It Fl i
+Try not to read from the user input file descriptor. Assume that we a receiving
+only.
+.It Fl l Ar N
+Loose every Nth message. This is used for testing.
+.It Fl r
+Revert user and SSCOP file descriptors. That means, that user input and output
+is done on standard output and SSCOP input and output on standard input.
+.It Fl t Ar t Ns Li = Ns Ar m
+Set SSCOP timer
+.Ar t
+to
+.Ar m
+milliseconds. The following timers may be set:
+.Bl -tag -width ".It Li stat Ns = Ns Ar N"
+.It Li cc Ns = Ns Ar m
+Set the connection control timer to
+.Ar m .
+This timer controls the retransmission of connection control messages.
+.It Li poll Ns = Ns Ar m
+Set the poll timer to
+.Ar m .
+This timer controls the transmission of POLL messages.
+.It Li ka Ns = Ns Ar m
+Set the keep-alive timer to
+.Ar m .
+This timer controls the maximum length of the transient phase.
+.It Li nr Ns = Ns Ar m
+Set the no-response timer to
+.Ar m .
+This timer controls the maximum time between two received STAT PDUs before
+the connection is aborted.
+.It Li idle Ns = Ns Ar m
+Set the idle timer to
+.Ar m .
+This timer controls the length of the idle phase.
+.El
+.It Fl v Ar X
+Set the SSCOP library verbose flag to the hex value.
+.It Fl w
+Don't start the SSCOP protocol. Wait for a establish indication from the remote
+side.
+.It Fl x
+Enable to POLL after retransmission flag.
+.It Fl 3
+Send user output to file descriptor 3.
+.El
+.Sh EXAMPLES
+The following command line sends the file
+.Pa Makefile
+over a pipe (this depends on the feature that pipes are bi-directional):
+.Bd -literal
+cat Makefile | sscop -reF | sscop -weF
+.Ed
+.Sh SEE ALSO
+.Xr libunimsg 3
+.Sh STANDARDS
+The implemented protocol conforms to ITU-T recommendation Q.2110.
+.Sh AUTHORS
+.An Hartmut Brandt Aq harti@freebsd.org
diff --git a/contrib/ngatm/sscop/sscop_main.c b/contrib/ngatm/sscop/sscop_main.c
new file mode 100644
index 000000000000..c4265352c1e0
--- /dev/null
+++ b/contrib/ngatm/sscop/sscop_main.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2001-2003
+ * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Author: Harti Brandt <harti@freebsd.org>
+ *
+ * $Begemot: libunimsg/sscop/sscop_main.c,v 1.3 2003/09/19 13:10:35 hbb Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+#include <assert.h>
+#include <err.h>
+#include <isc/eventlib.h>
+
+#include <netnatm/unimsg.h>
+#include <netnatm/saal/sscop.h>
+#include "common.h"
+
+static int sigusr1; /* got SIGUSR1 */
+static int unidir; /* write only user */
+static int end_at_eof = 1; /* send RELEASE_request at user EOF */
+
+static volatile int ready; /* flag if connection is established */
+static volatile int finished; /* got release confirm or indication */
+
+static const char usgtxt[] = "\
+SSCOP transport protocol\n\
+Usage: sscop [-h] [-Fbefirwx3] [-ap=v] [-lN] [-tt=m] [-v X] [-V X] [-W N]\n\
+Options:\n\
+ -F use framing for sscop also\n\
+ -V X set verbose flags to hex X\n\
+ -W N set initial window to N\n\
+ -a p=v set parameter 'p' to 'v'\n\
+ -b enable robustness enhancement\n\
+ -e don't RELEASE_request on user EOF\n\
+ -f use begemot frame functions for user fd\n\
+ -h print this info\n\
+ -i use user fd only for output\n\
+ -lN loose every nth message\n\
+ -r reverse user and sscop file descriptors\n\
+ -t t=m set timer 't' to 'm' milliseconds\n\
+ -v X set sscop verbose flags to hex X\n\
+ -w don't start conversation\n\
+ -x enable POLL after retransmission\n\
+ -3 redirect output to fd 3\n\
+Timers are cc, poll, ka, nr or idle; parameters are j, k, cc, pd or stat.\n";
+
+static void sscop_send_manage(struct sscop *, void *,
+ enum sscop_maasig, struct uni_msg *, u_int, u_int);
+static void sscop_send_upper(struct sscop *, void *, enum sscop_aasig,
+ struct SSCOP_MBUF_T *, u_int);
+static void sscop_send_lower(struct sscop *, void *, struct SSCOP_MBUF_T *);
+
+static const struct sscop_funcs sscop_funcs = {
+ sscop_send_manage,
+ sscop_send_upper,
+ sscop_send_lower,
+ sscop_verbose,
+ sscop_start_timer,
+ sscop_stop_timer
+};
+
+/*
+ * SSCOP file descriptor is ready. Allocate and read one message
+ * and dispatch a signal.
+ */
+static void
+proto_infunc(evContext ctx __unused, void *uap, int fd, int mask __unused)
+{
+ struct uni_msg *m;
+
+ if ((m = proto_msgin(fd)) != NULL)
+ sscop_input((struct sscop *)uap, m);
+}
+
+/*
+ * User input. Allocate and read message and dispatch signal.
+ */
+static void
+user_infunc(evContext ctx __unused, void *uap, int fd, int mask __unused)
+{
+ struct uni_msg *m;
+
+ if ((m = user_msgin(fd)) != NULL)
+ sscop_aasig((struct sscop *)uap, SSCOP_DATA_request, m, 0);
+
+ else if (end_at_eof)
+ sscop_aasig((struct sscop *)uap, SSCOP_RELEASE_request, 0, 0);
+}
+
+static void
+onusr1(int s __unused)
+{
+ sigusr1++;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int opt;
+ struct sscop *sscop;
+ struct sscop_param param;
+ struct sigaction sa;
+ int wait = 0;
+ u_int mask;
+ evEvent ev;
+
+ /*
+ * Default is to have the USER on stdin and SSCOP on stdout
+ */
+ sscop_fd = 0;
+ user_fd = 1;
+ user_out_fd = -1;
+
+ memset(&param, 0, sizeof(param));
+ param.maxk = MAXUSRMSG;
+ param.maxj = 0;
+ param.maxcc = 4;
+ mask = SSCOP_SET_MAXK | SSCOP_SET_MAXJ | SSCOP_SET_MAXCC;
+
+ while((opt = getopt(argc, argv, "3a:befFhil:rt:v:V:wW:x")) != -1)
+ switch(opt) {
+
+ case '3':
+ user_out_fd = 3;
+ break;
+
+ case 'e':
+ end_at_eof = 0;
+ break;
+
+ case 'f':
+ useframe = 1;
+ break;
+
+ case 'F':
+ sscopframe = 1;
+ break;
+
+ case 'h':
+ fprintf(stderr, usgtxt);
+ exit(0);
+
+ case 'i':
+ unidir++;
+ break;
+
+ case 'l':
+ loose = strtoul(optarg, NULL, 0);
+ break;
+
+ case 'r':
+ sscop_fd = 1;
+ user_fd = 0;
+ break;
+
+ case 'v':
+ sscop_vflag = strtoul(optarg, NULL, 16);
+ break;
+
+ case 'V':
+ verbose = strtoul(optarg, NULL, 16);
+ break;
+
+ case 'w':
+ wait = 1;
+ break;
+
+ case 'a':
+ case 't':
+ case 'b':
+ case 'x':
+ case 'W':
+ parse_param(&param, &mask, opt, optarg);
+ break;
+ }
+
+ if(user_out_fd < 0)
+ user_out_fd = user_fd;
+
+ if (evCreate(&evctx))
+ err(1, "evCreate");
+
+ /*
+ * Catch USR1
+ */
+ sa.sa_handler = onusr1;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ if(sigaction(SIGUSR1, &sa, NULL))
+ err(1, "sigaction(SIGUSR1)");
+
+ /*
+ * Allocate and initialize SSCOP
+ */
+ if ((sscop = sscop_create(NULL, &sscop_funcs)) == NULL)
+ err(1, NULL);
+ sscop_setdebug(sscop, sscop_vflag);
+ if ((errno = sscop_setparam(sscop, &param, &mask)) != 0)
+ err(1, "can't set sscop parameters %#x", mask);
+
+ /*
+ * Register sscop fd
+ */
+ if (evSelectFD(evctx, sscop_fd, EV_READ, proto_infunc, sscop, &sscop_h))
+ err(1, "can't select on sscop fd");
+
+ /*
+ * if we are active - send establish request
+ */
+ if(!wait)
+ sscop_aasig(sscop, SSCOP_ESTABLISH_request, NULL, 1);
+
+ /*
+ * Run protocol until it get's ready
+ */
+ while (sscop_fd >= 0 && !ready) {
+ if (evGetNext(evctx, &ev, EV_WAIT) == 0) {
+ if (evDispatch(evctx, ev))
+ err(1, "dispatch event");
+ } else if (errno != EINTR)
+ err(1, "get event");
+ }
+
+ /*
+ * If this led to a closed file - exit.
+ */
+ if (sscop_fd < 0) {
+ VERBOSE(("SSCOP file descriptor closed - exiting"));
+ sscop_destroy(sscop);
+ return 0;
+ }
+
+ VERBOSE(("READY - starting data transfer"));
+
+ if (!unidir &&
+ evSelectFD(evctx, user_fd, EV_READ, user_infunc, sscop, &user_h))
+ err(1, "can't select on sscop fd");
+
+ while (!sigusr1 && sscop_fd >= 0) {
+ if (evGetNext(evctx, &ev, EV_WAIT) == 0) {
+ if (evDispatch(evctx, ev))
+ err(1, "dispatch event");
+ } else if (errno != EINTR)
+ err(1, "get event");
+ }
+
+ if (sigusr1 && sscop_fd >= 0) {
+ /*
+ * Release if we still have the connection
+ */
+ sscop_aasig(sscop, SSCOP_RELEASE_request, NULL, 0);
+ while (!finished && sscop_fd >= 0) {
+ if (evGetNext(evctx, &ev, EV_WAIT) == 0) {
+ if (evDispatch(evctx, ev))
+ err(1, "dispatch event");
+ } else if (errno != EINTR)
+ err(1, "get event");
+ }
+ }
+
+ VERBOSE(("SSCOP file descriptor closed - exiting"));
+ sscop_destroy(sscop);
+
+ return (0);
+}
+
+
+
+/*
+ * AAL OUTPUT
+ */
+static void
+sscop_send_lower(struct sscop *sscop __unused, void *arg __unused,
+ struct SSCOP_MBUF_T *m)
+{
+ proto_msgout(m);
+}
+
+
+/*
+ * Write the message to the user and move the window
+ */
+static void
+uoutput(struct sscop *sscop, struct uni_msg *m)
+{
+ user_msgout(m);
+ sscop_window(sscop, +1);
+}
+
+/*
+ * SSCOP AA-SIGNALS
+ */
+static void
+sscop_send_upper(struct sscop *sscop, void *arg __unused, enum sscop_aasig sig,
+ struct SSCOP_MBUF_T *m, u_int p __unused)
+{
+ VERBOSE(("--> got aa %d(%s)", sig, sscop_signame(sig)));
+
+ switch (sig) {
+
+ case SSCOP_RELEASE_indication:
+ if (end_at_eof) {
+ VERBOSE((" ... exiting"));
+ evDeselectFD(evctx, sscop_h);
+ (void)close(sscop_fd);
+ sscop_fd = -1;
+ }
+ finished++;
+ if (m)
+ uni_msg_destroy(m);
+ break;
+
+ case SSCOP_RELEASE_confirm:
+ if (end_at_eof) {
+ VERBOSE((" ... exiting"));
+ evDeselectFD(evctx, sscop_h);
+ (void)close(sscop_fd);
+ sscop_fd = -1;
+ }
+ finished++;
+ break;
+
+ case SSCOP_ESTABLISH_indication:
+ sscop_aasig(sscop, SSCOP_ESTABLISH_response, NULL, 1);
+ ready++;
+ if (m)
+ uni_msg_destroy(m);
+ break;
+
+ case SSCOP_ESTABLISH_confirm:
+ ready++;
+ if (m)
+ uni_msg_destroy(m);
+ break;
+
+ case SSCOP_DATA_indication:
+ assert(m != NULL);
+ uoutput(sscop, m);
+ break;
+
+ case SSCOP_UDATA_indication:
+ assert(m != NULL);
+ VERBOSE(("UDATA.indication ignored"));
+ uni_msg_destroy(m);
+ break;
+
+ case SSCOP_RECOVER_indication:
+ sscop_aasig(sscop, SSCOP_RECOVER_response, NULL, 0);
+ break;
+
+ case SSCOP_RESYNC_indication:
+ sscop_aasig(sscop, SSCOP_RESYNC_response, NULL, 0);
+ if (m)
+ uni_msg_destroy(m);
+ break;
+
+ case SSCOP_RESYNC_confirm:
+ break;
+
+ case SSCOP_RETRIEVE_indication:
+ case SSCOP_RETRIEVE_COMPL_indication:
+ warnx("Ooops. A retrieve indication");
+ abort();
+
+ case SSCOP_ESTABLISH_request:
+ case SSCOP_RELEASE_request:
+ case SSCOP_ESTABLISH_response:
+ case SSCOP_DATA_request:
+ case SSCOP_UDATA_request:
+ case SSCOP_RECOVER_response:
+ case SSCOP_RESYNC_request:
+ case SSCOP_RESYNC_response:
+ case SSCOP_RETRIEVE_request:
+ warnx("bad signal for this direction");
+ abort();
+ }
+}
+
+/*
+ * This get's called for MAAL
+ */
+static void
+sscop_send_manage(struct sscop *sscop __unused, void *arg __unused,
+ enum sscop_maasig sig, struct uni_msg *m, u_int error, u_int cnt)
+{
+ VERBOSE(("--> got maa %d(%s)", sig, sscop_msigname(sig)));
+
+ switch (sig) {
+
+ case SSCOP_MDATA_indication:
+ VERBOSE(("MDATA.indication ignored"));
+ uni_msg_destroy(m);
+ break;
+
+ case SSCOP_MERROR_indication:
+ VERBOSE(("MAAL-ERROR.indication '%c' %u", error, cnt));
+ break;
+
+ case SSCOP_MDATA_request:
+ warnx("bad signal for this direction");
+ abort();
+ }
+}