149352Sbostic /*- 249352Sbostic * Copyright (c) 1988, 1990 The Regents of the University of California. 344323Ssklower * All rights reserved. 444323Ssklower * 544323Ssklower * %sccs.include.redist.c% 644323Ssklower */ 749352Sbostic 844323Ssklower #ifndef lint 949352Sbostic char copyright[] = 1049352Sbostic "@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\ 1149352Sbostic All rights reserved.\n"; 1244323Ssklower #endif /* not lint */ 1344323Ssklower 1449352Sbostic #ifndef lint 15*50891Ssklower static char sccsid[] = "@(#)tisrc.c 7.6 (Berkeley) 08/22/91"; 1649352Sbostic #endif /* not lint */ 1749352Sbostic 1844323Ssklower /* 1948713Ssklower * This is a test program to be a source for ISO transport. 2044323Ssklower */ 2144323Ssklower #include <sys/types.h> 2244323Ssklower #include <sys/socket.h> 2344323Ssklower #include <sys/uio.h> 2444323Ssklower #include <sys/ioctl.h> 2544323Ssklower #include <net/route.h> 2644323Ssklower #include <net/if.h> 2744323Ssklower #define TCPT_NTIMERS 4 2844323Ssklower #include <netiso/iso.h> 2944323Ssklower #include <netiso/tp_user.h> 3044323Ssklower 3144323Ssklower #include <stdio.h> 3244323Ssklower #include <errno.h> 3344323Ssklower #include <ctype.h> 3444323Ssklower #include <netdb.h> 3544323Ssklower 3644323Ssklower 3744323Ssklower #define dbprintf if(verbose)printf 38*50891Ssklower #ifdef __STDC__ 39*50891Ssklower #define try(a,b,c) {x = (a b); dbprintf("%s%s returns %d\n",c,#a,x);\ 40*50891Ssklower if (x<0) {perror(#a); exit(1);}} 41*50891Ssklower #else 42*50891Ssklower #define try(a,b,c) {x = (a b); dbprintf("%s%s returns %d\n",c,"a",x);\ 43*50891Ssklower if (x<0) {perror("a");exit(1);}} 44*50891Ssklower #endif 4544323Ssklower 4644323Ssklower struct iso_addr eon = {20, 0x47, 0, 6, 3, 0, 0, 0, 25 /*EGP for Berkeley*/}; 4749065Ssklower struct iso_addr *iso_addr(); 4844323Ssklower struct sockaddr_iso to_s = { sizeof(to_s), AF_ISO }, *to = &to_s; 4948713Ssklower struct sockaddr_iso old_s = { sizeof(to_s), AF_ISO }, *old = &old_s; 5048843Ssklower struct tp_conn_param tp_params; 5144323Ssklower fd_set readfds, writefds, exceptfds; 52*50891Ssklower long size, count = 0; 5344323Ssklower int verbose = 1, selectp, type = SOCK_SEQPACKET, nobuffs, errno, playtag = 0; 54*50891Ssklower int echop = 0, dgramp = 0, debug = 0, tp0mode = 0, dumpnodata = 0; 5544323Ssklower short portnumber = 3000; 5644323Ssklower char your_it[] = "You're it!"; 57*50891Ssklower char *Servername, *conndata, data_msg[8192]; 5848713Ssklower char Serverbuf[128]; 5948713Ssklower char name[128]; 6044323Ssklower struct iovec iov[1] = {data_msg}; 6144323Ssklower union { 6244323Ssklower struct { 6344323Ssklower struct cmsghdr cmhdr; 6448713Ssklower char cmdata[128 - sizeof(struct cmsghdr)]; 6544323Ssklower } cm; 6644323Ssklower char data[128]; 6744323Ssklower } cm; 6844323Ssklower struct msghdr msg = { 0, 0, iov, 1, 0, 0, 0}; 6944323Ssklower 7044323Ssklower main(argc, argv) 7144323Ssklower int argc; 7244323Ssklower char *argv[]; 7344323Ssklower { 7444323Ssklower register char **av = argv; 7544323Ssklower register char *cp; 7644323Ssklower u_long len; 7744323Ssklower int handy; 7844323Ssklower 7944323Ssklower while(--argc > 0) { 8044323Ssklower av++; 8144323Ssklower if(strcmp(*av,"Servername")==0) { 8244323Ssklower av++; 8348713Ssklower Servername = *av; 8444323Ssklower argc--; 8544323Ssklower } else if(strcmp(*av,"conndata")==0) { 8644323Ssklower av++; 8744323Ssklower conndata = *av; 8844323Ssklower argc--; 8944323Ssklower } else if(strcmp(*av,"host")==0) { 9044323Ssklower av++; 9148713Ssklower to_s.siso_addr = *iso_addr(*av); 9244323Ssklower argc--; 9344323Ssklower } else if(strcmp(*av,"port")==0) { 9444323Ssklower av++; 9544323Ssklower sscanf(*av,"%hd",&portnumber); 9644323Ssklower argc--; 9744323Ssklower } else if(strcmp(*av,"count")==0) { 9844323Ssklower av++; 9944323Ssklower sscanf(*av,"%ld",&count); 10044323Ssklower argc--; 10144323Ssklower } else if(strcmp(*av,"size")==0) { 10244323Ssklower av++; 10344323Ssklower sscanf(*av,"%ld",&size); 10444323Ssklower iov->iov_len = size; 10544323Ssklower } else if(strcmp(*av,"stream")==0) { 10644323Ssklower type = SOCK_STREAM; 107*50891Ssklower } else if (strcmp(*av, "echo")==0) { 108*50891Ssklower echop++; 10944323Ssklower } else if (strcmp(*av,"eon") == 0) { 11044323Ssklower unsigned long l, inet_addr(); 11144323Ssklower 11244323Ssklower l = inet_addr(*++av); argc--; 11344323Ssklower to_s.siso_addr = eon; 11444323Ssklower bcopy((char *)&l, &to_s.siso_data[15], 4); 11544323Ssklower } 11644323Ssklower } 11748713Ssklower maketoaddr(); 11848713Ssklower tisrc(); 11948713Ssklower } 12048713Ssklower 12148713Ssklower maketoaddr() 12248713Ssklower { 12348713Ssklower if (Servername) { 12448713Ssklower int tlen = strlen(Servername); 12548713Ssklower int len = tlen + TSEL(to) - (caddr_t) to; 12648713Ssklower if (len < sizeof(*to)) len = sizeof(*to); 12748713Ssklower if (len > to->siso_len) { 12849065Ssklower old = to; 12944323Ssklower to = (struct sockaddr_iso *)malloc(len); 13049065Ssklower *to = *old; /* We dont care if all old tsel is copied*/ 13149065Ssklower if (old != &to_s) free(old); 13244323Ssklower } 13349065Ssklower bcopy(Servername, TSEL(to), tlen); 13449065Ssklower to->siso_tlen = tlen; 13544323Ssklower } else { 13649065Ssklower to->siso_tlen = sizeof(portnumber); 13744323Ssklower portnumber = htons(portnumber); 13849065Ssklower bcopy((char *)&portnumber, TSEL(to), sizeof(portnumber)); 13944323Ssklower } 14044323Ssklower } 14144323Ssklower 14244323Ssklower tisrc() { 14348843Ssklower int x, s, pid, on = 1, flags = 8, n, proto = tp0mode ? ISOPROTO_TP0: 0; 14444323Ssklower 14548713Ssklower if (dgramp) type = SOCK_DGRAM; 14648843Ssklower try(socket, (AF_ISO, type, proto),""); 14744323Ssklower s = x; 14844323Ssklower 14948713Ssklower if (debug) 15048713Ssklower try(setsockopt, (s, SOL_SOCKET, SO_DEBUG, &on, sizeof on), ""); 15148713Ssklower if (dgramp == 0) { 15248713Ssklower if (conndata) 15348713Ssklower doconndata(s); 15448713Ssklower try(connect, (s, (struct sockaddr *) to, to->siso_len), ""); 155*50891Ssklower recv_cdata(s); 15648713Ssklower } 15744323Ssklower if (selectp) { 15844323Ssklower FD_ZERO(&writefds); FD_SET(s, &writefds); 15944323Ssklower select(1, &writefds, 0, 0, 0); 16044323Ssklower } 161*50891Ssklower do { 16244323Ssklower if (size <= 0 && get_record(&flags) == EOF) 16344323Ssklower exit(0); 16444323Ssklower n = put_record(s, flags); 16544323Ssklower if (n < iov->iov_len) { 166*50891Ssklower if (n == -1 && errno == 55) { 16744323Ssklower nobuffs++; 168*50891Ssklower if (count) ++count; 16944323Ssklower continue; 17044323Ssklower } 17144323Ssklower fprintf(stderr, "wrote %d < %d, count %d,", 17244323Ssklower n, iov->iov_len, count); 17344323Ssklower perror("due to"); 17444323Ssklower } 175*50891Ssklower } while (count == 0 || --count >= 1); 17644323Ssklower if (playtag) { 17744323Ssklower printf("Tag time!\n"); 17844323Ssklower iov->iov_base = your_it; 17944323Ssklower iov->iov_len = sizeof your_it; 18044323Ssklower sendmsg(s, &msg, MSG_EOR); 18144323Ssklower sendmsg(s, &msg, MSG_EOR); 18244323Ssklower iov->iov_base = data_msg; 18344323Ssklower iov->iov_len = sizeof data_msg; 18444323Ssklower try(recvmsg, (s, &msg, flags), " playtag "); 18544323Ssklower } 18644323Ssklower if(nobuffs) { 18744323Ssklower printf("looped %d times waiting for bufs\n", nobuffs); 18844323Ssklower } 18944323Ssklower } 190*50891Ssklower 191*50891Ssklower recv_cdata(s) 192*50891Ssklower int s; 193*50891Ssklower { 194*50891Ssklower int x; 195*50891Ssklower iov->iov_len = 0; 196*50891Ssklower msg.msg_controllen = sizeof(cm); 197*50891Ssklower msg.msg_control = (char *)&cm; 198*50891Ssklower try(recvmsg,(s, &msg, 0), "confirm data?"); 199*50891Ssklower if (msg.msg_controllen) 200*50891Ssklower dumpit("", (u_short *)&cm, msg.msg_controllen); 201*50891Ssklower msg.msg_control = 0; 202*50891Ssklower msg.msg_controllen = 0; 203*50891Ssklower } 204*50891Ssklower 20544323Ssklower int localsize; 20644323Ssklower char dupbuf[4096]; 20744323Ssklower 208*50891Ssklower struct savebuf { 209*50891Ssklower struct savebuf *s_next; 210*50891Ssklower struct savebuf *s_prev; 211*50891Ssklower int s_n; 212*50891Ssklower int s_flags; 213*50891Ssklower } savebuf = {&savebuf, &savebuf}; 214*50891Ssklower 215*50891Ssklower void 216*50891Ssklower savedata(n, flags) 217*50891Ssklower int n; 218*50891Ssklower { 219*50891Ssklower register struct savebuf *s = (struct savebuf *)malloc(n + sizeof *s); 220*50891Ssklower if (s == 0) 221*50891Ssklower return; 222*50891Ssklower insque(s, savebuf.s_prev); 223*50891Ssklower s->s_n = n; 224*50891Ssklower s->s_flags = flags; 225*50891Ssklower bcopy(iov->iov_base, (char *)(s + 1), n); 226*50891Ssklower } 227*50891Ssklower 228*50891Ssklower checkback(s) 229*50891Ssklower int s; 230*50891Ssklower { 231*50891Ssklower int n, nn; 232*50891Ssklower register struct savebuf *s = savebuf.s_next, *t; 233*50891Ssklower register char *cp = data_msg; 234*50891Ssklower while (s != &savebuf) { 235*50891Ssklower nn = s->s_n; 236*50891Ssklower do { 237*50891Ssklower msg.msg_flags = 0; 238*50891Ssklower iov->iov_len = nn; 239*50891Ssklower iov->iov_base = cp; 240*50891Ssklower n = recvmsg(s, &msg, s->s_flags); 241*50891Ssklower cp += n; 242*50891Ssklower nn -= n; 243*50891Ssklower } while (dgramp == 0 && nn > 0 && !(msg.msg_flags & MSG_EOR)); 244*50891Ssklower iov->iov_base = data_msg; 245*50891Ssklower if (dgramp) { 246*50891Ssklower if (msg.msg_namelen) 247*50891Ssklower dumpit("from: ", to, msg.msg_namelen); 248*50891Ssklower msg.msg_namelen = old->siso_len; 249*50891Ssklower } 250*50891Ssklower n = s->s_n - nn; 251*50891Ssklower dbprintf("echoed %d", n); 252*50891Ssklower if (nn) 253*50891Ssklower dbprintf(" instead of %d", s->s_n); 254*50891Ssklower if (bcmp((char *)(s + 1), data_msg, n)) 255*50891Ssklower dbprintf(", with mismatched data"); 256*50891Ssklower if (nn && (msg.msg_flags & MSG_EOR)) 257*50891Ssklower dbprintf(" and with %d unchecked after EOR", nn); 258*50891Ssklower dbprintf("\n"); 259*50891Ssklower t = s; s = s->s_next; remque(t); free((char *)t); 260*50891Ssklower } 261*50891Ssklower } 262*50891Ssklower 263*50891Ssklower 26444323Ssklower put_record(s, flags) 26544323Ssklower int s, flags; 26644323Ssklower { 26744323Ssklower char *buf; 26844323Ssklower int x, saved_x; 26944323Ssklower 27044323Ssklower msg.msg_flags = flags; 27144323Ssklower if (verbose) { 27244323Ssklower if (msg.msg_controllen) { 27344323Ssklower printf("(CMessage Type is %x) ", cm.cm.cmhdr.cmsg_type); 27448713Ssklower dumpit("CMsg data:\n", &msg.msg_control, msg.msg_controllen); 27544323Ssklower } 27644323Ssklower if (iov->iov_len) { 27744323Ssklower printf("sending: %s %s", 27844323Ssklower (flags & MSG_OOB ? "(OOB Data)" : ""), 27944323Ssklower (flags & MSG_EOR ? "(Record Mark)" : "")); 28048713Ssklower dumpit("data: ", data_msg, localsize); 28144323Ssklower } 28244323Ssklower } 283*50891Ssklower if (echop) 284*50891Ssklower savedata(iov->iov_len, flags); 28548713Ssklower if (dgramp) { 28648713Ssklower msg.msg_name = (caddr_t)to; 28748713Ssklower msg.msg_namelen = to->siso_len; 28848713Ssklower } 28944323Ssklower try(sendmsg, (s, &msg, flags), " put_record "); 29044323Ssklower saved_x = x; 291*50891Ssklower if (echop && (flags & MSG_EOR)) 292*50891Ssklower checkback(s); 29348713Ssklower bcopy(old, to, old->siso_len); 29444323Ssklower msg.msg_control = 0; 29544323Ssklower return (saved_x); 29644323Ssklower } 29748713Ssklower dumpit(what, where, n) 29848713Ssklower char *what; unsigned short *where; int n; 29948713Ssklower { 30048713Ssklower unsigned short *s = where; 30148713Ssklower unsigned short *z = where + (n+1)/2; 30248713Ssklower int count = 0; 303*50891Ssklower if (dumpnodata) 30448713Ssklower return; 30548713Ssklower printf(what); 30648713Ssklower while(s < z) { 30748713Ssklower count++; 30848713Ssklower printf("%x ",*s++); 30948713Ssklower if ((count & 15) == 0) 31048713Ssklower putchar('\n'); 31148713Ssklower } 31248713Ssklower if (count & 15) 31348713Ssklower putchar('\n'); 31448713Ssklower fflush(stdout); 31548713Ssklower } 31644323Ssklower int *datasize = &iov->iov_len; 31744323Ssklower char *cp, *cplim; 31844323Ssklower 31944323Ssklower get_control_data(type) 32044323Ssklower { 32144323Ssklower 32244323Ssklower datasize = (int *)&msg.msg_controllen; 32344323Ssklower cp = cm.cm.cmdata; 32444323Ssklower cplim = cp + sizeof(cm.cm.cmdata); 32544323Ssklower cm.cm.cmhdr.cmsg_level = SOL_TRANSPORT; 32644323Ssklower cm.cm.cmhdr.cmsg_type = type; 32744323Ssklower msg.msg_control = cm.data; 32844323Ssklower } 32944323Ssklower 33044323Ssklower doconndata(s) 33144323Ssklower { 33244323Ssklower get_control_data(TPOPT_CONN_DATA); 33344323Ssklower *datasize = strlen(conndata) + sizeof(cm.cm.cmhdr); 33444323Ssklower cm.cm.cmhdr.cmsg_len = *datasize; 33544323Ssklower bcopy(conndata, cp, *datasize); 33644323Ssklower put_record(s, 0); 33744323Ssklower } 33844323Ssklower 33948713Ssklower get_altbuf(addrbuf) 34048713Ssklower char *addrbuf; 34148713Ssklower { 34248713Ssklower if (dgramp == 0) { 34348713Ssklower printf("illegal option for stream\n"); 34448713Ssklower return 1; 34548713Ssklower } 34648713Ssklower return (scanf("%s", addrbuf) == EOF ? 1 : 0); 34748713Ssklower } 34844323Ssklower 34944323Ssklower get_record(flags) 35044323Ssklower int *flags; 35144323Ssklower { 35248713Ssklower int factor = 1, x = 0, newaddr = 0; 35348713Ssklower static repeatcount, repeatsize; 35444323Ssklower char workbuf[10240]; 35548713Ssklower char addrbuf[128]; 35644323Ssklower 35748713Ssklower if (repeatcount > 0) { 35848713Ssklower repeatcount--; 35948713Ssklower return; 36048713Ssklower } 36148713Ssklower 36244323Ssklower *flags = 0; 36344323Ssklower *datasize = 0; 36444323Ssklower datasize = &iov->iov_len; 36544323Ssklower cp = data_msg; 36644323Ssklower cplim = cp + sizeof(data_msg); 36744323Ssklower 36844323Ssklower for(;;) { 36944323Ssklower x = scanf("%s", workbuf); 37044323Ssklower if (x == EOF) 37144323Ssklower break; 37248713Ssklower if (strcmp(workbuf, "host") == 0) { 37348713Ssklower if (get_altbuf(addrbuf)) 37448713Ssklower break; 37548713Ssklower to->siso_addr = *iso_addr(addrbuf); 37648713Ssklower newaddr = 1; 37748713Ssklower } else if (strcmp(workbuf, "Servername") == 0) { 37848713Ssklower if (get_altbuf(Serverbuf)) 37948713Ssklower break; 38048713Ssklower Servername = Serverbuf; 38148713Ssklower newaddr = 1; 38248713Ssklower } else if (strcmp(workbuf, "port") == 0) { 38348713Ssklower x = scanf("%hd", &portnumber); 38448713Ssklower if (x == EOF) 38548713Ssklower break; 38648713Ssklower Servername = 0; 38748713Ssklower newaddr = 1; 38848713Ssklower } else if (strcmp(workbuf, "repeat") == 0) { 38948713Ssklower x = scanf("%d", &repeatcount); 39048713Ssklower if (repeatcount <= 0) repeatcount = 1; 39148713Ssklower repeatcount--; 39248713Ssklower if (x == EOF) 39348713Ssklower break; 39448713Ssklower } else if (strcmp(workbuf, "disc") == 0) 39544323Ssklower x = get_control_data(TPOPT_DISC_DATA); 39644323Ssklower else if (strcmp(workbuf, "cfrm") == 0) 39744323Ssklower x = get_control_data(TPOPT_CFRM_DATA); 39844323Ssklower else if (strcmp(workbuf, "oob") == 0) 39944323Ssklower *flags |= MSG_OOB; 40044323Ssklower else if (strcmp(workbuf, "eom") == 0) 40144323Ssklower *flags |= MSG_EOR; 40244323Ssklower else if (strcmp(workbuf, "factor") == 0) { 40344323Ssklower x = scanf("%d", &factor); 40444323Ssklower if (factor <= 0) factor = 1; 40544323Ssklower if (x == EOF) 40644323Ssklower break; 40744323Ssklower } else { 40844323Ssklower int len = strlen(workbuf); 40944323Ssklower localsize = 0; 41044323Ssklower while ((factor-- > 0) && 41144323Ssklower ((cp + len) < cplim)) { 41244323Ssklower strcpy(cp, workbuf); 41344323Ssklower cp += len; 41444323Ssklower localsize += len; 41544323Ssklower } 41644323Ssklower *datasize = localsize; 41744323Ssklower if (datasize != &iov->iov_len) { 41844323Ssklower *datasize += sizeof(cm.cm.cmhdr); 41948713Ssklower repeatsize = cm.cm.cmhdr.cmsg_len = *datasize; 42044323Ssklower } 42144323Ssklower break; 42244323Ssklower } 42344323Ssklower } 42444323Ssklower errno = 0; 42548713Ssklower if (newaddr) 42648713Ssklower maketoaddr(); 42744323Ssklower return (x); 42844323Ssklower } 429