|
|
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.
1.1.1.6 ! root 13: * 3. Neither the name of the University nor the names of its contributors
1.1 root 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.
1.1.1.5 root 36: *
37: * Please read the file COPYRIGHT for the
1.1 root 38: * terms and conditions of the copyright.
39: */
40:
41: #include <slirp.h>
42: #include "ip_icmp.h"
43:
1.1.1.5 root 44: #ifdef LOG_ENABLED
1.1 root 45: struct udpstat udpstat;
1.1.1.5 root 46: #endif
1.1 root 47:
48: struct socket udb;
49:
1.1.1.5 root 50: static u_int8_t udp_tos(struct socket *so);
51: static void udp_emu(struct socket *so, struct mbuf *m);
52:
1.1 root 53: /*
54: * UDP protocol implementation.
55: * Per RFC 768, August, 1980.
56: */
57: #ifndef COMPAT_42
1.1.1.5 root 58: #define UDPCKSUM 1
1.1 root 59: #else
1.1.1.5 root 60: #define UDPCKSUM 0 /* XXX */
1.1 root 61: #endif
62:
63: struct socket *udp_last_so = &udb;
64:
65: void
66: udp_init()
67: {
68: udb.so_next = udb.so_prev = &udb;
69: }
1.1.1.5 root 70: /* m->m_data points at ip packet header
71: * m->m_len length ip packet
1.1 root 72: * ip->ip_len length data (IPDU)
73: */
74: void
75: udp_input(m, iphlen)
76: register struct mbuf *m;
77: int iphlen;
78: {
79: register struct ip *ip;
80: register struct udphdr *uh;
81: /* struct mbuf *opts = 0;*/
82: int len;
1.1.1.5 root 83: struct ip save_ip;
1.1 root 84: struct socket *so;
1.1.1.5 root 85:
1.1 root 86: DEBUG_CALL("udp_input");
87: DEBUG_ARG("m = %lx", (long)m);
88: DEBUG_ARG("iphlen = %d", iphlen);
1.1.1.5 root 89:
90: STAT(udpstat.udps_ipackets++);
1.1 root 91:
92: /*
93: * Strip IP options, if any; should skip this,
94: * make available to user, and use on returned packets,
95: * but we don't yet have a way to check the checksum
96: * with options still present.
97: */
98: if(iphlen > sizeof(struct ip)) {
99: ip_stripoptions(m, (struct mbuf *)0);
100: iphlen = sizeof(struct ip);
101: }
102:
103: /*
104: * Get IP and UDP header together in first mbuf.
105: */
106: ip = mtod(m, struct ip *);
107: uh = (struct udphdr *)((caddr_t)ip + iphlen);
108:
109: /*
110: * Make mbuf data length reflect UDP length.
111: * If not enough data to reflect UDP length, drop.
112: */
113: len = ntohs((u_int16_t)uh->uh_ulen);
114:
115: if (ip->ip_len != len) {
116: if (len > ip->ip_len) {
1.1.1.5 root 117: STAT(udpstat.udps_badlen++);
1.1 root 118: goto bad;
119: }
120: m_adj(m, len - ip->ip_len);
121: ip->ip_len = len;
122: }
1.1.1.5 root 123:
1.1 root 124: /*
125: * Save a copy of the IP header in case we want restore it
126: * for sending an ICMP error message in response.
127: */
1.1.1.5 root 128: save_ip = *ip;
1.1 root 129: save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
130:
131: /*
132: * Checksum extended UDP header and data.
133: */
1.1.1.5 root 134: if (UDPCKSUM && uh->uh_sum) {
1.1.1.6 ! root 135: memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
1.1 root 136: ((struct ipovly *)ip)->ih_x1 = 0;
137: ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
138: /* keep uh_sum for ICMP reply
1.1.1.5 root 139: * uh->uh_sum = cksum(m, len + sizeof (struct ip));
140: * if (uh->uh_sum) {
1.1 root 141: */
142: if(cksum(m, len + sizeof(struct ip))) {
1.1.1.5 root 143: STAT(udpstat.udps_badsum++);
1.1 root 144: goto bad;
145: }
146: }
147:
148: /*
149: * handle DHCP/BOOTP
150: */
151: if (ntohs(uh->uh_dport) == BOOTP_SERVER) {
152: bootp_input(m);
153: goto bad;
154: }
155:
1.1.1.6 ! root 156: if (slirp_restrict)
! 157: goto bad;
! 158:
1.1 root 159: /*
160: * handle TFTP
161: */
162: if (ntohs(uh->uh_dport) == TFTP_SERVER) {
163: tftp_input(m);
164: goto bad;
165: }
166:
167: /*
168: * Locate pcb for datagram.
169: */
170: so = udp_last_so;
171: if (so->so_lport != uh->uh_sport ||
172: so->so_laddr.s_addr != ip->ip_src.s_addr) {
173: struct socket *tmp;
1.1.1.5 root 174:
1.1 root 175: for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
176: if (tmp->so_lport == uh->uh_sport &&
177: tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
178: tmp->so_faddr.s_addr = ip->ip_dst.s_addr;
179: tmp->so_fport = uh->uh_dport;
180: so = tmp;
181: break;
182: }
183: }
184: if (tmp == &udb) {
185: so = NULL;
186: } else {
1.1.1.5 root 187: STAT(udpstat.udpps_pcbcachemiss++);
1.1 root 188: udp_last_so = so;
189: }
190: }
1.1.1.5 root 191:
1.1 root 192: if (so == NULL) {
193: /*
194: * If there's no socket for this packet,
195: * create one
196: */
197: if ((so = socreate()) == NULL) goto bad;
198: if(udp_attach(so) == -1) {
1.1.1.5 root 199: DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
1.1 root 200: errno,strerror(errno)));
201: sofree(so);
202: goto bad;
203: }
1.1.1.5 root 204:
1.1 root 205: /*
206: * Setup fields
207: */
208: /* udp_last_so = so; */
209: so->so_laddr = ip->ip_src;
210: so->so_lport = uh->uh_sport;
1.1.1.5 root 211:
1.1 root 212: if ((so->so_iptos = udp_tos(so)) == 0)
213: so->so_iptos = ip->ip_tos;
1.1.1.5 root 214:
1.1 root 215: /*
216: * XXXXX Here, check if it's in udpexec_list,
217: * and if it is, do the fork_exec() etc.
218: */
219: }
220:
1.1.1.4 root 221: so->so_faddr = ip->ip_dst; /* XXX */
222: so->so_fport = uh->uh_dport; /* XXX */
223:
1.1 root 224: iphlen += sizeof(struct udphdr);
225: m->m_len -= iphlen;
226: m->m_data += iphlen;
227:
228: /*
229: * Now we sendto() the packet.
230: */
231: if (so->so_emu)
232: udp_emu(so, m);
233:
234: if(sosendto(so,m) == -1) {
235: m->m_len += iphlen;
236: m->m_data -= iphlen;
237: *ip=save_ip;
238: DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
1.1.1.5 root 239: icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
1.1 root 240: }
241:
242: m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
243:
244: /* restore the orig mbuf packet */
245: m->m_len += iphlen;
246: m->m_data -= iphlen;
247: *ip=save_ip;
248: so->so_m=m; /* ICMP backup */
249:
250: return;
251: bad:
252: m_freem(m);
253: /* if (opts) m_freem(opts); */
254: return;
255: }
256:
1.1.1.5 root 257: int udp_output2(struct socket *so, struct mbuf *m,
1.1 root 258: struct sockaddr_in *saddr, struct sockaddr_in *daddr,
259: int iptos)
260: {
261: register struct udpiphdr *ui;
262: int error = 0;
263:
264: DEBUG_CALL("udp_output");
265: DEBUG_ARG("so = %lx", (long)so);
266: DEBUG_ARG("m = %lx", (long)m);
267: DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
268: DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);
269:
270: /*
271: * Adjust for header
272: */
273: m->m_data -= sizeof(struct udpiphdr);
274: m->m_len += sizeof(struct udpiphdr);
1.1.1.5 root 275:
1.1 root 276: /*
277: * Fill in mbuf with extended UDP header
278: * and addresses and length put into network format.
279: */
280: ui = mtod(m, struct udpiphdr *);
1.1.1.6 ! root 281: memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
1.1 root 282: ui->ui_x1 = 0;
283: ui->ui_pr = IPPROTO_UDP;
284: ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
285: /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
286: ui->ui_src = saddr->sin_addr;
287: ui->ui_dst = daddr->sin_addr;
288: ui->ui_sport = saddr->sin_port;
289: ui->ui_dport = daddr->sin_port;
290: ui->ui_ulen = ui->ui_len;
291:
292: /*
293: * Stuff checksum and output datagram.
294: */
295: ui->ui_sum = 0;
1.1.1.5 root 296: if (UDPCKSUM) {
1.1 root 297: if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
298: ui->ui_sum = 0xffff;
299: }
300: ((struct ip *)ui)->ip_len = m->m_len;
301:
1.1.1.5 root 302: ((struct ip *)ui)->ip_ttl = IPDEFTTL;
1.1 root 303: ((struct ip *)ui)->ip_tos = iptos;
1.1.1.5 root 304:
305: STAT(udpstat.udps_opackets++);
306:
1.1 root 307: error = ip_output(so, m);
1.1.1.5 root 308:
1.1 root 309: return (error);
310: }
311:
1.1.1.5 root 312: int udp_output(struct socket *so, struct mbuf *m,
1.1 root 313: struct sockaddr_in *addr)
314:
315: {
316: struct sockaddr_in saddr, daddr;
317:
318: saddr = *addr;
1.1.1.3 root 319: if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
320: if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))
321: saddr.sin_addr.s_addr = alias_addr.s_addr;
1.1.1.6 ! root 322: else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
! 323: (ntohl(so->so_faddr.s_addr) & 0xff) != CTL_ALIAS)
! 324: saddr.sin_addr.s_addr = so->so_faddr.s_addr;
1.1.1.3 root 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;
1.1.1.6 ! root 411: socklen_t addrlen = sizeof(addr);
1.1 root 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;
1.1.1.6 ! root 476: pstrcpy(omsg->l_name, NAME_SIZE_OLD, getlogin());
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;
1.1.1.6 ! root 483: pstrcpy(nmsg->l_name, NAME_SIZE_OLD, getlogin());
1.1 root 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;
1.1.1.6 ! root 642: socklen_t 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.