|
|
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(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 = 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 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: memset(&addr, 0, sizeof(struct sockaddr_in)); ! 649: addr.sin_family = AF_INET; ! 650: addr.sin_addr.s_addr = INADDR_ANY; ! 651: addr.sin_port = port; ! 652: ! 653: if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) { ! 654: udp_detach(so); ! 655: return NULL; ! 656: } ! 657: setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); ! 658: /* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */ ! 659: ! 660: getsockname(so->s,(struct sockaddr *)&addr,&addrlen); ! 661: so->so_fport = addr.sin_port; ! 662: if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) ! 663: so->so_faddr = alias_addr; ! 664: else ! 665: so->so_faddr = addr.sin_addr; ! 666: ! 667: so->so_lport = lport; ! 668: so->so_laddr.s_addr = laddr; ! 669: if (flags != SS_FACCEPTONCE) ! 670: so->so_expire = 0; ! 671: ! 672: so->so_state = SS_ISFCONNECTED; ! 673: ! 674: return so; ! 675: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.