1 /*- 2 * Copyright (c) 1988, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)tisrc.c 7.8 (Berkeley) 02/25/93"; 16 #endif /* not lint */ 17 18 /* 19 * This is a test program to be a source for ISO transport. 20 */ 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <sys/uio.h> 24 #include <sys/ioctl.h> 25 #include <net/route.h> 26 #include <net/if.h> 27 #define TCPT_NTIMERS 4 28 #include <netiso/iso.h> 29 #include <netiso/tp_user.h> 30 31 #include <stdio.h> 32 #include <errno.h> 33 #include <ctype.h> 34 #include <netdb.h> 35 36 37 #define dbprintf if(verbose)printf 38 #ifdef __STDC__ 39 #define try(a,b,c) {x = (a b); dbprintf("%s%s returns %d\n",c,#a,x);\ 40 if (x<0) {perror(#a); exit(1);}} 41 #else 42 #define try(a,b,c) {x = (a b); dbprintf("%s%s returns %d\n",c,"a",x);\ 43 if (x<0) {perror("a");exit(1);}} 44 #endif 45 46 struct iso_addr eon = {20, 0x47, 0, 6, 3, 0, 0, 0, 25 /*EGP for Berkeley*/}; 47 struct iso_addr *iso_addr(); 48 struct sockaddr_iso to_s = { sizeof(to_s), AF_ISO }, *to = &to_s; 49 struct sockaddr_iso from_s = { sizeof(from_s), AF_ISO }, *from = 0; 50 struct sockaddr_iso old_s = { sizeof(to_s), AF_ISO }, *old = &old_s; 51 struct tp_conn_param tp_params; 52 fd_set readfds, writefds, exceptfds; 53 long size, count = 0; 54 int verbose = 1, selectp, socktype = SOCK_SEQPACKET, nobuffs, errno, playtag = 0; 55 int echop = 0, dgramp = 0, debug = 0, tp0mode = 0, dumpnodata = 0, tuba = 0; 56 short portnumber = 3000; 57 char your_it[] = "You're it!"; 58 char *Servername, *conndata, data_msg[8192]; 59 char Serverbuf[128]; 60 char name[128]; 61 struct iovec iov[1] = {data_msg}; 62 union { 63 struct { 64 struct cmsghdr cmhdr; 65 char cmdata[128 - sizeof(struct cmsghdr)]; 66 } cm; 67 char data[128]; 68 } cm; 69 struct msghdr msg = { 0, 0, iov, 1, 0, 0, 0}; 70 71 main(argc, argv) 72 int argc; 73 char *argv[]; 74 { 75 register char **av = argv; 76 register char *cp; 77 u_long len; 78 int handy; 79 80 while(--argc > 0) { 81 av++; 82 if(strcmp(*av,"Servername")==0) { 83 av++; 84 Servername = *av; 85 argc--; 86 } else if(strcmp(*av,"conndata")==0) { 87 av++; 88 conndata = *av; 89 argc--; 90 } else if(strcmp(*av,"host")==0) { 91 av++; 92 to_s.siso_addr = *iso_addr(*av); 93 argc--; 94 } else if(strcmp(*av,"from")==0) { 95 av++; 96 from_s.siso_addr = *iso_addr(*av); 97 from = &from_s; 98 argc--; 99 } else if(strcmp(*av,"port")==0) { 100 av++; 101 sscanf(*av,"%hd",&portnumber); 102 argc--; 103 } else if(strcmp(*av,"count")==0) { 104 av++; 105 sscanf(*av,"%ld",&count); 106 argc--; 107 } else if(strcmp(*av,"size")==0) { 108 av++; 109 sscanf(*av,"%ld",&size); 110 iov->iov_len = size; 111 } else if(strcmp(*av,"stream")==0) { 112 socktype = SOCK_STREAM; 113 } else if (strcmp(*av, "echo")==0) { 114 echop++; 115 } else if (strcmp(*av,"eon") == 0) { 116 unsigned long l, inet_addr(); 117 118 l = inet_addr(*++av); argc--; 119 to_s.siso_addr = eon; 120 bcopy((char *)&l, &to_s.siso_data[15], 4); 121 } 122 } 123 maketoaddr(); 124 tisrc(); 125 } 126 127 maketoaddr() 128 { 129 if (Servername) { 130 int tlen = strlen(Servername); 131 int len = tlen + TSEL(to) - (caddr_t) to; 132 if (len < sizeof(*to)) len = sizeof(*to); 133 if (len > to->siso_len) { 134 old = to; 135 to = (struct sockaddr_iso *)malloc(len); 136 *to = *old; /* We dont care if all old tsel is copied*/ 137 if (old != &to_s) free(old); 138 } 139 bcopy(Servername, TSEL(to), tlen); 140 to->siso_tlen = tlen; 141 } else { 142 to->siso_tlen = sizeof(portnumber); 143 portnumber = htons(portnumber); 144 bcopy((char *)&portnumber, TSEL(to), sizeof(portnumber)); 145 } 146 } 147 148 tisrc() { 149 int x, s, pid, on = 1, flags = 8, n; 150 int proto = (tp0mode ? ISOPROTO_TP0 : (tuba ? ISOPROTO_TCP : 0 )); 151 int socktype = (dgramp ? SOCK_DGRAM : 152 (tuba ? SOCK_STREAM :SOCK_SEQPACKET)); 153 154 try(socket, (AF_ISO, socktype, proto),""); 155 s = x; 156 157 if (debug) 158 try(setsockopt, (s, SOL_SOCKET, SO_DEBUG, &on, sizeof on), ""); 159 if (dgramp == 0) { 160 if (conndata) 161 doconndata(s); 162 if (from) { 163 try(bind, 164 (s, (struct sockaddr *)from, from->siso_len), ""); 165 } 166 try(connect, (s, (struct sockaddr *) to, to->siso_len), ""); 167 recv_cdata(s); 168 } 169 if (selectp) { 170 FD_ZERO(&writefds); FD_SET(s, &writefds); 171 select(1, &writefds, 0, 0, 0); 172 } 173 do { 174 if (size <= 0 && get_record(&flags) == EOF) 175 exit(0); 176 n = put_record(s, flags); 177 if (n < iov->iov_len) { 178 if (n == -1 && errno == 55) { 179 nobuffs++; 180 if (count) ++count; 181 continue; 182 } 183 fprintf(stderr, "wrote %d < %d, count %d,", 184 n, iov->iov_len, count); 185 perror("due to"); 186 } 187 } while (count == 0 || --count >= 1); 188 if (playtag) { 189 printf("Tag time!\n"); 190 iov->iov_base = your_it; 191 iov->iov_len = sizeof your_it; 192 sendmsg(s, &msg, MSG_EOR); 193 sendmsg(s, &msg, MSG_EOR); 194 iov->iov_base = data_msg; 195 iov->iov_len = sizeof data_msg; 196 try(recvmsg, (s, &msg, flags), " playtag "); 197 } 198 if(nobuffs) { 199 printf("looped %d times waiting for bufs\n", nobuffs); 200 } 201 } 202 203 recv_cdata(s) 204 int s; 205 { 206 int x; 207 iov->iov_len = 0; 208 msg.msg_controllen = sizeof(cm); 209 msg.msg_control = (char *)&cm; 210 try(recvmsg,(s, &msg, 0), "confirm data?"); 211 if (msg.msg_controllen) 212 dumpit("", (u_short *)&cm, msg.msg_controllen); 213 msg.msg_control = 0; 214 msg.msg_controllen = 0; 215 } 216 217 int localsize; 218 char dupbuf[4096]; 219 220 struct savebuf { 221 struct savebuf *s_next; 222 struct savebuf *s_prev; 223 int s_n; 224 int s_flags; 225 } savebuf = {&savebuf, &savebuf}; 226 227 void 228 savedata(n, flags) 229 int n; 230 { 231 register struct savebuf *s = (struct savebuf *)malloc(n + sizeof *s); 232 if (s == 0) 233 return; 234 insque(s, savebuf.s_prev); 235 s->s_n = n; 236 s->s_flags = flags; 237 bcopy(iov->iov_base, (char *)(s + 1), n); 238 } 239 240 checkback(fd) 241 int fd; 242 { 243 int n, nn; 244 register struct savebuf *s = savebuf.s_next, *t; 245 register char *cp = data_msg; 246 while (s != &savebuf) { 247 nn = s->s_n; 248 do { 249 msg.msg_flags = 0; 250 iov->iov_len = nn; 251 iov->iov_base = cp; 252 n = recvmsg(fd, &msg, 0); 253 cp += n; 254 nn -= n; 255 } while (dgramp == 0 && nn > 0 && !(msg.msg_flags & MSG_EOR)); 256 iov->iov_base = data_msg; 257 if (dgramp) { 258 if (msg.msg_namelen) 259 dumpit("from: ", to, msg.msg_namelen); 260 msg.msg_namelen = old->siso_len; 261 } 262 n = s->s_n - nn; 263 dbprintf("echoed %d", n); 264 if (nn) 265 dbprintf(" instead of %d", s->s_n); 266 if (bcmp((char *)(s + 1), data_msg, n)) 267 dbprintf(", with mismatched data"); 268 if (nn && (msg.msg_flags & MSG_EOR)) 269 dbprintf(" and with %d unchecked after EOR", nn); 270 dbprintf("\n"); 271 t = s; s = s->s_next; remque(t); free((char *)t); 272 } 273 } 274 275 276 put_record(s, flags) 277 int s, flags; 278 { 279 char *buf; 280 int x, saved_x; 281 282 msg.msg_flags = flags; 283 if (verbose) { 284 if (msg.msg_controllen) { 285 printf("(CMessage Type is %x) ", cm.cm.cmhdr.cmsg_type); 286 dumpit("CMsg data:\n", &msg.msg_control, msg.msg_controllen); 287 } 288 if (iov->iov_len) { 289 printf("sending: %s %s", 290 (flags & MSG_OOB ? "(OOB Data)" : ""), 291 (flags & MSG_EOR ? "(Record Mark)" : "")); 292 dumpit("data: ", data_msg, localsize); 293 } 294 } 295 if (echop) 296 savedata(iov->iov_len, flags); 297 if (dgramp) { 298 msg.msg_name = (caddr_t)to; 299 msg.msg_namelen = to->siso_len; 300 } 301 try(sendmsg, (s, &msg, flags), " put_record "); 302 saved_x = x; 303 if (echop && (flags & MSG_EOR)) 304 checkback(s); 305 bcopy(old, to, old->siso_len); 306 msg.msg_control = 0; 307 return (saved_x); 308 } 309 dumpit(what, where, n) 310 char *what; unsigned short *where; int n; 311 { 312 unsigned short *s = where; 313 unsigned short *z = where + (n+1)/2; 314 int count = 0; 315 if (dumpnodata) 316 return; 317 printf(what); 318 while(s < z) { 319 count++; 320 printf("%x ",*s++); 321 if ((count & 15) == 0) 322 putchar('\n'); 323 } 324 if (count & 15) 325 putchar('\n'); 326 fflush(stdout); 327 } 328 int *datasize = &iov->iov_len; 329 char *cp, *cplim; 330 331 get_control_data(type) 332 { 333 334 datasize = (int *)&msg.msg_controllen; 335 cp = cm.cm.cmdata; 336 cplim = cp + sizeof(cm.cm.cmdata); 337 cm.cm.cmhdr.cmsg_level = SOL_TRANSPORT; 338 cm.cm.cmhdr.cmsg_type = type; 339 msg.msg_control = cm.data; 340 } 341 342 doconndata(s) 343 { 344 get_control_data(TPOPT_CONN_DATA); 345 *datasize = strlen(conndata) + sizeof(cm.cm.cmhdr); 346 cm.cm.cmhdr.cmsg_len = *datasize; 347 bcopy(conndata, cp, *datasize); 348 put_record(s, 0); 349 } 350 351 get_altbuf(addrbuf) 352 char *addrbuf; 353 { 354 if (dgramp == 0) { 355 printf("illegal option for stream\n"); 356 return 1; 357 } 358 return (scanf("%s", addrbuf) == EOF ? 1 : 0); 359 } 360 361 get_record(flags) 362 int *flags; 363 { 364 int factor = 1, x = 0, newaddr = 0; 365 static repeatcount, repeatsize; 366 char workbuf[10240]; 367 char addrbuf[128]; 368 369 if (repeatcount > 0) { 370 repeatcount--; 371 return; 372 } 373 374 *flags = 0; 375 *datasize = 0; 376 datasize = &iov->iov_len; 377 cp = data_msg; 378 cplim = cp + sizeof(data_msg); 379 380 for(;;) { 381 x = scanf("%s", workbuf); 382 if (x == EOF) 383 break; 384 if (strcmp(workbuf, "host") == 0) { 385 if (get_altbuf(addrbuf)) 386 break; 387 to->siso_addr = *iso_addr(addrbuf); 388 newaddr = 1; 389 } else if (strcmp(workbuf, "Servername") == 0) { 390 if (get_altbuf(Serverbuf)) 391 break; 392 Servername = Serverbuf; 393 newaddr = 1; 394 } else if (strcmp(workbuf, "port") == 0) { 395 x = scanf("%hd", &portnumber); 396 if (x == EOF) 397 break; 398 Servername = 0; 399 newaddr = 1; 400 } else if (strcmp(workbuf, "repeat") == 0) { 401 x = scanf("%d", &repeatcount); 402 if (repeatcount <= 0) repeatcount = 1; 403 repeatcount--; 404 if (x == EOF) 405 break; 406 } else if (strcmp(workbuf, "disc") == 0) 407 x = get_control_data(TPOPT_DISC_DATA); 408 else if (strcmp(workbuf, "cfrm") == 0) 409 x = get_control_data(TPOPT_CFRM_DATA); 410 else if (strcmp(workbuf, "oob") == 0) 411 *flags |= MSG_OOB; 412 else if (strcmp(workbuf, "eom") == 0) 413 *flags |= MSG_EOR; 414 else if (strcmp(workbuf, "factor") == 0) { 415 x = scanf("%d", &factor); 416 if (factor <= 0) factor = 1; 417 if (x == EOF) 418 break; 419 } else { 420 int len = strlen(workbuf); 421 localsize = 0; 422 while ((factor-- > 0) && 423 ((cp + len) < cplim)) { 424 strcpy(cp, workbuf); 425 cp += len; 426 localsize += len; 427 } 428 *datasize = localsize; 429 if (datasize != &iov->iov_len) { 430 *datasize += sizeof(cm.cm.cmhdr); 431 repeatsize = cm.cm.cmhdr.cmsg_len = *datasize; 432 } 433 break; 434 } 435 } 436 errno = 0; 437 if (newaddr) 438 maketoaddr(); 439 return (x); 440 } 441