Commit | Line | Data |
---|---|---|
a529adbe KB |
1 | /*- |
2 | * Copyright (c) 1988, 1990 The Regents of the University of California. | |
b160707d KS |
3 | * All rights reserved. |
4 | * | |
5 | * %sccs.include.redist.c% | |
6 | */ | |
a529adbe KB |
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 | ||
b160707d | 14 | #ifndef lint |
40ebfc64 | 15 | static char sccsid[] = "@(#)tisink.c 7.10 (Berkeley) %G%"; |
b160707d KS |
16 | #endif /* not lint */ |
17 | ||
18 | /* | |
63e079a3 | 19 | * This is a test program to be a sink for ISO packets. |
b160707d | 20 | */ |
40ebfc64 | 21 | #include <unistd.h> |
b160707d KS |
22 | #include <sys/param.h> |
23 | #include <sys/uio.h> | |
24 | #include <sys/socket.h> | |
25 | #include <sys/ioctl.h> | |
40ebfc64 | 26 | #include <sys/syscall.h> |
b160707d KS |
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 | |
ba17459f KS |
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 | |
b160707d | 45 | #define try(a,b,c) {x = (a b); dbprintf("%s%s returns %d\n",c,"a",x);\ |
ba17459f KS |
46 | if (x<0) {perror("a"); myexit(0);}} |
47 | #endif | |
b160707d KS |
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; | |
d21b31b2 | 54 | char **xenvp; |
b160707d | 55 | |
40ebfc64 | 56 | long size, forkp = 0, confp = 0, mynamep, verbose = 1, echop = 0; |
71fb498c | 57 | long records, intercept = 0, isode_mode = 0, dgramp = 0, tp0mode = 0; |
40ebfc64 | 58 | long dumpnodata = 0, playtag = 0, select_mode = 0; |
71fb498c | 59 | void savedata(); |
b160707d KS |
60 | |
61 | char buf[2048]; | |
62 | char your_it[] = "You're it!"; | |
40ebfc64 | 63 | fd_set readfds, exceptfds; |
b160707d KS |
64 | |
65 | char *Servername; | |
66 | ||
d21b31b2 | 67 | main(argc, argv, envp) |
b160707d KS |
68 | int argc; |
69 | char *argv[]; | |
d21b31b2 | 70 | char *envp[]; |
b160707d KS |
71 | { |
72 | register char **av = argv; | |
73 | register char *cp; | |
63e079a3 | 74 | struct iso_addr *iso_addr(); |
b160707d | 75 | |
d21b31b2 | 76 | xenvp = envp; |
b160707d KS |
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++; | |
63e079a3 | 85 | laddr.siso_addr = *iso_addr(*av); |
b160707d | 86 | argc--; |
b160707d KS |
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--; | |
ba17459f KS |
95 | } else if (strcmp(*av, "echo")==0) { |
96 | echop++; | |
896d6177 KS |
97 | } else if (strcmp(*av, "intercept")==0) { |
98 | intercept++; | |
b160707d KS |
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 | ||
140 | tisink() | |
141 | { | |
63e079a3 | 142 | int x, s, pid, on = 1, loop = 0, n, ns; |
b160707d | 143 | extern int errno; |
63e079a3 | 144 | int socktype = (dgramp ? SOCK_DGRAM : SOCK_SEQPACKET); |
71fb498c | 145 | int proto = (tp0mode ? ISOPROTO_TP0 : 0 ); |
63e079a3 | 146 | int addrlen = sizeof(faddr); |
b160707d | 147 | |
71fb498c | 148 | try(socket, (AF_ISO, socktype, proto),""); |
b160707d KS |
149 | |
150 | s = x; | |
151 | ||
152 | try(bind, (s, (struct sockaddr *) siso, siso->siso_len), ""); | |
153 | ||
154 | /*try(setsockopt, (s, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)), ""); */ | |
63e079a3 KS |
155 | if (dgramp) { |
156 | ns = s; | |
157 | goto dgram1; | |
158 | } | |
b160707d KS |
159 | |
160 | try(listen, (s, 5), ""); | |
63f88aec KS |
161 | if (intercept) { |
162 | try(setsockopt, | |
163 | (s, SOL_TRANSPORT, TPOPT_INTERCEPT, &on, sizeof(on)), ""); | |
164 | } | |
b160707d | 165 | for(;;) { |
63e079a3 | 166 | int child; |
b160707d KS |
167 | char childname[50]; |
168 | ||
71fb498c | 169 | try (accept, (s, (struct sockaddr *)&faddr, &addrlen), ""); |
b160707d KS |
170 | ns = x; |
171 | dumpit("connection from:", &faddr, sizeof faddr); | |
896d6177 | 172 | if (mynamep || intercept) { |
b160707d | 173 | addrlen = sizeof(faddr); |
71fb498c KS |
174 | try (getsockname, |
175 | (ns, (struct sockaddr *)&faddr, &addrlen), ""); | |
b160707d KS |
176 | dumpit("connected as:", &faddr, addrlen); |
177 | } | |
178 | loop++; | |
63e079a3 | 179 | if(loop > 3) myexit(0); |
b160707d KS |
180 | if (forkp) { |
181 | try(fork, (), ""); | |
182 | } else | |
183 | x = 0; | |
184 | if (x == 0) { | |
185 | long n, count = 0, cn, flags; | |
186 | records = 0; | |
187 | if (confp) { | |
188 | msghdr.msg_iovlen = 0; | |
189 | msghdr.msg_namelen = 0; | |
190 | msghdr.msg_controllen = | |
191 | cbuf.cm.cmhdr.cmsg_len = sizeof (cbuf.cm.cmhdr); | |
192 | cbuf.cm.cmhdr.cmsg_level = SOL_TRANSPORT; | |
193 | cbuf.cm.cmhdr.cmsg_type = TPOPT_CFRM_DATA; | |
194 | n = sendmsg(ns, &msghdr, 0); | |
63e079a3 | 195 | if (n < 0) { |
b160707d KS |
196 | printf("confirm: errno is %d\n", errno); |
197 | fflush(stdout); | |
198 | perror("Confirm error"); | |
199 | } else { | |
200 | dbprintf("confim ok\n"); | |
201 | } | |
40ebfc64 | 202 | sleep(3); |
b160707d | 203 | } |
d21b31b2 KS |
204 | #ifdef ISODE_MODE |
205 | if (isode_mode) { | |
206 | static char fdbuf[10]; | |
207 | static char *nargv[4] = | |
208 | {"/usr/sbin/isod.tsap", fdbuf, "", 0}; | |
209 | sprintf(fdbuf, "Z%d", ns); | |
210 | old_isod_main(3, nargv, xenvp); | |
40ebfc64 KS |
211 | myexit(0); |
212 | } | |
d21b31b2 | 213 | #endif |
b160707d | 214 | for (;;) { |
63e079a3 | 215 | dgram1: |
b160707d KS |
216 | msghdr.msg_iovlen = 1; |
217 | msghdr.msg_controllen = sizeof(control); | |
63e079a3 | 218 | msghdr.msg_namelen = (dgramp ? (sizeof name) : 0); |
b160707d | 219 | iov->iov_len = sizeof(readbuf); |
40ebfc64 KS |
220 | if (select_mode) |
221 | sel_recvwait(ns); | |
b160707d KS |
222 | n = recvmsg(ns, &msghdr, 0); |
223 | flags = msghdr.msg_flags; | |
224 | count++; | |
225 | dbprintf("recvmsg from child %d got %d ctl %d flags %x\n", | |
63e079a3 | 226 | getpid(), n, (cn = msghdr.msg_controllen), flags); |
b160707d | 227 | fflush(stdout); |
63e079a3 KS |
228 | if (dgramp && msghdr.msg_namelen && verbose) |
229 | dumpit("from:\n", name, msghdr.msg_namelen); | |
b160707d KS |
230 | if (cn && verbose) |
231 | dumpit("control data:\n", control, cn); | |
232 | if (n < 0) { | |
233 | fprintf(stderr, "errno is %d\n", errno); | |
234 | perror("recvmsg"); | |
235 | /*sleep (10);*/ | |
236 | break; | |
237 | } else { | |
238 | if (verbose) | |
239 | dumpit("data:\n", readbuf, n); | |
240 | } | |
71fb498c KS |
241 | if (echop) |
242 | savedata(n, flags); | |
243 | if (flags & MSG_EOR) { | |
b160707d | 244 | records++; |
71fb498c KS |
245 | if (echop) |
246 | answerback(ns); | |
b160707d KS |
247 | } |
248 | errno = 0; | |
249 | } | |
ba17459f | 250 | myexit(0); |
b160707d | 251 | } |
b160707d KS |
252 | } |
253 | } | |
71fb498c KS |
254 | struct savebuf { |
255 | struct savebuf *s_next; | |
256 | struct savebuf *s_prev; | |
257 | int s_n; | |
258 | int s_flags; | |
259 | } savebuf = {&savebuf, &savebuf}; | |
260 | ||
261 | void | |
262 | savedata(n, flags) | |
263 | int n, flags; | |
264 | { | |
265 | register struct savebuf *s = (struct savebuf *)malloc(n + sizeof *s); | |
266 | if (s == 0) | |
267 | return; | |
268 | insque(s, savebuf.s_prev); | |
269 | s->s_n = n; | |
270 | s->s_flags = flags; | |
271 | bcopy(readbuf, (char *)(s + 1), n); | |
272 | } | |
273 | ||
274 | answerback(ns) | |
b160707d | 275 | { |
71fb498c KS |
276 | int n; |
277 | register struct savebuf *s = savebuf.s_next, *t; | |
278 | static struct iovec iov[1]; | |
279 | static struct msghdr msghdr = { 0, 0, iov, 1, 0, 0, 0}; | |
280 | while (s != &savebuf) { | |
281 | iov->iov_len = s->s_n; | |
282 | iov->iov_base = (char *)(s + 1); | |
283 | n = sendmsg(ns, &msghdr, s->s_flags); | |
284 | dbprintf("echoed %d\n", n); | |
285 | t = s; s = s->s_next; remque(t); free((char *)t); | |
286 | } | |
b160707d KS |
287 | } |
288 | ||
289 | dumpit(what, where, n) | |
290 | char *what; unsigned short *where; int n; | |
291 | { | |
292 | unsigned short *s = where; | |
293 | unsigned short *z = where + (n+1)/2; | |
294 | int count = 0; | |
ba17459f KS |
295 | if (dumpnodata) |
296 | return; | |
b160707d KS |
297 | printf(what); |
298 | while(s < z) { | |
299 | count++; | |
300 | printf("%x ",*s++); | |
301 | if ((count & 15) == 0) | |
302 | putchar('\n'); | |
303 | } | |
304 | if (count & 15) | |
305 | putchar('\n'); | |
306 | fflush(stdout); | |
307 | } | |
308 | myexit(n) | |
309 | { | |
310 | fflush(stderr); | |
311 | printf("got %d records\n", records); | |
312 | fflush(stdout); | |
313 | exit(n); | |
314 | } | |
40ebfc64 KS |
315 | |
316 | sel_recvwait(fd) | |
317 | int fd; | |
318 | { | |
319 | int x; | |
320 | do { | |
321 | FD_ZERO(&readfds); | |
322 | FD_ZERO(&exceptfds); | |
323 | FD_SET(fd, &readfds); | |
324 | FD_SET(fd, &exceptfds); | |
325 | x = select(fd+1, &readfds, (fd_set *)0, &exceptfds, (void *)0); | |
326 | dbprintf("select returns %d\n", x); | |
327 | } while (x <= 0 || | |
328 | (FD_ISSET(fd,&readfds) == 0 && FD_ISSET(fd,&exceptfds) == 0)); | |
329 | } | |
330 | ||
331 | #include <sys/syscall.h> | |
332 | /* Here for gdb trapping */ | |
333 | setsockopt(s, level, optname, optval, optlen) | |
334 | int s, level, optname, optlen; | |
335 | const void *optval; | |
336 | { | |
337 | ||
338 | dbprintf("setsocket called s %d, level 0x%x, optname %d, optlen %d\n", | |
339 | s, level, optname, optlen); | |
340 | dumpit("", optval, optlen); | |
341 | return syscall(SYS_setsockopt, s, level, optname, optval, optlen); | |
342 | } |