15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 1982, 1986, 1988, 1990, 1993 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The Regents of the University of California. All rights reserved. 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Redistribution and use in source and binary forms, with or without 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * modification, are permitted provided that the following conditions 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * are met: 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 1. Redistributions of source code must retain the above copyright 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * notice, this list of conditions and the following disclaimer. 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 2. Redistributions in binary form must reproduce the above copyright 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * notice, this list of conditions and the following disclaimer in the 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 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 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * may be used to endorse or promote products derived from this software 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * without specific prior written permission. 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * SUCH DAMAGE. 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Changes and additions relating to SLiRP 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 1995 Danny Gasparovski. 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Please read the file COPYRIGHT for the 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * terms and conditions of the copyright. 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <slirp.h> 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "ip_icmp.h" 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef LOG_ENABLED 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct udpstat udpstat; 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct socket udb; 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic u_int8_t udp_tos(struct socket *so); 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void udp_emu(struct socket *so, struct mbuf *m); 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * UDP protocol implementation. 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Per RFC 768, August, 1980. 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef COMPAT_42 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define UDPCKSUM 1 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define UDPCKSUM 0 /* XXX */ 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct socket *udp_last_so = &udb; 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_init(void) 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner udb.so_next = udb.so_prev = &udb; 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* m->m_data points at ip packet header 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * m->m_len length ip packet 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * ip->ip_len length data (IPDU) 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_input(register struct mbuf *m, int iphlen) 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct ip *ip; 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct udphdr *uh; 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* struct mbuf *opts = 0;*/ 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len; 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ip save_ip; 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so; 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_CALL("udp_input"); 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("m = %lx", (long)m); 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("iphlen = %d", iphlen); 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udps_ipackets++); 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Strip IP options, if any; should skip this, 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * make available to user, and use on returned packets, 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * but we don't yet have a way to check the checksum 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * with options still present. 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(iphlen > sizeof(struct ip)) { 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip_stripoptions(m, (struct mbuf *)0); 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iphlen = sizeof(struct ip); 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Get IP and UDP header together in first mbuf. 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip = mtod(m, struct ip *); 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uh = (struct udphdr *)((caddr_t)ip + iphlen); 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Make mbuf data length reflect UDP length. 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * If not enough data to reflect UDP length, drop. 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = ntohs((u_int16_t)uh->uh_ulen); 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ip->ip_len != len) { 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len > ip->ip_len) { 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udps_badlen++); 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_adj(m, len - ip->ip_len); 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip->ip_len = len; 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Save a copy of the IP header in case we want restore it 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * for sending an ICMP error message in response. 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner save_ip = *ip; 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner save_ip.ip_len+= iphlen; /* tcp_input subtracts this */ 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Checksum extended UDP header and data. 1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (UDPCKSUM && uh->uh_sum) { 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr)); 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ipovly *)ip)->ih_x1 = 0; 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ipovly *)ip)->ih_len = uh->uh_ulen; 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* keep uh_sum for ICMP reply 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * uh->uh_sum = cksum(m, len + sizeof (struct ip)); 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * if (uh->uh_sum) { 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(cksum(m, len + sizeof(struct ip))) { 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udps_badsum++); 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * handle DHCP/BOOTP 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ntohs(uh->uh_dport) == BOOTP_SERVER) { 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bootp_input(m); 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_restrict) 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * handle TFTP 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ntohs(uh->uh_dport) == TFTP_SERVER) { 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tftp_input(m); 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Locate pcb for datagram. 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so = udp_last_so; 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_lport != uh->uh_sport || 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr.s_addr != ip->ip_src.s_addr) { 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *tmp; 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tmp->so_lport == uh->uh_sport && 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp->so_laddr.s_addr == ip->ip_src.s_addr) { 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp->so_faddr.s_addr = ip->ip_dst.s_addr; 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp->so_fport = uh->uh_dport; 1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so = tmp; 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tmp == &udb) { 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so = NULL; 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udpps_pcbcachemiss++); 1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner udp_last_so = so; 1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so == NULL) { 1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * If there's no socket for this packet, 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * create one 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so = socreate()) == NULL) goto bad; 1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(udp_attach(so) == -1) { 1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno,strerror(errno))); 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sofree(so); 2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto bad; 2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Setup fields 2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* udp_last_so = so; */ 2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr = ip->ip_src; 2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_lport = uh->uh_sport; 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_iptos = udp_tos(so)) == 0) 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_iptos = ip->ip_tos; 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * XXXXX Here, check if it's in udpexec_list, 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * and if it is, do the fork_exec() etc. 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr = ip->ip_dst; /* XXX */ 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_fport = uh->uh_dport; /* XXX */ 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner iphlen += sizeof(struct udphdr); 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len -= iphlen; 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data += iphlen; 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Now we sendto() the packet. 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so->so_emu) 2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner udp_emu(so, m); 2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(sosendto(so,m) == -1) { 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len += iphlen; 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data -= iphlen; 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *ip=save_ip; 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ 2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* restore the orig mbuf packet */ 2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len += iphlen; 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data -= iphlen; 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *ip=save_ip; 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_m=m; /* ICMP backup */ 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerbad: 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m_freem(m); 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* if (opts) m_freem(opts); */ 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint udp_output2(struct socket *so, struct mbuf *m, 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in *saddr, struct sockaddr_in *daddr, 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int iptos) 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner register struct udpiphdr *ui; 2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int error = 0; 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_CALL("udp_output"); 2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("so = %lx", (long)so); 2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("m = %lx", (long)m); 2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr); 2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr); 2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Adjust for header 2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_data -= sizeof(struct udpiphdr); 2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner m->m_len += sizeof(struct udpiphdr); 2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Fill in mbuf with extended UDP header 2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * and addresses and length put into network format. 2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui = mtod(m, struct udpiphdr *); 2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_x1 = 0; 2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_pr = IPPROTO_UDP; 2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */ 2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXXXX Check for from-one-location sockets, or from-any-location sockets */ 2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_src = saddr->sin_addr; 2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_dst = daddr->sin_addr; 2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_sport = saddr->sin_port; 2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_dport = daddr->sin_port; 2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_ulen = ui->ui_len; 2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Stuff checksum and output datagram. 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_sum = 0; 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (UDPCKSUM) { 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ui->ui_sum = 0xffff; 2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ip *)ui)->ip_len = m->m_len; 2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ip *)ui)->ip_ttl = IPDEFTTL; 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ((struct ip *)ui)->ip_tos = iptos; 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner STAT(udpstat.udps_opackets++); 3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner error = ip_output(so, m); 3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return (error); 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint udp_output(struct socket *so, struct mbuf *m, 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in *addr) 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in saddr, daddr; 3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner saddr = *addr; 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff)) 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner saddr.sin_addr.s_addr = alias_addr.s_addr; 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (addr->sin_addr.s_addr == loopback_addr.s_addr || 3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (ntohl(so->so_faddr.s_addr) & 0xff) != CTL_ALIAS) 3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner saddr.sin_addr.s_addr = so->so_faddr.s_addr; 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner daddr.sin_addr = so->so_laddr; 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner daddr.sin_port = so->so_lport; 3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return udp_output2(so, m, &saddr, &daddr, so->so_iptos); 3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_attach(struct socket *so) 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in addr; 3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) { 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Here, we bind() the socket. Although not really needed 3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * (sendto() on an unbound socket will bind it), it's done 3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * here so that emulation of ytalk etc. don't have to do it 3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_family = AF_INET; 3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_port = 0; 3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_addr.s_addr = INADDR_ANY; 3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) { 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int lasterrno=errno; 3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(so->s); 3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->s=-1; 3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WSASetLastError(lasterrno); 3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno=lasterrno; 3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* success, insert in queue */ 3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_expire = curtime + SO_EXPIRE; 3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner insque(so,&udb); 3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return(so->s); 3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid 3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_detach(struct socket *so) 3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(so->s); 3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* if (so->so_m) m_free(so->so_m); done by sofree */ 3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sofree(so); 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const struct tos_t udptos[] = { 3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ 3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ 3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner {0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME}, /* Cu-Seeme */ 3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner {0, 0, 0, 0} 3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic u_int8_t 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_tos(struct socket *so) 3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i = 0; 3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while(udptos[i].tos) { 3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || 3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { 3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_emu = udptos[i].emu; 3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return udptos[i].tos; 3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner i++; 3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef EMULATE_TALK 3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "talkd.h" 3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Here, talk/ytalk/ntalk requests must be emulated 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void 4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_emu(struct socket *so, struct mbuf *m) 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in addr; 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t addrlen = sizeof(addr); 4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef EMULATE_TALK 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CTL_MSG_OLD *omsg; 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CTL_MSG *nmsg; 4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buff[sizeof(CTL_MSG)]; 4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner u_char type; 4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct talk_request { 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct talk_request *next; 4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *udp_so; 4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *tcp_so; 4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} *req; 4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static struct talk_request *req_tbl = 0; 4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct cu_header { 4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t d_family; // destination family 4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t d_port; // destination port 4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t d_addr; // destination address 4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t s_family; // source family 4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t s_port; // source port 4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t so_addr; // source address 4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t seqn; // sequence number 4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t message; // message 4335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t data_type; // data type 4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t pkt_len; // packet length 4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} *cu_head; 4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(so->so_emu) { 4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef EMULATE_TALK 4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case EMU_TALK: 4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case EMU_NTALK: 4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Talk emulation. We always change the ctl_addr to get 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * some answers from the daemon. When an ANNOUNCE comes, 4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * we send LEAVE_INVITE to the local daemons. Also when a 4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * DELETE comes, we send copies to the local daemons. 4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) 4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define IS_OLD (so->so_emu == EMU_TALK) 4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define COPY_MSG(dest, src) { dest->type = src->type; \ 4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dest->id_num = src->id_num; \ 4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dest->pid = src->pid; \ 4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dest->addr = src->addr; \ 4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dest->ctl_addr = src->ctl_addr; \ 4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \ 4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \ 4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE); } 4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field) 4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* old_sockaddr to sockaddr_in */ 4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_OLD) { /* old talk */ 4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner omsg = mtod(m, CTL_MSG_OLD*); 4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nmsg = (CTL_MSG *) buff; 4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner type = omsg->type; 4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; 4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; 4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(omsg->l_name, NAME_SIZE_OLD, getlogin()); 4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { /* new talk */ 4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner omsg = (CTL_MSG_OLD *) buff; 4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nmsg = mtod(m, CTL_MSG *); 4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner type = nmsg->type; 4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port; 4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; 4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(nmsg->l_name, NAME_SIZE_OLD, getlogin()); 4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (type == LOOK_UP) 4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; /* for LOOK_UP this is enough */ 4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_OLD) { /* make a copy of the message */ 4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner COPY_MSG(nmsg, omsg); 4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nmsg->vers = 1; 4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nmsg->answer = 0; 4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner COPY_MSG(omsg, nmsg); 4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * If if is an ANNOUNCE message, we go through the 4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * request table to see if a tcp port has already 4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * been redirected for this socket. If not, we solisten() 4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * a new socket and add this entry to the table. 4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The port number of the tcp socket and our IP 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * are put to the addr field of the message structures. 4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Then a LEAVE_INVITE is sent to both local daemon 5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * ports, 517 and 518. This is why we have two copies 5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * of the message, one in old talk and one in new talk 5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * format. 5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (type == ANNOUNCE) { 5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int s; 5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner u_short temp_port; 5085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(req = req_tbl; req; req = req->next) 5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so == req->udp_so) 5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; /* found it */ 5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!req) { /* no entry for so, create new */ 5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner req = (struct talk_request *) 5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner malloc(sizeof(struct talk_request)); 5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner req->udp_so = so; 5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner req->tcp_so = solisten(0, 5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, addr)->sin_addr.s_addr, 5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, addr)->sin_port, 5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SS_FACCEPTONCE); 5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner req->next = req_tbl; 5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner req_tbl = req; 5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* replace port number in addr field */ 5265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addrlen = sizeof(addr); 5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner getsockname(req->tcp_so->s, 5285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *) &addr, 5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner &addrlen); 5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, addr)->sin_port = addr.sin_port; 5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, addr)->sin_addr = our_addr; 5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(nmsg, addr)->sin_port = addr.sin_port; 5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(nmsg, addr)->sin_addr = our_addr; 5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* send LEAVE_INVITEs */ 5365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner temp_port = OTOSIN(omsg, ctl_addr)->sin_port; 5375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, ctl_addr)->sin_port = 0; 5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(nmsg, ctl_addr)->sin_port = 0; 5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner omsg->type = nmsg->type = LEAVE_INVITE; 5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_addr = our_addr; 5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_family = AF_INET; 5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_port = htons(517); 5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sendto(s, (char *)omsg, sizeof(*omsg), 0, 5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *)&addr, sizeof(addr)); 5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_port = htons(518); 5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sendto(s, (char *)nmsg, sizeof(*nmsg), 0, 5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *) &addr, sizeof(addr)); 5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(s) ; 5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner omsg->type = nmsg->type = ANNOUNCE; 5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, ctl_addr)->sin_port = temp_port; 5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; 5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * If it is a DELETE message, we send a copy to the 5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * local daemons. Then we delete the entry corresponding 5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to our socket from the request table. 5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (type == DELETE) { 5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct talk_request *temp_req, *req_next; 5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int s; 5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner u_short temp_port; 5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner temp_port = OTOSIN(omsg, ctl_addr)->sin_port; 5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, ctl_addr)->sin_port = 0; 5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(nmsg, ctl_addr)->sin_port = 0; 5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_addr = our_addr; 5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_family = AF_INET; 5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_port = htons(517); 5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sendto(s, (char *)omsg, sizeof(*omsg), 0, 5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *)&addr, sizeof(addr)); 5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_port = htons(518); 5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sendto(s, (char *)nmsg, sizeof(*nmsg), 0, 5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *)&addr, sizeof(addr)); 5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(s); 5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(omsg, ctl_addr)->sin_port = temp_port; 5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; 5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* delete table entry */ 5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so == req_tbl->udp_so) { 5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner temp_req = req_tbl; 5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner req_tbl = req_tbl->next; 5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(temp_req); 5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner temp_req = req_tbl; 5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(req = req_tbl->next; req; req = req_next) { 5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner req_next = req->next; 5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (so == req->udp_so) { 5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner temp_req->next = req_next; 5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(req); 5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner temp_req = req; 6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case EMU_CUSEEME: 6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Cu-SeeMe emulation. 6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Hopefully the packet is more that 16 bytes long. We don't 6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * do any other tests, just replace the address and port 6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * fields. 6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (m->m_len >= sizeof (*cu_head)) { 6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) 6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cu_head = mtod(m, struct cu_header *); 6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cu_head->s_port = addr.sin_port; 6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cu_head->so_addr = our_addr.s_addr; 6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct socket * 6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerudp_listen(u_int port, u_int32_t laddr, u_int lport, int flags) 6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in addr; 6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct socket *so; 6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1; 6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((so = socreate()) == NULL) { 6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(so); 6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->s = socket(AF_INET,SOCK_DGRAM,0); 6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_expire = curtime + SO_EXPIRE; 6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner insque(so,&udb); 6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_family = AF_INET; 6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_addr.s_addr = INADDR_ANY; 6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr.sin_port = port; 6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) { 6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner udp_detach(so); 6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); 6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */ 6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner getsockname(so->s,(struct sockaddr *)&addr,&addrlen); 6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_fport = addr.sin_port; 6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) 6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr = alias_addr; 6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_faddr = addr.sin_addr; 6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_lport = lport; 6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_laddr.s_addr = laddr; 6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (flags != SS_FACCEPTONCE) 6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_expire = 0; 6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner so->so_state = SS_ISFCONNECTED; 6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return so; 6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 671