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