Home | History | Annotate | Download | only in slirp-android
      1 /*
      2  * Copyright (c) 1995 Danny Gasparovski.
      3  *
      4  * Please read the file COPYRIGHT for the
      5  * terms and conditions of the copyright.
      6  */
      7 
      8 #define WANT_SYS_IOCTL_H
      9 #include "qemu-common.h"
     10 #include <slirp.h>
     11 #include "ip_icmp.h"
     12 #include "main.h"
     13 #ifdef __sun__
     14 #include <sys/filio.h>
     15 #endif
     16 #define  SLIRP_COMPILATION 1
     17 #include "sockets.h"
     18 #include "proxy_common.h"
     19 
     20 static void sofcantrcvmore(struct socket *so);
     21 static void sofcantsendmore(struct socket *so);
     22 
     23 #if 0
     24 static void
     25 so_init()
     26 {
     27 	/* Nothing yet */
     28 }
     29 #endif
     30 
     31 struct socket *
     32 solookup(struct socket *head, uint32_t laddr, u_int lport,
     33          uint32_t faddr, u_int fport)
     34 {
     35 	struct socket *so;
     36 
     37 	for (so = head->so_next; so != head; so = so->so_next) {
     38 		if (so->so_laddr_port == lport &&
     39 		    so->so_laddr_ip   == laddr &&
     40 		    so->so_faddr_ip   == faddr &&
     41 		    so->so_faddr_port == fport)
     42 		   break;
     43 	}
     44 
     45 	if (so == head)
     46 	   return (struct socket *)NULL;
     47 	return so;
     48 
     49 }
     50 
     51 /*
     52  * Create a new socket, initialise the fields
     53  * It is the responsibility of the caller to
     54  * insque() it into the correct linked-list
     55  */
     56 struct socket *
     57 socreate(void)
     58 {
     59   struct socket *so;
     60 
     61   so = (struct socket *)malloc(sizeof(struct socket));
     62   if(so) {
     63     memset(so, 0, sizeof(struct socket));
     64     so->so_state = SS_NOFDREF;
     65     so->s = -1;
     66   }
     67   return(so);
     68 }
     69 
     70 /*
     71  * remque and free a socket, clobber cache
     72  */
     73 void
     74 sofree(struct socket *so)
     75 {
     76   if (so->so_state & SS_PROXIFIED)
     77     proxy_manager_del(so);
     78 
     79   if (so->so_emu==EMU_RSH && so->extra) {
     80 	sofree(so->extra);
     81 	so->extra=NULL;
     82   }
     83   if (so == tcp_last_so)
     84     tcp_last_so = &tcb;
     85   else if (so == udp_last_so)
     86     udp_last_so = &udb;
     87 
     88   m_free(so->so_m);
     89 
     90   if(so->so_next && so->so_prev)
     91     remque(so);  /* crashes if so is not in a queue */
     92 
     93   free(so);
     94 }
     95 
     96 size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
     97 {
     98 	int n, lss, total;
     99 	struct sbuf *sb = &so->so_snd;
    100 	int len = sb->sb_datalen - sb->sb_cc;
    101 	int mss = so->so_tcpcb->t_maxseg;
    102 
    103 	DEBUG_CALL("sopreprbuf");
    104 	DEBUG_ARG("so = %lx", (long )so);
    105 
    106 	len = sb->sb_datalen - sb->sb_cc;
    107 
    108 	if (len <= 0)
    109 		return 0;
    110 
    111 	iov[0].iov_base = sb->sb_wptr;
    112         iov[1].iov_base = NULL;
    113         iov[1].iov_len = 0;
    114 	if (sb->sb_wptr < sb->sb_rptr) {
    115 		iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
    116 		/* Should never succeed, but... */
    117 		if (iov[0].iov_len > len)
    118 		   iov[0].iov_len = len;
    119 		if (iov[0].iov_len > mss)
    120 		   iov[0].iov_len -= iov[0].iov_len%mss;
    121 		n = 1;
    122 	} else {
    123 		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
    124 		/* Should never succeed, but... */
    125 		if (iov[0].iov_len > len) iov[0].iov_len = len;
    126 		len -= iov[0].iov_len;
    127 		if (len) {
    128 			iov[1].iov_base = sb->sb_data;
    129 			iov[1].iov_len = sb->sb_rptr - sb->sb_data;
    130 			if(iov[1].iov_len > len)
    131 			   iov[1].iov_len = len;
    132 			total = iov[0].iov_len + iov[1].iov_len;
    133 			if (total > mss) {
    134 				lss = total%mss;
    135 				if (iov[1].iov_len > lss) {
    136 					iov[1].iov_len -= lss;
    137 					n = 2;
    138 				} else {
    139 					lss -= iov[1].iov_len;
    140 					iov[0].iov_len -= lss;
    141 					n = 1;
    142 				}
    143 			} else
    144 				n = 2;
    145 		} else {
    146 			if (iov[0].iov_len > mss)
    147 			   iov[0].iov_len -= iov[0].iov_len%mss;
    148 			n = 1;
    149 		}
    150 	}
    151 	if (np)
    152 		*np = n;
    153 
    154 	return iov[0].iov_len + (n - 1) * iov[1].iov_len;
    155 }
    156 
    157 /*
    158  * Read from so's socket into sb_snd, updating all relevant sbuf fields
    159  * NOTE: This will only be called if it is select()ed for reading, so
    160  * a read() of 0 (or less) means it's disconnected
    161  */
    162 int
    163 soread(struct socket *so)
    164 {
    165 	int n, nn;
    166 	struct sbuf *sb = &so->so_snd;
    167 	struct iovec iov[2];
    168 
    169 	DEBUG_CALL("soread");
    170 	DEBUG_ARG("so = %lx", (long )so);
    171 
    172 	/*
    173 	 * No need to check if there's enough room to read.
    174 	 * soread wouldn't have been called if there weren't
    175 	 */
    176 	sopreprbuf(so, iov, &n);
    177 
    178 #ifdef HAVE_READV
    179 	nn = readv(so->s, (struct iovec *)iov, n);
    180 	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
    181 #else
    182 	nn = socket_recv(so->s, iov[0].iov_base, iov[0].iov_len);
    183 #endif
    184 	if (nn <= 0) {
    185 		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
    186 			return 0;
    187 		else {
    188 			DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,errno_str));
    189 			sofcantrcvmore(so);
    190 			tcp_sockclosed(sototcpcb(so));
    191 			return -1;
    192 		}
    193 	}
    194 
    195 #ifndef HAVE_READV
    196 	/*
    197 	 * If there was no error, try and read the second time round
    198 	 * We read again if n = 2 (ie, there's another part of the buffer)
    199 	 * and we read as much as we could in the first read
    200 	 * We don't test for <= 0 this time, because there legitimately
    201 	 * might not be any more data (since the socket is non-blocking),
    202 	 * a close will be detected on next iteration.
    203 	 * A return of -1 wont (shouldn't) happen, since it didn't happen above
    204 	 */
    205 	if (n == 2 && nn == iov[0].iov_len) {
    206             int ret;
    207             ret = socket_recv(so->s, iov[1].iov_base, iov[1].iov_len);
    208             if (ret > 0)
    209                 nn += ret;
    210         }
    211 
    212 	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
    213 #endif
    214 
    215 	/* Update fields */
    216 	sb->sb_cc += nn;
    217 	sb->sb_wptr += nn;
    218 	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
    219 		sb->sb_wptr -= sb->sb_datalen;
    220 	return nn;
    221 }
    222 
    223 int soreadbuf(struct socket *so, const char *buf, int size)
    224 {
    225     int n, nn, copy = size;
    226 	struct sbuf *sb = &so->so_snd;
    227 	struct iovec iov[2];
    228 
    229 	DEBUG_CALL("soreadbuf");
    230 	DEBUG_ARG("so = %lx", (long )so);
    231 
    232 	/*
    233 	 * No need to check if there's enough room to read.
    234 	 * soread wouldn't have been called if there weren't
    235 	 */
    236 	if (sopreprbuf(so, iov, &n) < size)
    237         goto err;
    238 
    239     nn = MIN(iov[0].iov_len, copy);
    240     memcpy(iov[0].iov_base, buf, nn);
    241 
    242     copy -= nn;
    243     buf += nn;
    244 
    245     if (copy == 0)
    246         goto done;
    247 
    248     memcpy(iov[1].iov_base, buf, copy);
    249 
    250 done:
    251     /* Update fields */
    252 	sb->sb_cc += size;
    253 	sb->sb_wptr += size;
    254 	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
    255 		sb->sb_wptr -= sb->sb_datalen;
    256     return size;
    257 err:
    258 
    259     sofcantrcvmore(so);
    260     tcp_sockclosed(sototcpcb(so));
    261     fprintf(stderr, "soreadbuf buffer to small");
    262     return -1;
    263 }
    264 
    265 /*
    266  * Get urgent data
    267  *
    268  * When the socket is created, we set it SO_OOBINLINE,
    269  * so when OOB data arrives, we soread() it and everything
    270  * in the send buffer is sent as urgent data
    271  */
    272 void
    273 sorecvoob(struct socket *so)
    274 {
    275 	struct tcpcb *tp = sototcpcb(so);
    276 
    277 	DEBUG_CALL("sorecvoob");
    278 	DEBUG_ARG("so = %lx", (long)so);
    279 
    280 	/*
    281 	 * We take a guess at how much urgent data has arrived.
    282 	 * In most situations, when urgent data arrives, the next
    283 	 * read() should get all the urgent data.  This guess will
    284 	 * be wrong however if more data arrives just after the
    285 	 * urgent data, or the read() doesn't return all the
    286 	 * urgent data.
    287 	 */
    288 	soread(so);
    289 	tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
    290 	tp->t_force = 1;
    291 	tcp_output(tp);
    292 	tp->t_force = 0;
    293 }
    294 
    295 /*
    296  * Send urgent data
    297  * There's a lot duplicated code here, but...
    298  */
    299 int
    300 sosendoob(struct socket *so)
    301 {
    302 	struct sbuf *sb = &so->so_rcv;
    303 	char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
    304 
    305 	int n, len;
    306 
    307 	DEBUG_CALL("sosendoob");
    308 	DEBUG_ARG("so = %lx", (long)so);
    309 	DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
    310 
    311 	if (so->so_urgc > 2048)
    312 	   so->so_urgc = 2048; /* XXXX */
    313 
    314 	if (sb->sb_rptr < sb->sb_wptr) {
    315 		/* We can send it directly */
    316 		n = socket_send_oob(so->s, sb->sb_rptr, so->so_urgc); /* |MSG_DONTWAIT)); */
    317 		so->so_urgc -= n;
    318 
    319 		DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
    320 	} else {
    321 		/*
    322 		 * Since there's no sendv or sendtov like writev,
    323 		 * we must copy all data to a linear buffer then
    324 		 * send it all
    325 		 */
    326 		len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
    327 		if (len > so->so_urgc) len = so->so_urgc;
    328 		memcpy(buff, sb->sb_rptr, len);
    329 		so->so_urgc -= len;
    330 		if (so->so_urgc) {
    331 			n = sb->sb_wptr - sb->sb_data;
    332 			if (n > so->so_urgc) n = so->so_urgc;
    333 			memcpy((buff + len), sb->sb_data, n);
    334 			so->so_urgc -= n;
    335 			len += n;
    336 		}
    337 		n = socket_send_oob(so->s, buff, len); /* |MSG_DONTWAIT)); */
    338 #ifdef DEBUG
    339 		if (n != len)
    340 		   DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
    341 #endif
    342 		DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
    343 	}
    344 
    345 	sb->sb_cc -= n;
    346 	sb->sb_rptr += n;
    347 	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
    348 		sb->sb_rptr -= sb->sb_datalen;
    349 
    350 	return n;
    351 }
    352 
    353 /*
    354  * Write data from so_rcv to so's socket,
    355  * updating all sbuf field as necessary
    356  */
    357 int
    358 sowrite(struct socket *so)
    359 {
    360 	int  n,nn;
    361 	struct sbuf *sb = &so->so_rcv;
    362 	int len = sb->sb_cc;
    363 	struct iovec iov[2];
    364 
    365 	DEBUG_CALL("sowrite");
    366 	DEBUG_ARG("so = %lx", (long)so);
    367 
    368 	if (so->so_urgc) {
    369 		sosendoob(so);
    370 		if (sb->sb_cc == 0)
    371 			return 0;
    372 	}
    373 
    374 	/*
    375 	 * No need to check if there's something to write,
    376 	 * sowrite wouldn't have been called otherwise
    377 	 */
    378 
    379         len = sb->sb_cc;
    380 
    381 	iov[0].iov_base = sb->sb_rptr;
    382         iov[1].iov_base = NULL;
    383         iov[1].iov_len = 0;
    384 	if (sb->sb_rptr < sb->sb_wptr) {
    385 		iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
    386 		/* Should never succeed, but... */
    387 		if (iov[0].iov_len > len) iov[0].iov_len = len;
    388 		n = 1;
    389 	} else {
    390 		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
    391 		if (iov[0].iov_len > len) iov[0].iov_len = len;
    392 		len -= iov[0].iov_len;
    393 		if (len) {
    394 			iov[1].iov_base = sb->sb_data;
    395 			iov[1].iov_len = sb->sb_wptr - sb->sb_data;
    396 			if (iov[1].iov_len > len) iov[1].iov_len = len;
    397 			n = 2;
    398 		} else
    399 			n = 1;
    400 	}
    401 	/* Check if there's urgent data to send, and if so, send it */
    402 
    403 #ifdef HAVE_READV
    404 	nn = writev(so->s, (const struct iovec *)iov, n);
    405 
    406 	DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
    407 #else
    408 	nn = socket_send(so->s, iov[0].iov_base, iov[0].iov_len);
    409 #endif
    410 	/* This should never happen, but people tell me it does *shrug* */
    411 	if (nn < 0 && (errno == EAGAIN || errno == EINTR))
    412 		return 0;
    413 
    414 	if (nn <= 0) {
    415 		DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
    416 			so->so_state, errno));
    417 		sofcantsendmore(so);
    418 		tcp_sockclosed(sototcpcb(so));
    419 		return -1;
    420 	}
    421 
    422 #ifndef HAVE_READV
    423 	if (n == 2 && nn == iov[0].iov_len) {
    424             int ret;
    425             ret = socket_send(so->s, iov[1].iov_base, iov[1].iov_len);
    426             if (ret > 0)
    427                 nn += ret;
    428         }
    429         DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
    430 #endif
    431 
    432 	/* Update sbuf */
    433 	sb->sb_cc -= nn;
    434 	sb->sb_rptr += nn;
    435 	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
    436 		sb->sb_rptr -= sb->sb_datalen;
    437 
    438 	/*
    439 	 * If in DRAIN mode, and there's no more data, set
    440 	 * it CANTSENDMORE
    441 	 */
    442 	if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
    443 		sofcantsendmore(so);
    444 
    445 	return nn;
    446 }
    447 
    448 /*
    449  * recvfrom() a UDP socket
    450  */
    451 void
    452 sorecvfrom(struct socket *so)
    453 {
    454         SockAddress  addr;
    455 
    456 	DEBUG_CALL("sorecvfrom");
    457 	DEBUG_ARG("so = %lx", (long)so);
    458 
    459 	if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */
    460 	  char buff[256];
    461 	  int len;
    462 
    463 	  len = socket_recvfrom(so->s, buff, 256, &addr);
    464 	  /* XXX Check if reply is "correct"? */
    465 
    466 	  if(len == -1 || len == 0) {
    467 	    u_char code=ICMP_UNREACH_PORT;
    468 
    469 	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
    470 	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
    471 
    472 	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
    473 			errno,errno_str));
    474 	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str);
    475 	  } else {
    476 	    icmp_reflect(so->so_m);
    477 	    so->so_m = 0; /* Don't mbuf_free() it again! */
    478 	  }
    479 	  /* No need for this socket anymore, udp_detach it */
    480 	  udp_detach(so);
    481 	} else {                            	/* A "normal" UDP packet */
    482 	  struct mbuf *m;
    483           int len;
    484 		  int n;
    485 
    486 	  if (!(m = m_get())) return;
    487 	  m->m_data += IF_MAXLINKHDR;
    488 
    489 	  /*
    490 	   * XXX Shouldn't FIONREAD packets destined for port 53,
    491 	   * but I don't know the max packet size for DNS lookups
    492 	   */
    493 	  len = M_FREEROOM(m);
    494 	  /* if (so->so_fport != htons(53)) { */
    495 	  n = socket_can_read(so->s);
    496 
    497 	  if (n > len) {
    498 	    n = (m->m_data - m->m_dat) + m->m_len + n + 1;
    499 	    m_inc(m, n);
    500 	    len = M_FREEROOM(m);
    501 	  }
    502 	  /* } */
    503 
    504 	  m->m_len = socket_recvfrom(so->s, m->m_data, len, &addr);
    505 	  DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
    506 		      m->m_len, errno,errno_str));
    507 	  if(m->m_len<0) {
    508 	    u_char code=ICMP_UNREACH_PORT;
    509 
    510 	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
    511 	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
    512 
    513 	    DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
    514 	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str);
    515 	    m_free(m);
    516 	  } else {
    517 	  /*
    518 	   * Hack: domain name lookup will be used the most for UDP,
    519 	   * and since they'll only be used once there's no need
    520 	   * for the 4 minute (or whatever) timeout... So we time them
    521 	   * out much quicker (10 seconds  for now...)
    522 	   */
    523 	    if (so->so_expire) {
    524 	      if (so->so_faddr_port == 53)
    525 		so->so_expire = curtime + SO_EXPIREFAST;
    526 	      else
    527 		so->so_expire = curtime + SO_EXPIRE;
    528 	    }
    529 
    530 	    /*		if (m->m_len == len) {
    531 	     *			m_inc(m, MINCSIZE);
    532 	     *			m->m_len = 0;
    533 	     *		}
    534 	     */
    535 
    536 	    /*
    537 	     * If this packet was destined for CTL_ADDR,
    538 	     * make it look like that's where it came from, done by udp_output
    539 	     */
    540 	    udp_output_(so, m, &addr);
    541 	  } /* rx error */
    542 	} /* if ping packet */
    543 }
    544 
    545 /*
    546  * sendto() a socket
    547  */
    548 int
    549 sosendto(struct socket *so, struct mbuf *m)
    550 {
    551 	int ret;
    552     SockAddress   addr;
    553     uint32_t      addr_ip;
    554     uint16_t      addr_port;
    555 
    556 	DEBUG_CALL("sosendto");
    557 	DEBUG_ARG("so = %lx", (long)so);
    558 	DEBUG_ARG("m = %lx", (long)m);
    559 
    560 	if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) {
    561         /* It's an alias */
    562       	int  low = so->so_faddr_ip & 0xff;
    563 
    564         if ( CTL_IS_DNS(low) )
    565             addr_ip = dns_addr[low - CTL_DNS];
    566         else
    567             addr_ip = loopback_addr_ip;
    568 	} else
    569 	    addr_ip = so->so_faddr_ip;
    570 
    571 	addr_port = so->so_faddr_port;
    572 
    573         sock_address_init_inet(&addr, addr_ip, addr_port);
    574 
    575 	DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%08x\n", addr_port, addr_ip));
    576 
    577 	/* Don't care what port we get */
    578 	ret = socket_sendto(so->s, m->m_data, m->m_len,&addr);
    579 	if (ret < 0)
    580 		return -1;
    581 
    582 	/*
    583 	 * Kill the socket if there's no reply in 4 minutes,
    584 	 * but only if it's an expirable socket
    585 	 */
    586 	if (so->so_expire)
    587 		so->so_expire = curtime + SO_EXPIRE;
    588 	so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
    589 	return 0;
    590 }
    591 
    592 /*
    593  * XXX This should really be tcp_listen
    594  */
    595 struct socket *
    596 solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
    597 {
    598 	SockAddress  addr;
    599 	uint32_t     addr_ip;
    600 	struct socket *so;
    601 	int s;
    602 
    603 	DEBUG_CALL("solisten");
    604 	DEBUG_ARG("port = %d", port);
    605 	DEBUG_ARG("laddr = %x", laddr);
    606 	DEBUG_ARG("lport = %d", lport);
    607 	DEBUG_ARG("flags = %x", flags);
    608 
    609 	if ((so = socreate()) == NULL) {
    610 	  /* free(so);      Not sofree() ??? free(NULL) == NOP */
    611 	  return NULL;
    612 	}
    613 
    614 	/* Don't tcp_attach... we don't need so_snd nor so_rcv */
    615 	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
    616 		free(so);
    617 		return NULL;
    618 	}
    619 	insque(so,&tcb);
    620 
    621 	/*
    622 	 * SS_FACCEPTONCE sockets must time out.
    623 	 */
    624 	if (flags & SS_FACCEPTONCE)
    625 	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
    626 
    627 	so->so_state      = (SS_FACCEPTCONN|flags);
    628 	so->so_laddr_port = lport; /* Kept in host format */
    629     so->so_laddr_ip   = laddr; /* Ditto */
    630     so->so_haddr_port = port;
    631 
    632     s = socket_loopback_server( port, SOCKET_STREAM );
    633     if (s < 0)
    634         return NULL;
    635 
    636     socket_get_address(s, &addr);
    637 
    638 	so->so_faddr_port = sock_address_get_port(&addr);
    639 
    640     addr_ip = (uint32_t) sock_address_get_ip(&addr);
    641 
    642     if (addr_ip == 0 || addr_ip == loopback_addr_ip)
    643         so->so_faddr_ip = alias_addr_ip;
    644     else
    645         so->so_faddr_ip = addr_ip;
    646 
    647 	so->s = s;
    648 	return so;
    649 }
    650 
    651 
    652 int
    653 sounlisten(u_int  port)
    654 {
    655     struct socket *so;
    656 
    657     for (so = tcb.so_next; so != &tcb; so = so->so_next) {
    658         if (so->so_haddr_port == port) {
    659             break;
    660         }
    661     }
    662 
    663     if (so == &tcb) {
    664         return -1;
    665     }
    666 
    667     sofcantrcvmore( so );
    668     sofcantsendmore( so );
    669     close( so->s );
    670     so->s = -1;
    671     sofree( so );
    672     return 0;
    673 }
    674 
    675 
    676 #if 0
    677 /*
    678  * Data is available in so_rcv
    679  * Just write() the data to the socket
    680  * XXX not yet...
    681  */
    682 static void
    683 sorwakeup(so)
    684 	struct socket *so;
    685 {
    686 /*	sowrite(so); */
    687 /*	FD_CLR(so->s,&writefds); */
    688 }
    689 
    690 /*
    691  * Data has been freed in so_snd
    692  * We have room for a read() if we want to
    693  * For now, don't read, it'll be done in the main loop
    694  */
    695 static void
    696 sowwakeup(so)
    697 	struct socket *so;
    698 {
    699 	/* Nothing, yet */
    700 }
    701 #endif
    702 
    703 /*
    704  * Various session state calls
    705  * XXX Should be #define's
    706  * The socket state stuff needs work, these often get call 2 or 3
    707  * times each when only 1 was needed
    708  */
    709 void
    710 soisfconnecting(struct socket *so)
    711 {
    712 	so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
    713 			  SS_FCANTSENDMORE|SS_FWDRAIN);
    714 	so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
    715 }
    716 
    717 void
    718 soisfconnected(struct socket *so)
    719 {
    720 	so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
    721 	so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
    722 }
    723 
    724 static void
    725 sofcantrcvmore(struct socket *so)
    726 {
    727 	if ((so->so_state & SS_NOFDREF) == 0) {
    728 		shutdown(so->s,0);
    729 		if(global_writefds) {
    730 		  FD_CLR(so->s,global_writefds);
    731 		}
    732 	}
    733 	so->so_state &= ~(SS_ISFCONNECTING);
    734 	if (so->so_state & SS_FCANTSENDMORE)
    735 	   so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */
    736 	else
    737 	   so->so_state |= SS_FCANTRCVMORE;
    738 }
    739 
    740 static void
    741 sofcantsendmore(struct socket *so)
    742 {
    743 	if ((so->so_state & SS_NOFDREF) == 0) {
    744             shutdown(so->s,1);           /* send FIN to fhost */
    745             if (global_readfds) {
    746                 FD_CLR(so->s,global_readfds);
    747             }
    748             if (global_xfds) {
    749                 FD_CLR(so->s,global_xfds);
    750             }
    751 	}
    752 	so->so_state &= ~(SS_ISFCONNECTING);
    753 	if (so->so_state & SS_FCANTRCVMORE)
    754 	   so->so_state = SS_NOFDREF; /* as above */
    755 	else
    756 	   so->so_state |= SS_FCANTSENDMORE;
    757 }
    758 
    759 void
    760 soisfdisconnected(struct socket *so)
    761 {
    762 /*	so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
    763 /*	close(so->s); */
    764 /*	so->so_state = SS_ISFDISCONNECTED; */
    765 	/*
    766 	 * XXX Do nothing ... ?
    767 	 */
    768 }
    769 
    770 /*
    771  * Set write drain mode
    772  * Set CANTSENDMORE once all data has been write()n
    773  */
    774 void
    775 sofwdrain(struct socket *so)
    776 {
    777 	if (so->so_rcv.sb_cc)
    778 		so->so_state |= SS_FWDRAIN;
    779 	else
    780 		sofcantsendmore(so);
    781 }
    782 
    783