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
main(argc,argv)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
maketoaddr()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
tisrc()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
recv_cdata(s)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
savedata(n,flags)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
checkback(fd)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
put_record(s,flags)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 }
dumpit(what,where,n)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
get_control_data(type)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
doconndata(s)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
get_altbuf(addrbuf)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
get_record(flags)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