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