* Network Interface Machine Server
extern char chartab
[128];
jmp_buf JmpBuf
; /* non-local goto buffer for interval timer */
short PtyFd
= -1, NetFd
= -1;
short TimerOn
; /* interval timer armed */
char Banner
[] = "NIM daemon\r";
char *TraceFile
; /* trace file name */
struct bufhd ptyoqueue
, netoqueue
;
struct netinfo NetInfo
= { CCITT1980
, NX29_1980_PARMS
, 128 };
char p_data
[1]; /* usually more than one byte */
* If this host doesn't support X.25, give up.
s
= socket(AF_CCITT
, SOCK_STREAM
, 0);
if (s
< 0 && errno
== EPROTONOSUPPORT
) {
fprint(2, "nimd: X.25 is not supported on this machine\n");
for (argv
++; argc
> 1; argc
--, argv
++)
for (p
= *argv
+1; *p
; p
++)
if (strcmp (*argv
, "1978") == 0) {
NetInfo
.n_nparms
= NX29_1978_PARMS
;
} else if (strcmp (*argv
, "1980") == 0) {
NetInfo
.n_nparms
= NX29_1980_PARMS
;
fatal ("1978 or 1980 expected after -c");
fatal ("trace file name expected");
fatal("usage: nimd [-c ccitt-date] [-h size] [-n size] [-t trace_file] pty_name");
fatal ("No pseudo-tty specified");
{ int tt
= open("/dev/tty", 2);
ioctl(tt
, TIOCNOTTY
, (char *)0);
packet
= getbuf (MAXPSIZ
);
signal (SIGPIPE
, SIG_IGN
);
if ((PtyFd
= open (PtyName
, 2)) < 0)
ioctl (PtyFd
, FIONBIO
, (char *)&on
);
ioctl (PtyFd
, TIOCPKT
, (char *)&on
);
ioctl (PtyFd
, TIOCREMOTE
, (char *)&on
);
select (16, (int *)0, &bits
, (int *)0, (struct timeval
*)0);
sleep (1); /* wait for pty to settle down */
if (ioctl(PtyFd
, TIOCGSUID
, &uid
) < 0) {
perror("nimd: ioctl TIOCGSUID");
if (uid
< 0 || (pw
= getpwuid(uid
)) == 0) {
message("nimd: uid %d: Who are you?\n", uid
);
strcpy(user_name
, pw
->pw_name
);
* Set effective uid to the slave
* so he/she will be charged for X.25 usage.
sleep (1); /* wait for slave to disconnect */
CloseLog(); OpenLog(); /* allow log rollover */
print ("nimd: %s\n", msg
);
message(fmt
, a1
, a2
, a3
, a4
, a5
)
sprint (buf
, fmt
, a1
, a2
, a3
, a4
, a5
);
ToPty (buf
, strlen (buf
), FROMNIM
);
errp
= x25err ((char *)0);
message ("nimd: %s\r", errp
);
* Main loop. Select from pty and network, and
* hand data to nim receiver.
int on
= 1, ibits
, obits
, first
= 1;
InitProfile (DEFAULT_PROFILE
);
log("slave connect: %s", user_name
);
* Never look for input if there's still
* stuff in the corresponding output buffer
if (NetFd
>= 0 && State
== ST_DATA
)
if (!QEMPTY(&netoqueue
) && NetFd
>= 0) {
if (ibits
== 0 && obits
== 0) /* nothing to do; go home */
if (State
& ST_COMMAND
) {
if (select (16, &ibits
, &obits
, (int *)0, &TimeOut
) <= 0) {
log ("slave inactivity timeout");
(void) select (16, &ibits
, &obits
, (int *)0, (struct timeval
*)0);
sigsetmask (1 << (SIGALRM
-1 ));
* Something to read from the network...
if (ibits
& (1 << NetFd
))
if ((len
= ReadAndTrace(NetFd
, buf
, MAXPSIZ
, "net rx")) == 0) {
if (errno
!= EWOULDBLOCK
)
* Something to read from the pty...
if (ibits
& (1 << PtyFd
))
if ((len
= ReadAndTrace (PtyFd
, buf
, NetInfo
.n_psize
+1, "pty rx")) == 0) {
if (errno
!= EWOULDBLOCK
) {
FromPty ((struct PtyPacket
*)buf
, len
);
if (obits
& (1<<NetFd
)) {
if (FlushQueue (NetFd
, &netoqueue
, "net tx") < 0 &&
if (obits
& (1 << PtyFd
))
if (FlushQueue (PtyFd
, &ptyoqueue
, "pty tx") < 0 &&
ReadAndTrace (fd
, buf
, len
, who
)
bytes
= read (fd
, buf
, len
);
NimTrace (who
, buf
, bytes
);
log ("slave disconnect");
register char *end
= str
+ len
, c
, c1
;
register struct buf
*bp
= 0;
if (CurrentX29Parms
[X29_AUX_DEV_CONTROL_CODE
]) {
if (ptyoqueue
.b_count
> 256)
if (SIZE (bp
) >= MAXPSIZ
-1) {
enqueue (bp
, &ptyoqueue
);
if (c1
!= '\r' || (lfcode
= CurrentX29Parms
[X29_LF_AFTER_CR
]) <= 0)
if ((lfcode
& 01) && from
== FROMNET
||
(lfcode
& 04) && from
== FROMPTY
||
enqueue (bp
, &ptyoqueue
);
register struct PtyPacket
*pp
;
register struct buf
*tp
= packet
;
if (pp
->p_type
!= TIOCPKT_DATA
) { /* fetch control byte */
if (State
& ST_UGLY_50_BAUD_BREAK_IN_PROGRESS
)
echo
= CurrentX29Parms
[X29_ECHO_CODE
] > 0 && ptyoqueue
.b_count
< 256;
while (cp
< ((char *)pp
)+len
) {
if (State
& ST_ESCSEEN
&& C_TYPE(c
) != C_ESCAPE
)
ToPty ("\b \b", 3, FROMPTY
);
ToPty ("*poof*\r", 7, FROMPTY
);
ToPty (tp
->b_bot
, SIZE (tp
), FROMPTY
);
if ((State
& (ST_COMMAND
|ST_ESCSEEN
)) == 0) {
if (State
& ST_COMMAND
) {
FlushQueue (PtyFd
, &ptyoqueue
, "pty tx");
if (SIZE (tp
) < MAXPSIZ
-1) {
/* ToPty ("\007", 1, FROMPTY)*/;
if (ISFORWARD(c
) || SIZE (tp
) >= NetInfo
.n_psize
) {
if (!ISEMPTY (tp
) && (State
& ST_COMMAND
) == 0)
register struct PtyPacket
*pp
;
if ((pp
->p_type
& (TIOCPKT_FLUSHWRITE
|TIOCPKT_FLUSHREAD
)) ==
(TIOCPKT_FLUSHWRITE
|TIOCPKT_FLUSHREAD
)) { /* break indication from pty */
Break (CurrentX29Parms
[X29_BREAK_PROCEDURE_CODE
]);
if (pp
->p_type
& TIOCPKT_IOCTL
) { /* some kind of set tty done by slave */
static short UnixToX29Speed
[] = {
0, 10, 5, 0, 1, 6, 8, 2, 4, 3, /* B0 thru B1200 */
12, 13, 14, 15, 16 /* B2400 thru EXTB */
ioctl(PtyFd
, TIOCGETP
, (char *)&sg
);
if (sg
.sg_ospeed
== B50
) {
State
|= ST_UGLY_50_BAUD_BREAK_IN_PROGRESS
;
CurrentX29Parms
[X29_TRANSMISSION_SPEED_CODE
]
= UnixToX29Speed
[sg
.sg_ospeed
];
if (State
& ST_UGLY_50_BAUD_BREAK_IN_PROGRESS
&& sg
.sg_ospeed
!= B50
) {
State
&= ~ST_UGLY_50_BAUD_BREAK_IN_PROGRESS
;
Break (CurrentX29Parms
[X29_BREAK_PROCEDURE_CODE
]);
State
|= ST_COMMAND
| ST_ESCCOMM
;
CurrentX29Parms
[X29_DISCARD_OUTPUT_CODE
] = 0;
message ("nimd: Call cleared - %s\r", cause
);
log ("Call cleared - %s", cause
);
register struct buf
*bp
, *tp
= packet
;
if (!ISEMPTY(tp
) && (State
& ST_COMMAND
) == 0) {
AddParity (tp
->b_bot
, SIZE (tp
));
bp
= getbuf (SIZE (tp
) + 1);
enqueue (bp
, &netoqueue
);
* round buffer size up to a multiple of 64 bytes
* to reduce accumulation of small and usually
* useless buffers in the free list. This speeds
bp
= getbuf ((len
+ 63) & ~63);
bcopy ((char *)pp
, bp
->b_bot
, len
);
bp
->b_top
= bp
->b_bot
+ len
;
enqueue (bp
, &netoqueue
);
if (TimerOn
|| (t
= CurrentX29Parms
[X29_IDLE_TIMER_CODE
]) <= 0)
itv
.it_interval
.tv_sec
= 0;
itv
.it_interval
.tv_usec
= 0;
itv
.it_value
.tv_sec
= t
/ 20;
itv
.it_value
.tv_usec
= t
% 20 * 1000000 / 20;
signal (SIGALRM
, SIG_IGN
); /* cancel possible pending signal */
signal (SIGALRM
, timeout
);
sigsetmask (1 << (SIGALRM
- 1));
setitimer (ITIMER_REAL
, &itv
, (struct itimerval
*)0);
signal (SIGALRM
, SIG_IGN
);
bzero ((char *)&itv
, sizeof (itv
));
setitimer (ITIMER_REAL
, &itv
, (struct itimerval
*)0);
if ((*bp
& Q_BIT
) == 0) {
register struct x25packet
*xp
= (struct x25packet
*)bp
;
if (CurrentX29Parms
[X29_DISCARD_OUTPUT_CODE
] == 0) {
AddParity (xp
->p_x25data
, len
- 1);
ToPty (xp
->p_x25data
, len
- 1, FROMNET
);
X29ControlMessage ((struct x29packet
*)bp
, len
);
send (NetFd
, &c
, 1, MSG_OOB
);
#ifdef fastidious /* we need stdio */
* Defining this dummy procedure prevents the stdio package
* (about 17K bytes worth) from being loaded. This program
* does not require any support from the 4.2bsd stdio library.
if(fd
<= 0 && (fd
= creat(TraceFile
, 0640)) < 0)
DisplayPacketContents (fd
, who
, bp
, n
);
if (LogDev
= rindex (PtyName
, '/'))
if ((LogFd
= open (LOGFILE
, 1)) >= 0)
LogFd
= creat (LOGFILE
, 0640);
log(fmt
, a1
, a2
, a3
, a4
, a5
)
char format
[128], *ctime ();
sprint (format
, "%s %s %s\n", DateTime
+4, LogDev
, fmt
);
lseek (LogFd
, (long)0, 2);
fprint (LogFd
, format
, a1
, a2
, a3
, a4
, a5
);
DisplayPacketContents (LogFd
, "net rx", bp
, len
);
DisplayPacketContents (fd
, from
, pp
, len
)
ConvertToOctal (pp
, len
, buf
);
fprint (fd
, "%s[%d]\t%s\n", from
, len
, buf
);
fprint (fd
, "\t\t%s\n", buf
);
ConvertToAscii (pp
, len
, buf
);
fprint (fd
, "\t\t%s\n", buf
);
ConvertToOctal (start
, len
, bp
)
register char *start
, *bp
;
for (cp
= start
; cp
- start
< len
; cp
++) {
*bp
++ = ((*cp
& 0300) >> 6) + '0';
*bp
++ = ((*cp
& 070) >> 3) + '0';
*bp
++ = (*cp
& 07) + '0';
ConvertToAscii (start
, len
, bp
)
register char *start
, *bp
;
for (cp
= start
; cp
- start
< len
; cp
++) {
if ((*cp
&0177) > ' ' && (*cp
&0177) < 0177)