udp.c revision c1490f719c97f91d4ca70499df678df22051f763
828c58761d90445b8b9d20a82d85dc1479317f71Tripp/*
a89ad754cce3cfc8aee71760e10217b54020360dTripp * Copyright (c) 1982, 1986, 1988, 1990, 1993
a89ad754cce3cfc8aee71760e10217b54020360dTripp * The Regents of the University of California. All rights reserved.
828c58761d90445b8b9d20a82d85dc1479317f71Tripp *
828c58761d90445b8b9d20a82d85dc1479317f71Tripp * Redistribution and use in source and binary forms, with or without
828c58761d90445b8b9d20a82d85dc1479317f71Tripp * modification, are permitted provided that the following conditions
828c58761d90445b8b9d20a82d85dc1479317f71Tripp * are met:
828c58761d90445b8b9d20a82d85dc1479317f71Tripp * 1. Redistributions of source code must retain the above copyright
828c58761d90445b8b9d20a82d85dc1479317f71Tripp * notice, this list of conditions and the following disclaimer.
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp * 2. Redistributions in binary form must reproduce the above copyright
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * notice, this list of conditions and the following disclaimer in the
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * documentation and/or other materials provided with the distribution.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * 3. All advertising materials mentioning features or use of this software
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * must display the following acknowledgement:
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * This product includes software developed by the University of
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * California, Berkeley and its contributors.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * 4. Neither the name of the University nor the names of its contributors
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * may be used to endorse or promote products derived from this software
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * without specific prior written permission.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp *
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * SUCH DAMAGE.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp *
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp/*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Changes and additions relating to SLiRP
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Copyright (c) 1995 Danny Gasparovski.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp *
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Please read the file COPYRIGHT for the
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * terms and conditions of the copyright.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#include <slirp.h>
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#include "ip_icmp.h"
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp/*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * UDP protocol implementation.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Per RFC 768, August, 1980.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#define udpcksum 1
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippvoid
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTrippudp_init(PNATState pData)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp{
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp udp_last_so = &udb;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp udb.so_next = udb.so_prev = &udb;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp}
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp/* m->m_data points at ip packet header
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * m->m_len length ip packet
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * ip->ip_len length data (IPDU)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippvoid
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippudp_input(PNATState pData, register struct mbuf *m, int iphlen)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp{
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp register struct ip *ip;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp register struct udphdr *uh;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int len;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct ip save_ip;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct socket *so;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int ret;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int ttl;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_CALL("udp_input");
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_ARG("m = %lx", (long)m);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_ARG("iphlen = %d", iphlen);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp udpstat.udps_ipackets++;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
9eaaa502227248d304ac9170902697d02158c1d9Tripp /*
9eaaa502227248d304ac9170902697d02158c1d9Tripp * Strip IP options, if any; should skip this,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * make available to user, and use on returned packets,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * but we don't yet have a way to check the checksum
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * with options still present.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (iphlen > sizeof(struct ip))
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ip_stripoptions(m, (struct mbuf *)0);
9eaaa502227248d304ac9170902697d02158c1d9Tripp iphlen = sizeof(struct ip);
9eaaa502227248d304ac9170902697d02158c1d9Tripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Get IP and UDP header together in first mbuf.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ip = mtod(m, struct ip *);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uh = (struct udphdr *)((caddr_t)ip + iphlen);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
9eaaa502227248d304ac9170902697d02158c1d9Tripp * Make mbuf data length reflect UDP length.
9eaaa502227248d304ac9170902697d02158c1d9Tripp * If not enough data to reflect UDP length, drop.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp len = ntohs((u_int16_t)uh->uh_ulen);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (ip->ip_len != len)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (len > ip->ip_len)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp udpstat.udps_badlen++;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp goto bad;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp m_adj(m, len - ip->ip_len);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ip->ip_len = len;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Save a copy of the IP header in case we want restore it
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * for sending an ICMP error message in response.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp save_ip = *ip;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Checksum extended UDP header and data.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (udpcksum && uh->uh_sum)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp memset(((struct ipovly *)ip)->ih_x1, 0, 9);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#if 0
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* keep uh_sum for ICMP reply */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uh->uh_sum = cksum(m, len + sizeof (struct ip));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (uh->uh_sum)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp#endif
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp if(cksum(m, len + sizeof(struct ip)))
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp udpstat.udps_badsum++;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp goto bad;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp }
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp }
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp#if 0
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#endif
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * handle DHCP/BOOTP
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (ntohs(uh->uh_dport) == BOOTP_SERVER)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp bootp_input(pData, m);
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp goto bad;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp }
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp /*
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp * handle TFTP
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp */
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp if (ntohs(uh->uh_dport) == TFTP_SERVER)
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp {
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp tftp_input(pData, m);
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp goto bad;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp }
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Locate pcb for datagram.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so = udp_last_so;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ( so->so_lport != uh->uh_sport
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp || so->so_laddr.s_addr != ip->ip_src.s_addr)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct socket *tmp;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ( tmp->so_lport == uh->uh_sport
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp && tmp->so_laddr.s_addr == ip->ip_src.s_addr)
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so = tmp;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp break;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp }
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (tmp == &udb)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so = NULL;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp else
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp udpstat.udpps_pcbcachemiss++;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp udp_last_so = so;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (so == NULL)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * If there's no socket for this packet,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * create one
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ((so = socreate()) == NULL)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp goto bad;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (udp_attach(pData, so) == -1)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp errno,strerror(errno)));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp sofree(pData, so);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp goto bad;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp * Setup fields
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp */
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp /* udp_last_so = so; */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->so_laddr = ip->ip_src;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->so_lport = uh->uh_sport;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ((so->so_iptos = udp_tos(so)) == 0)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->so_iptos = ip->ip_tos;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * XXXXX Here, check if it's in udpexec_list,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * and if it is, do the fork_exec() etc.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->so_faddr = ip->ip_dst; /* XXX */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->so_fport = uh->uh_dport; /* XXX */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp iphlen += sizeof(struct udphdr);
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp m->m_len -= iphlen;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp m->m_data += iphlen;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Now we sendto() the packet.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (so->so_emu)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp udp_emu(pData, so, m);
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp ttl = ip->ip_ttl = save_ip.ip_ttl;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp ret = setsockopt(so->s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (ret < 0) {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp LogRel(("NAT: Error (%s) occurred while setting TTL(%d) attribute of IP packet to socket %R[natsock]\n", strerror(errno), ip->ip_ttl, so));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (sosendto(pData, so, m) == -1)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp m->m_len += iphlen;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp m->m_data -= iphlen;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp *ip = save_ip;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_MISC((dfd,"udp tx errno = %d-%s\n", errno, strerror(errno)));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp icmp_error(pData, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0, strerror(errno));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp m_free(pData, so->so_m); /* used for ICMP if error on sorecvfrom */
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* restore the orig mbuf packet */
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp m->m_len += iphlen;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp m->m_data -= iphlen;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp *ip = save_ip;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp so->so_m = m; /* ICMP backup */
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippbad:
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp m_freem(pData, m);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp}
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippint udp_output2(PNATState pData, struct socket *so, struct mbuf *m,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct sockaddr_in *saddr, struct sockaddr_in *daddr,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int iptos)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp{
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp register struct udpiphdr *ui;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int error = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_CALL("udp_output");
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_ARG("so = %lx", (long)so);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_ARG("m = %lx", (long)m);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Adjust for header
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp m->m_data -= sizeof(struct udpiphdr);
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp m->m_len += sizeof(struct udpiphdr);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Fill in mbuf with extended UDP header
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * and addresses and length put into network format.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ui = mtod(m, struct udpiphdr *);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp memset(ui->ui_x1, 0, 9);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ui->ui_pr = IPPROTO_UDP;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ui->ui_src = saddr->sin_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ui->ui_dst = daddr->sin_addr;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp ui->ui_sport = saddr->sin_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ui->ui_dport = daddr->sin_port;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp ui->ui_ulen = ui->ui_len;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Stuff checksum and output datagram.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ui->ui_sum = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (udpcksum)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ui->ui_sum = 0xffff;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ((struct ip *)ui)->ip_len = m->m_len;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ((struct ip *)ui)->ip_ttl = ip_defttl;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp ((struct ip *)ui)->ip_tos = iptos;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp udpstat.udps_opackets++;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp error = ip_output(pData, so, m);
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp return error;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp}
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTrippint udp_output(PNATState pData, struct socket *so, struct mbuf *m,
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp struct sockaddr_in *addr)
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp{
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct sockaddr_in saddr, daddr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp saddr = *addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp saddr.sin_addr.s_addr = so->so_faddr.s_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ((so->so_faddr.s_addr & htonl(~pData->netmask)) == htonl(~pData->netmask))
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp saddr.sin_addr.s_addr = alias_addr.s_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* Any UDP packet to the loopback address must be translated to be from
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * the forwarding address, i.e. 10.0.2.2. */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ( (saddr.sin_addr.s_addr & htonl(IN_CLASSA_NET))
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp == htonl(INADDR_LOOPBACK & IN_CLASSA_NET))
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp saddr.sin_addr.s_addr = alias_addr.s_addr;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp daddr.sin_addr = so->so_laddr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp daddr.sin_port = so->so_lport;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return udp_output2(pData, so, m, &saddr, &daddr, so->so_iptos);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp}
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippint
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippudp_attach(PNATState pData, struct socket *so)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp{
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct sockaddr_in addr;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp struct sockaddr sa_addr;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp socklen_t socklen = sizeof(struct sockaddr);
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp int status;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Here, we bind() the socket. Although not really needed
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * (sendto() on an unbound socket will bind it), it's done
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * here so that emulation of ytalk etc. don't have to do it
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_family = AF_INET;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_port = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_addr.s_addr = INADDR_ANY;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (bind(so->s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int lasterrno = errno;
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp closesocket(so->s);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->s = -1;
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp#ifdef RT_OS_WINDOWS
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp WSASetLastError(lasterrno);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#else
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp errno = lasterrno;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#endif
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp else
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int opt = 1;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* success, insert in queue */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->so_expire = curtime + SO_EXPIRE;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* enable broadcast for later use */
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp insque(pData, so,&udb);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp status = getsockname(so->s, &sa_addr, &socklen);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp Assert(status == 0 && sa_addr.sa_family == AF_INET);
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return so->s;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp}
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippvoid
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippudp_detach(PNATState pData, struct socket *so)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp{
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (so != &pData->icmp_socket)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp closesocket(so->s);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp sofree(pData, so);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp}
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippstatic const struct tos_t udptos[] =
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp{
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp { 0, 53, IPTOS_LOWDELAY, 0 }, /* DNS */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp { 517, 517, IPTOS_LOWDELAY, EMU_TALK }, /* talk */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp { 518, 518, IPTOS_LOWDELAY, EMU_NTALK }, /* ntalk */
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp { 0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME }, /* Cu-Seeme */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp { 0, 0, 0, 0 }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp};
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippu_int8_t
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippudp_tos(struct socket *so)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp{
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp int i = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp while(udptos[i].tos)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if ( (udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp || (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport))
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp so->so_emu = udptos[i].emu;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return udptos[i].tos;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp i++;
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return 0;
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp}
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp#ifdef EMULATE_TALK
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp#include "talkd.h"
bbd1285cbb2183b7f89010412ad97ae1680b4b5eTripp#endif
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp/*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Here, talk/ytalk/ntalk requests must be emulated
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippvoid
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTrippudp_emu(PNATState pData, struct socket *so, struct mbuf *m)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp{
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct sockaddr_in addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp socklen_t addrlen = sizeof(addr);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#ifdef EMULATE_TALK
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp CTL_MSG_OLD *omsg;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp CTL_MSG *nmsg;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp char buff[sizeof(CTL_MSG)];
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp u_char type;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct talk_request
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct talk_request *next;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct socket *udp_so;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct socket *tcp_so;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp } *req;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp static struct talk_request *req_tbl = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#endif
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct cu_header
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint16_t d_family; /* destination family */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint16_t d_port; /* destination port */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint32_t d_addr; /* destination address */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint16_t s_family; /* source family */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint16_t s_port; /* source port */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint32_t so_addr; /* source address */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint32_t seqn; /* sequence number */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint16_t message; /* message */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint16_t data_type; /* data type */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp uint16_t pkt_len; /* packet length */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp } *cu_head;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp switch(so->so_emu)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#ifdef EMULATE_TALK
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp case EMU_TALK:
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp case EMU_NTALK:
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Talk emulation. We always change the ctl_addr to get
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * some answers from the daemon. When an ANNOUNCE comes,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * we send LEAVE_INVITE to the local daemons. Also when a
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * DELETE comes, we send copies to the local daemons.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#define IS_OLD (so->so_emu == EMU_TALK)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#define COPY_MSG(dest, src) \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp do { \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp dest->type = src->type; \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp dest->id_num = src->id_num; \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp dest->pid = src->pid; \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp dest->addr = src->addr; \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp dest->ctl_addr = src->ctl_addr; \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp } while (0)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp#define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp/* old_sockaddr to sockaddr_in */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (IS_OLD)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* old talk */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp omsg = mtod(m, CTL_MSG_OLD*);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp nmsg = (CTL_MSG *) buff;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp type = omsg->type;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp else
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* new talk */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp omsg = (CTL_MSG_OLD *) buff;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp nmsg = mtod(m, CTL_MSG *);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp type = nmsg->type;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (type == LOOK_UP)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return; /* for LOOK_UP this is enough */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (IS_OLD)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* make a copy of the message */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp COPY_MSG(nmsg, omsg);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp nmsg->vers = 1;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp nmsg->answer = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp else
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp COPY_MSG(omsg, nmsg);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * If if is an ANNOUNCE message, we go through the
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * request table to see if a tcp port has already
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * been redirected for this socket. If not, we solisten()
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * a new socket and add this entry to the table.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * The port number of the tcp socket and our IP
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * are put to the addr field of the message structures.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Then a LEAVE_INVITE is sent to both local daemon
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * ports, 517 and 518. This is why we have two copies
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * of the message, one in old talk and one in new talk
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * format.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (type == ANNOUNCE)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int s;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp u_short temp_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp for(req = req_tbl; req; req = req->next)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (so == req->udp_so)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp break; /* found it */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (!req)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* no entry for so, create new */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp req = (struct talk_request *)malloc(sizeof(struct talk_request));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp req->udp_so = so;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp req->tcp_so = solisten(0,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, addr)->sin_addr.s_addr,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, addr)->sin_port,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp SS_FACCEPTONCE);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp req->next = req_tbl;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp req_tbl = req;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* replace port number in addr field */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addrlen = sizeof(addr);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp getsockname(req->tcp_so->s, (struct sockaddr *) &addr, &addrlen);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, addr)->sin_port = addr.sin_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, addr)->sin_addr = our_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(nmsg, addr)->sin_addr = our_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* send LEAVE_INVITEs */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, ctl_addr)->sin_port = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(nmsg, ctl_addr)->sin_port = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp omsg->type = nmsg->type = LEAVE_INVITE;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_addr = our_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_family = AF_INET;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_port = htons(517);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp sendto(s, (char *)omsg, sizeof(*omsg), 0,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp (struct sockaddr *)&addr, sizeof(addr));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_port = htons(518);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp (struct sockaddr *) &addr, sizeof(addr));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp closesocket(s) ;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp omsg->type = nmsg->type = ANNOUNCE;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * If it is a DELETE message, we send a copy to the
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * local daemons. Then we delete the entry corresponding
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * to our socket from the request table.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (type == DELETE)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp struct talk_request *temp_req, *req_next;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp int s;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp u_short temp_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, ctl_addr)->sin_port = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(nmsg, ctl_addr)->sin_port = 0;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_addr = our_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_family = AF_INET;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_port = htons(517);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp sendto(s, (char *)omsg, sizeof(*omsg), 0,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp (struct sockaddr *)&addr, sizeof(addr));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp addr.sin_port = htons(518);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp (struct sockaddr *)&addr, sizeof(addr));
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp closesocket(s);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /* delete table entry */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (so == req_tbl->udp_so)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp temp_req = req_tbl;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp req_tbl = req_tbl->next;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp free(temp_req);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp else
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp temp_req = req_tbl;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp for (req = req_tbl->next; req; req = req_next)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp req_next = req->next;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (so == req->udp_so)
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp temp_req->next = req_next;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp free(req);
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp break;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp else
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp temp_req = req;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp return;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp#endif
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp case EMU_CUSEEME:
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp /*
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp * Cu-SeeMe emulation.
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * Hopefully the packet is more that 16 bytes long. We don't
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp * do any other tests, just replace the address and port
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp * fields.
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp */
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (m->m_len >= sizeof (*cu_head))
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp {
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp return;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp cu_head = mtod(m, struct cu_header *);
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp cu_head->s_port = addr.sin_port;
c7ba96d16d58075a9ab8d5c1e46c6c83ce11cb4eTripp cu_head->so_addr = our_addr.s_addr;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp return;
09688ec5ffb8b9cf9883a770e2f9ebd60b28888dTripp }
}
struct socket *
udp_listen(PNATState pData, u_int port, u_int32_t laddr, u_int lport, int flags)
{
struct sockaddr_in addr;
struct socket *so;
socklen_t addrlen = sizeof(struct sockaddr_in);
int opt = 1;
if ((so = socreate()) == NULL)
return NULL;
so->s = socket(AF_INET,SOCK_DGRAM,0);
so->so_expire = curtime + SO_EXPIRE;
insque(pData, so,&udb);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = port;
if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0)
{
udp_detach(pData, so);
return NULL;
}
setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
so->so_fport = addr.sin_port;
/* The original check was completely broken, as the commented out
* if statement was always true (INADDR_ANY=0). */
/* if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) */
if (1 == 0) /* always use the else part */
so->so_faddr = alias_addr;
else
so->so_faddr = addr.sin_addr;
so->so_lport = lport;
so->so_laddr.s_addr = laddr;
if (flags != SS_FACCEPTONCE)
so->so_expire = 0;
so->so_state = SS_ISFCONNECTED;
return so;
}