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.10 (Berkeley) 07/23/92"; 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; 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 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 140 tisink() 141 { 142 int x, s, pid, on = 1, loop = 0, n, ns; 143 extern int errno; 144 int socktype = (dgramp ? SOCK_DGRAM : SOCK_SEQPACKET); 145 int proto = (tp0mode ? ISOPROTO_TP0 : 0 ); 146 int addrlen = sizeof(faddr); 147 148 try(socket, (AF_ISO, socktype, proto),""); 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)), ""); */ 155 if (dgramp) { 156 ns = s; 157 goto dgram1; 158 } 159 160 try(listen, (s, 5), ""); 161 if (intercept) { 162 try(setsockopt, 163 (s, SOL_TRANSPORT, TPOPT_INTERCEPT, &on, sizeof(on)), ""); 164 } 165 for(;;) { 166 int child; 167 char childname[50]; 168 169 try (accept, (s, (struct sockaddr *)&faddr, &addrlen), ""); 170 ns = x; 171 dumpit("connection from:", &faddr, sizeof faddr); 172 if (mynamep || intercept) { 173 addrlen = sizeof(faddr); 174 try (getsockname, 175 (ns, (struct sockaddr *)&faddr, &addrlen), ""); 176 dumpit("connected as:", &faddr, addrlen); 177 } 178 loop++; 179 if(loop > 3) myexit(0); 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); 195 if (n < 0) { 196 printf("confirm: errno is %d\n", errno); 197 fflush(stdout); 198 perror("Confirm error"); 199 } else { 200 dbprintf("confim ok\n"); 201 } 202 sleep(3); 203 } 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); 211 myexit(0); 212 } 213 #endif 214 for (;;) { 215 dgram1: 216 msghdr.msg_iovlen = 1; 217 msghdr.msg_controllen = sizeof(control); 218 msghdr.msg_namelen = (dgramp ? (sizeof name) : 0); 219 iov->iov_len = sizeof(readbuf); 220 if (select_mode) 221 sel_recvwait(ns); 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", 226 getpid(), n, (cn = msghdr.msg_controllen), flags); 227 fflush(stdout); 228 if (dgramp && msghdr.msg_namelen && verbose) 229 dumpit("from:\n", name, msghdr.msg_namelen); 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 } 241 if (echop) 242 savedata(n, flags); 243 if (flags & MSG_EOR) { 244 records++; 245 if (echop) 246 answerback(ns); 247 } 248 errno = 0; 249 } 250 myexit(0); 251 } 252 } 253 } 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) 275 { 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 } 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; 295 if (dumpnodata) 296 return; 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 } 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 } 343