15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 1982, 1986, 1988, 1990, 1993 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Regents of the University of California. All rights reserved. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are met: 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * documentation and/or other materials provided with the distribution. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3. Neither the name of the University nor the names of its contributors 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * may be used to endorse or promote products derived from this software 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without specific prior written permission. 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SUCH DAMAGE. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Changes and additions relating to SLiRP 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 1995 Danny Gasparovski. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Please read the file COPYRIGHT for the 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * terms and conditions of the copyright. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <slirp.h> 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ip_icmp.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef LOG_ENABLED 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct udpstat udpstat; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct socket udb; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static u_int8_t udp_tos(struct socket *so); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void udp_emu(struct socket *so, struct mbuf *m); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * UDP protocol implementation. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Per RFC 768, August, 1980. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef COMPAT_42 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UDPCKSUM 1 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UDPCKSUM 0 /* XXX */ 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct socket *udp_last_so = &udb; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)udp_init(void) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) udb.so_next = udb.so_prev = &udb; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* m->m_data points at ip packet header 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * m->m_len length ip packet 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ip->ip_len length data (IPDU) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)udp_input(register struct mbuf *m, int iphlen) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register struct ip *ip; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register struct udphdr *uh; 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* struct mbuf *opts = 0;*/ 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct ip save_ip; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct socket *so; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_CALL("udp_input"); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_ARG("m = %lx", (long)m); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_ARG("iphlen = %d", iphlen); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STAT(udpstat.udps_ipackets++); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Strip IP options, if any; should skip this, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * make available to user, and use on returned packets, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * but we don't yet have a way to check the checksum 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with options still present. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(iphlen > sizeof(struct ip)) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ip_stripoptions(m, (struct mbuf *)0); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iphlen = sizeof(struct ip); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Get IP and UDP header together in first mbuf. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ip = mtod(m, struct ip *); 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uh = (struct udphdr *)((caddr_t)ip + iphlen); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Make mbuf data length reflect UDP length. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If not enough data to reflect UDP length, drop. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = ntohs((u_int16_t)uh->uh_ulen); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ip->ip_len != len) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len > ip->ip_len) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STAT(udpstat.udps_badlen++); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goto bad; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m_adj(m, len - ip->ip_len); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ip->ip_len = len; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Save a copy of the IP header in case we want restore it 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for sending an ICMP error message in response. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_ip = *ip; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_ip.ip_len+= iphlen; /* tcp_input subtracts this */ 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Checksum extended UDP header and data. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (UDPCKSUM && uh->uh_sum) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((struct ipovly *)ip)->ih_x1 = 0; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((struct ipovly *)ip)->ih_len = uh->uh_ulen; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* keep uh_sum for ICMP reply 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * uh->uh_sum = cksum(m, len + sizeof (struct ip)); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * if (uh->uh_sum) { 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if(cksum(m, len + sizeof(struct ip))) { 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) STAT(udpstat.udps_badsum++); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bad; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * handle DHCP/BOOTP 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ntohs(uh->uh_dport) == BOOTP_SERVER) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bootp_input(m); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bad; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (slirp_restrict) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bad; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * handle TFTP 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ntohs(uh->uh_dport) == TFTP_SERVER) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tftp_input(m); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bad; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Locate pcb for datagram. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so = udp_last_so; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (so->so_lport != uh->uh_sport || 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->so_laddr.s_addr != ip->ip_src.s_addr) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct socket *tmp; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tmp->so_lport == uh->uh_sport && 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp->so_laddr.s_addr == ip->ip_src.s_addr) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp->so_faddr.s_addr = ip->ip_dst.s_addr; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp->so_fport = uh->uh_dport; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so = tmp; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tmp == &udb) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so = NULL; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STAT(udpstat.udpps_pcbcachemiss++); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) udp_last_so = so; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (so == NULL) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If there's no socket for this packet, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * create one 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((so = socreate()) == NULL) goto bad; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(udp_attach(so) == -1) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno,strerror(errno))); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sofree(so); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bad; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Setup fields 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* udp_last_so = so; */ 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->so_laddr = ip->ip_src; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->so_lport = uh->uh_sport; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((so->so_iptos = udp_tos(so)) == 0) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->so_iptos = ip->ip_tos; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * XXXXX Here, check if it's in udpexec_list, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and if it is, do the fork_exec() etc. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->so_faddr = ip->ip_dst; /* XXX */ 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->so_fport = uh->uh_dport; /* XXX */ 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iphlen += sizeof(struct udphdr); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m->m_len -= iphlen; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m->m_data += iphlen; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Now we sendto() the packet. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (so->so_emu) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) udp_emu(so, m); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(sosendto(so,m) == -1) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m->m_len += iphlen; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m->m_data -= iphlen; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ip=save_ip; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* restore the orig mbuf packet */ 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m->m_len += iphlen; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m->m_data -= iphlen; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ip=save_ip; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->so_m=m; /* ICMP backup */ 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bad: 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m_freem(m); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if (opts) m_freem(opts); */ 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int udp_output2(struct socket *so, struct mbuf *m, 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) struct sockaddr_in *saddr, struct sockaddr_in *daddr, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iptos) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) register struct udpiphdr *ui; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error = 0; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_CALL("udp_output"); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_ARG("so = %lx", (long)so); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_ARG("m = %lx", (long)m); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Adjust for header 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) m->m_data -= sizeof(struct udpiphdr); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) m->m_len += sizeof(struct udpiphdr); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Fill in mbuf with extended UDP header 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and addresses and length put into network format. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui = mtod(m, struct udpiphdr *); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_x1 = 0; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_pr = IPPROTO_UDP; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */ 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* XXXXX Check for from-one-location sockets, or from-any-location sockets */ 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_src = saddr->sin_addr; 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui->ui_dst = daddr->sin_addr; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_sport = saddr->sin_port; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_dport = daddr->sin_port; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_ulen = ui->ui_len; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Stuff checksum and output datagram. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_sum = 0; 2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (UDPCKSUM) { 2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui->ui_sum = 0xffff; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((struct ip *)ui)->ip_len = m->m_len; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((struct ip *)ui)->ip_ttl = IPDEFTTL; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((struct ip *)ui)->ip_tos = iptos; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STAT(udpstat.udps_opackets++); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = ip_output(so, m); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (error); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int udp_output(struct socket *so, struct mbuf *m, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in *addr) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in saddr, daddr; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saddr = *addr; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff)) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saddr.sin_addr.s_addr = alias_addr.s_addr; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (addr->sin_addr.s_addr == loopback_addr.s_addr || 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ntohl(so->so_faddr.s_addr) & 0xff) != CTL_ALIAS) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saddr.sin_addr.s_addr = so->so_faddr.s_addr; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) daddr.sin_addr = so->so_laddr; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) daddr.sin_port = so->so_lport; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return udp_output2(so, m, &saddr, &daddr, so->so_iptos); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)udp_attach(struct socket *so) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in addr; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Here, we bind() the socket. Although not really needed 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (sendto() on an unbound socket will bind it), it's done 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * here so that emulation of ytalk etc. don't have to do it 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_family = AF_INET; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_port = 0; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_addr.s_addr = INADDR_ANY; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int lasterrno=errno; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closesocket(so->s); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->s=-1; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN32 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WSASetLastError(lasterrno); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno=lasterrno; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* success, insert in queue */ 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) so->so_expire = curtime + SO_EXPIRE; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insque(so,&udb); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(so->s); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)udp_detach(struct socket *so) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closesocket(so->s); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if (so->so_m) m_free(so->so_m); done by sofree */ 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sofree(so); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const struct tos_t udptos[] = { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME}, /* Cu-Seeme */ 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {0, 0, 0, 0} 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static u_int8_t 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)udp_tos(struct socket *so) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while(udptos[i].tos) { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) so->so_emu = udptos[i].emu; 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return udptos[i].tos; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i++; 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef EMULATE_TALK 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "talkd.h" 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Here, talk/ytalk/ntalk requests must be emulated 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)udp_emu(struct socket *so, struct mbuf *m) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in addr; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t addrlen = sizeof(addr); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef EMULATE_TALK 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CTL_MSG_OLD *omsg; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CTL_MSG *nmsg; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buff[sizeof(CTL_MSG)]; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_char type; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct talk_request { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct talk_request *next; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct socket *udp_so; 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) struct socket *tcp_so; 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} *req; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static struct talk_request *req_tbl = 0; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct cu_header { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t d_family; // destination family 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t d_port; // destination port 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32_t d_addr; // destination address 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t s_family; // source family 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16_t s_port; // source port 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t so_addr; // source address 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t seqn; // sequence number 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16_t message; // message 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16_t data_type; // data type 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16_t pkt_len; // packet length 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} *cu_head; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch(so->so_emu) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef EMULATE_TALK 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EMU_TALK: 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EMU_NTALK: 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Talk emulation. We always change the ctl_addr to get 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * some answers from the daemon. When an ANNOUNCE comes, 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we send LEAVE_INVITE to the local daemons. Also when a 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DELETE comes, we send copies to the local daemons. 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IS_OLD (so->so_emu == EMU_TALK) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define COPY_MSG(dest, src) { dest->type = src->type; \ 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest->id_num = src->id_num; \ 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest->pid = src->pid; \ 456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dest->addr = src->addr; \ 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest->ctl_addr = src->ctl_addr; \ 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \ 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \ 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE); } 461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* old_sockaddr to sockaddr_in */ 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 466424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (IS_OLD) { /* old talk */ 467424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) omsg = mtod(m, CTL_MSG_OLD*); 468424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) nmsg = (CTL_MSG *) buff; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type = omsg->type; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pstrcpy(omsg->l_name, NAME_SIZE_OLD, getlogin()); 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { /* new talk */ 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) omsg = (CTL_MSG_OLD *) buff; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nmsg = mtod(m, CTL_MSG *); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type = nmsg->type; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pstrcpy(nmsg->l_name, NAME_SIZE_OLD, getlogin()); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == LOOK_UP) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; /* for LOOK_UP this is enough */ 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IS_OLD) { /* make a copy of the message */ 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COPY_MSG(nmsg, omsg); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nmsg->vers = 1; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nmsg->answer = 0; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COPY_MSG(omsg, nmsg); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If if is an ANNOUNCE message, we go through the 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * request table to see if a tcp port has already 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * been redirected for this socket. If not, we solisten() 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a new socket and add this entry to the table. 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The port number of the tcp socket and our IP 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are put to the addr field of the message structures. 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Then a LEAVE_INVITE is sent to both local daemon 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ports, 517 and 518. This is why we have two copies 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of the message, one in old talk and one in new talk 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * format. 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == ANNOUNCE) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int s; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_short temp_port; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(req = req_tbl; req; req = req->next) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (so == req->udp_so) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; /* found it */ 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!req) { /* no entry for so, create new */ 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) req = (struct talk_request *) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) malloc(sizeof(struct talk_request)); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->udp_so = so; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->tcp_so = solisten(0, 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, addr)->sin_addr.s_addr, 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, addr)->sin_port, 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SS_FACCEPTONCE); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->next = req_tbl; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req_tbl = req; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* replace port number in addr field */ 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addrlen = sizeof(addr); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getsockname(req->tcp_so->s, 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct sockaddr *) &addr, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &addrlen); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, addr)->sin_port = addr.sin_port; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, addr)->sin_addr = our_addr; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(nmsg, addr)->sin_port = addr.sin_port; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(nmsg, addr)->sin_addr = our_addr; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* send LEAVE_INVITEs */ 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_port = OTOSIN(omsg, ctl_addr)->sin_port; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, ctl_addr)->sin_port = 0; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(nmsg, ctl_addr)->sin_port = 0; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) omsg->type = nmsg->type = LEAVE_INVITE; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_addr = our_addr; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_family = AF_INET; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_port = htons(517); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sendto(s, (char *)omsg, sizeof(*omsg), 0, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct sockaddr *)&addr, sizeof(addr)); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_port = htons(518); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sendto(s, (char *)nmsg, sizeof(*nmsg), 0, 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (struct sockaddr *) &addr, sizeof(addr)); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closesocket(s) ; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) omsg->type = nmsg->type = ANNOUNCE; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, ctl_addr)->sin_port = temp_port; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If it is a DELETE message, we send a copy to the 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * local daemons. Then we delete the entry corresponding 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to our socket from the request table. 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (type == DELETE) { 564424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) struct talk_request *temp_req, *req_next; 565424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int s; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_short temp_port; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_port = OTOSIN(omsg, ctl_addr)->sin_port; 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(omsg, ctl_addr)->sin_port = 0; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OTOSIN(nmsg, ctl_addr)->sin_port = 0; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_addr = our_addr; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr.sin_family = AF_INET; 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) addr.sin_port = htons(517); 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sendto(s, (char *)omsg, sizeof(*omsg), 0, 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (struct sockaddr *)&addr, sizeof(addr)); 578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) addr.sin_port = htons(518); 579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sendto(s, (char *)nmsg, sizeof(*nmsg), 0, 580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (struct sockaddr *)&addr, sizeof(addr)); 581424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) closesocket(s); 582424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 583424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) OTOSIN(omsg, ctl_addr)->sin_port = temp_port; 584424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; 585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 586a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /* delete table entry */ 587a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (so == req_tbl->udp_so) { 5884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) temp_req = req_tbl; 589a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) req_tbl = req_tbl->next; 590a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) free(temp_req); 591a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_req = req_tbl; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(req = req_tbl->next; req; req = req_next) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req_next = req->next; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (so == req->udp_so) { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_req->next = req_next; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req); 598 break; 599 } else { 600 temp_req = req; 601 } 602 } 603 } 604 } 605 606 return; 607#endif 608 609 case EMU_CUSEEME: 610 611 /* 612 * Cu-SeeMe emulation. 613 * Hopefully the packet is more that 16 bytes long. We don't 614 * do any other tests, just replace the address and port 615 * fields. 616 */ 617 if (m->m_len >= sizeof (*cu_head)) { 618 if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) 619 return; 620 cu_head = mtod(m, struct cu_header *); 621 cu_head->s_port = addr.sin_port; 622 cu_head->so_addr = our_addr.s_addr; 623 } 624 625 return; 626 } 627} 628 629struct socket * 630udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags) 631{ 632 struct sockaddr_in addr; 633 struct socket *so; 634 socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1; 635 636 if ((so = socreate()) == NULL) { 637 free(so); 638 return NULL; 639 } 640 so->s = socket(AF_INET,SOCK_DGRAM,0); 641 so->so_expire = curtime + SO_EXPIRE; 642 insque(so,&udb); 643 644 addr.sin_family = AF_INET; 645 addr.sin_addr.s_addr = INADDR_ANY; 646 addr.sin_port = port; 647 648 if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) { 649 udp_detach(so); 650 return NULL; 651 } 652 setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); 653/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */ 654 655 getsockname(so->s,(struct sockaddr *)&addr,&addrlen); 656 so->so_fport = addr.sin_port; 657 if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) 658 so->so_faddr = alias_addr; 659 else 660 so->so_faddr = addr.sin_addr; 661 662 so->so_lport = lport; 663 so->so_laddr.s_addr = laddr; 664 if (flags != SS_FACCEPTONCE) 665 so->so_expire = 0; 666 667 so->so_state = SS_ISFCONNECTED; 668 669 return so; 670} 671