163
155
**********************************************************************
168
159
#include <errno.h>
169
160
#include <sys/types.h>
170
161
#include <sys/stat.h>
171
162
#include <sys/file.h>
172
163
#include <sys/time.h>
164
#include <sys/poll.h>
165
#include "supcdefs.h"
166
#include "supextern.h"
174
167
#include "supmsg.h"
178
172
/*************************
179
173
*** M A C R O S ***
180
174
*************************/
182
176
/* end of message */
183
#define ENDCOUNT (-1) /* end of message marker */
184
#define NULLCOUNT (-2) /* used for sending NULL pointer */
177
#define ENDCOUNT (-1) /* end of message marker */
178
#define NULLCOUNT (-2) /* used for sending NULL pointer */
186
#define RETRIES 15 /* # of times to retry io */
187
#define FILEXFER 2048 /* block transfer size */
180
#define RETRIES 15 /* # of times to retry io */
181
#define FILEXFER 2048 /* block transfer size */
188
182
#define XFERSIZE(count) ((count > FILEXFER) ? FILEXFER : count)
190
184
/*********************************************
191
185
*** G L O B A L V A R I A B L E S ***
192
186
*********************************************/
194
extern int scmerr (); /* error printing routine */
195
extern int netfile; /* network file descriptor */
197
int scmdebug; /* scm debug flag */
199
int cryptflag; /* whether to encrypt/decrypt data */
200
char *cryptbuf; /* buffer for data encryption/decryption */
202
extern char *goawayreason; /* reason for goaway message */
188
extern int netfile; /* network file descriptor */
190
int scmdebug; /* scm debug flag */
192
int cryptflag; /* whether to encrypt/decrypt data */
193
char *cryptbuf; /* buffer for data encryption/decryption */
195
extern char *goawayreason; /* reason for goaway message */
205
char b_data[FILEXFER]; /* buffered data */
206
char *b_ptr; /* pointer to end of buffer */
207
int b_cnt; /* number of bytes in buffer */
209
struct buf *bufptr; /* buffer pointer */
198
char b_data[FILEXFER]; /* buffered data */
199
char *b_ptr; /* pointer to end of buffer */
200
int b_cnt; /* number of bytes in buffer */
202
struct buf *bufptr; /* buffer pointer */
204
static int writedata(int, char *);
205
static int writeblock(int, char *);
206
static int readdata(int, char *);
207
static int readcount(int *);
212
210
/***********************************************
213
211
*** O U T P U T T O N E T W O R K ***
214
212
***********************************************/
217
writedata (count,data) /* write raw data to network */
221
register int x,tries;
222
register struct buf *bp;
215
writedata(int count, char *data)
216
{ /* write raw data to network */
225
221
if (bufptr->b_cnt + count <= FILEXFER) {
226
bcopy (data,bufptr->b_ptr,count);
222
memcpy(bufptr->b_ptr, data, count);
227
223
bufptr->b_cnt += count;
228
224
bufptr->b_ptr += count;
231
227
bp = (bufptr == buffers) ? &buffers[1] : buffers;
232
bcopy (data,bp->b_data,count);
228
memcpy(bp->b_data, data, count);
233
229
bp->b_cnt = count;
234
230
bp->b_ptr = bp->b_data + count;
235
231
data = bufptr->b_data;
244
x = write (netfile,data,count);
247
if (++tries > RETRIES) break;
240
x = write(netfile, data, count);
245
if (++tries > RETRIES)
248
247
if (scmdebug > 0)
249
logerr ("SCM Retrying failed network write");
248
logerr("SCM Retrying failed network write");
252
251
if (errno == EPIPE)
253
return (scmerr (-1,"Network write timed out"));
252
return (scmerr(-1, "Network write timed out"));
255
return (scmerr (errno,"Write error on network"));
256
return (scmerr (-1,"Write retries failed"));
254
return (scmerr(errno, "Write error on network"));
255
return (scmerr(-1, "Write retries failed"));
259
return (scmerr (-1,"Write error on network returned %d on write of %d",x,count));
258
return (scmerr(-1, "Write error on network returned %d on write of %d", x, count));
264
writeblock (count,data) /* write data block */
263
writeblock(int count, char *data)
264
{ /* write data block */
269
266
int y = byteswap(count);
271
x = writedata (sizeof(int),(char *)&y);
272
if (x == SCMOK) x = writedata (count,data);
268
x = writedata(sizeof(int), (char *) &y);
270
x = writedata(count, data);
276
writemsg (msg) /* write start of message */
276
{ /* write start of message */
281
279
if (scmdebug > 1)
282
loginfo ("SCM Writing message %d",msg);
280
loginfo("SCM Writing message %d", msg);
284
return (scmerr (-1,"Buffering already enabled"));
282
return (scmerr(-1, "Buffering already enabled"));
285
283
bufptr = buffers;
286
284
bufptr->b_ptr = bufptr->b_data;
287
285
bufptr->b_cnt = 0;
289
return (writedata(sizeof(int),(char *)&x));
287
return (writedata(sizeof(int), (char *) &x));
292
writemend () /* write end of message */
292
{ /* write end of message */
298
x = byteswap (ENDCOUNT);
299
x = writedata (sizeof(int),(char *)&x);
300
if (x != SCMOK) return (x);
297
x = byteswap(ENDCOUNT);
298
x = writedata(sizeof(int), (char *) &x);
301
301
if (bufptr == NULL)
302
return (scmerr (-1,"Buffering already disabled"));
302
return (scmerr(-1, "Buffering already disabled"));
303
303
if (bufptr->b_cnt == 0) {
307
307
data = bufptr->b_data;
308
308
count = bufptr->b_cnt;
310
return (writedata (count, data));
310
return (writedata(count, data));
313
writeint (i) /* write int as data block */
315
{ /* write int as data block */
317
317
if (scmdebug > 2)
318
loginfo ("SCM Writing integer %d",i);
318
loginfo("SCM Writing integer %d", i);
320
return (writeblock(sizeof(int),(char *)&x));
320
return (writeblock(sizeof(int), (char *) &x));
323
writestring (p) /* write string as data block */
325
{ /* write string as data block */
328
328
int y = byteswap(NULLCOUNT);
329
329
if (scmdebug > 2)
330
loginfo ("SCM Writing string NULL");
331
return (writedata (sizeof(int),(char *)&y));
330
loginfo("SCM Writing string NULL");
331
return (writedata(sizeof(int), (char *) &y));
333
333
if (scmdebug > 2)
334
loginfo ("SCM Writing string %s",p);
334
loginfo("SCM Writing string %s", p);
337
x = getcryptbuf (len+1);
337
x = getcryptbuf(len + 1);
340
encode (p,cryptbuf,len);
340
encode(p, cryptbuf, len);
343
return (writeblock(len,p));
343
return (writeblock(len, p));
346
writefile (f) /* write open file as a data block */
348
{ /* write open file as a data block */
349
349
char buf[FILEXFER];
350
register int number,sum,filesize,x;
350
int number = 0, sum = 0, filesize, x;
352
352
struct stat statbuf;
354
if (fstat(f,&statbuf) < 0)
355
return (scmerr (errno,"Can't access open file for message"));
354
if (fstat(f, &statbuf) < 0)
355
return (scmerr(errno, "Can't access open file for message"));
356
356
filesize = statbuf.st_size;
357
357
y = byteswap(filesize);
358
x = writedata (sizeof(int),(char *)&y);
358
x = writedata(sizeof(int), (char *) &y);
360
if (cryptflag) x = getcryptbuf (FILEXFER);
361
x = getcryptbuf(FILEXFER);
362
363
if (x == SCMOK) {
365
number = read (f,buf,FILEXFER);
366
number = read(f, buf, FILEXFER);
366
367
if (number > 0) {
368
encode (buf,cryptbuf,number);
369
x = writedata (number,cryptbuf);
372
x = writedata (number,buf);
369
encode(buf, cryptbuf, number);
370
x = writedata(number, cryptbuf);
372
x = writedata(number, buf);
376
376
} while (x == SCMOK && number > 0);
378
378
if (sum != filesize)
379
return (scmerr (-1,"File size error on output message"));
379
return (scmerr(-1, "File size error on output message"));
381
return (scmerr (errno,"Read error on file output message"));
385
writemnull (msg) /* write message with no data */
390
if (x == SCMOK) x = writemend ();
394
writemint (msg,i) /* write message of one int */
399
if (x == SCMOK) x = writeint (i);
400
if (x == SCMOK) x = writemend ();
404
writemstr (msg,p) /* write message of one string */
410
if (x == SCMOK) x = writestring (p);
411
if (x == SCMOK) x = writemend ();
381
return (scmerr(errno, "Read error on file output message"));
387
{ /* write message with no data */
396
writemint(int msg, int i)
397
{ /* write message of one int */
408
writemstr(int msg, char *p)
409
{ /* write message of one string */
415
418
/*************************************************
416
419
*** I N P U T F R O M N E T W O R K ***
417
420
*************************************************/
420
readdata (count,data) /* read raw data from network */
423
readdata(int count, char *data)
424
{ /* read raw data from network */
427
427
static int bufcnt = 0;
428
428
static char *bufptr;
429
429
static char buffer[FILEXFER];
431
static struct timeval timout;
430
struct pollfd set[1];
434
433
if (bufptr + count < buffer)
435
return (scmerr (-1,"No space in buffer %d",count));
434
return (scmerr(-1, "No space in buffer %d", count));
438
bcopy (data,bufptr,-count);
437
memcpy(bufptr, data, -count);
441
440
if (count == 0 && data == NULL) {
445
444
if (count <= bufcnt) {
446
bcopy (bufptr,data,count);
445
memcpy(data, bufptr, count);
451
450
if (bufcnt > 0) {
452
bcopy (bufptr,data,bufcnt);
451
memcpy(data, bufptr, bufcnt);
459
timout.tv_sec = 2*60*60;
458
set[0].events = POLLIN;
466
imask = 1 << netfile;
467
if (select(32,(fd_set *)&imask,(fd_set *)0,(fd_set *)0,&timout) < 0)
471
x = read (netfile,p,n);
473
return (scmerr (-1,"Timeout on network input"));
476
return (scmerr (-1,"Premature EOF on network input"));
478
if (++tries > RETRIES) break;
480
loginfo ("SCM Retrying failed network read");
484
return (scmerr (errno,"Read error on network"));
485
return (scmerr (-1,"Read retries failed"));
463
while ((c = poll(set, 1, 2 * 60 * 60 * 1000)) < 1) {
465
return (scmerr(-1, "Timeout on network input"));
469
x = read(netfile, p, n);
471
return (scmerr(-1, "Premature EOF on network input"));
473
return (scmerr(errno, "Read error on network"));
492
bcopy (bufptr,data,count);
479
memcpy(data, bufptr, count);
499
int readcount (count) /* read count of data block */
504
x = readdata (sizeof(int),(char *)&y);
505
if (x != SCMOK) return (x);
506
*count = byteswap(y);
510
int prereadcount (count) /* preread count of data block */
515
x = readdata (sizeof(int),(char *)&y);
516
if (x != SCMOK) return (x);
517
x = readdata (-sizeof(int),(char *)&y);
518
if (x != SCMOK) return (x);
519
*count = byteswap(y);
525
return (readdata (0, (char *)NULL));
528
readmsg (msg) /* read header for expected message */
529
int msg; /* if message is unexpected, send back SCMHUH */
486
readcount(int *count)
487
{ /* read count of data block */
490
x = readdata(sizeof(int), (char *) &y);
493
*count = byteswap(y);
498
prereadcount(int *count)
499
{ /* preread count of data block */
502
x = readdata(sizeof(int), (char *) &y);
505
x = readdata(-((int) (sizeof(int))), (char *) &y);
508
*count = byteswap(y);
515
return (readdata(0, (char *) NULL));
520
{ /* read header for expected message */
521
/* if message is unexpected, send back SCMHUH */
533
524
if (scmdebug > 1)
534
loginfo ("SCM Reading message %d",msg);
535
x = readdata (sizeof(int),(char *)&m); /* msg type */
536
if (x != SCMOK) return (x);
525
loginfo("SCM Reading message %d", msg);
526
x = readdata(sizeof(int), (char *) &m); /* msg type */
538
if (m == msg) return (x);
540
533
/* check for MSGGOAWAY in case he noticed problems first */
541
534
if (m != MSGGOAWAY)
542
return (scmerr (-1,"Received unexpected message %d",m));
543
(void) netcrypt ((char *)NULL);
544
(void) readstring (&goawayreason);
535
return (scmerr(-1, "Received unexpected message %d", m));
536
(void) netcrypt((char *) NULL);
537
(void) readstring(&goawayreason);
546
539
if (goawayreason == NULL)
548
logerr ("SCM GOAWAY %s",goawayreason);
541
logerr("SCM GOAWAY %s", goawayreason);
556
x = readdata (sizeof(int),(char *)&y);
550
x = readdata(sizeof(int), (char *) &y);
558
552
if (x == SCMOK && y != ENDCOUNT)
559
return (scmerr (-1,"Error reading end of message"));
553
return (scmerr(-1, "Error reading end of message"));
563
readskip () /* skip over one input block */
559
{ /* skip over one input block */
567
562
char buf[FILEXFER];
569
if (x != SCMOK) return (x);
571
return (scmerr (-1,"Invalid message count %d",n));
567
return (scmerr(-1, "Invalid message count %d", n));
572
568
while (x == SCMOK && n > 0) {
573
x = readdata (XFERSIZE(n),buf);
569
x = readdata(XFERSIZE(n), buf);
574
570
n -= XFERSIZE(n);
579
int readint (buf) /* read int data block */
577
{ /* read int data block */
585
if (x != SCMOK) return (x);
587
return (scmerr (-1,"Invalid message count %d",y));
584
return (scmerr(-1, "Invalid message count %d", y));
588
585
if (y != sizeof(int))
589
return (scmerr (-1,"Size error for int message is %d",y));
590
x = readdata (sizeof(int),(char *)&y);
586
return (scmerr(-1, "Size error for int message is %d", y));
587
x = readdata(sizeof(int), (char *) &y);
591
588
(*buf) = byteswap(y);
592
589
if (scmdebug > 2)
593
loginfo ("SCM Reading integer %d",*buf);
590
loginfo("SCM Reading integer %d", *buf);
597
int readstring (buf) /* read string data block */
595
readstring(char **buf)
596
{ /* read string data block */
604
x = readcount (&count);
605
if (x != SCMOK) return (x);
601
x = readcount(&count);
606
604
if (count == NULLCOUNT) {
607
605
if (scmdebug > 2)
608
loginfo ("SCM Reading string NULL");
606
loginfo("SCM Reading string NULL");
613
return (scmerr (-1,"Invalid message count %d",count));
611
return (scmerr(-1, "Invalid message count %d", count));
614
612
if (scmdebug > 3)
615
loginfo ("SCM Reading string count %d",count);
616
if ((p = (char *)malloc ((unsigned)count+1)) == NULL)
617
return (scmerr (-1,"Can't malloc %d bytes for string",count));
613
loginfo("SCM Reading string count %d", count);
614
if ((p = (char *) malloc((unsigned) count + 1)) == NULL)
615
return (scmerr(-1, "Can't malloc %d bytes for string", count));
619
x = getcryptbuf (count+1);
620
if (x == SCMOK) x = readdata (count,cryptbuf);
621
if (x != SCMOK) return (x);
623
printf ("SCM Reading encrypted string %s\n",cryptbuf);
624
decode (cryptbuf,p,count);
627
x = readdata (count,p);
628
if (x != SCMOK) return (x);
617
x = getcryptbuf(count + 1);
619
x = readdata(count, cryptbuf);
625
printf("SCM Reading encrypted string %s\n", cryptbuf);
626
decode(cryptbuf, p, count);
628
x = readdata(count, p);
630
634
p[count] = 0; /* NULL at end of string */
632
636
if (scmdebug > 2)
633
loginfo ("SCM Reading string %s",*buf);
637
loginfo("SCM Reading string %s", *buf);
637
readfile (f) /* read data block into open file */
643
{ /* read data block into open file */
642
646
char buf[FILEXFER];
645
x = getcryptbuf (FILEXFER);
646
if (x != SCMOK) return (x);
649
x = getcryptbuf(FILEXFER);
648
x = readcount (&count);
649
if (x != SCMOK) return (x);
653
x = readcount(&count);
651
return (scmerr (-1,"Invalid message count %d",count));
657
return (scmerr(-1, "Invalid message count %d", count));
652
658
while (x == SCMOK && count > 0) {
654
x = readdata (XFERSIZE(count),cryptbuf);
655
if (x == SCMOK) decode (cryptbuf,buf,XFERSIZE(count));
658
x = readdata (XFERSIZE(count),buf);
660
x = readdata(XFERSIZE(count), cryptbuf);
662
decode(cryptbuf, buf, XFERSIZE(count));
664
x = readdata(XFERSIZE(count), buf);
659
665
if (x == SCMOK) {
660
(void) write (f,buf,XFERSIZE(count));
666
(void) write(f, buf, XFERSIZE(count));
661
667
count -= XFERSIZE(count);
667
readmnull (msg) /* read null message */
672
if (x == SCMOK) x = readmend ();
676
readmint (msg,buf) /* read int message */
681
if (x == SCMOK) x = readint (buf);
682
if (x == SCMOK) x = readmend ();
686
int readmstr (msg,buf) /* read string message */
692
if (x == SCMOK) x = readstring (buf);
693
if (x == SCMOK) x = readmend ();
675
{ /* read null message */
684
readmint(int msg, int *buf)
685
{ /* read int message */
696
readmstr(int msg, char **buf)
697
{ /* read string message */
697
706
/**********************************
698
707
*** C R O S S P A T C H ***
699
708
**********************************/
703
fd_set ibits, obits, xbits;
713
struct pollfd set[2];
705
715
char buf[STRINGLENGTH];
717
set[0].fd = STDIN_FILENO;
718
set[0].events = POLLIN;
720
set[1].events = POLLIN;
712
FD_SET (netfile,&ibits);
713
if ((c = select(16, &ibits, &obits, &xbits,
714
(struct timeval *)NULL)) < 1) {
722
if ((c = poll(set, 2, INFTIM)) < 1) {
716
724
if (errno == EINTR) {
723
if (FD_ISSET (netfile,&ibits)) {
724
c = read (netfile,buf,sizeof (buf));
731
if (set[1].revents & POLLIN) {
732
c = read(netfile, buf, sizeof(buf));
725
733
if (c < 0 && errno == EWOULDBLOCK)
731
(void) write (1,buf,c);
739
(void) write(1, buf, c);
734
if (FD_ISSET(0, &ibits)) {
735
c = read (0,buf,sizeof (buf));
742
if (set[0].revents & POLLIN) {
743
c = read(0, buf, sizeof(buf));
736
744
if (c < 0 && errno == EWOULDBLOCK)
741
(void) write (netfile,buf,c);
749
(void) write(netfile, buf, c);