18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1982, 1986, 1988, 1990, 1993 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The Regents of the University of California. All rights reserved. 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modification, are permitted provided that the following conditions 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are met: 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * documentation and/or other materials provided with the distribution. 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 3. Neither the name of the University nor the names of its contributors 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * may be used to endorse or promote products derived from this software 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * without specific prior written permission. 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SUCH DAMAGE. 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Changes and additions relating to SLiRP 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1995 Danny Gasparovski. 368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Please read the file COPYRIGHT for the 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * terms and conditions of the copyright. 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h> 428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ip_icmp.h" 438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SLIRP_COMPILATION 1 44cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/sockets.h" 458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef LOG_ENABLED 478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct udpstat udpstat; 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 507339b55944e97077e4f74c4be34cd956ae44198brich cannings/* Keeps track of the number of DNS requests. Used to implement the firewall 517339b55944e97077e4f74c4be34cd956ae44198brich cannings * option that restricts the number of DNS requests (-max_dns_conns). */ 527339b55944e97077e4f74c4be34cd956ae44198brich canningsu_int dns_num_conns; 537339b55944e97077e4f74c4be34cd956ae44198brich cannings 548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket udb; 558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic u_int8_t udp_tos(struct socket *so); 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void udp_emu(struct socket *so, struct mbuf *m); 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * UDP protocol implementation. 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Per RFC 768, August, 1980. 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef COMPAT_42 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define UDPCKSUM 1 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define UDPCKSUM 0 /* XXX */ 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket *udp_last_so = &udb; 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_init(void) 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udb.so_next = udb.so_prev = &udb; 757339b55944e97077e4f74c4be34cd956ae44198brich cannings dns_num_conns = 0; 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* m->m_data points at ip packet header 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * m->m_len length ip packet 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ip->ip_len length data (IPDU) 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_input(register struct mbuf *m, int iphlen) 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct ip *ip; 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct udphdr *uh; 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* struct mbuf *opts = 0;*/ 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int len; 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct ip save_ip; 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("udp_input"); 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("m = %lx", (long)m); 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("iphlen = %d", iphlen); 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udps_ipackets++); 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Strip IP options, if any; should skip this, 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * make available to user, and use on returned packets, 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but we don't yet have a way to check the checksum 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * with options still present. 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(iphlen > sizeof(struct ip)) { 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_stripoptions(m, (struct mbuf *)0); 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iphlen = sizeof(struct ip); 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Get IP and UDP header together in first mbuf. 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip = mtod(m, struct ip *); 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uh = (struct udphdr *)((caddr_t)ip + iphlen); 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Make mbuf data length reflect UDP length. 1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If not enough data to reflect UDP length, drop. 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = ntohs((u_int16_t)uh->uh_ulen); 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ip->ip_len != len) { 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (len > ip->ip_len) { 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udps_badlen++); 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(m, len - ip->ip_len); 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ip->ip_len = len; 1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1297339b55944e97077e4f74c4be34cd956ae44198brich cannings /* ------------------------------------------------------*/ 1307339b55944e97077e4f74c4be34cd956ae44198brich cannings /* User mode network stack restrictions */ 1317339b55944e97077e4f74c4be34cd956ae44198brich cannings /* slirp_should_drop requires host byte ordering in arguments */ 132d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings time_t timestamp = time(NULL); 133d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings 1347339b55944e97077e4f74c4be34cd956ae44198brich cannings if (slirp_should_drop(ntohl(ip->ip_dst.addr), ntohs(uh->uh_dport.port), 1357339b55944e97077e4f74c4be34cd956ae44198brich cannings IPPROTO_UDP)) { 1367339b55944e97077e4f74c4be34cd956ae44198brich cannings slirp_drop_log( 137d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings "Dropped UDP: src: 0x%08lx:0x%04x dst: 0x%08lx:0x%04x %ld\n", 138d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings ntohl(ip->ip_src.addr), 139d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings ntohs(uh->uh_sport.port), 140d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings ntohl(ip->ip_dst.addr), 141d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings ntohs(uh->uh_dport.port), 142d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings timestamp 1437339b55944e97077e4f74c4be34cd956ae44198brich cannings ); 1447339b55944e97077e4f74c4be34cd956ae44198brich cannings goto bad; /* drop the packet */ 1457339b55944e97077e4f74c4be34cd956ae44198brich cannings } 1467339b55944e97077e4f74c4be34cd956ae44198brich cannings else { 1477339b55944e97077e4f74c4be34cd956ae44198brich cannings slirp_drop_log( 148d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings "Allowed UDP: src: 0x%08lx:0x%04x dst: 0x%08lx:0x%04x %ld\n", 149d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings ntohl(ip->ip_src.addr), 150d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings ntohs(uh->uh_sport.port), 151d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings ntohl(ip->ip_dst.addr), 152d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings ntohs(uh->uh_dport.port), 153d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings timestamp 1547339b55944e97077e4f74c4be34cd956ae44198brich cannings ); 1557339b55944e97077e4f74c4be34cd956ae44198brich cannings } 1567339b55944e97077e4f74c4be34cd956ae44198brich cannings /* ------------------------------------------------------*/ 1577339b55944e97077e4f74c4be34cd956ae44198brich cannings 1587339b55944e97077e4f74c4be34cd956ae44198brich cannings 1597339b55944e97077e4f74c4be34cd956ae44198brich cannings 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Save a copy of the IP header in case we want restore it 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for sending an ICMP error message in response. 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project save_ip = *ip; 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project save_ip.ip_len+= iphlen; /* tcp_input subtracts this */ 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Checksum extended UDP header and data. 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (UDPCKSUM && uh->uh_sum) { 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr)); 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((struct ipovly *)ip)->ih_x1 = 0; 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((struct ipovly *)ip)->ih_len = uh->uh_ulen; 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* keep uh_sum for ICMP reply 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * uh->uh_sum = cksum(m, len + sizeof (struct ip)); 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if (uh->uh_sum) { 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(cksum(m, len + sizeof(struct ip))) { 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udps_badsum++); 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * handle DHCP/BOOTP 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (port_geth(uh->uh_dport) == BOOTP_SERVER) { 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bootp_input(m); 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_restrict) 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * handle TFTP 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (port_geth(uh->uh_dport) == TFTP_SERVER) { 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tftp_input(m); 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2037339b55944e97077e4f74c4be34cd956ae44198brich cannings // DNS logging and FW rules 2047339b55944e97077e4f74c4be34cd956ae44198brich cannings if (ntohs(uh->uh_dport.port) == 53) { 2057339b55944e97077e4f74c4be34cd956ae44198brich cannings if (!slirp_dump_dns(m)) { 2067339b55944e97077e4f74c4be34cd956ae44198brich cannings DEBUG_MISC((dfd,"Error logging DNS packet")); 2077339b55944e97077e4f74c4be34cd956ae44198brich cannings } 2087339b55944e97077e4f74c4be34cd956ae44198brich cannings dns_num_conns++; 2097339b55944e97077e4f74c4be34cd956ae44198brich cannings if (slirp_get_max_dns_conns() != -1 && 2107339b55944e97077e4f74c4be34cd956ae44198brich cannings dns_num_conns > slirp_get_max_dns_conns()) 2117339b55944e97077e4f74c4be34cd956ae44198brich cannings goto bad; 2127339b55944e97077e4f74c4be34cd956ae44198brich cannings } 2137339b55944e97077e4f74c4be34cd956ae44198brich cannings 2147339b55944e97077e4f74c4be34cd956ae44198brich cannings 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Locate pcb for datagram. 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so = udp_last_so; 2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_laddr_port != port_geth(uh->uh_sport) || 2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_laddr_ip != ip_geth(ip->ip_src)) { 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *tmp; 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { 2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tmp->so_laddr_port == port_geth(uh->uh_sport) && 2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp->so_laddr_ip == ip_geth(ip->ip_src)) { 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp->so_faddr_ip = ip_geth(ip->ip_dst); 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp->so_faddr_port = port_geth(uh->uh_dport); 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so = tmp; 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tmp == &udb) { 2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so = NULL; 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udpps_pcbcachemiss++); 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_last_so = so; 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so == NULL) { 2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If there's no socket for this packet, 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * create one 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so = socreate()) == NULL) goto bad; 2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(udp_attach(so) == -1) { 2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", 2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project errno,errno_str)); 2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofree(so); 2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto bad; 2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Setup fields 2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* udp_last_so = so; */ 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_laddr_ip = ip_geth(ip->ip_src); 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_laddr_port = port_geth(uh->uh_sport); 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_iptos = udp_tos(so)) == 0) 2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_iptos = ip->ip_tos; 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXXXX Here, check if it's in udpexec_list, 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and if it is, do the fork_exec() etc. 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_faddr_ip = ip_geth(ip->ip_dst); /* XXX */ 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_faddr_port = port_geth(uh->uh_dport); /* XXX */ 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iphlen += sizeof(struct udphdr); 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len -= iphlen; 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data += iphlen; 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Now we sendto() the packet. 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->so_emu) 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_emu(so, m); 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if(sosendto(so,m) == -1) { 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len += iphlen; 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data -= iphlen; 2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *ip=save_ip; 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno, errno_str)); 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,errno_str); 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ 2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* restore the orig mbuf packet */ 2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_len += iphlen; 2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project m->m_data -= iphlen; 2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *ip=save_ip; 2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_m=m; /* ICMP backup */ 2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbad: 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* if (opts) m_freem(opts); */ 3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint udp_output2_(struct socket *so, struct mbuf *m, 306c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner const SockAddress* saddr, 3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project const SockAddress* daddr, 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int iptos) 3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project register struct udpiphdr *ui; 3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t saddr_ip = sock_address_get_ip(saddr); 3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t daddr_ip = sock_address_get_ip(daddr); 3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int saddr_port = sock_address_get_port(saddr); 3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int daddr_port = sock_address_get_port(daddr); 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int error = 0; 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_CALL("udp_output"); 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("so = %lx", (long)so); 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("m = %lx", (long)m); 3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("saddr = %lx", (long) saddr_ip); 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DEBUG_ARG("daddr = %lx", (long) daddr_ip); 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Adjust for header 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data -= sizeof(struct udpiphdr); 3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len += sizeof(struct udpiphdr); 3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Fill in mbuf with extended UDP header 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * and addresses and length put into network format. 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui = mtod(m, struct udpiphdr *); 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_x1 = 0; 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_pr = IPPROTO_UDP; 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */ 3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXXXX Check for from-one-location sockets, or from-any-location sockets */ 3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ui->ui_src = ip_seth(saddr_ip); 3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ui->ui_dst = ip_seth(daddr_ip); 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ui->ui_sport = port_seth(saddr_port); 3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ui->ui_dport = port_seth(daddr_port); 3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_ulen = ui->ui_len; 3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Stuff checksum and output datagram. 3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_sum = 0; 3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (UDPCKSUM) { 3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) 3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_sum = 0xffff; 3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ip *)ui)->ip_len = m->m_len; 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ip *)ui)->ip_ttl = IPDEFTTL; 3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ip *)ui)->ip_tos = iptos; 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udps_opackets++); 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3607339b55944e97077e4f74c4be34cd956ae44198brich cannings // DNS logging 361d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings if (so != NULL && so->so_faddr_port == 53) { /*so has host byte order */ 3627339b55944e97077e4f74c4be34cd956ae44198brich cannings if (!slirp_dump_dns(m)) { 3637339b55944e97077e4f74c4be34cd956ae44198brich cannings DEBUG_MISC((dfd,"Error logging DNS packet")); 3647339b55944e97077e4f74c4be34cd956ae44198brich cannings } 3657339b55944e97077e4f74c4be34cd956ae44198brich cannings } 3667339b55944e97077e4f74c4be34cd956ae44198brich cannings 3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner error = ip_output(so, m); 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return (error); 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint udp_output_(struct socket *so, struct mbuf *m, 3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SockAddress* from) 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SockAddress saddr, daddr; 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t saddr_ip; 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t saddr_port; 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project saddr_ip = sock_address_get_ip(from); 3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project saddr_port = sock_address_get_port(from); 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) { 3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project saddr_ip = so->so_faddr_ip; 3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so->so_faddr_ip & 0x000000ff) == 0xff) 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project saddr_ip = alias_addr_ip; 3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sock_address_init_inet( &saddr, saddr_ip, saddr_port ); 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sock_address_init_inet( &daddr, so->so_laddr_ip, so->so_laddr_port ); 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return udp_output2_(so, m, &saddr, &daddr, so->so_iptos); 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint 3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_attach(struct socket *so) 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->s = socket_anyaddr_server( 0, SOCKET_DGRAM ); 3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->s != -1) { 3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* success, insert in queue */ 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = curtime + SO_EXPIRE; 4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insque(so,&udb); 4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return(so->s); 4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_detach(struct socket *so) 4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project socket_close(so->s); 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* if (so->so_m) m_free(so->so_m); done by sofree */ 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sofree(so); 4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const struct tos_t udptos[] = { 4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ 4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ 4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME}, /* Cu-Seeme */ 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {0, 0, 0, 0} 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic u_int8_t 4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_tos(struct socket *so) 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i = 0; 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while(udptos[i].tos) { 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((udptos[i].fport && so->so_faddr_port == udptos[i].fport) || 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (udptos[i].lport && so->so_laddr_port == udptos[i].lport)) { 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_emu = udptos[i].emu; 4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return udptos[i].tos; 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i++; 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Here, talk/ytalk/ntalk requests must be emulated 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_emu(struct socket *so, struct mbuf *m) 4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SockAddress sockaddr; 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct cu_header { 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t d_family; // destination family 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t d_port; // destination port 4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t d_addr; // destination address 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t s_family; // source family 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t s_port; // source port 4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t so_addr; // source address 4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t seqn; // sequence number 4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t message; // message 4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t data_type; // data type 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t pkt_len; // packet length 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} *cu_head; 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(so->so_emu) { 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case EMU_CUSEEME: 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Cu-SeeMe emulation. 4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Hopefully the packet is more that 16 bytes long. We don't 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * do any other tests, just replace the address and port 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * fields. 4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (m->m_len >= sizeof (*cu_head)) { 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (socket_get_address(so->s, &sockaddr) < 0) 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cu_head = mtod(m, struct cu_header *); 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cu_head->s_port = htons( sock_address_get_port(&sockaddr)); 4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cu_head->so_addr = htonl( sock_address_get_ip(&sockaddr)); 4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket * 4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_listen(u_int port, u_int32_t laddr, u_int lport, int flags) 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct socket *so; 4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project SockAddress addr; 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t addr_ip; 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((so = socreate()) == NULL) { 4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project free(so); 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->s = socket_anyaddr_server( port, SOCKET_DGRAM ); 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = curtime + SO_EXPIRE; 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_haddr_port = port; 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insque(so,&udb); 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (so->s < 0) { 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project udp_detach(so); 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return NULL; 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project socket_get_address(so->s, &addr); 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_faddr_port = sock_address_get_port(&addr); 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr_ip = sock_address_get_ip(&addr); 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (addr_ip == 0 || addr_ip == loopback_addr_ip) 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_faddr_ip = alias_addr_ip; 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_faddr_ip = addr_ip; 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_laddr_port = lport; 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_laddr_ip = laddr; 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags != SS_FACCEPTONCE) 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_expire = 0; 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so->so_state = SS_ISFCONNECTED; 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return so; 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint udp_unlisten (u_int port) 5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return slirp_unredir(1, port); 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 530