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