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 "android/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 	/*
    574 	 * test for generic forwarding; this function replaces the arguments
    575 	 * only on success
    576 	 */
    577 	unsigned long faddr = addr_ip;
    578         int fport = addr_port;
    579 
    580 	if (slirp_should_net_forward(faddr, fport, &faddr, &fport)) {
    581       time_t timestamp = time(NULL);
    582       slirp_drop_log(
    583 	       "Redirected UDP: src: 0x%08lx:0x%04x org dst: 0x%08lx:0x%04x "
    584 	       "new dst: 0x%08lx:0x%04x %ld\n",
    585 	        so->so_laddr_ip, so->so_laddr_port,
    586 	        addr_ip, addr_port,
    587 	        faddr, fport, timestamp
    588 	    );
    589 	}
    590 	addr_ip = faddr;
    591 	addr_port = fport;
    592 
    593 
    594         sock_address_init_inet(&addr, addr_ip, addr_port);
    595 
    596 	DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%08x\n", addr_port, addr_ip));
    597 
    598 	/* Don't care what port we get */
    599 	ret = socket_sendto(so->s, m->m_data, m->m_len,&addr);
    600 	if (ret < 0)
    601 		return -1;
    602 
    603 	/*
    604 	 * Kill the socket if there's no reply in 4 minutes,
    605 	 * but only if it's an expirable socket
    606 	 */
    607 	if (so->so_expire)
    608 		so->so_expire = curtime + SO_EXPIRE;
    609 	so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
    610 	return 0;
    611 }
    612 
    613 /*
    614  * XXX This should really be tcp_listen
    615  */
    616 struct socket *
    617 solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
    618 {
    619 	SockAddress  addr;
    620 	uint32_t     addr_ip;
    621 	struct socket *so;
    622 	int s;
    623 
    624 	DEBUG_CALL("solisten");
    625 	DEBUG_ARG("port = %d", port);
    626 	DEBUG_ARG("laddr = %x", laddr);
    627 	DEBUG_ARG("lport = %d", lport);
    628 	DEBUG_ARG("flags = %x", flags);
    629 
    630 	if ((so = socreate()) == NULL) {
    631 	  /* free(so);      Not sofree() ??? free(NULL) == NOP */
    632 	  return NULL;
    633 	}
    634 
    635 	/* Don't tcp_attach... we don't need so_snd nor so_rcv */
    636 	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
    637 		free(so);
    638 		return NULL;
    639 	}
    640 	insque(so,&tcb);
    641 
    642 	/*
    643 	 * SS_FACCEPTONCE sockets must time out.
    644 	 */
    645 	if (flags & SS_FACCEPTONCE)
    646 	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
    647 
    648 	so->so_state      = (SS_FACCEPTCONN|flags);
    649 	so->so_laddr_port = lport; /* Kept in host format */
    650     so->so_laddr_ip   = laddr; /* Ditto */
    651     so->so_haddr_port = port;
    652 
    653     s = socket_loopback_server( port, SOCKET_STREAM );
    654     if (s < 0)
    655         return NULL;
    656 
    657     socket_get_address(s, &addr);
    658 
    659 	so->so_faddr_port = sock_address_get_port(&addr);
    660 
    661     addr_ip = (uint32_t) sock_address_get_ip(&addr);
    662 
    663     if (addr_ip == 0 || addr_ip == loopback_addr_ip)
    664         so->so_faddr_ip = alias_addr_ip;
    665     else
    666         so->so_faddr_ip = addr_ip;
    667 
    668 	so->s = s;
    669 	return so;
    670 }
    671 
    672 
    673 int
    674 sounlisten(u_int  port)
    675 {
    676     struct socket *so;
    677 
    678     for (so = tcb.so_next; so != &tcb; so = so->so_next) {
    679         if (so->so_haddr_port == port) {
    680             break;
    681         }
    682     }
    683 
    684     if (so == &tcb) {
    685         return -1;
    686     }
    687 
    688     sofcantrcvmore( so );
    689     sofcantsendmore( so );
    690     close( so->s );
    691     so->s = -1;
    692     sofree( so );
    693     return 0;
    694 }
    695 
    696 
    697 #if 0
    698 /*
    699  * Data is available in so_rcv
    700  * Just write() the data to the socket
    701  * XXX not yet...
    702  */
    703 static void
    704 sorwakeup(so)
    705 	struct socket *so;
    706 {
    707 /*	sowrite(so); */
    708 /*	FD_CLR(so->s,&writefds); */
    709 }
    710 
    711 /*
    712  * Data has been freed in so_snd
    713  * We have room for a read() if we want to
    714  * For now, don't read, it'll be done in the main loop
    715  */
    716 static void
    717 sowwakeup(so)
    718 	struct socket *so;
    719 {
    720 	/* Nothing, yet */
    721 }
    722 #endif
    723 
    724 /*
    725  * Various session state calls
    726  * XXX Should be #define's
    727  * The socket state stuff needs work, these often get call 2 or 3
    728  * times each when only 1 was needed
    729  */
    730 void
    731 soisfconnecting(struct socket *so)
    732 {
    733 	so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
    734 			  SS_FCANTSENDMORE|SS_FWDRAIN);
    735 	so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
    736 }
    737 
    738 void
    739 soisfconnected(struct socket *so)
    740 {
    741 	so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
    742 	so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
    743 }
    744 
    745 static void
    746 sofcantrcvmore(struct socket *so)
    747 {
    748 	if ((so->so_state & SS_NOFDREF) == 0) {
    749 		shutdown(so->s,0);
    750 		if(global_writefds) {
    751 		  FD_CLR(so->s,global_writefds);
    752 		}
    753 	}
    754 	so->so_state &= ~(SS_ISFCONNECTING);
    755 	if (so->so_state & SS_FCANTSENDMORE)
    756 	   so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */
    757 	else
    758 	   so->so_state |= SS_FCANTRCVMORE;
    759 }
    760 
    761 static void
    762 sofcantsendmore(struct socket *so)
    763 {
    764 	if ((so->so_state & SS_NOFDREF) == 0) {
    765             shutdown(so->s,1);           /* send FIN to fhost */
    766             if (global_readfds) {
    767                 FD_CLR(so->s,global_readfds);
    768             }
    769             if (global_xfds) {
    770                 FD_CLR(so->s,global_xfds);
    771             }
    772 	}
    773 	so->so_state &= ~(SS_ISFCONNECTING);
    774 	if (so->so_state & SS_FCANTRCVMORE)
    775 	   so->so_state = SS_NOFDREF; /* as above */
    776 	else
    777 	   so->so_state |= SS_FCANTSENDMORE;
    778 }
    779 
    780 void
    781 soisfdisconnected(struct socket *so)
    782 {
    783 /*	so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
    784 /*	close(so->s); */
    785 /*	so->so_state = SS_ISFDISCONNECTED; */
    786 	/*
    787 	 * XXX Do nothing ... ?
    788 	 */
    789 }
    790 
    791 /*
    792  * Set write drain mode
    793  * Set CANTSENDMORE once all data has been write()n
    794  */
    795 void
    796 sofwdrain(struct socket *so)
    797 {
    798 	if (so->so_rcv.sb_cc)
    799 		so->so_state |= SS_FWDRAIN;
    800 	else
    801 		sofcantsendmore(so);
    802 }
    803