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[] = "@(#)tisink.c 7.11 (Berkeley) 02/25/93";
16 #endif /* not lint */
17
18 /*
19 * This is a test program to be a sink for ISO packets.
20 */
21 #include <unistd.h>
22 #include <sys/param.h>
23 #include <sys/uio.h>
24 #include <sys/socket.h>
25 #include <sys/ioctl.h>
26 #include <sys/syscall.h>
27 #include <net/route.h>
28 #include <net/if.h>
29 #define TCPT_NTIMERS 4
30 #include <netiso/iso.h>
31 #include <netiso/tp_param.h>
32 #include <netiso/tp_user.h>
33
34 #include <stdio.h>
35 #include <errno.h>
36 #include <ctype.h>
37 #include <netdb.h>
38
39
40 #define dbprintf if(verbose)printf
41 #ifdef __STDC__
42 #define try(a,b,c) {x = (a b); dbprintf("%s%s returns %d\n",c,#a,x);\
43 if (x<0) {perror(#a); myexit(0);}}
44 #else
45 #define try(a,b,c) {x = (a b); dbprintf("%s%s returns %d\n",c,"a",x);\
46 if (x<0) {perror("a"); myexit(0);}}
47 #endif
48
49
50 struct ifreq ifr;
51 short port = 3000;
52 struct sockaddr_iso faddr, laddr = { sizeof(laddr), AF_ISO };
53 struct sockaddr_iso *siso = &laddr;
54 char **xenvp;
55
56 long size, forkp = 0, confp = 0, mynamep, verbose = 1, echop = 0;
57 long records, intercept = 0, isode_mode = 0, dgramp = 0, tp0mode = 0;
58 long dumpnodata = 0, playtag = 0, select_mode = 0, tuba = 0;
59 void savedata();
60
61 char buf[2048];
62 char your_it[] = "You're it!";
63 fd_set readfds, exceptfds;
64
65 char *Servername;
66
main(argc,argv,envp)67 main(argc, argv, envp)
68 int argc;
69 char *argv[];
70 char *envp[];
71 {
72 register char **av = argv;
73 register char *cp;
74 struct iso_addr *iso_addr();
75
76 xenvp = envp;
77 while(--argc > 0) {
78 av++;
79 if(strcmp(*av,"Servername")==0) {
80 av++;
81 Servername = *av;
82 argc--;
83 } else if (strcmp(*av,"host")==0) {
84 av++;
85 laddr.siso_addr = *iso_addr(*av);
86 argc--;
87 } else if (strcmp(*av,"port")==0) {
88 av++;
89 sscanf(*av,"%hd",&port);
90 argc--;
91 } else if (strcmp(*av,"size")==0) {
92 av++;
93 sscanf(*av,"%ld",&size);
94 argc--;
95 } else if (strcmp(*av, "echo")==0) {
96 echop++;
97 } else if (strcmp(*av, "intercept")==0) {
98 intercept++;
99 }
100 }
101 if (Servername) {
102 int tlen = laddr.siso_tlen = strlen(Servername);
103 int len = TSEL(siso) + tlen - (caddr_t) &siso;
104 if (len > sizeof(*siso)) {
105 siso = (struct sockaddr_iso *)malloc(len);
106 *siso = laddr;
107 siso->siso_len = len;
108 }
109 bcopy(Servername, TSEL(siso), tlen);
110 } else {
111 port = htons(port);
112 laddr.siso_tlen = sizeof(port);
113 bcopy((char *)&port, TSEL(siso), sizeof(port));
114 }
115 tisink();
116 }
117 #define BIG 2048
118 #define MIDLIN 512
119 char readbuf[BIG];
120 struct iovec iov[1] = {
121 readbuf,
122 sizeof readbuf,
123 };
124 char name[MIDLIN];
125 union {
126 struct {
127 struct cmsghdr cmhdr;
128 char cmdata[128 - sizeof(struct cmsghdr)];
129 } cm;
130 char data[128];
131 } cbuf;
132 #define control cbuf.data
133 struct msghdr msghdr = {
134 name, sizeof(name),
135 iov, sizeof(iov)/sizeof(iov[1]),
136 control, sizeof control,
137 0 /* flags */
138 };
139
tisink()140 tisink()
141 {
142 int x, s, pid, on = 1, loop = 0, n, ns;
143 extern int errno;
144 int socktype = (dgramp ? SOCK_DGRAM :
145 (tuba ? SOCK_STREAM :SOCK_SEQPACKET));
146 int proto = (tp0mode ? ISOPROTO_TP0 : (tuba ? ISOPROTO_TCP : 0 ));
147 int addrlen = sizeof(faddr);
148
149 try(socket, (AF_ISO, socktype, proto),"");
150
151 s = x;
152
153 try(bind, (s, (struct sockaddr *) siso, siso->siso_len), "");
154
155 /*try(setsockopt, (s, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)), ""); */
156 if (dgramp) {
157 ns = s;
158 goto dgram1;
159 }
160
161 try(listen, (s, 5), "");
162 if (intercept) {
163 try(setsockopt,
164 (s, SOL_TRANSPORT, TPOPT_INTERCEPT, &on, sizeof(on)), "");
165 }
166 for(;;) {
167 int child;
168 char childname[50];
169
170 try (accept, (s, (struct sockaddr *)&faddr, &addrlen), "");
171 ns = x;
172 dumpit("connection from:", &faddr, sizeof faddr);
173 if (mynamep || intercept) {
174 addrlen = sizeof(faddr);
175 try (getsockname,
176 (ns, (struct sockaddr *)&faddr, &addrlen), "");
177 dumpit("connected as:", &faddr, addrlen);
178 }
179 loop++;
180 if(loop > 3) myexit(0);
181 if (forkp) {
182 try(fork, (), "");
183 } else
184 x = 0;
185 if (x == 0) {
186 long n, count = 0, cn, flags;
187 records = 0;
188 if (confp) {
189 msghdr.msg_iovlen = 0;
190 msghdr.msg_namelen = 0;
191 msghdr.msg_controllen =
192 cbuf.cm.cmhdr.cmsg_len = sizeof (cbuf.cm.cmhdr);
193 cbuf.cm.cmhdr.cmsg_level = SOL_TRANSPORT;
194 cbuf.cm.cmhdr.cmsg_type = TPOPT_CFRM_DATA;
195 n = sendmsg(ns, &msghdr, 0);
196 if (n < 0) {
197 printf("confirm: errno is %d\n", errno);
198 fflush(stdout);
199 perror("Confirm error");
200 } else {
201 dbprintf("confim ok\n");
202 }
203 sleep(3);
204 }
205 #ifdef ISODE_MODE
206 if (isode_mode) {
207 static char fdbuf[10];
208 static char *nargv[4] =
209 {"/usr/sbin/isod.tsap", fdbuf, "", 0};
210 sprintf(fdbuf, "Z%d", ns);
211 old_isod_main(3, nargv, xenvp);
212 myexit(0);
213 }
214 #endif
215 for (;;) {
216 dgram1:
217 msghdr.msg_iovlen = 1;
218 msghdr.msg_controllen = sizeof(control);
219 msghdr.msg_namelen = (dgramp ? (sizeof name) : 0);
220 iov->iov_len = sizeof(readbuf);
221 if (select_mode)
222 sel_recvwait(ns);
223 n = recvmsg(ns, &msghdr, 0);
224 flags = msghdr.msg_flags;
225 count++;
226 dbprintf("recvmsg from child %d got %d ctl %d flags %x\n",
227 getpid(), n, (cn = msghdr.msg_controllen), flags);
228 fflush(stdout);
229 if (dgramp && msghdr.msg_namelen && verbose)
230 dumpit("from:\n", name, msghdr.msg_namelen);
231 if (cn && verbose)
232 dumpit("control data:\n", control, cn);
233 if (n < 0) {
234 fprintf(stderr, "errno is %d\n", errno);
235 perror("recvmsg");
236 /*sleep (10);*/
237 break;
238 } else {
239 if (verbose)
240 dumpit("data:\n", readbuf, n);
241 }
242 if (echop)
243 savedata(n, flags);
244 if (flags & MSG_EOR) {
245 records++;
246 if (echop)
247 answerback(ns);
248 }
249 errno = 0;
250 }
251 myexit(0);
252 }
253 }
254 }
255 struct savebuf {
256 struct savebuf *s_next;
257 struct savebuf *s_prev;
258 int s_n;
259 int s_flags;
260 } savebuf = {&savebuf, &savebuf};
261
262 void
savedata(n,flags)263 savedata(n, flags)
264 int n, flags;
265 {
266 register struct savebuf *s = (struct savebuf *)malloc(n + sizeof *s);
267 if (s == 0)
268 return;
269 insque(s, savebuf.s_prev);
270 s->s_n = n;
271 s->s_flags = flags;
272 bcopy(readbuf, (char *)(s + 1), n);
273 }
274
answerback(ns)275 answerback(ns)
276 {
277 int n;
278 register struct savebuf *s = savebuf.s_next, *t;
279 static struct iovec iov[1];
280 static struct msghdr msghdr = { 0, 0, iov, 1, 0, 0, 0};
281 while (s != &savebuf) {
282 iov->iov_len = s->s_n;
283 iov->iov_base = (char *)(s + 1);
284 n = sendmsg(ns, &msghdr, s->s_flags);
285 dbprintf("echoed %d\n", n);
286 t = s; s = s->s_next; remque(t); free((char *)t);
287 }
288 }
289
dumpit(what,where,n)290 dumpit(what, where, n)
291 char *what; unsigned short *where; int n;
292 {
293 unsigned short *s = where;
294 unsigned short *z = where + (n+1)/2;
295 int count = 0;
296 if (dumpnodata)
297 return;
298 printf(what);
299 while(s < z) {
300 count++;
301 printf("%x ",*s++);
302 if ((count & 15) == 0)
303 putchar('\n');
304 }
305 if (count & 15)
306 putchar('\n');
307 fflush(stdout);
308 }
myexit(n)309 myexit(n)
310 {
311 fflush(stderr);
312 printf("got %d records\n", records);
313 fflush(stdout);
314 exit(n);
315 }
316
sel_recvwait(fd)317 sel_recvwait(fd)
318 int fd;
319 {
320 int x;
321 do {
322 FD_ZERO(&readfds);
323 FD_ZERO(&exceptfds);
324 FD_SET(fd, &readfds);
325 FD_SET(fd, &exceptfds);
326 x = select(fd+1, &readfds, (fd_set *)0, &exceptfds, (void *)0);
327 dbprintf("select returns %d\n", x);
328 } while (x <= 0 ||
329 (FD_ISSET(fd,&readfds) == 0 && FD_ISSET(fd,&exceptfds) == 0));
330 }
331
332 #include <sys/syscall.h>
333 /* Here for gdb trapping */
setsockopt(s,level,optname,optval,optlen)334 setsockopt(s, level, optname, optval, optlen)
335 int s, level, optname, optlen;
336 const void *optval;
337 {
338
339 dbprintf("setsocket called s %d, level 0x%x, optname %d, optlen %d\n",
340 s, level, optname, optlen);
341 dumpit("", optval, optlen);
342 return syscall(SYS_setsockopt, s, level, optname, optval, optlen);
343 }
344