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