symbian-qemu-0.9.1-12/qemu-symbian-svp/slirp/udp.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * Copyright (c) 1982, 1986, 1988, 1990, 1993
       
     3  *	The Regents of the University of California.  All rights reserved.
       
     4  *
       
     5  * Redistribution and use in source and binary forms, with or without
       
     6  * modification, are permitted provided that the following conditions
       
     7  * are met:
       
     8  * 1. Redistributions of source code must retain the above copyright
       
     9  *    notice, this list of conditions and the following disclaimer.
       
    10  * 2. Redistributions in binary form must reproduce the above copyright
       
    11  *    notice, this list of conditions and the following disclaimer in the
       
    12  *    documentation and/or other materials provided with the distribution.
       
    13  * 3. All advertising materials mentioning features or use of this software
       
    14  *    must display the following acknowledgement:
       
    15  *	This product includes software developed by the University of
       
    16  *	California, Berkeley and its contributors.
       
    17  * 4. Neither the name of the University nor the names of its contributors
       
    18  *    may be used to endorse or promote products derived from this software
       
    19  *    without specific prior written permission.
       
    20  *
       
    21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
       
    22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
       
    25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       
    26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
       
    27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
       
    29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
       
    30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    31  * SUCH DAMAGE.
       
    32  *
       
    33  *	@(#)udp_usrreq.c	8.4 (Berkeley) 1/21/94
       
    34  * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
       
    35  */
       
    36 
       
    37 /*
       
    38  * Changes and additions relating to SLiRP
       
    39  * Copyright (c) 1995 Danny Gasparovski.
       
    40  *
       
    41  * Please read the file COPYRIGHT for the
       
    42  * terms and conditions of the copyright.
       
    43  */
       
    44 
       
    45 #include <slirp.h>
       
    46 #include "ip_icmp.h"
       
    47 
       
    48 #ifdef LOG_ENABLED
       
    49 struct udpstat udpstat;
       
    50 #endif
       
    51 
       
    52 struct socket udb;
       
    53 
       
    54 static u_int8_t udp_tos(struct socket *so);
       
    55 static void udp_emu(struct socket *so, struct mbuf *m);
       
    56 
       
    57 /*
       
    58  * UDP protocol implementation.
       
    59  * Per RFC 768, August, 1980.
       
    60  */
       
    61 #ifndef	COMPAT_42
       
    62 #define UDPCKSUM 1
       
    63 #else
       
    64 #define UDPCKSUM 0 /* XXX */
       
    65 #endif
       
    66 
       
    67 struct	socket *udp_last_so = &udb;
       
    68 
       
    69 void
       
    70 udp_init()
       
    71 {
       
    72 	udb.so_next = udb.so_prev = &udb;
       
    73 }
       
    74 /* m->m_data  points at ip packet header
       
    75  * m->m_len   length ip packet
       
    76  * ip->ip_len length data (IPDU)
       
    77  */
       
    78 void
       
    79 udp_input(m, iphlen)
       
    80 	register struct mbuf *m;
       
    81 	int iphlen;
       
    82 {
       
    83 	register struct ip *ip;
       
    84 	register struct udphdr *uh;
       
    85 /*	struct mbuf *opts = 0;*/
       
    86 	int len;
       
    87 	struct ip save_ip;
       
    88 	struct socket *so;
       
    89 
       
    90 	DEBUG_CALL("udp_input");
       
    91 	DEBUG_ARG("m = %lx", (long)m);
       
    92 	DEBUG_ARG("iphlen = %d", iphlen);
       
    93 
       
    94 	STAT(udpstat.udps_ipackets++);
       
    95 
       
    96 	/*
       
    97 	 * Strip IP options, if any; should skip this,
       
    98 	 * make available to user, and use on returned packets,
       
    99 	 * but we don't yet have a way to check the checksum
       
   100 	 * with options still present.
       
   101 	 */
       
   102 	if(iphlen > sizeof(struct ip)) {
       
   103 		ip_stripoptions(m, (struct mbuf *)0);
       
   104 		iphlen = sizeof(struct ip);
       
   105 	}
       
   106 
       
   107 	/*
       
   108 	 * Get IP and UDP header together in first mbuf.
       
   109 	 */
       
   110 	ip = mtod(m, struct ip *);
       
   111 	uh = (struct udphdr *)((caddr_t)ip + iphlen);
       
   112 
       
   113 	/*
       
   114 	 * Make mbuf data length reflect UDP length.
       
   115 	 * If not enough data to reflect UDP length, drop.
       
   116 	 */
       
   117 	len = ntohs((u_int16_t)uh->uh_ulen);
       
   118 
       
   119 	if (ip->ip_len != len) {
       
   120 		if (len > ip->ip_len) {
       
   121 			STAT(udpstat.udps_badlen++);
       
   122 			goto bad;
       
   123 		}
       
   124 		m_adj(m, len - ip->ip_len);
       
   125 		ip->ip_len = len;
       
   126 	}
       
   127 
       
   128 	/*
       
   129 	 * Save a copy of the IP header in case we want restore it
       
   130 	 * for sending an ICMP error message in response.
       
   131 	 */
       
   132 	save_ip = *ip;
       
   133 	save_ip.ip_len+= iphlen;         /* tcp_input subtracts this */
       
   134 
       
   135 	/*
       
   136 	 * Checksum extended UDP header and data.
       
   137 	 */
       
   138 	if (UDPCKSUM && uh->uh_sum) {
       
   139 	  ((struct ipovly *)ip)->ih_next = 0;
       
   140 	  ((struct ipovly *)ip)->ih_prev = 0;
       
   141 	  ((struct ipovly *)ip)->ih_x1 = 0;
       
   142 	  ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
       
   143 	  /* keep uh_sum for ICMP reply
       
   144 	   * uh->uh_sum = cksum(m, len + sizeof (struct ip));
       
   145 	   * if (uh->uh_sum) {
       
   146 	   */
       
   147 	  if(cksum(m, len + sizeof(struct ip))) {
       
   148 	    STAT(udpstat.udps_badsum++);
       
   149 	    goto bad;
       
   150 	  }
       
   151 	}
       
   152 
       
   153         /*
       
   154          *  handle DHCP/BOOTP
       
   155          */
       
   156         if (ntohs(uh->uh_dport) == BOOTP_SERVER) {
       
   157             bootp_input(m);
       
   158             goto bad;
       
   159         }
       
   160 
       
   161         /*
       
   162          *  handle TFTP
       
   163          */
       
   164         if (ntohs(uh->uh_dport) == TFTP_SERVER) {
       
   165             tftp_input(m);
       
   166             goto bad;
       
   167         }
       
   168 
       
   169 	/*
       
   170 	 * Locate pcb for datagram.
       
   171 	 */
       
   172 	so = udp_last_so;
       
   173 	if (so->so_lport != uh->uh_sport ||
       
   174 	    so->so_laddr.s_addr != ip->ip_src.s_addr) {
       
   175 		struct socket *tmp;
       
   176 
       
   177 		for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
       
   178 			if (tmp->so_lport == uh->uh_sport &&
       
   179 			    tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
       
   180 				tmp->so_faddr.s_addr = ip->ip_dst.s_addr;
       
   181 				tmp->so_fport = uh->uh_dport;
       
   182 				so = tmp;
       
   183 				break;
       
   184 			}
       
   185 		}
       
   186 		if (tmp == &udb) {
       
   187 		  so = NULL;
       
   188 		} else {
       
   189 		  STAT(udpstat.udpps_pcbcachemiss++);
       
   190 		  udp_last_so = so;
       
   191 		}
       
   192 	}
       
   193 
       
   194 	if (so == NULL) {
       
   195 	  /*
       
   196 	   * If there's no socket for this packet,
       
   197 	   * create one
       
   198 	   */
       
   199 	  if ((so = socreate()) == NULL) goto bad;
       
   200 	  if(udp_attach(so) == -1) {
       
   201 	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
       
   202 			errno,strerror(errno)));
       
   203 	    sofree(so);
       
   204 	    goto bad;
       
   205 	  }
       
   206 
       
   207 	  /*
       
   208 	   * Setup fields
       
   209 	   */
       
   210 	  /* udp_last_so = so; */
       
   211 	  so->so_laddr = ip->ip_src;
       
   212 	  so->so_lport = uh->uh_sport;
       
   213 
       
   214 	  if ((so->so_iptos = udp_tos(so)) == 0)
       
   215 	    so->so_iptos = ip->ip_tos;
       
   216 
       
   217 	  /*
       
   218 	   * XXXXX Here, check if it's in udpexec_list,
       
   219 	   * and if it is, do the fork_exec() etc.
       
   220 	   */
       
   221 	}
       
   222 
       
   223         so->so_faddr = ip->ip_dst; /* XXX */
       
   224         so->so_fport = uh->uh_dport; /* XXX */
       
   225 
       
   226 	iphlen += sizeof(struct udphdr);
       
   227 	m->m_len -= iphlen;
       
   228 	m->m_data += iphlen;
       
   229 
       
   230 	/*
       
   231 	 * Now we sendto() the packet.
       
   232 	 */
       
   233 	if (so->so_emu)
       
   234 	   udp_emu(so, m);
       
   235 
       
   236 	if(sosendto(so,m) == -1) {
       
   237 	  m->m_len += iphlen;
       
   238 	  m->m_data -= iphlen;
       
   239 	  *ip=save_ip;
       
   240 	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
       
   241 	  icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
       
   242 	}
       
   243 
       
   244 	m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */
       
   245 
       
   246 	/* restore the orig mbuf packet */
       
   247 	m->m_len += iphlen;
       
   248 	m->m_data -= iphlen;
       
   249 	*ip=save_ip;
       
   250 	so->so_m=m;         /* ICMP backup */
       
   251 
       
   252 	return;
       
   253 bad:
       
   254 	m_freem(m);
       
   255 	/* if (opts) m_freem(opts); */
       
   256 	return;
       
   257 }
       
   258 
       
   259 int udp_output2(struct socket *so, struct mbuf *m,
       
   260                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
       
   261                 int iptos)
       
   262 {
       
   263 	register struct udpiphdr *ui;
       
   264 	int error = 0;
       
   265 
       
   266 	DEBUG_CALL("udp_output");
       
   267 	DEBUG_ARG("so = %lx", (long)so);
       
   268 	DEBUG_ARG("m = %lx", (long)m);
       
   269 	DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
       
   270 	DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
       
   271 
       
   272 	/*
       
   273 	 * Adjust for header
       
   274 	 */
       
   275 	m->m_data -= sizeof(struct udpiphdr);
       
   276 	m->m_len += sizeof(struct udpiphdr);
       
   277 
       
   278 	/*
       
   279 	 * Fill in mbuf with extended UDP header
       
   280 	 * and addresses and length put into network format.
       
   281 	 */
       
   282 	ui = mtod(m, struct udpiphdr *);
       
   283 	ui->ui_next = ui->ui_prev = 0;
       
   284 	ui->ui_x1 = 0;
       
   285 	ui->ui_pr = IPPROTO_UDP;
       
   286 	ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
       
   287 	/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
       
   288         ui->ui_src = saddr->sin_addr;
       
   289 	ui->ui_dst = daddr->sin_addr;
       
   290 	ui->ui_sport = saddr->sin_port;
       
   291 	ui->ui_dport = daddr->sin_port;
       
   292 	ui->ui_ulen = ui->ui_len;
       
   293 
       
   294 	/*
       
   295 	 * Stuff checksum and output datagram.
       
   296 	 */
       
   297 	ui->ui_sum = 0;
       
   298 	if (UDPCKSUM) {
       
   299 	    if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
       
   300 		ui->ui_sum = 0xffff;
       
   301 	}
       
   302 	((struct ip *)ui)->ip_len = m->m_len;
       
   303 
       
   304 	((struct ip *)ui)->ip_ttl = IPDEFTTL;
       
   305 	((struct ip *)ui)->ip_tos = iptos;
       
   306 
       
   307 	STAT(udpstat.udps_opackets++);
       
   308 
       
   309 	error = ip_output(so, m);
       
   310 
       
   311 	return (error);
       
   312 }
       
   313 
       
   314 int udp_output(struct socket *so, struct mbuf *m,
       
   315                struct sockaddr_in *addr)
       
   316 
       
   317 {
       
   318     struct sockaddr_in saddr, daddr;
       
   319 
       
   320     saddr = *addr;
       
   321     if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
       
   322         if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))
       
   323             saddr.sin_addr.s_addr = alias_addr.s_addr;
       
   324         else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
       
   325                  (ntohl(so->so_faddr.s_addr) & 0xff) != CTL_ALIAS)
       
   326             saddr.sin_addr.s_addr = so->so_faddr.s_addr;
       
   327     }
       
   328     daddr.sin_addr = so->so_laddr;
       
   329     daddr.sin_port = so->so_lport;
       
   330 
       
   331     return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
       
   332 }
       
   333 
       
   334 int
       
   335 udp_attach(so)
       
   336      struct socket *so;
       
   337 {
       
   338   struct sockaddr_in addr;
       
   339 
       
   340   if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
       
   341     /*
       
   342      * Here, we bind() the socket.  Although not really needed
       
   343      * (sendto() on an unbound socket will bind it), it's done
       
   344      * here so that emulation of ytalk etc. don't have to do it
       
   345      */
       
   346     addr.sin_family = AF_INET;
       
   347     addr.sin_port = 0;
       
   348     addr.sin_addr.s_addr = INADDR_ANY;
       
   349     if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
       
   350       int lasterrno=errno;
       
   351       closesocket(so->s);
       
   352       so->s=-1;
       
   353 #ifdef _WIN32
       
   354       WSASetLastError(lasterrno);
       
   355 #else
       
   356       errno=lasterrno;
       
   357 #endif
       
   358     } else {
       
   359       /* success, insert in queue */
       
   360       so->so_expire = curtime + SO_EXPIRE;
       
   361       insque(so,&udb);
       
   362     }
       
   363   }
       
   364   return(so->s);
       
   365 }
       
   366 
       
   367 void
       
   368 udp_detach(so)
       
   369 	struct socket *so;
       
   370 {
       
   371 	closesocket(so->s);
       
   372 	/* if (so->so_m) m_free(so->so_m);    done by sofree */
       
   373 
       
   374 	sofree(so);
       
   375 }
       
   376 
       
   377 static const struct tos_t udptos[] = {
       
   378 	{0, 53, IPTOS_LOWDELAY, 0},			/* DNS */
       
   379 	{517, 517, IPTOS_LOWDELAY, EMU_TALK},	/* talk */
       
   380 	{518, 518, IPTOS_LOWDELAY, EMU_NTALK},	/* ntalk */
       
   381 	{0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME},	/* Cu-Seeme */
       
   382 	{0, 0, 0, 0}
       
   383 };
       
   384 
       
   385 static u_int8_t
       
   386 udp_tos(struct socket *so)
       
   387 {
       
   388 	int i = 0;
       
   389 
       
   390 	while(udptos[i].tos) {
       
   391 		if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
       
   392 		    (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
       
   393 		    	so->so_emu = udptos[i].emu;
       
   394 			return udptos[i].tos;
       
   395 		}
       
   396 		i++;
       
   397 	}
       
   398 
       
   399 	return 0;
       
   400 }
       
   401 
       
   402 #ifdef EMULATE_TALK
       
   403 #include "talkd.h"
       
   404 #endif
       
   405 
       
   406 /*
       
   407  * Here, talk/ytalk/ntalk requests must be emulated
       
   408  */
       
   409 static void
       
   410 udp_emu(struct socket *so, struct mbuf *m)
       
   411 {
       
   412 	struct sockaddr_in addr;
       
   413 	socklen_t addrlen = sizeof(addr);
       
   414 #ifdef EMULATE_TALK
       
   415 	CTL_MSG_OLD *omsg;
       
   416 	CTL_MSG *nmsg;
       
   417 	char buff[sizeof(CTL_MSG)];
       
   418 	u_char type;
       
   419 
       
   420 struct talk_request {
       
   421 	struct talk_request *next;
       
   422 	struct socket *udp_so;
       
   423 	struct socket *tcp_so;
       
   424 } *req;
       
   425 
       
   426 	static struct talk_request *req_tbl = 0;
       
   427 
       
   428 #endif
       
   429 
       
   430 struct cu_header {
       
   431 	uint16_t	d_family;		// destination family
       
   432 	uint16_t	d_port;			// destination port
       
   433 	uint32_t	d_addr;			// destination address
       
   434 	uint16_t	s_family;		// source family
       
   435 	uint16_t	s_port;			// source port
       
   436 	uint32_t	so_addr;		// source address
       
   437 	uint32_t	seqn;			// sequence number
       
   438 	uint16_t	message;		// message
       
   439 	uint16_t	data_type;		// data type
       
   440 	uint16_t	pkt_len;		// packet length
       
   441 } *cu_head;
       
   442 
       
   443 	switch(so->so_emu) {
       
   444 
       
   445 #ifdef EMULATE_TALK
       
   446 	 case EMU_TALK:
       
   447 	 case EMU_NTALK:
       
   448 		/*
       
   449 		 * Talk emulation. We always change the ctl_addr to get
       
   450 		 * some answers from the daemon. When an ANNOUNCE comes,
       
   451 		 * we send LEAVE_INVITE to the local daemons. Also when a
       
   452 		 * DELETE comes, we send copies to the local daemons.
       
   453 		 */
       
   454 		if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
       
   455 			return;
       
   456 
       
   457 #define	IS_OLD	(so->so_emu == EMU_TALK)
       
   458 
       
   459 #define COPY_MSG(dest, src) { dest->type = src->type; \
       
   460 			      dest->id_num = src->id_num; \
       
   461 			      dest->pid = src->pid; \
       
   462 			      dest->addr = src->addr; \
       
   463 			      dest->ctl_addr = src->ctl_addr; \
       
   464 			      memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \
       
   465 			      memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \
       
   466 	         	      memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE); }
       
   467 
       
   468 #define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field)
       
   469 /* old_sockaddr to sockaddr_in */
       
   470 
       
   471 
       
   472 		if (IS_OLD) {  		/* old talk */
       
   473 			omsg = mtod(m, CTL_MSG_OLD*);
       
   474 			nmsg = (CTL_MSG *) buff;
       
   475 			type = omsg->type;
       
   476 			OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
       
   477 			OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
       
   478                         pstrcpy(omsg->l_name, NAME_SIZE_OLD, getlogin());
       
   479 		} else {		/* new talk */
       
   480 			omsg = (CTL_MSG_OLD *) buff;
       
   481 			nmsg = mtod(m, CTL_MSG *);
       
   482 			type = nmsg->type;
       
   483 			OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port;
       
   484 			OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
       
   485                         pstrcpy(nmsg->l_name, NAME_SIZE_OLD, getlogin());
       
   486 		}
       
   487 
       
   488 		if (type == LOOK_UP)
       
   489 			return;		/* for LOOK_UP this is enough */
       
   490 
       
   491 		if (IS_OLD) {		/* make a copy of the message */
       
   492 			COPY_MSG(nmsg, omsg);
       
   493 			nmsg->vers = 1;
       
   494 			nmsg->answer = 0;
       
   495 		} else
       
   496 			COPY_MSG(omsg, nmsg);
       
   497 
       
   498 		/*
       
   499 		 * If if is an ANNOUNCE message, we go through the
       
   500 		 * request table to see if a tcp port has already
       
   501 		 * been redirected for this socket. If not, we solisten()
       
   502 		 * a new socket and add this entry to the table.
       
   503 		 * The port number of the tcp socket and our IP
       
   504 		 * are put to the addr field of the message structures.
       
   505 		 * Then a LEAVE_INVITE is sent to both local daemon
       
   506 		 * ports, 517 and 518. This is why we have two copies
       
   507 		 * of the message, one in old talk and one in new talk
       
   508 		 * format.
       
   509 		 */
       
   510 
       
   511 		if (type == ANNOUNCE) {
       
   512 			int s;
       
   513 			u_short temp_port;
       
   514 
       
   515 			for(req = req_tbl; req; req = req->next)
       
   516 				if (so == req->udp_so)
       
   517 					break;  	/* found it */
       
   518 
       
   519 			if (!req) {	/* no entry for so, create new */
       
   520 				req = (struct talk_request *)
       
   521 					malloc(sizeof(struct talk_request));
       
   522 				req->udp_so = so;
       
   523 				req->tcp_so = solisten(0,
       
   524 					OTOSIN(omsg, addr)->sin_addr.s_addr,
       
   525 					OTOSIN(omsg, addr)->sin_port,
       
   526 					SS_FACCEPTONCE);
       
   527 				req->next = req_tbl;
       
   528 				req_tbl = req;
       
   529 			}
       
   530 
       
   531 			/* replace port number in addr field */
       
   532 			addrlen = sizeof(addr);
       
   533 			getsockname(req->tcp_so->s,
       
   534 					(struct sockaddr *) &addr,
       
   535 					&addrlen);
       
   536 			OTOSIN(omsg, addr)->sin_port = addr.sin_port;
       
   537 			OTOSIN(omsg, addr)->sin_addr = our_addr;
       
   538 			OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
       
   539 			OTOSIN(nmsg, addr)->sin_addr = our_addr;
       
   540 
       
   541 			/* send LEAVE_INVITEs */
       
   542 			temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
       
   543 			OTOSIN(omsg, ctl_addr)->sin_port = 0;
       
   544 			OTOSIN(nmsg, ctl_addr)->sin_port = 0;
       
   545 			omsg->type = nmsg->type = LEAVE_INVITE;
       
   546 
       
   547 			s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
       
   548 			addr.sin_addr = our_addr;
       
   549 			addr.sin_family = AF_INET;
       
   550 			addr.sin_port = htons(517);
       
   551 			sendto(s, (char *)omsg, sizeof(*omsg), 0,
       
   552 				(struct sockaddr *)&addr, sizeof(addr));
       
   553 			addr.sin_port = htons(518);
       
   554 			sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
       
   555 				(struct sockaddr *) &addr, sizeof(addr));
       
   556 			closesocket(s) ;
       
   557 
       
   558 			omsg->type = nmsg->type = ANNOUNCE;
       
   559 			OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
       
   560 			OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
       
   561 		}
       
   562 
       
   563 		/*
       
   564 		 * If it is a DELETE message, we send a copy to the
       
   565 		 * local daemons. Then we delete the entry corresponding
       
   566 		 * to our socket from the request table.
       
   567 		 */
       
   568 
       
   569 		if (type == DELETE) {
       
   570 			struct talk_request *temp_req, *req_next;
       
   571 			int s;
       
   572 			u_short temp_port;
       
   573 
       
   574 			temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
       
   575 			OTOSIN(omsg, ctl_addr)->sin_port = 0;
       
   576 			OTOSIN(nmsg, ctl_addr)->sin_port = 0;
       
   577 
       
   578 			s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
       
   579 			addr.sin_addr = our_addr;
       
   580 			addr.sin_family = AF_INET;
       
   581 			addr.sin_port = htons(517);
       
   582 			sendto(s, (char *)omsg, sizeof(*omsg), 0,
       
   583 				(struct sockaddr *)&addr, sizeof(addr));
       
   584 			addr.sin_port = htons(518);
       
   585 			sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
       
   586 				(struct sockaddr *)&addr, sizeof(addr));
       
   587 			closesocket(s);
       
   588 
       
   589 			OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
       
   590 			OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
       
   591 
       
   592 			/* delete table entry */
       
   593 			if (so == req_tbl->udp_so) {
       
   594 				temp_req = req_tbl;
       
   595 				req_tbl = req_tbl->next;
       
   596 				free(temp_req);
       
   597 			} else {
       
   598 				temp_req = req_tbl;
       
   599 				for(req = req_tbl->next; req; req = req_next) {
       
   600 					req_next = req->next;
       
   601 					if (so == req->udp_so) {
       
   602 						temp_req->next = req_next;
       
   603 						free(req);
       
   604 						break;
       
   605 					} else {
       
   606 						temp_req = req;
       
   607 					}
       
   608 				}
       
   609 			}
       
   610 		}
       
   611 
       
   612 		return;
       
   613 #endif
       
   614 
       
   615 	case EMU_CUSEEME:
       
   616 
       
   617 		/*
       
   618 		 * Cu-SeeMe emulation.
       
   619 		 * Hopefully the packet is more that 16 bytes long. We don't
       
   620 		 * do any other tests, just replace the address and port
       
   621 		 * fields.
       
   622 		 */
       
   623 		if (m->m_len >= sizeof (*cu_head)) {
       
   624 			if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
       
   625 				return;
       
   626 			cu_head = mtod(m, struct cu_header *);
       
   627 			cu_head->s_port = addr.sin_port;
       
   628 			cu_head->so_addr = our_addr.s_addr;
       
   629 		}
       
   630 
       
   631 		return;
       
   632 	}
       
   633 }
       
   634 
       
   635 struct socket *
       
   636 udp_listen(port, laddr, lport, flags)
       
   637 	u_int port;
       
   638 	u_int32_t laddr;
       
   639 	u_int lport;
       
   640 	int flags;
       
   641 {
       
   642 	struct sockaddr_in addr;
       
   643 	struct socket *so;
       
   644 	socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1;
       
   645 
       
   646 	if ((so = socreate()) == NULL) {
       
   647 		free(so);
       
   648 		return NULL;
       
   649 	}
       
   650 	so->s = socket(AF_INET,SOCK_DGRAM,0);
       
   651 	so->so_expire = curtime + SO_EXPIRE;
       
   652 	insque(so,&udb);
       
   653 
       
   654 	addr.sin_family = AF_INET;
       
   655 	addr.sin_addr.s_addr = INADDR_ANY;
       
   656 	addr.sin_port = port;
       
   657 
       
   658 	if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
       
   659 		udp_detach(so);
       
   660 		return NULL;
       
   661 	}
       
   662 	setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
       
   663 /*	setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */
       
   664 
       
   665 	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
       
   666 	so->so_fport = addr.sin_port;
       
   667 	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
       
   668 	   so->so_faddr = alias_addr;
       
   669 	else
       
   670 	   so->so_faddr = addr.sin_addr;
       
   671 
       
   672 	so->so_lport = lport;
       
   673 	so->so_laddr.s_addr = laddr;
       
   674 	if (flags != SS_FACCEPTONCE)
       
   675 	   so->so_expire = 0;
       
   676 
       
   677 	so->so_state = SS_ISFCONNECTED;
       
   678 
       
   679 	return so;
       
   680 }