rem: int dolisten(IA *rad, USHORT rp, IA *lad, USHORT lp)
add: int dolisten(struct in_addr *rad, USHORT rp, struct in_addr *lad, USHORT lp)
context: int dolisten(IA *rad, USHORT rp, IA *lad, USHORT lp){  register int nnetfd;  register int rr;  netcat_host *whozis = NULL;  int x;  char *cp;  USHORT z;  errno = 0;/* Pass everything off to doconnect, who in opt_listen mode just gets a socket */  nnetfd = doconnect(rad, rp, lad, lp);  if (nnetfd <= 0)    return -1;  if (opt_udpmode) {		/* apparently UDP can listen ON */    if (!lp)			/* "port 0",  but that's not useful */      bail("UDP listen needs -p arg");  }  else {    rr = listen(nnetfd, 1);	/* gotta listen() before we can get */    if (rr < 0)			/* our local random port.  sheesh. */      bail("local listen fuxored");  }/* Various things that follow temporarily trash bigbuf_net, which might contain   a copy of any recvfrom()ed packet, but we'll read() another copy later. *//* I can't believe I have to do all this to get my own goddamn bound address   and port number.  It should just get filled in during bind() or something.   All this is only useful if we didn't say -p for listening, since if we   said -p we *know* what port we're listening on.  At any rate we won't bother   with it all unless we wanted to see it, although listening quietly on a   random unknown port is probably not very useful without "netstat". */  if (opt_verbose) {    x = sizeof(SA);		/* how 'bout getsockNUM instead, pinheads?! */    rr = getsockname(nnetfd, (SA *) lclend, &x);    if (rr < 0)      holler("local getsockname failed");    strcpy(bigbuf_net, "listening on [");	/* buffer reuse... */    if (lclend->sin_addr.s_addr)      strcat(bigbuf_net, inet_ntoa(lclend->sin_addr));    else      strcat(bigbuf_net, "any");    strcat(bigbuf_net, "] %d ...");    z = ntohs(lclend->sin_port);    holler(bigbuf_net, z);  }				/* verbose -- whew!! *//* UDP is a speeeeecial case -- we have to do I/O *and* get the calling   party's particulars all at once, listen() and accept() don't apply.   At least in the BSD universe, however, recvfrom/PEEK is enough to tell   us something came in, and we can set things up so straight read/write   actually does work after all.  Yow.  YMMV on strange platforms!  */  if (opt_udpmode) {    x = sizeof(SA);		/* retval for recvfrom */    arm(2, o_wait);		/* might as well timeout this, too */    if (setjmp(jbuf) == 0) {	/* do timeout for initial connect */      rr = recvfrom		/* and here we block... */	(nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend, &x);    Debug(("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net))}    else      goto dol_tmo;		/* timeout */    arm(0, 0);/* I'm not completely clear on how this works -- BSD seems to make UDP   just magically work in a connect()ed context, but we'll undoubtedly run   into systems this deal doesn't work on.  For now, we apparently have to   issue a connect() on our just-tickled socket so we can write() back.   Again, why the fuck doesn't it just get filled in and taken care of?!   This hack is anything but optimal.  Basically, if you want your listener   to also be able to send data back, you need this connect() line, which   also has the side effect that now anything from a different source or even a   different port on the other end won't show up and will cause ICMP errors.   I guess that's what they meant by "connect".   Let's try to remember what the "U" is *really* for, eh? */    rr = connect(nnetfd, (SA *) remend, sizeof(SA));    goto whoisit;  }				/* opt_udpmode *//* fall here for TCP */  x = sizeof(SA);		/* retval for accept */  arm(2, o_wait);		/* wrap this in a timer, too; 0 = forever */  if (setjmp(jbuf) == 0) {    rr = accept(nnetfd, (SA *) remend, &x);  }  else    goto dol_tmo;		/* timeout */  arm(0, 0);  close(nnetfd);		/* dump the old socket */  nnetfd = rr;			/* here's our new one */whoisit:  if (rr < 0)    goto dol_err;		/* bail out if any errors so far *//* If we can, look for any IP options.  Useful for testing the receiving end of   such things, and is a good exercise in dealing with it.  We do this before   the connect message, to ensure that the connect msg is uniformly the LAST   thing to emerge after all the intervening crud.  Doesn't work for UDP on   any machines I've tested, but feel free to surprise me. */#ifdef IP_OPTIONS  if (!opt_verbose)		/* if we wont see it, we dont care */    goto dol_noop;  optbuf = Hmalloc(40);  x = 40;  rr = getsockopt(nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x);  if (rr < 0)    holler("getsockopt failed");  Debug(("ipoptions ret len %d", x)) if (x) {	/* we've got options, lessee em... */    unsigned char *q = (unsigned char *) optbuf;    char *p = bigbuf_net;	/* local variables, yuk! */    char *pp = &bigbuf_net[128];	/* get random space farther out... */    memset(bigbuf_net, 0, 256);	/* clear it all first */    while (x > 0) {      sprintf(pp, "%2.2x ", *q);	/* clumsy, but works: turn into hex */      strcat(p, pp);		/* and build the final string */      q++;      p++;      x--;    }    holler("IP options: %s", bigbuf_net);  }				/* if x, i.e. any options */dol_noop:#endif /* IP_OPTIONS *//* find out what address the connection was *to* on our end, in case we're   doing a listen-on-any on a multihomed machine.  This allows one to   offer different services via different alias addresses, such as the   "virtual web site" hack. */  memset(bigbuf_net, 0, 64);  cp = &bigbuf_net[32];  x = sizeof(SA);  rr = getsockname(nnetfd, (SA *) lclend, &x);  if (rr < 0)    holler("post-rcv getsockname failed");  strcpy(cp, inet_ntoa(lclend->sin_addr));/* now check out who it is.  We don't care about mismatched DNS names here,   but any ADDR and PORT we specified had better fucking well match the caller.   Converting from addr to inet_ntoa and back again is a bit of a kludge, but   netcat_resolvehost wants a string and there's much gnarlier code out there already,   so I don't feel bad.   The *real* question is why BFD sockets wasn't designed to allow listens for   connections *from* specific hosts/ports, instead of requiring the caller to   accept the connection and then reject undesireable ones by closing.  In   other words, we need a TCP MSG_PEEK. */  z = ntohs(remend->sin_port);  strcpy(bigbuf_net, inet_ntoa(remend->sin_addr));  whozis = netcat_resolvehost(bigbuf_net);  errno = 0;  x = 0;			/* use as a flag... */  if (rad)			/* xxx: fix to go down the *list* if we have one? */    if (memcmp(rad, whozis->iaddrs, sizeof(SA)))      x = 1;  if (rp)    if (z != rp)      x = 1;  if (x)			/* guilty! */    bail("invalid connection to [%s] from %s [%s] %d",	 cp, whozis->name, whozis->addrs[0], z);  holler("connect to [%s] from %s [%s] %d",	/* oh, you're okay.. */	 cp, whozis->name, whozis->addrs[0], z);  return nnetfd;		/* open! */dol_tmo:  errno = ETIMEDOUT;		/* fake it */dol_err:  close(nnetfd);  return -1;}				/* dolisten */