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