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 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define WANT_SYS_IOCTL_H 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h" 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h> 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ip_icmp.h" 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "main.h" 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __sun__ 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/filio.h> 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SLIRP_COMPILATION 1 17cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/sockets.h" 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "proxy_common.h" 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void sofcantrcvmore(struct socket *so); 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void sofcantsendmore(struct socket *so); 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectso_init() 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Nothing yet */ 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket * 325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersolookup(struct socket *head, uint32_t laddr, u_int lport, 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t faddr, u_int fport) 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (so = head->so_next; so != head; so = so->so_next) { 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_laddr_port == lport && 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_laddr_ip == laddr && 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_faddr_ip == faddr && 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_faddr_port == fport) 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so == head) 468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (struct socket *)NULL; 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return so; 488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Create a new socket, initialise the fields 538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * It is the responsibility of the caller to 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * insque() it into the correct linked-list 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket * 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersocreate(void) 588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so = (struct socket *)malloc(sizeof(struct socket)); 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(so) { 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(so, 0, sizeof(struct socket)); 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_NOFDREF; 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->s = -1; 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return(so); 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * remque and free a socket, clobber cache 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofree(struct socket *so) 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_PROXIFIED) 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project proxy_manager_del(so); 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_emu==EMU_RSH && so->extra) { 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofree(so->extra); 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->extra=NULL; 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so == tcp_last_so) 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_last_so = &tcb; 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (so == udp_last_so) 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_last_so = &udb; 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(so->so_m); 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(so->so_next && so->so_prev) 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project remque(so); /* crashes if so is not in a queue */ 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(so); 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersize_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n, lss, total; 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_snd; 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len = sb->sb_datalen - sb->sb_cc; 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int mss = so->so_tcpcb->t_maxseg; 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_CALL("sopreprbuf"); 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long )so); 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = sb->sb_datalen - sb->sb_cc; 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len <= 0) 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_base = sb->sb_wptr; 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iov[1].iov_base = NULL; 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iov[1].iov_len = 0; 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_wptr < sb->sb_rptr) { 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should never succeed, but... */ 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > len) 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = len; 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > mss) 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len -= iov[0].iov_len%mss; 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should never succeed, but... */ 1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > len) iov[0].iov_len = len; 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= iov[0].iov_len; 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) { 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_base = sb->sb_data; 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_len = sb->sb_rptr - sb->sb_data; 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(iov[1].iov_len > len) 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_len = len; 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project total = iov[0].iov_len + iov[1].iov_len; 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (total > mss) { 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lss = total%mss; 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[1].iov_len > lss) { 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_len -= lss; 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 2; 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lss -= iov[1].iov_len; 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len -= lss; 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 2; 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > mss) 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len -= iov[0].iov_len%mss; 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (np) 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *np = n; 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return iov[0].iov_len + (n - 1) * iov[1].iov_len; 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Read from so's socket into sb_snd, updating all relevant sbuf fields 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NOTE: This will only be called if it is select()ed for reading, so 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * a read() of 0 (or less) means it's disconnected 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoread(struct socket *so) 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n, nn; 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_snd; 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct iovec iov[2]; 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_CALL("soread"); 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("so = %lx", (long )so); 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * No need to check if there's enough room to read. 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * soread wouldn't have been called if there weren't 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sopreprbuf(so, iov, &n); 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_READV 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn = readv(so->s, (struct iovec *)iov, n); 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn = socket_recv(so->s, iov[0].iov_base, iov[0].iov_len); 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn <= 0) { 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn < 0 && (errno == EINTR || errno == EAGAIN)) 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else { 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,errno_str)); 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantrcvmore(so); 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_sockclosed(sototcpcb(so)); 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef HAVE_READV 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If there was no error, try and read the second time round 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We read again if n = 2 (ie, there's another part of the buffer) 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and we read as much as we could in the first read 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We don't test for <= 0 this time, because there legitimately 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * might not be any more data (since the socket is non-blocking), 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * a close will be detected on next iteration. 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * A return of -1 wont (shouldn't) happen, since it didn't happen above 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n == 2 && nn == iov[0].iov_len) { 2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = socket_recv(so->s, iov[1].iov_base, iov[1].iov_len); 2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret > 0) 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn += ret; 2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Update fields */ 2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc += nn; 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_wptr += nn; 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) 2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_wptr -= sb->sb_datalen; 2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return nn; 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint soreadbuf(struct socket *so, const char *buf, int size) 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n, nn, copy = size; 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_snd; 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct iovec iov[2]; 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_CALL("soreadbuf"); 2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("so = %lx", (long )so); 2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * No need to check if there's enough room to read. 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * soread wouldn't have been called if there weren't 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sopreprbuf(so, iov, &n) < size) 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto err; 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nn = MIN(iov[0].iov_len, copy); 2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(iov[0].iov_base, buf, nn); 2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner copy -= nn; 2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf += nn; 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (copy == 0) 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto done; 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(iov[1].iov_base, buf, copy); 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerdone: 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Update fields */ 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sb->sb_cc += size; 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sb->sb_wptr += size; 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sb->sb_wptr -= sb->sb_datalen; 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return size; 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnererr: 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sofcantrcvmore(so); 2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_sockclosed(sototcpcb(so)); 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "soreadbuf buffer to small"); 2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Get urgent data 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * When the socket is created, we set it SO_OOBINLINE, 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so when OOB data arrives, we soread() it and everything 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the send buffer is sent as urgent data 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersorecvoob(struct socket *so) 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct tcpcb *tp = sototcpcb(so); 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sorecvoob"); 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We take a guess at how much urgent data has arrived. 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In most situations, when urgent data arrives, the next 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * read() should get all the urgent data. This guess will 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * be wrong however if more data arrives just after the 2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * urgent data, or the read() doesn't return all the 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * urgent data. 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project soread(so); 2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_force = 1; 2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_output(tp); 2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tp->t_force = 0; 2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Send urgent data 2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * There's a lot duplicated code here, but... 2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersosendoob(struct socket *so) 3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_rcv; 3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ 3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n, len; 3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sosendoob"); 3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); 3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_urgc > 2048) 3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc = 2048; /* XXXX */ 3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_rptr < sb->sb_wptr) { 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We can send it directly */ 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = socket_send_oob(so->s, sb->sb_rptr, so->so_urgc); /* |MSG_DONTWAIT)); */ 3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc -= n; 3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Since there's no sendv or sendtov like writev, 3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we must copy all data to a linear buffer then 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * send it all 3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len > so->so_urgc) len = so->so_urgc; 3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy(buff, sb->sb_rptr, len); 3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc -= len; 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_urgc) { 3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = sb->sb_wptr - sb->sb_data; 3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n > so->so_urgc) n = so->so_urgc; 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memcpy((buff + len), sb->sb_data, n); 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_urgc -= n; 3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len += n; 3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = socket_send_oob(so->s, buff, len); /* |MSG_DONTWAIT)); */ 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG 3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n != len) 3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc -= n; 3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr += n; 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr -= sb->sb_datalen; 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return n; 3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Write data from so_rcv to so's socket, 3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * updating all sbuf field as necessary 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersowrite(struct socket *so) 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n,nn; 3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sbuf *sb = &so->so_rcv; 3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len = sb->sb_cc; 3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct iovec iov[2]; 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sowrite"); 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_urgc) { 3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sosendoob(so); 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_cc == 0) 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * No need to check if there's something to write, 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sowrite wouldn't have been called otherwise 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = sb->sb_cc; 3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_base = sb->sb_rptr; 3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iov[1].iov_base = NULL; 3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iov[1].iov_len = 0; 3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_rptr < sb->sb_wptr) { 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; 3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should never succeed, but... */ 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > len) iov[0].iov_len = len; 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[0].iov_len > len) iov[0].iov_len = len; 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len -= iov[0].iov_len; 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len) { 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_base = sb->sb_data; 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iov[1].iov_len = sb->sb_wptr - sb->sb_data; 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (iov[1].iov_len > len) iov[1].iov_len = len; 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 2; 3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 1; 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Check if there's urgent data to send, and if so, send it */ 4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_READV 4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn = writev(so->s, (const struct iovec *)iov, n); 4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn = socket_send(so->s, iov[0].iov_base, iov[0].iov_len); 4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* This should never happen, but people tell me it does *shrug* */ 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn < 0 && (errno == EAGAIN || errno == EINTR)) 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (nn <= 0) { 4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", 4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state, errno)); 4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantsendmore(so); 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcp_sockclosed(sototcpcb(so)); 4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef HAVE_READV 4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n == 2 && nn == iov[0].iov_len) { 4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int ret; 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = socket_send(so->s, iov[1].iov_base, iov[1].iov_len); 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret > 0) 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nn += ret; 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Update sbuf */ 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_cc -= nn; 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr += nn; 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sb->sb_rptr -= sb->sb_datalen; 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If in DRAIN mode, and there's no more data, set 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * it CANTSENDMORE 4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantsendmore(so); 4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return nn; 4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * recvfrom() a UDP socket 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersorecvfrom(struct socket *so) 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SockAddress addr; 4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sorecvfrom"); 4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char buff[256]; 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int len; 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = socket_recvfrom(so->s, buff, 256, &addr); 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX Check if reply is "correct"? */ 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(len == -1 || len == 0) { 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_char code=ICMP_UNREACH_PORT; 4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; 4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project errno,errno_str)); 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str); 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project icmp_reflect(so->so_m); 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_m = 0; /* Don't mbuf_free() it again! */ 4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* No need for this socket anymore, udp_detach it */ 4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_detach(so); 4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* A "normal" UDP packet */ 4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct mbuf *m; 4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len; 4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n; 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!(m = m_get())) return; 4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data += IF_MAXLINKHDR; 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Shouldn't FIONREAD packets destined for port 53, 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but I don't know the max packet size for DNS lookups 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = M_FREEROOM(m); 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if (so->so_fport != htons(53)) { */ 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = socket_can_read(so->s); 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n > len) { 4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = (m->m_data - m->m_dat) + m->m_len + n + 1; 4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_inc(m, n); 5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = M_FREEROOM(m); 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* } */ 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len = socket_recvfrom(so->s, m->m_data, len, &addr); 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len, errno,errno_str)); 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(m->m_len<0) { 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u_char code=ICMP_UNREACH_PORT; 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str); 5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(m); 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Hack: domain name lookup will be used the most for UDP, 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and since they'll only be used once there's no need 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for the 4 minute (or whatever) timeout... So we time them 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * out much quicker (10 seconds for now...) 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_expire) { 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_faddr_port == 53) 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = curtime + SO_EXPIREFAST; 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = curtime + SO_EXPIRE; 5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if (m->m_len == len) { 5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * m_inc(m, MINCSIZE); 5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * m->m_len = 0; 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * } 5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If this packet was destined for CTL_ADDR, 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * make it look like that's where it came from, done by udp_output 5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_output_(so, m, &addr); 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* rx error */ 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* if ping packet */ 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sendto() a socket 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersosendto(struct socket *so, struct mbuf *m) 5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SockAddress addr; 5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t addr_ip; 5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t addr_port; 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("sosendto"); 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("so = %lx", (long)so); 5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("m = %lx", (long)m); 5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) { 5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* It's an alias */ 5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int low = so->so_faddr_ip & 0xff; 5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ( CTL_IS_DNS(low) ) 5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr_ip = dns_addr[low - CTL_DNS]; 5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr_ip = loopback_addr_ip; 5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else 5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr_ip = so->so_faddr_ip; 5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr_port = so->so_faddr_port; 5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5737339b55944e97077e4f74c4be34cd956ae44198brich cannings /* 5747339b55944e97077e4f74c4be34cd956ae44198brich cannings * test for generic forwarding; this function replaces the arguments 5757339b55944e97077e4f74c4be34cd956ae44198brich cannings * only on success 5767339b55944e97077e4f74c4be34cd956ae44198brich cannings */ 5777339b55944e97077e4f74c4be34cd956ae44198brich cannings unsigned long faddr = addr_ip; 5787339b55944e97077e4f74c4be34cd956ae44198brich cannings int fport = addr_port; 5797339b55944e97077e4f74c4be34cd956ae44198brich cannings 5807339b55944e97077e4f74c4be34cd956ae44198brich cannings if (slirp_should_net_forward(faddr, fport, &faddr, &fport)) { 581d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings time_t timestamp = time(NULL); 582d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings slirp_drop_log( 5837339b55944e97077e4f74c4be34cd956ae44198brich cannings "Redirected UDP: src: 0x%08lx:0x%04x org dst: 0x%08lx:0x%04x " 584d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings "new dst: 0x%08lx:0x%04x %ld\n", 5857339b55944e97077e4f74c4be34cd956ae44198brich cannings so->so_laddr_ip, so->so_laddr_port, 5867339b55944e97077e4f74c4be34cd956ae44198brich cannings addr_ip, addr_port, 587d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings faddr, fport, timestamp 5887339b55944e97077e4f74c4be34cd956ae44198brich cannings ); 5897339b55944e97077e4f74c4be34cd956ae44198brich cannings } 5907339b55944e97077e4f74c4be34cd956ae44198brich cannings addr_ip = faddr; 5917339b55944e97077e4f74c4be34cd956ae44198brich cannings addr_port = fport; 5927339b55944e97077e4f74c4be34cd956ae44198brich cannings 5937339b55944e97077e4f74c4be34cd956ae44198brich cannings 5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sock_address_init_inet(&addr, addr_ip, addr_port); 5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%08x\n", addr_port, addr_ip)); 5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Don't care what port we get */ 5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = socket_sendto(so->s, m->m_data, m->m_len,&addr); 6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret < 0) 6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Kill the socket if there's no reply in 4 minutes, 6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but only if it's an expirable socket 6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_expire) 6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = curtime + SO_EXPIRE; 6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */ 6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX This should really be tcp_listen 6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket * 6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersolisten(u_int port, u_int32_t laddr, u_int lport, int flags) 6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SockAddress addr; 6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t addr_ip; 6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int s; 6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("solisten"); 6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("port = %d", port); 6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("laddr = %x", laddr); 6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("lport = %d", lport); 6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("flags = %x", flags); 6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so = socreate()) == NULL) { 6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* free(so); Not sofree() ??? free(NULL) == NOP */ 6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Don't tcp_attach... we don't need so_snd nor so_rcv */ 6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { 6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(so); 6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insque(so,&tcb); 6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SS_FACCEPTONCE sockets must time out. 6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & SS_FACCEPTONCE) 6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; 6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = (SS_FACCEPTCONN|flags); 6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_laddr_port = lport; /* Kept in host format */ 6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr_ip = laddr; /* Ditto */ 6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_haddr_port = port; 6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = socket_loopback_server( port, SOCKET_STREAM ); 6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s < 0) 6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_get_address(s, &addr); 6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_faddr_port = sock_address_get_port(&addr); 6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr_ip = (uint32_t) sock_address_get_ip(&addr); 6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (addr_ip == 0 || addr_ip == loopback_addr_ip) 6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr_ip = alias_addr_ip; 6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr_ip = addr_ip; 6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->s = s; 6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return so; 6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsounlisten(u_int port) 6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (so = tcb.so_next; so != &tcb; so = so->so_next) { 6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_haddr_port == port) { 6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so == &tcb) { 6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantrcvmore( so ); 6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantsendmore( so ); 6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project close( so->s ); 6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->s = -1; 6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofree( so ); 6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0 6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data is available in so_rcv 7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Just write() the data to the socket 7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX not yet... 7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsorwakeup(so) 7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sowrite(so); */ 7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FD_CLR(so->s,&writefds); */ 7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data has been freed in so_snd 7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We have room for a read() if we want to 7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * For now, don't read, it'll be done in the main loop 7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsowwakeup(so) 7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Nothing, yet */ 7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Various session state calls 7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Should be #define's 7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The socket state stuff needs work, these often get call 2 or 3 7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * times each when only 1 was needed 7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfconnecting(struct socket *so) 7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| 7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SS_FCANTSENDMORE|SS_FWDRAIN); 7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ 7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfconnected(struct socket *so) 7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); 7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ 7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofcantrcvmore(struct socket *so) 7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_state & SS_NOFDREF) == 0) { 7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shutdown(so->s,0); 7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(global_writefds) { 7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FD_CLR(so->s,global_writefds); 7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~(SS_ISFCONNECTING); 7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_FCANTSENDMORE) 7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */ 7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_FCANTRCVMORE; 7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofcantsendmore(struct socket *so) 7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_state & SS_NOFDREF) == 0) { 7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shutdown(so->s,1); /* send FIN to fhost */ 7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (global_readfds) { 7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FD_CLR(so->s,global_readfds); 7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (global_xfds) { 7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project FD_CLR(so->s,global_xfds); 7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state &= ~(SS_ISFCONNECTING); 7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_state & SS_FCANTRCVMORE) 7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_NOFDREF; /* as above */ 7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_FCANTSENDMORE; 7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfdisconnected(struct socket *so) 7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */ 7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* close(so->s); */ 7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* so->so_state = SS_ISFDISCONNECTED; */ 7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Do nothing ... ? 7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set write drain mode 7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set CANTSENDMORE once all data has been write()n 7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofwdrain(struct socket *so) 7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_rcv.sb_cc) 7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state |= SS_FWDRAIN; 8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofcantsendmore(so); 8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 803