|
|
1.1 root 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.
1.1.1.5 ! root 40: *
! 41: * Please read the file COPYRIGHT for the
1.1 root 42: * terms and conditions of the copyright.
43: */
44:
45: #include <slirp.h>
46: #include "ip_icmp.h"
47:
1.1.1.5 ! root 48: #ifdef LOG_ENABLED
1.1 root 49: struct udpstat udpstat;
1.1.1.5 ! root 50: #endif
1.1 root 51:
52: struct socket udb;
53:
1.1.1.5 ! root 54: static u_int8_t udp_tos(struct socket *so);
! 55: static void udp_emu(struct socket *so, struct mbuf *m);
! 56:
1.1 root 57: /*
58: * UDP protocol implementation.
59: * Per RFC 768, August, 1980.
60: */
61: #ifndef COMPAT_42
1.1.1.5 ! root 62: #define UDPCKSUM 1
1.1 root 63: #else
1.1.1.5 ! root 64: #define UDPCKSUM 0 /* XXX */
1.1 root 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: }
1.1.1.5 ! root 74: /* m->m_data points at ip packet header
! 75: * m->m_len length ip packet
1.1 root 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;
1.1.1.5 ! root 87: struct ip save_ip;
1.1 root 88: struct socket *so;
1.1.1.5 ! root 89:
1.1 root 90: DEBUG_CALL("udp_input");
91: DEBUG_ARG("m = %lx", (long)m);
92: DEBUG_ARG("iphlen = %d", iphlen);
1.1.1.5 ! root 93:
! 94: STAT(udpstat.udps_ipackets++);
1.1 root 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) {
1.1.1.5 ! root 121: STAT(udpstat.udps_badlen++);
1.1 root 122: goto bad;
123: }
124: m_adj(m, len - ip->ip_len);
125: ip->ip_len = len;
126: }
1.1.1.5 ! root 127:
1.1 root 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: */
1.1.1.5 ! root 132: save_ip = *ip;
1.1 root 133: save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
134:
135: /*
136: * Checksum extended UDP header and data.
137: */
1.1.1.5 ! root 138: if (UDPCKSUM && uh->uh_sum) {
1.1 root 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
1.1.1.5 ! root 144: * uh->uh_sum = cksum(m, len + sizeof (struct ip));
! 145: * if (uh->uh_sum) {
1.1 root 146: */
147: if(cksum(m, len + sizeof(struct ip))) {
1.1.1.5 ! root 148: STAT(udpstat.udps_badsum++);
1.1 root 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;
1.1.1.5 ! root 176:
1.1 root 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 {
1.1.1.5 ! root 189: STAT(udpstat.udpps_pcbcachemiss++);
1.1 root 190: udp_last_so = so;
191: }
192: }
1.1.1.5 ! root 193:
1.1 root 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) {
1.1.1.5 ! root 201: DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
1.1 root 202: errno,strerror(errno)));
203: sofree(so);
204: goto bad;
205: }
1.1.1.5 ! root 206:
1.1 root 207: /*
208: * Setup fields
209: */
210: /* udp_last_so = so; */
211: so->so_laddr = ip->ip_src;
212: so->so_lport = uh->uh_sport;
1.1.1.5 ! root 213:
1.1 root 214: if ((so->so_iptos = udp_tos(so)) == 0)
215: so->so_iptos = ip->ip_tos;
1.1.1.5 ! root 216:
1.1 root 217: /*
218: * XXXXX Here, check if it's in udpexec_list,
219: * and if it is, do the fork_exec() etc.
220: */
221: }
222:
1.1.1.4 root 223: so->so_faddr = ip->ip_dst; /* XXX */
224: so->so_fport = uh->uh_dport; /* XXX */
225:
1.1 root 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)));
1.1.1.5 ! root 241: icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
1.1 root 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:
1.1.1.5 ! root 259: int udp_output2(struct socket *so, struct mbuf *m,
1.1 root 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);
1.1.1.5 ! root 277:
1.1 root 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;
1.1.1.5 ! root 298: if (UDPCKSUM) {
1.1 root 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:
1.1.1.5 ! root 304: ((struct ip *)ui)->ip_ttl = IPDEFTTL;
1.1 root 305: ((struct ip *)ui)->ip_tos = iptos;
1.1.1.5 ! root 306:
! 307: STAT(udpstat.udps_opackets++);
! 308:
1.1 root 309: error = ip_output(so, m);
1.1.1.5 ! root 310:
1.1 root 311: return (error);
312: }
313:
1.1.1.5 ! root 314: int udp_output(struct socket *so, struct mbuf *m,
1.1 root 315: struct sockaddr_in *addr)
316:
317: {
318: struct sockaddr_in saddr, daddr;
319:
320: saddr = *addr;
1.1.1.3 root 321: if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
1.1 root 322: saddr.sin_addr.s_addr = so->so_faddr.s_addr;
1.1.1.3 root 323: if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))
324: saddr.sin_addr.s_addr = alias_addr.s_addr;
325: }
1.1 root 326: daddr.sin_addr = so->so_laddr;
327: daddr.sin_port = so->so_lport;
1.1.1.5 ! root 328:
1.1 root 329: return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
330: }
331:
332: int
333: udp_attach(so)
334: struct socket *so;
335: {
336: struct sockaddr_in addr;
1.1.1.5 ! root 337:
1.1 root 338: if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
339: /*
340: * Here, we bind() the socket. Although not really needed
341: * (sendto() on an unbound socket will bind it), it's done
342: * here so that emulation of ytalk etc. don't have to do it
343: */
344: addr.sin_family = AF_INET;
345: addr.sin_port = 0;
346: addr.sin_addr.s_addr = INADDR_ANY;
347: if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
348: int lasterrno=errno;
349: closesocket(so->s);
350: so->s=-1;
351: #ifdef _WIN32
352: WSASetLastError(lasterrno);
353: #else
354: errno=lasterrno;
355: #endif
356: } else {
357: /* success, insert in queue */
358: so->so_expire = curtime + SO_EXPIRE;
359: insque(so,&udb);
360: }
361: }
362: return(so->s);
363: }
364:
365: void
366: udp_detach(so)
367: struct socket *so;
368: {
369: closesocket(so->s);
370: /* if (so->so_m) m_free(so->so_m); done by sofree */
371:
372: sofree(so);
373: }
374:
1.1.1.5 ! root 375: static const struct tos_t udptos[] = {
1.1 root 376: {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
377: {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */
378: {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */
379: {0, 7648, IPTOS_LOWDELAY, EMU_CUSEEME}, /* Cu-Seeme */
380: {0, 0, 0, 0}
381: };
382:
1.1.1.5 ! root 383: static u_int8_t
! 384: udp_tos(struct socket *so)
1.1 root 385: {
386: int i = 0;
1.1.1.5 ! root 387:
1.1 root 388: while(udptos[i].tos) {
389: if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
390: (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
391: so->so_emu = udptos[i].emu;
392: return udptos[i].tos;
393: }
394: i++;
395: }
1.1.1.5 ! root 396:
1.1 root 397: return 0;
398: }
399:
400: #ifdef EMULATE_TALK
401: #include "talkd.h"
402: #endif
403:
404: /*
405: * Here, talk/ytalk/ntalk requests must be emulated
406: */
1.1.1.5 ! root 407: static void
! 408: udp_emu(struct socket *so, struct mbuf *m)
1.1 root 409: {
410: struct sockaddr_in addr;
411: int addrlen = sizeof(addr);
412: #ifdef EMULATE_TALK
413: CTL_MSG_OLD *omsg;
414: CTL_MSG *nmsg;
415: char buff[sizeof(CTL_MSG)];
416: u_char type;
1.1.1.5 ! root 417:
1.1 root 418: struct talk_request {
419: struct talk_request *next;
420: struct socket *udp_so;
421: struct socket *tcp_so;
422: } *req;
1.1.1.5 ! root 423:
! 424: static struct talk_request *req_tbl = 0;
! 425:
1.1 root 426: #endif
1.1.1.5 ! root 427:
1.1 root 428: struct cu_header {
429: uint16_t d_family; // destination family
430: uint16_t d_port; // destination port
431: uint32_t d_addr; // destination address
432: uint16_t s_family; // source family
433: uint16_t s_port; // source port
434: uint32_t so_addr; // source address
435: uint32_t seqn; // sequence number
436: uint16_t message; // message
437: uint16_t data_type; // data type
438: uint16_t pkt_len; // packet length
439: } *cu_head;
440:
441: switch(so->so_emu) {
442:
443: #ifdef EMULATE_TALK
444: case EMU_TALK:
445: case EMU_NTALK:
446: /*
447: * Talk emulation. We always change the ctl_addr to get
448: * some answers from the daemon. When an ANNOUNCE comes,
449: * we send LEAVE_INVITE to the local daemons. Also when a
450: * DELETE comes, we send copies to the local daemons.
451: */
452: if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
453: return;
1.1.1.5 ! root 454:
1.1 root 455: #define IS_OLD (so->so_emu == EMU_TALK)
456:
457: #define COPY_MSG(dest, src) { dest->type = src->type; \
458: dest->id_num = src->id_num; \
459: dest->pid = src->pid; \
460: dest->addr = src->addr; \
461: dest->ctl_addr = src->ctl_addr; \
462: memcpy(&dest->l_name, &src->l_name, NAME_SIZE_OLD); \
463: memcpy(&dest->r_name, &src->r_name, NAME_SIZE_OLD); \
464: memcpy(&dest->r_tty, &src->r_tty, TTY_SIZE); }
465:
466: #define OTOSIN(ptr, field) ((struct sockaddr_in *)&ptr->field)
467: /* old_sockaddr to sockaddr_in */
468:
469:
470: if (IS_OLD) { /* old talk */
471: omsg = mtod(m, CTL_MSG_OLD*);
472: nmsg = (CTL_MSG *) buff;
473: type = omsg->type;
474: OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
475: OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
476: strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
1.1.1.5 ! root 477: } else { /* new talk */
1.1 root 478: omsg = (CTL_MSG_OLD *) buff;
479: nmsg = mtod(m, CTL_MSG *);
480: type = nmsg->type;
481: OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port;
482: OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
483: strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
484: }
1.1.1.5 ! root 485:
! 486: if (type == LOOK_UP)
1.1 root 487: return; /* for LOOK_UP this is enough */
1.1.1.5 ! root 488:
1.1 root 489: if (IS_OLD) { /* make a copy of the message */
490: COPY_MSG(nmsg, omsg);
491: nmsg->vers = 1;
492: nmsg->answer = 0;
493: } else
494: COPY_MSG(omsg, nmsg);
495:
496: /*
497: * If if is an ANNOUNCE message, we go through the
498: * request table to see if a tcp port has already
499: * been redirected for this socket. If not, we solisten()
500: * a new socket and add this entry to the table.
501: * The port number of the tcp socket and our IP
502: * are put to the addr field of the message structures.
503: * Then a LEAVE_INVITE is sent to both local daemon
504: * ports, 517 and 518. This is why we have two copies
505: * of the message, one in old talk and one in new talk
506: * format.
1.1.1.5 ! root 507: */
1.1 root 508:
509: if (type == ANNOUNCE) {
510: int s;
511: u_short temp_port;
1.1.1.5 ! root 512:
1.1 root 513: for(req = req_tbl; req; req = req->next)
514: if (so == req->udp_so)
515: break; /* found it */
1.1.1.5 ! root 516:
1.1 root 517: if (!req) { /* no entry for so, create new */
518: req = (struct talk_request *)
519: malloc(sizeof(struct talk_request));
520: req->udp_so = so;
1.1.1.5 ! root 521: req->tcp_so = solisten(0,
! 522: OTOSIN(omsg, addr)->sin_addr.s_addr,
1.1 root 523: OTOSIN(omsg, addr)->sin_port,
524: SS_FACCEPTONCE);
525: req->next = req_tbl;
526: req_tbl = req;
1.1.1.5 ! root 527: }
! 528:
1.1 root 529: /* replace port number in addr field */
530: addrlen = sizeof(addr);
1.1.1.5 ! root 531: getsockname(req->tcp_so->s,
1.1 root 532: (struct sockaddr *) &addr,
1.1.1.5 ! root 533: &addrlen);
1.1 root 534: OTOSIN(omsg, addr)->sin_port = addr.sin_port;
535: OTOSIN(omsg, addr)->sin_addr = our_addr;
536: OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
1.1.1.5 ! root 537: OTOSIN(nmsg, addr)->sin_addr = our_addr;
! 538:
1.1 root 539: /* send LEAVE_INVITEs */
540: temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
541: OTOSIN(omsg, ctl_addr)->sin_port = 0;
542: OTOSIN(nmsg, ctl_addr)->sin_port = 0;
1.1.1.5 ! root 543: omsg->type = nmsg->type = LEAVE_INVITE;
! 544:
1.1 root 545: s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
546: addr.sin_addr = our_addr;
547: addr.sin_family = AF_INET;
548: addr.sin_port = htons(517);
1.1.1.5 ! root 549: sendto(s, (char *)omsg, sizeof(*omsg), 0,
1.1 root 550: (struct sockaddr *)&addr, sizeof(addr));
551: addr.sin_port = htons(518);
552: sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
553: (struct sockaddr *) &addr, sizeof(addr));
554: closesocket(s) ;
555:
1.1.1.5 ! root 556: omsg->type = nmsg->type = ANNOUNCE;
1.1 root 557: OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
558: OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
559: }
1.1.1.5 ! root 560:
! 561: /*
1.1 root 562: * If it is a DELETE message, we send a copy to the
563: * local daemons. Then we delete the entry corresponding
564: * to our socket from the request table.
565: */
1.1.1.5 ! root 566:
1.1 root 567: if (type == DELETE) {
568: struct talk_request *temp_req, *req_next;
569: int s;
570: u_short temp_port;
1.1.1.5 ! root 571:
1.1 root 572: temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
573: OTOSIN(omsg, ctl_addr)->sin_port = 0;
574: OTOSIN(nmsg, ctl_addr)->sin_port = 0;
1.1.1.5 ! root 575:
1.1 root 576: s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
577: addr.sin_addr = our_addr;
578: addr.sin_family = AF_INET;
579: addr.sin_port = htons(517);
580: sendto(s, (char *)omsg, sizeof(*omsg), 0,
581: (struct sockaddr *)&addr, sizeof(addr));
582: addr.sin_port = htons(518);
583: sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
584: (struct sockaddr *)&addr, sizeof(addr));
585: closesocket(s);
1.1.1.5 ! root 586:
1.1 root 587: OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
588: OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
589:
590: /* delete table entry */
591: if (so == req_tbl->udp_so) {
592: temp_req = req_tbl;
593: req_tbl = req_tbl->next;
594: free(temp_req);
595: } else {
596: temp_req = req_tbl;
597: for(req = req_tbl->next; req; req = req_next) {
598: req_next = req->next;
599: if (so == req->udp_so) {
600: temp_req->next = req_next;
601: free(req);
602: break;
603: } else {
604: temp_req = req;
605: }
606: }
607: }
608: }
1.1.1.5 ! root 609:
! 610: return;
1.1 root 611: #endif
1.1.1.5 ! root 612:
1.1 root 613: case EMU_CUSEEME:
1.1.1.5 ! root 614:
1.1 root 615: /*
616: * Cu-SeeMe emulation.
617: * Hopefully the packet is more that 16 bytes long. We don't
618: * do any other tests, just replace the address and port
619: * fields.
1.1.1.5 ! root 620: */
1.1 root 621: if (m->m_len >= sizeof (*cu_head)) {
622: if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
623: return;
624: cu_head = mtod(m, struct cu_header *);
625: cu_head->s_port = addr.sin_port;
626: cu_head->so_addr = our_addr.s_addr;
627: }
1.1.1.5 ! root 628:
1.1 root 629: return;
630: }
631: }
632:
633: struct socket *
634: udp_listen(port, laddr, lport, flags)
635: u_int port;
636: u_int32_t laddr;
637: u_int lport;
638: int flags;
639: {
640: struct sockaddr_in addr;
641: struct socket *so;
642: int addrlen = sizeof(struct sockaddr_in), opt = 1;
1.1.1.5 ! root 643:
1.1 root 644: if ((so = socreate()) == NULL) {
645: free(so);
646: return NULL;
647: }
648: so->s = socket(AF_INET,SOCK_DGRAM,0);
649: so->so_expire = curtime + SO_EXPIRE;
650: insque(so,&udb);
651:
652: addr.sin_family = AF_INET;
653: addr.sin_addr.s_addr = INADDR_ANY;
654: addr.sin_port = port;
655:
656: if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
657: udp_detach(so);
658: return NULL;
659: }
660: setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
661: /* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */
1.1.1.5 ! root 662:
1.1 root 663: getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
664: so->so_fport = addr.sin_port;
665: if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
1.1.1.2 root 666: so->so_faddr = alias_addr;
1.1 root 667: else
668: so->so_faddr = addr.sin_addr;
1.1.1.5 ! root 669:
1.1 root 670: so->so_lport = lport;
671: so->so_laddr.s_addr = laddr;
672: if (flags != SS_FACCEPTONCE)
673: so->so_expire = 0;
1.1.1.5 ! root 674:
1.1 root 675: so->so_state = SS_ISFCONNECTED;
1.1.1.5 ! root 676:
1.1 root 677: return so;
678: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.