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 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 : 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 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 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 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 } 309 myexit(n) 310 { 311 fflush(stderr); 312 printf("got %d records\n", records); 313 fflush(stdout); 314 exit(n); 315 } 316 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 */ 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