ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/slirp/udp.c
Revision: 1.8
Committed: 2012-03-30T01:10:28Z (12 years, 7 months ago) by asvitkine
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +1 -5 lines
Log Message:
Switch slirp to 3-clause BSD license. This change went in upstream to QEMU's
version of slirp (where this code comes from), with the following checkin:

commit 2f5f89963186d42a7ded253bc6cf5b32abb45cec
Author: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Mon Jan 26 19:37:41 2009 +0000

    Remove the advertising clause from the slirp license

    According to the FSF, the 4-clause BSD license, which slirp is covered under,
    is not compatible with the GPL or LGPL[1].

    [1] http://www.fsf.org/licensing/licenses/index_html#GPLIncompatibleLicenses

    There are three declared copyright holders in slirp that use the 4-clause
    BSD license, the Regents of UC Berkley, Danny Gasparovski, and Kelly Price.
    Below are the appropriate permissions to remove the advertise clause from slirp
    from each party.

    Special thanks go to Richard Fontana from Red Hat for contacting all of the
    necessary authors to resolve this issue!

    Regents of UC Berkley:
    From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change

    July 22, 1999

    To All Licensees, Distributors of Any Version of BSD:

    As you know, certain of the Berkeley Software Distribution ("BSD") source
    code files require that further distributions of products containing all or
    portions of the software, acknowledge within their advertising materials
    that such products contain software developed by UC Berkeley and its
    contributors.

    Specifically, the provision reads:

    "     * 3. All advertising materials mentioning features or use of this software
          *    must display the following acknowledgement:
          *    This product includes software developed by the University of
          *    California, Berkeley and its contributors."

    Effective immediately, licensees and distributors are no longer required to
    include the acknowledgement within advertising materials.  Accordingly, the
    foregoing paragraph of those BSD Unix files containing it is hereby deleted
    in its entirety.

    William Hoskins
    Director, Office of Technology Licensing
    University of California, Berkeley

    Danny Gasparovski:

    Subject: RE: Slirp license
    Date: Thu, 8 Jan 2009 10:51:00 +1100
    From: "Gasparovski, Daniel" <Daniel.Gasparovski@ato.gov.au>
    To: "Richard Fontana" <rfontana@redhat.com>

    Hi Richard,

    I have no objection to having Slirp code in QEMU be licensed under the
    3-clause BSD license.

    Thanks for taking the effort to consult me about this.


    Dan ...

    Kelly Price:

    Date: Thu, 8 Jan 2009 19:38:56 -0500
    From: "Kelly Price" <strredwolf@gmail.com>
    To: "Richard Fontana" <rfontana@redhat.com>
    Subject: Re: Slirp license

    Thanks for contacting me, Richard.  I'm glad you were able to find
    Dan, as I've been "keeping the light on" for Slirp.  I have no use for
    it now, and I have little time for it (now holding onto Keenspot's
    Comic Genesis and having a regular US state government position). If
    Dan would like to return to the project, I'd love to give it back to
    him.

    As for copyright, I don't own all of it.  Dan does, so I will defer to
    him.  Any of my patches I will gladly license to the 3-part BSD
    license.  My interest in re-licensing was because we didn't have ready
    info to contact Dan.  If Dan would like to port Slirp back out of
    QEMU, a lot of us 64-bit users would be grateful.

    Feel free to share this email address with Dan.  I will be glad to
    effect a transfer of the project to him and Mr. Bellard of the QEMU
    project.

    Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6451 c046a42c-6fe2-441c-8c8c-71466251a162

File Contents

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