summaryrefslogtreecommitdiff
path: root/usr/src/lib/libnsl/dial/interface.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libnsl/dial/interface.c
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libnsl/dial/interface.c')
-rw-r--r--usr/src/lib/libnsl/dial/interface.c507
1 files changed, 507 insertions, 0 deletions
diff --git a/usr/src/lib/libnsl/dial/interface.c b/usr/src/lib/libnsl/dial/interface.c
new file mode 100644
index 0000000000..bd69864ba7
--- /dev/null
+++ b/usr/src/lib/libnsl/dial/interface.c
@@ -0,0 +1,507 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* interface( label )
+ provide alternate definitions for the I/O functions through global
+ interfaces.
+*/
+#include "uucp.h"
+#include <rpc/trace.h>
+
+
+#ifdef TLI
+#include <tiuser.h>
+char *t_alloc();
+int t_bind(), t_close(), t_connect(), t_free(), t_look(), t_open(), t_rcvdis();
+int t_getinfo(), t_getstate(), t_look(), t_rcv(), t_snd(), t_sync(), t_unbind();
+#endif /* TLI */
+
+#ifdef DATAKIT
+#include "dk.h"
+
+static int dksetup();
+static int dkteardown();
+#endif /* DATAKIT */
+
+EXTERN void sethup();
+EXTERN int restline();
+extern ssize_t read(), write();
+static int usetup(), uteardown();
+
+GLOBAL ssize_t (*Read)() = read,
+ (*Write)() = write;
+GLOBAL int (*Ioctl)(int,int,...) = ioctl,
+ (*Setup)() = usetup,
+ (*Teardown)() = uteardown;
+
+#ifdef TLI
+EXTERN void tfaillog(int fd, const char *s);
+EXTERN void show_tlook();
+static ssize_t tread(), twrite(); /* TLI i/o */
+static int tioctl(int, int, ...),
+ tsetup(), /* TLI setup without streams module */
+ tssetup(), /* TLI setup with streams module */
+ tteardown(); /* TLI teardown, works with either setup
+ */
+#endif /* TLI */
+/* The IN_label in Interface[] imply different caller routines:
+ e.g. tlicall().
+ If so, the names here and the names in callers.c must match.
+*/
+
+static
+ struct Interface {
+ const char *IN_label; /* interface name */
+ ssize_t (*IN_read)(); /* read function */
+ ssize_t (*IN_write)(); /* write function */
+ int (*IN_ioctl)(int,int,...);
+ int (*IN_setup)(); /* setup function, called before first
+ i/o operation */
+ int (*IN_teardown)(); /* teardown function, called after last
+ i/o operation */
+} Interface[] = {
+ /* vanilla UNIX */
+ { "UNIX", read, write, ioctl, usetup, uteardown },
+#ifdef SYTEK
+ /* Sytek network */
+ { "Sytek", read, write, ioctl, usetup, uteardown },
+#endif /* Sytek network */
+#ifdef DIAL801
+ /* 801 auto dialers */
+ { "801", read, write, ioctl, usetup, uteardown },
+#endif /* DIAL801 */
+#ifdef DIAL801
+ /* 212 auto dialers */
+ { "212", read, write, ioctl, usetup, uteardown },
+#endif /* DIAL801 */
+#ifdef TLI
+ /* AT&T Transport Interface Library WITHOUT streams */
+ { "TLI", tread, twrite, tioctl, tsetup, tteardown },
+#ifdef TLIS
+ /* AT&T Transport Interface Library WITH streams */
+ { "TLIS", read, write, tioctl, tssetup, uteardown },
+#endif /* TLIS */
+#endif /* TLI */
+#ifdef DATAKIT
+ { "DK", read, write, ioctl, dksetup, dkteardown },
+#endif /* DATAKIT */
+#ifdef UNET /* this should work for 4.2BSD and 3com */
+ { "TCP", read, write, ioctl, usetup, uteardown },
+#endif
+#ifdef UNET
+ { "Unetserver", read, write, ioctl, usetup, uteardown },
+#endif
+ { 0, 0, 0, 0, 0, 0 }
+ };
+
+
+GLOBAL int
+interface(label)
+char *label;
+{
+ register int i;
+
+ trace1(TR_interface, 0);
+ for (i = 0; Interface[i].IN_label; ++i) {
+ if (!strcmp(Interface[i].IN_label, label)) {
+ Read = Interface[i].IN_read;
+ Write = Interface[i].IN_write;
+ Ioctl = Interface[i].IN_ioctl;
+ Setup = Interface[i].IN_setup;
+ Teardown = Interface[i].IN_teardown;
+ DEBUG(5, "set interface %s\n", label);
+ trace1(TR_interface, 1);
+ return (0);
+ }
+ }
+ trace1(TR_interface, 1);
+ return (FAIL);
+}
+
+/*
+ * usetup - vanilla unix setup routine
+ */
+static int
+usetup(int role, int *fdreadp, int *fdwritep)
+{
+ trace1(TR_usetup, 0);
+ if (role == SLAVE) {
+ *fdreadp = 0;
+ *fdwritep = 1;
+ /* 2 has been re-opened to RMTDEBUG in main() */
+ }
+ trace1(TR_usetup, 1);
+ return (SUCCESS);
+}
+
+/*
+ * uteardown - vanilla unix teardown routine
+ */
+static int
+uteardown(int role, int fdread, int fdwrite)
+{
+ int ret;
+ char *ttyn;
+
+ trace1(TR_uteardown, 0);
+ if (role == SLAVE) {
+ ret = restline();
+ DEBUG(4, "ret restline - %d\n", ret);
+ sethup(0);
+ }
+ if (fdread != -1) {
+ ttyn = ttyname(fdread);
+ if (ttyn != NULL)
+ chmod(ttyn, Dev_mode); /* can fail, but who cares? */
+ (void) close(fdread);
+ (void) close(fdwrite);
+ }
+ trace1(TR_uteardown, 1);
+ return (SUCCESS);
+}
+
+#ifdef DATAKIT
+/*
+ * dksetup - DATAKIT setup routine
+ *
+ * Put line in block mode.
+ */
+
+static int
+dksetup (role, fdreadp, fdwritep)
+int role;
+int * fdreadp;
+int * fdwritep;
+{
+ static short dkrmode[3] = { DKR_BLOCK | DKR_TIME, 0, 0 };
+ int ret;
+
+ trace2(TR_dksetup, 0, role);
+ (void) usetup(role, fdreadp, fdwritep);
+ if ((ret = (*Ioctl)(*fdreadp, DIOCRMODE, dkrmode)) < 0) {
+ DEBUG(4, "dksetup: failed to set block mode. ret=%d,\n", ret);
+ DEBUG(4, "read fd=%d, ", *fdreadp);
+ DEBUG(4, "errno=%d\n", errno);
+ trace1(TR_dksetup, 1);
+ return (FAIL);
+ }
+ trace1(TR_dksetup, 1);
+ return (SUCCESS);
+}
+
+/*
+ * dkteardown - DATAKIT teardown routine
+ */
+static int
+dkteardown(role, fdread, fdwrite)
+int role, fdread, fdwrite;
+{
+ char *ttyn;
+
+ trace4(TR_dkteardown, 0, role, fdread, fdwrite);
+ if (role == MASTER) {
+ ttyn = ttyname(fdread);
+ if (ttyn != NULL)
+ chmod(ttyn, Dev_mode); /* can fail, but who cares? */
+ }
+
+ /* must flush fd's for datakit */
+ /* else close can hang */
+ if (ioctl(fdread, DIOCFLUSH, NULL) != 0)
+ DEBUG(4, "dkteardown: DIOCFLUSH of input fd %d failed", fdread);
+ if (ioctl(fdwrite, DIOCFLUSH, NULL) != 0)
+ DEBUG(4, "dkteardown: DIOCFLUSH of output fd %d failed", fdwrite);
+
+ (void) close(fdread);
+ (void) close(fdwrite);
+ trace1(TR_dkteardown, 1);
+ return (SUCCESS);
+}
+#endif /* DATAKIT */
+
+
+#ifdef TLI
+/*
+ * tread - tli read routine
+ */
+static ssize_t
+tread(fd, buf, nbytes)
+int fd;
+char *buf;
+unsigned nbytes;
+{
+ int rcvflags;
+ int dummy;
+
+ trace2(TR_tread, 0, fd);
+ dummy = t_rcv(fd, buf, nbytes, &rcvflags);
+ trace1(TR_tread, 1);
+ return ((ssize_t)dummy);
+}
+
+/*
+ * twrite - tli write routine
+ */
+#define N_CHECK 100
+static ssize_t
+twrite(fd, buf, nbytes)
+int fd;
+char *buf;
+unsigned nbytes;
+{
+ register int i, ret;
+ static int n_writ, got_info;
+ static struct t_info info;
+ int dummy;
+
+ trace3(TR_twrite, 0, fd, nbytes);
+ if (got_info == 0) {
+ if (t_getinfo(fd, &info) != 0) {
+ tfaillog(fd, "twrite: t_getinfo\n");
+ trace1(TR_twrite, 1);
+ return (FAIL);
+ }
+ got_info = 1;
+ }
+
+ /* on every N_CHECKth call, check that are still in DATAXFER state */
+ if (++n_writ == N_CHECK) {
+ n_writ = 0;
+ if (t_getstate(fd) != T_DATAXFER) {
+ trace1(TR_twrite, 1);
+ return (FAIL);
+ }
+ }
+
+ if (info.tsdu <= 0 || nbytes <= info.tsdu) {
+ dummy = t_snd(fd, buf, nbytes, NULL);
+ trace1(TR_twrite, 1);
+ return ((ssize_t)dummy);
+ }
+ /* if get here, then there is a limit on transmit size */
+ /* (info.tsdu > 0) and buf exceeds it */
+ i = ret = 0;
+ while (nbytes >= info.tsdu) {
+ if ((ret = t_snd(fd, &buf[i], info.tsdu, NULL)) != info.tsdu) {
+ trace1(TR_twrite, 1);
+ return ((ssize_t)(ret >= 0 ? (i + ret) : ret));
+ }
+ i += info.tsdu;
+ nbytes -= info.tsdu;
+ }
+ if (nbytes != 0) {
+ if ((ret = t_snd(fd, &buf[i], nbytes, NULL)) != nbytes) {
+ trace1(TR_twrite, 1);
+ return ((ssize_t)(ret >= 0 ? (i + ret) : ret));
+ }
+ i += nbytes;
+ }
+ trace1(TR_twrite, 1);
+ return ((ssize_t)i);
+}
+
+/*
+ * tioctl - stub for tli ioctl routine
+ */
+/* ARGSUSED */
+static int
+#ifdef __STDC__
+tioctl(int fd, int request, ...)
+#else
+tioctl(fd, request, arg)
+int fd, request;
+#endif
+{
+ trace1(TR_tioctl, 0);
+ trace1(TR_tioctl, 1);
+ return (SUCCESS);
+}
+
+/*
+ * tsetup - tli setup routine
+ * note blatant assumption that *fdreadp == *fdwritep == 0
+ */
+static int
+tsetup(int role, int *fdreadp, int *fdwritep)
+{
+ trace1(TR_tsetup, 0);
+ if (role == SLAVE) {
+ *fdreadp = 0;
+ *fdwritep = 1;
+ /* 2 has been re-opened to RMTDEBUG in main() */
+ errno = t_errno = 0;
+ if (t_sync(*fdreadp) == -1 || t_sync(*fdwritep) == -1) {
+ tfaillog(*fdreadp, "tsetup: t_sync\n");
+ trace1(TR_tsetup, 1);
+ return (FAIL);
+ }
+ }
+ trace1(TR_tsetup, 1);
+ return (SUCCESS);
+}
+
+/*
+ * tteardown - tli shutdown routine
+ */
+/* ARGSUSED */
+static int
+tteardown(int role, int fdread, int fdwrite)
+{
+ trace1(TR_tteardown, 0);
+ (void) t_unbind(fdread);
+ (void) t_close(fdread);
+ trace1(TR_tteardown, 1);
+ return (SUCCESS);
+}
+
+#ifdef TLIS
+/*
+ * tssetup - tli, with streams module, setup routine
+ * note blatant assumption that *fdreadp == *fdwritep
+ */
+static int
+tssetup(role, fdreadp, fdwritep)
+int role;
+int *fdreadp;
+int *fdwritep;
+{
+ trace2(TR_tssetup, 0, role);
+ if (role == SLAVE) {
+ *fdreadp = 0;
+ *fdwritep = 1;
+ /* 2 has been re-opened to RMTDEBUG in main() */
+ DEBUG(5, "tssetup: SLAVE mode: leaving ok\n%s", "");
+ trace1(TR_tssetup, 1);
+ return (SUCCESS);
+ }
+
+ DEBUG(4, "tssetup: MASTER mode: leaving ok\n%s", "");
+ trace1(TR_tssetup, 1);
+ return (SUCCESS);
+}
+
+/*
+ * Report why a TLI call failed.
+ */
+GLOBAL void
+tfaillog(fd, s)
+int fd;
+const char *s;
+{
+ char fmt[ BUFSIZ ];
+
+ trace2(TR_tfaillog, 0, fd);
+ if (0 < t_errno && t_errno < t_nerr) {
+ sprintf(fmt, "%s: %%s\n", s);
+ DEBUG(5, fmt, t_errlist[t_errno]);
+ logent(s, t_errlist[t_errno]);
+ if (t_errno == TSYSERR) {
+ strcpy(fmt, "tlicall: system error: %s\n");
+ DEBUG(5, fmt, strerror(errno));
+ } else if (t_errno == TLOOK) {
+ show_tlook(fd);
+ }
+ } else {
+ sprintf(fmt, "unknown tli error %d", t_errno);
+ logent(s, fmt);
+ sprintf(fmt, "%s: unknown tli error %d", s, t_errno);
+ DEBUG(5, fmt, 0);
+ sprintf(fmt, "%s: %%s\n", s);
+ DEBUG(5, fmt, strerror(errno));
+ }
+ trace1(TR_tfaillog, 1);
+ return;
+}
+
+GLOBAL void
+show_tlook(fd)
+int fd;
+{
+ register int reason;
+ register const char *msg;
+
+/*
+ * Find out the current state of the interface.
+ */
+ trace2(TR_show_tlook, 0, fd);
+ errno = t_errno = 0;
+ switch(reason = t_getstate(fd)) {
+ case T_UNBND: msg = (const char *)"T_UNBIND"; break;
+ case T_IDLE: msg = (const char *)"T_IDLE"; break;
+ case T_OUTCON: msg = (const char *)"T_OUTCON"; break;
+ case T_INCON: msg = (const char *)"T_INCON"; break;
+ case T_DATAXFER: msg = (const char *)"T_DATAXFER"; break;
+ case T_OUTREL: msg = (const char *)"T_OUTREL"; break;
+ case T_INREL: msg = (const char *)"T_INREL"; break;
+ default: msg = NULL; break;
+ }
+ if (msg == NULL) {
+ trace1(TR_show_tlook, 1);
+ return;
+ }
+ DEBUG(5, "state is %s", msg);
+ switch(reason = t_look(fd)) {
+ case -1: msg = (const char *)""; break;
+ case 0: msg = (const char *)"NO ERROR"; break;
+ case T_LISTEN: msg = (const char *)"T_LISTEN"; break;
+ case T_CONNECT: msg = (const char *)"T_CONNECT"; break;
+ case T_DATA: msg = (const char *)"T_DATA"; break;
+ case T_EXDATA: msg = (const char *)"T_EXDATA"; break;
+ case T_DISCONNECT: msg = (const char *)"T_DISCONNECT"; break;
+ case T_ORDREL: msg = (const char *)"T_ORDREL"; break;
+ case T_ERROR: msg = (const char *)"T_ERROR"; break;
+ case T_UDERR: msg = (const char *)"T_UDERR"; break;
+ default: msg = (const char *)"UNKNOWN ERROR"; break;
+ }
+ DEBUG(4, " reason is %s\n", msg);
+
+ if (reason == T_DISCONNECT)
+ {
+ struct t_discon *dropped;
+ if (((dropped =
+ (struct t_discon *)t_alloc(fd, T_DIS, T_ALL)) == 0)
+ || (t_rcvdis(fd, dropped) == -1)) {
+ if (dropped)
+ t_free((char *)dropped, T_DIS);
+ trace1(TR_show_tlook, 1);
+ return;
+ }
+ DEBUG(5, "disconnect reason #%d\n", dropped->reason);
+ t_free((char *)dropped, T_DIS);
+ }
+ trace1(TR_show_tlook, 1);
+ return;
+}
+
+#endif /* TLIS */
+
+#endif /* TLI */