18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1995 Danny Gasparovski. 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Please read the file COPYRIGHT for the 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * terms and conditions of the copyright. 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h" 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h> 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ip_icmp.h" 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __sun__ 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/filio.h> 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void sofcantrcvmore(struct socket *so); 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void sofcantsendmore(struct socket *so); 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectso_init() 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Nothing yet */ 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket * 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersolookup(struct socket *head, struct in_addr laddr, u_int lport, 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct in_addr faddr, u_int fport) 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (so = head->so_next; so != head; so = so->so_next) { 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_lport == lport && 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr.s_addr == laddr.s_addr && 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr.s_addr == faddr.s_addr && 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_fport == fport) 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so == head) 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (struct socket *)NULL; 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return so; 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Create a new socket, initialise the fields 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * It is the responsibility of the caller to 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * insque() it into the correct linked-list 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket * 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersocreate(void) 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so = (struct socket *)malloc(sizeof(struct socket)); 578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(so) { 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(so, 0, sizeof(struct socket)); 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_NOFDREF; 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->s = -1; 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return(so); 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * remque and free a socket, clobber cache 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofree(struct socket *so) 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_emu==EMU_RSH && so->extra) { 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofree(so->extra); 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->extra=NULL; 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so == tcp_last_so) 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_last_so = &tcb; 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (so == udp_last_so) 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_last_so = &udb; 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(so->so_m); 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(so->so_next && so->so_prev) 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project remque(so); /* crashes if so is not in a queue */ 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(so); 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersize_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n, lss, total; 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_snd; 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len = sb->sb_datalen - sb->sb_cc; 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int mss = so->so_tcpcb->t_maxseg; 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_CALL("sopreprbuf"); 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long )so); 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = sb->sb_datalen - sb->sb_cc; 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len <= 0) 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_base = sb->sb_wptr; 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iov[1].iov_base = NULL; 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iov[1].iov_len = 0; 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_wptr < sb->sb_rptr) { 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should never succeed, but... */ 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > len) 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = len; 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > mss) 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len -= iov[0].iov_len%mss; 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should never succeed, but... */ 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > len) iov[0].iov_len = len; 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= iov[0].iov_len; 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) { 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_base = sb->sb_data; 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_len = sb->sb_rptr - sb->sb_data; 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(iov[1].iov_len > len) 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_len = len; 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project total = iov[0].iov_len + iov[1].iov_len; 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (total > mss) { 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lss = total%mss; 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[1].iov_len > lss) { 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_len -= lss; 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 2; 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lss -= iov[1].iov_len; 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len -= lss; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 2; 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > mss) 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len -= iov[0].iov_len%mss; 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (np) 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *np = n; 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return iov[0].iov_len + (n - 1) * iov[1].iov_len; 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Read from so's socket into sb_snd, updating all relevant sbuf fields 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NOTE: This will only be called if it is select()ed for reading, so 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * a read() of 0 (or less) means it's disconnected 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoread(struct socket *so) 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n, nn; 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_snd; 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct iovec iov[2]; 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_CALL("soread"); 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("so = %lx", (long )so); 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * No need to check if there's enough room to read. 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * soread wouldn't have been called if there weren't 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sopreprbuf(so, iov, &n); 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_READV 1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn = readv(so->s, (struct iovec *)iov, n); 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0); 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn <= 0) { 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn < 0 && (errno == EINTR || errno == EAGAIN)) 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantrcvmore(so); 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_sockclosed(sototcpcb(so)); 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef HAVE_READV 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If there was no error, try and read the second time round 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We read again if n = 2 (ie, there's another part of the buffer) 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and we read as much as we could in the first read 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We don't test for <= 0 this time, because there legitimately 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * might not be any more data (since the socket is non-blocking), 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * a close will be detected on next iteration. 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * A return of -1 wont (shouldn't) happen, since it didn't happen above 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n == 2 && nn == iov[0].iov_len) { 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0); 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret > 0) 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn += ret; 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Update fields */ 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc += nn; 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_wptr += nn; 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_wptr -= sb->sb_datalen; 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return nn; 2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint soreadbuf(struct socket *so, const char *buf, int size) 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n, nn, copy = size; 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_snd; 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct iovec iov[2]; 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_CALL("soreadbuf"); 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("so = %lx", (long )so); 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * No need to check if there's enough room to read. 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * soread wouldn't have been called if there weren't 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sopreprbuf(so, iov, &n) < size) 2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto err; 2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nn = MIN(iov[0].iov_len, copy); 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(iov[0].iov_base, buf, nn); 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner copy -= nn; 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf += nn; 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (copy == 0) 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto done; 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(iov[1].iov_base, buf, copy); 2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerdone: 2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Update fields */ 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sb->sb_cc += size; 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sb->sb_wptr += size; 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sb->sb_wptr -= sb->sb_datalen; 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return size; 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnererr: 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sofcantrcvmore(so); 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_sockclosed(sototcpcb(so)); 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "soreadbuf buffer to small"); 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Get urgent data 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * When the socket is created, we set it SO_OOBINLINE, 2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so when OOB data arrives, we soread() it and everything 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the send buffer is sent as urgent data 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersorecvoob(struct socket *so) 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct tcpcb *tp = sototcpcb(so); 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sorecvoob"); 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We take a guess at how much urgent data has arrived. 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In most situations, when urgent data arrives, the next 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * read() should get all the urgent data. This guess will 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * be wrong however if more data arrives just after the 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * urgent data, or the read() doesn't return all the 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * urgent data. 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project soread(so); 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_force = 1; 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_output(tp); 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_force = 0; 2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Send urgent data 2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * There's a lot duplicated code here, but... 2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersosendoob(struct socket *so) 2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_rcv; 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n, len; 2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sosendoob"); 3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); 3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_urgc > 2048) 3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc = 2048; /* XXXX */ 3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_rptr < sb->sb_wptr) { 3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We can send it directly */ 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ 3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc -= n; 3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Since there's no sendv or sendtov like writev, 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we must copy all data to a linear buffer then 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * send it all 3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len > so->so_urgc) len = so->so_urgc; 3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(buff, sb->sb_rptr, len); 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc -= len; 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_urgc) { 3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = sb->sb_wptr - sb->sb_data; 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n > so->so_urgc) n = so->so_urgc; 3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy((buff + len), sb->sb_data, n); 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc -= n; 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len += n; 3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG 3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n != len) 3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc -= n; 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr += n; 3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr -= sb->sb_datalen; 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return n; 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Write data from so_rcv to so's socket, 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * updating all sbuf field as necessary 3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersowrite(struct socket *so) 3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n,nn; 3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_rcv; 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len = sb->sb_cc; 3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct iovec iov[2]; 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sowrite"); 3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_urgc) { 3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sosendoob(so); 3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_cc == 0) 3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * No need to check if there's something to write, 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sowrite wouldn't have been called otherwise 3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = sb->sb_cc; 3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_base = sb->sb_rptr; 3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iov[1].iov_base = NULL; 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iov[1].iov_len = 0; 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_rptr < sb->sb_wptr) { 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should never succeed, but... */ 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > len) iov[0].iov_len = len; 3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > len) iov[0].iov_len = len; 3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= iov[0].iov_len; 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) { 3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_base = sb->sb_data; 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_len = sb->sb_wptr - sb->sb_data; 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[1].iov_len > len) iov[1].iov_len = len; 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 2; 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Check if there's urgent data to send, and if so, send it */ 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_READV 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn = writev(so->s, (const struct iovec *)iov, n); 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0); 4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* This should never happen, but people tell me it does *shrug* */ 4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn < 0 && (errno == EAGAIN || errno == EINTR)) 4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn <= 0) { 4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", 4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state, errno)); 4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantsendmore(so); 4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_sockclosed(sototcpcb(so)); 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef HAVE_READV 4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n == 2 && nn == iov[0].iov_len) { 4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0); 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret > 0) 4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn += ret; 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Update sbuf */ 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc -= nn; 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr += nn; 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr -= sb->sb_datalen; 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If in DRAIN mode, and there's no more data, set 4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * it CANTSENDMORE 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantsendmore(so); 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return nn; 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * recvfrom() a UDP socket 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersorecvfrom(struct socket *so) 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in addr; 4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t addrlen = sizeof(struct sockaddr_in); 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sorecvfrom"); 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char buff[256]; 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int len; 4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = recvfrom(so->s, buff, 256, 0, 4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *)&addr, &addrlen); 4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX Check if reply is "correct"? */ 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(len == -1 || len == 0) { 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_char code=ICMP_UNREACH_PORT; 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", 4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno,strerror(errno))); 4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project icmp_reflect(so->so_m); 4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_m = NULL; /* Don't m_free() it again! */ 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* No need for this socket anymore, udp_detach it */ 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_detach(so); 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* A "normal" UDP packet */ 4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct mbuf *m; 4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len; 4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned long n; 4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n; 4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!(m = m_get())) return; 4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data += IF_MAXLINKHDR; 4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Shouldn't FIONREAD packets destined for port 53, 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but I don't know the max packet size for DNS lookups 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = M_FREEROOM(m); 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if (so->so_fport != htons(53)) { */ 4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ioctlsocket(so->s, FIONREAD, &n); 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n > len) { 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = (m->m_data - m->m_dat) + m->m_len + n + 1; 4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_inc(m, n); 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = M_FREEROOM(m); 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* } */ 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len = recvfrom(so->s, m->m_data, len, 0, 5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *)&addr, &addrlen); 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", 5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len, errno,strerror(errno))); 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(m->m_len<0) { 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_char code=ICMP_UNREACH_PORT; 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); 5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); 5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(m); 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Hack: domain name lookup will be used the most for UDP, 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and since they'll only be used once there's no need 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for the 4 minute (or whatever) timeout... So we time them 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * out much quicker (10 seconds for now...) 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_expire) { 5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_fport == htons(53)) 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = curtime + SO_EXPIREFAST; 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = curtime + SO_EXPIRE; 5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if (m->m_len == len) { 5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * m_inc(m, MINCSIZE); 5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * m->m_len = 0; 5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If this packet was destined for CTL_ADDR, 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * make it look like that's where it came from, done by udp_output 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner udp_output(so, m, &addr); 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* rx error */ 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* if ping packet */ 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sendto() a socket 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersosendto(struct socket *so, struct mbuf *m) 5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in addr; 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sosendto"); 5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("m = %lx", (long)m); 5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_family = AF_INET; 5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { 5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* It's an alias */ 5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(ntohl(so->so_faddr.s_addr) & 0xff) { 5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CTL_DNS: 5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_addr = dns_addr; 5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case CTL_ALIAS: 5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_addr = loopback_addr; 5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_addr = so->so_faddr; 5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_port = so->so_fport; 5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); 5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Don't care what port we get */ 5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = sendto(so->s, m->m_data, m->m_len, 0, 5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *)&addr, sizeof (struct sockaddr)); 5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret < 0) 5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Kill the socket if there's no reply in 4 minutes, 5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but only if it's an expirable socket 5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_expire) 5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = curtime + SO_EXPIRE; 5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */ 5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX This should really be tcp_listen 5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket * 5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersolisten(u_int port, u_int32_t laddr, u_int lport, int flags) 5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in addr; 5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int s, opt = 1; 6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t addrlen = sizeof(addr); 6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("solisten"); 6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("port = %d", port); 6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("laddr = %x", laddr); 6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("lport = %d", lport); 6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("flags = %x", flags); 6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so = socreate()) == NULL) { 6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* free(so); Not sofree() ??? free(NULL) == NOP */ 6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Don't tcp_attach... we don't need so_snd nor so_rcv */ 6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { 6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(so); 6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insque(so,&tcb); 6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SS_FACCEPTONCE sockets must time out. 6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & SS_FACCEPTONCE) 6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; 6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state = (SS_FACCEPTCONN|flags); 6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_lport = lport; /* Kept in network format */ 6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr.s_addr = laddr; /* Ditto */ 6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_family = AF_INET; 6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_addr.s_addr = INADDR_ANY; 6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_port = port; 6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || 6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || 6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || 6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (listen(s,1) < 0)) { 6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int tmperrno = errno; /* Don't clobber the real reason we failed */ 6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(s); 6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sofree(so); 6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Restore the real errno */ 6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WSASetLastError(tmperrno); 6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno = tmperrno; 6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); 6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner getsockname(s,(struct sockaddr *)&addr,&addrlen); 6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_fport = addr.sin_port; 6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) 6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr = alias_addr; 6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr = addr.sin_addr; 6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->s = s; 6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return so; 6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0 6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data is available in so_rcv 6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Just write() the data to the socket 6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX not yet... 6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsorwakeup(so) 6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sowrite(so); */ 6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FD_CLR(so->s,&writefds); */ 6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data has been freed in so_snd 6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We have room for a read() if we want to 6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * For now, don't read, it'll be done in the main loop 6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsowwakeup(so) 6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Nothing, yet */ 6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Various session state calls 6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Should be #define's 6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The socket state stuff needs work, these often get call 2 or 3 6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * times each when only 1 was needed 6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfconnecting(struct socket *so) 6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| 7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SS_FCANTSENDMORE|SS_FWDRAIN); 7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ 7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfconnected(struct socket *so) 7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); 7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ 7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofcantrcvmore(struct socket *so) 7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_state & SS_NOFDREF) == 0) { 7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shutdown(so->s,0); 7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(global_writefds) { 7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FD_CLR(so->s,global_writefds); 7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~(SS_ISFCONNECTING); 7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_FCANTSENDMORE) 7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */ 7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_FCANTRCVMORE; 7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofcantsendmore(struct socket *so) 7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_state & SS_NOFDREF) == 0) { 7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shutdown(so->s,1); /* send FIN to fhost */ 7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (global_readfds) { 7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FD_CLR(so->s,global_readfds); 7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (global_xfds) { 7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FD_CLR(so->s,global_xfds); 7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~(SS_ISFCONNECTING); 7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_FCANTRCVMORE) 7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_NOFDREF; /* as above */ 7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_FCANTSENDMORE; 7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfdisconnected(struct socket *so) 7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */ 7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* close(so->s); */ 7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* so->so_state = SS_ISFDISCONNECTED; */ 7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Do nothing ... ? 7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set write drain mode 7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set CANTSENDMORE once all data has been write()n 7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofwdrain(struct socket *so) 7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_rcv.sb_cc) 7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_FWDRAIN; 7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantsendmore(so); 7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 769