Virgin import of the NgATM SSCOP tool v0.9.
This commit is contained in:
parent
e869973eec
commit
f0be771edd
431
contrib/ngatm/sscop/common.c
Normal file
431
contrib/ngatm/sscop/common.c
Normal file
@ -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);
|
||||
}
|
72
contrib/ngatm/sscop/common.h
Normal file
72
contrib/ngatm/sscop/common.h
Normal file
@ -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_ */
|
169
contrib/ngatm/sscop/sscop.1
Normal file
169
contrib/ngatm/sscop/sscop.1
Normal file
@ -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
|
435
contrib/ngatm/sscop/sscop_main.c
Normal file
435
contrib/ngatm/sscop/sscop_main.c
Normal file
@ -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(¶m, 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(¶m, &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, ¶m, &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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user