163899Sarchie/* 263899Sarchie * alias_smedia.c 363899Sarchie * 463899Sarchie * Copyright (c) 2000 Whistle Communications, Inc. 563899Sarchie * All rights reserved. 663899Sarchie * 763899Sarchie * Subject to the following obligations and disclaimer of warranty, use and 863899Sarchie * redistribution of this software, in source or object code forms, with or 963899Sarchie * without modifications are expressly permitted by Whistle Communications; 1063899Sarchie * provided, however, that: 1163899Sarchie * 1. Any and all reproductions of the source or object code must include the 1263899Sarchie * copyright notice above and the following disclaimer of warranties; and 1363899Sarchie * 2. No rights are granted, in any manner or form, to use Whistle 1463899Sarchie * Communications, Inc. trademarks, including the mark "WHISTLE 1563899Sarchie * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 1663899Sarchie * such appears in the above copyright notice or in the software. 1763899Sarchie * 1863899Sarchie * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 1963899Sarchie * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 2063899Sarchie * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 2163899Sarchie * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 2263899Sarchie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 2363899Sarchie * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 2463899Sarchie * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 2563899Sarchie * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 2663899Sarchie * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2763899Sarchie * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 2863899Sarchie * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 2963899Sarchie * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 3063899Sarchie * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3163899Sarchie * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3263899Sarchie * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3363899Sarchie * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 3463899Sarchie * OF SUCH DAMAGE. 3563899Sarchie * 3663899Sarchie * Copyright (c) 2000 Junichi SATOH <junichi@astec.co.jp> 3763899Sarchie * <junichi@junichi.org> 3863899Sarchie * All rights reserved. 3963899Sarchie * 4063899Sarchie * Redistribution and use in source and binary forms, with or without 4163899Sarchie * modification, are permitted provided that the following conditions 4263899Sarchie * are met: 4363899Sarchie * 1. Redistributions of source code must retain the above copyright 4463899Sarchie * notice, this list of conditions and the following disclaimer. 4563899Sarchie * 2. Redistributions in binary form must reproduce the above copyright 4663899Sarchie * notice, this list of conditions and the following disclaimer in the 4763899Sarchie * documentation and/or other materials provided with the distribution. 4863899Sarchie * 4963899Sarchie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 5063899Sarchie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5163899Sarchie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5263899Sarchie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 5363899Sarchie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5463899Sarchie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5563899Sarchie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5663899Sarchie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5763899Sarchie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5863899Sarchie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5963899Sarchie * SUCH DAMAGE. 6063899Sarchie * 6163899Sarchie * Authors: Erik Salander <erik@whistle.com> 6263899Sarchie * Junichi SATOH <junichi@astec.co.jp> 6363899Sarchie * <junichi@junichi.org> 6463899Sarchie */ 6563899Sarchie 6684195Sdillon#include <sys/cdefs.h> 6784195Sdillon__FBSDID("$FreeBSD$"); 6884195Sdillon 6963899Sarchie/* 7063899Sarchie Alias_smedia.c is meant to contain the aliasing code for streaming media 7163899Sarchie protocols. It performs special processing for RSTP sessions under TCP. 7263899Sarchie Specifically, when a SETUP request is sent by a client, or a 200 reply 7399207Sbrian is sent by a server, it is intercepted and modified. The address is 7463899Sarchie changed to the gateway machine and an aliasing port is used. 7563899Sarchie 7699207Sbrian More specifically, the "client_port" configuration parameter is 7799207Sbrian parsed for SETUP requests. The "server_port" configuration parameter is 7863899Sarchie parsed for 200 replies eminating from a server. This is intended to handle 7963899Sarchie the unicast case. 8063899Sarchie 8163899Sarchie RTSP also allows a redirection of a stream to another client by using the 8263899Sarchie "destination" configuration parameter. The destination config parm would 8399207Sbrian indicate a different IP address. This function is NOT supported by the 8463899Sarchie RTSP translation code below. 8563899Sarchie 8663899Sarchie The RTSP multicast functions without any address translation intervention. 8763899Sarchie 8863899Sarchie For this routine to work, the SETUP/200 must fit entirely 8963899Sarchie into a single TCP packet. This is typically the case, but exceptions 9063899Sarchie can easily be envisioned under the actual specifications. 9163899Sarchie 9263899Sarchie Probably the most troubling aspect of the approach taken here is 9363899Sarchie that the new SETUP/200 will typically be a different length, and 9463899Sarchie this causes a certain amount of bookkeeping to keep track of the 9563899Sarchie changes of sequence and acknowledgment numbers, since the client 9663899Sarchie machine is totally unaware of the modification to the TCP stream. 9763899Sarchie 9899207Sbrian Initial version: May, 2000 (eds) 9963899Sarchie*/ 10063899Sarchie 101145921Sglebius#ifdef _KERNEL 102145921Sglebius#include <sys/param.h> 103162674Spiso#include <sys/systm.h> 104162674Spiso#include <sys/kernel.h> 105162674Spiso#include <sys/module.h> 106145921Sglebius#else 107162674Spiso#include <errno.h> 108145921Sglebius#include <sys/types.h> 10963899Sarchie#include <stdio.h> 11063899Sarchie#include <string.h> 111145921Sglebius#endif 112145921Sglebius 11363899Sarchie#include <netinet/in_systm.h> 11463899Sarchie#include <netinet/in.h> 11563899Sarchie#include <netinet/ip.h> 11663899Sarchie#include <netinet/tcp.h> 11763899Sarchie 118145921Sglebius#ifdef _KERNEL 119145932Sglebius#include <netinet/libalias/alias.h> 120145921Sglebius#include <netinet/libalias/alias_local.h> 121162674Spiso#include <netinet/libalias/alias_mod.h> 122145921Sglebius#else 12363899Sarchie#include "alias_local.h" 124162674Spiso#include "alias_mod.h" 125145921Sglebius#endif 12663899Sarchie 12799207Sbrian#define RTSP_CONTROL_PORT_NUMBER_1 554 12899207Sbrian#define RTSP_CONTROL_PORT_NUMBER_2 7070 129162674Spiso#define TFTP_PORT_NUMBER 69 130162674Spiso 131162674Spisostatic void 132162674SpisoAliasHandleRtspOut(struct libalias *, struct ip *, struct alias_link *, 133162674Spiso int maxpacketsize); 134259858Sglebiusstatic int 135190841Spisofingerprint(struct libalias *la, struct alias_data *ah) 136162674Spiso{ 137162674Spiso 138164075Smarcus if (ah->dport != NULL && ah->aport != NULL && ah->sport != NULL && 139164075Smarcus ntohs(*ah->dport) == TFTP_PORT_NUMBER) 140164075Smarcus return (0); 141259858Sglebius if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || 142162674Spiso ah->maxpktsize == 0) 143162674Spiso return (-1); 144162674Spiso if (ntohs(*ah->dport) == RTSP_CONTROL_PORT_NUMBER_1 145162674Spiso || ntohs(*ah->sport) == RTSP_CONTROL_PORT_NUMBER_1 146162674Spiso || ntohs(*ah->dport) == RTSP_CONTROL_PORT_NUMBER_2 147164075Smarcus || ntohs(*ah->sport) == RTSP_CONTROL_PORT_NUMBER_2) 148162674Spiso return (0); 149162674Spiso return (-1); 150162674Spiso} 151162674Spiso 152259858Sglebiusstatic int 153162674Spisoprotohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) 154162674Spiso{ 155162674Spiso 156162674Spiso if (ntohs(*ah->dport) == TFTP_PORT_NUMBER) 157162674Spiso FindRtspOut(la, pip->ip_src, pip->ip_dst, 158162674Spiso *ah->sport, *ah->aport, IPPROTO_UDP); 159162674Spiso else AliasHandleRtspOut(la, pip, ah->lnk, ah->maxpktsize); 160162674Spiso return (0); 161162674Spiso} 162162674Spiso 163162674Spisostruct proto_handler handlers[] = { 164259858Sglebius { 165259858Sglebius .pri = 100, 166259858Sglebius .dir = OUT, 167162674Spiso .proto = TCP|UDP, 168259858Sglebius .fingerprint = &fingerprint, 169162674Spiso .protohandler = &protohandler 170259858Sglebius }, 171162674Spiso { EOH } 172162674Spiso}; 173162674Spiso 174162674Spisostatic int 175162674Spisomod_handler(module_t mod, int type, void *data) 176162674Spiso{ 177162674Spiso int error; 178162674Spiso 179162674Spiso switch (type) { 180162674Spiso case MOD_LOAD: 181162674Spiso error = 0; 182162674Spiso LibAliasAttachHandlers(handlers); 183162674Spiso break; 184162674Spiso case MOD_UNLOAD: 185162674Spiso error = 0; 186162674Spiso LibAliasDetachHandlers(handlers); 187162674Spiso break; 188162674Spiso default: 189162674Spiso error = EINVAL; 190162674Spiso } 191162674Spiso return (error); 192162674Spiso} 193162674Spiso 194162674Spiso#ifdef _KERNEL 195259858Sglebiusstatic 196162674Spiso#endif 197162674Spisomoduledata_t alias_mod = { 198162674Spiso "alias_smedia", mod_handler, NULL 199162674Spiso}; 200162674Spiso 201162674Spiso#ifdef _KERNEL 202162674SpisoDECLARE_MODULE(alias_smedia, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 203162674SpisoMODULE_VERSION(alias_smedia, 1); 204162674SpisoMODULE_DEPEND(alias_smedia, libalias, 1, 1, 1); 205162674Spiso#endif 206162674Spiso 207162674Spiso#define RTSP_CONTROL_PORT_NUMBER_1 554 208162674Spiso#define RTSP_CONTROL_PORT_NUMBER_2 7070 20963899Sarchie#define RTSP_PORT_GROUP 2 21063899Sarchie 21163899Sarchie#define ISDIGIT(a) (((a) >= '0') && ((a) <= '9')) 21263899Sarchie 21365892Srustatic int 21471796Sbriansearch_string(char *data, int dlen, const char *search_str) 21563899Sarchie{ 216127094Sdes int i, j, k; 217127094Sdes int search_str_len; 21863899Sarchie 219127094Sdes search_str_len = strlen(search_str); 220127094Sdes for (i = 0; i < dlen - search_str_len; i++) { 221127094Sdes for (j = i, k = 0; j < dlen - search_str_len; j++, k++) { 222127094Sdes if (data[j] != search_str[k] && 223127094Sdes data[j] != search_str[k] - ('a' - 'A')) { 224127094Sdes break; 225127094Sdes } 226127094Sdes if (k == search_str_len - 1) { 227131613Sdes return (j + 1); 228127094Sdes } 229127094Sdes } 23063899Sarchie } 231131613Sdes return (-1); 23263899Sarchie} 23363899Sarchie 23465892Srustatic int 235124621Sphkalias_rtsp_out(struct libalias *la, struct ip *pip, 236131614Sdes struct alias_link *lnk, 237127094Sdes char *data, 238127094Sdes const char *port_str) 23963899Sarchie{ 240127094Sdes int hlen, tlen, dlen; 241127094Sdes struct tcphdr *tc; 242127094Sdes int i, j, pos, state, port_dlen, new_dlen, delta; 243127094Sdes u_short p[2], new_len; 244127094Sdes u_short sport, eport, base_port; 245127094Sdes u_short salias = 0, ealias = 0, base_alias = 0; 246127094Sdes const char *transport_str = "transport:"; 247127094Sdes char newdata[2048], *port_data, *port_newdata, stemp[80]; 248127094Sdes int links_created = 0, pkt_updated = 0; 249131614Sdes struct alias_link *rtsp_lnk = NULL; 250127094Sdes struct in_addr null_addr; 25163899Sarchie 252127094Sdes /* Calculate data length of TCP packet */ 253131699Sdes tc = (struct tcphdr *)ip_next(pip); 254127094Sdes hlen = (pip->ip_hl + tc->th_off) << 2; 255127094Sdes tlen = ntohs(pip->ip_len); 256127094Sdes dlen = tlen - hlen; 25763899Sarchie 258127094Sdes /* Find keyword, "Transport: " */ 259127094Sdes pos = search_string(data, dlen, transport_str); 26063899Sarchie if (pos < 0) { 261131613Sdes return (-1); 26263899Sarchie } 263127094Sdes port_data = data + pos; 264127094Sdes port_dlen = dlen - pos; 26563899Sarchie 266127094Sdes memcpy(newdata, data, pos); 267127094Sdes port_newdata = newdata + pos; 26863899Sarchie 269131614Sdes while (port_dlen > (int)strlen(port_str)) { 270127094Sdes /* Find keyword, appropriate port string */ 271127094Sdes pos = search_string(port_data, port_dlen, port_str); 272127094Sdes if (pos < 0) { 273127094Sdes break; 27463899Sarchie } 275127094Sdes memcpy(port_newdata, port_data, pos + 1); 276127094Sdes port_newdata += (pos + 1); 27763899Sarchie 278127094Sdes p[0] = p[1] = 0; 279127094Sdes sport = eport = 0; 280127094Sdes state = 0; 281127094Sdes for (i = pos; i < port_dlen; i++) { 282127094Sdes switch (state) { 283127094Sdes case 0: 284127094Sdes if (port_data[i] == '=') { 285127094Sdes state++; 286127094Sdes } 287127094Sdes break; 288127094Sdes case 1: 289127094Sdes if (ISDIGIT(port_data[i])) { 290127094Sdes p[0] = p[0] * 10 + port_data[i] - '0'; 291127094Sdes } else { 292127094Sdes if (port_data[i] == ';') { 293127094Sdes state = 3; 294127094Sdes } 295127094Sdes if (port_data[i] == '-') { 296127094Sdes state++; 297127094Sdes } 298127094Sdes } 299127094Sdes break; 300127094Sdes case 2: 301127094Sdes if (ISDIGIT(port_data[i])) { 302127094Sdes p[1] = p[1] * 10 + port_data[i] - '0'; 303127094Sdes } else { 304127094Sdes state++; 305127094Sdes } 306127094Sdes break; 307127094Sdes case 3: 308127094Sdes base_port = p[0]; 309127094Sdes sport = htons(p[0]); 310127094Sdes eport = htons(p[1]); 31163899Sarchie 312127094Sdes if (!links_created) { 313127094Sdes 314127094Sdes links_created = 1; 315127094Sdes /* 316127094Sdes * Find an even numbered port 317127094Sdes * number base that satisfies the 318127094Sdes * contiguous number of ports we 319127094Sdes * need 320127094Sdes */ 321127094Sdes null_addr.s_addr = 0; 322127094Sdes if (0 == (salias = FindNewPortGroup(la, null_addr, 323127094Sdes FindAliasAddress(la, pip->ip_src), 324127094Sdes sport, 0, 325127094Sdes RTSP_PORT_GROUP, 326127094Sdes IPPROTO_UDP, 1))) { 327145961Sglebius#ifdef LIBALIAS_DEBUG 328127094Sdes fprintf(stderr, 329127094Sdes "PacketAlias/RTSP: Cannot find contiguous RTSP data ports\n"); 33063899Sarchie#endif 331127094Sdes } else { 33263899Sarchie 333127094Sdes base_alias = ntohs(salias); 334127094Sdes for (j = 0; j < RTSP_PORT_GROUP; j++) { 335127094Sdes /* 336127094Sdes * Establish link 337127094Sdes * to port found in 338127094Sdes * RTSP packet 339127094Sdes */ 340131614Sdes rtsp_lnk = FindRtspOut(la, GetOriginalAddress(lnk), null_addr, 341127094Sdes htons(base_port + j), htons(base_alias + j), 342127094Sdes IPPROTO_UDP); 343131614Sdes if (rtsp_lnk != NULL) { 34463899Sarchie#ifndef NO_FW_PUNCH 345127094Sdes /* 346127094Sdes * Punch 347127094Sdes * hole in 348127094Sdes * firewall 349127094Sdes */ 350131614Sdes PunchFWHole(rtsp_lnk); 35163899Sarchie#endif 352127094Sdes } else { 353145961Sglebius#ifdef LIBALIAS_DEBUG 354127094Sdes fprintf(stderr, 355127094Sdes "PacketAlias/RTSP: Cannot allocate RTSP data ports\n"); 35663899Sarchie#endif 357127094Sdes break; 358127094Sdes } 359127094Sdes } 360127094Sdes } 361127094Sdes ealias = htons(base_alias + (RTSP_PORT_GROUP - 1)); 362127094Sdes } 363131614Sdes if (salias && rtsp_lnk) { 36463899Sarchie 365127094Sdes pkt_updated = 1; 36663899Sarchie 367127094Sdes /* Copy into IP packet */ 368127094Sdes sprintf(stemp, "%d", ntohs(salias)); 369127094Sdes memcpy(port_newdata, stemp, strlen(stemp)); 370127094Sdes port_newdata += strlen(stemp); 37163899Sarchie 372127094Sdes if (eport != 0) { 373127094Sdes *port_newdata = '-'; 374127094Sdes port_newdata++; 37563899Sarchie 376127094Sdes /* Copy into IP packet */ 377127094Sdes sprintf(stemp, "%d", ntohs(ealias)); 378127094Sdes memcpy(port_newdata, stemp, strlen(stemp)); 379127094Sdes port_newdata += strlen(stemp); 380127094Sdes } 381127094Sdes *port_newdata = ';'; 382127094Sdes port_newdata++; 383127094Sdes } 384127094Sdes state++; 385127094Sdes break; 386127094Sdes } 387127094Sdes if (state > 3) { 388127094Sdes break; 389127094Sdes } 39063899Sarchie } 391127094Sdes port_data += i; 392127094Sdes port_dlen -= i; 39363899Sarchie } 39463899Sarchie 395127094Sdes if (!pkt_updated) 396131613Sdes return (-1); 39763899Sarchie 398127094Sdes memcpy(port_newdata, port_data, port_dlen); 399127094Sdes port_newdata += port_dlen; 400127094Sdes *port_newdata = '\0'; 40163899Sarchie 402127094Sdes /* Create new packet */ 403127094Sdes new_dlen = port_newdata - newdata; 404127094Sdes memcpy(data, newdata, new_dlen); 40563899Sarchie 406131614Sdes SetAckModified(lnk); 407176884Spiso tc = (struct tcphdr *)ip_next(pip); 408176884Spiso delta = GetDeltaSeqOut(tc->th_seq, lnk); 409259858Sglebius AddSeq(lnk, delta + new_dlen - dlen, pip->ip_hl, pip->ip_len, 410176884Spiso tc->th_seq, tc->th_off); 41163899Sarchie 412127094Sdes new_len = htons(hlen + new_dlen); 413127094Sdes DifferentialChecksum(&pip->ip_sum, 414127094Sdes &new_len, 415127094Sdes &pip->ip_len, 416127094Sdes 1); 417127094Sdes pip->ip_len = new_len; 41863899Sarchie 419127094Sdes tc->th_sum = 0; 420147623Sglebius#ifdef _KERNEL 421147623Sglebius tc->th_x2 = 1; 422147623Sglebius#else 423127094Sdes tc->th_sum = TcpChecksum(pip); 424147623Sglebius#endif 425131613Sdes return (0); 42663899Sarchie} 42763899Sarchie 42863899Sarchie/* Support the protocol used by early versions of RealPlayer */ 42963899Sarchie 43065892Srustatic int 431124621Sphkalias_pna_out(struct libalias *la, struct ip *pip, 432131614Sdes struct alias_link *lnk, 433127094Sdes char *data, 434127094Sdes int dlen) 43563899Sarchie{ 436127094Sdes struct alias_link *pna_links; 437127094Sdes u_short msg_id, msg_len; 438127094Sdes char *work; 439127094Sdes u_short alias_port, port; 440127094Sdes struct tcphdr *tc; 44163899Sarchie 442127094Sdes work = data; 443127094Sdes work += 5; 444127094Sdes while (work + 4 < data + dlen) { 445127094Sdes memcpy(&msg_id, work, 2); 446127094Sdes work += 2; 447127094Sdes memcpy(&msg_len, work, 2); 448127094Sdes work += 2; 449127094Sdes if (ntohs(msg_id) == 0) { 450127094Sdes /* end of options */ 451131613Sdes return (0); 452127094Sdes } 453127094Sdes if ((ntohs(msg_id) == 1) || (ntohs(msg_id) == 7)) { 454127094Sdes memcpy(&port, work, 2); 455131614Sdes pna_links = FindUdpTcpOut(la, pip->ip_src, GetDestAddress(lnk), 456127094Sdes port, 0, IPPROTO_UDP, 1); 457127094Sdes if (pna_links != NULL) { 45863899Sarchie#ifndef NO_FW_PUNCH 459127094Sdes /* Punch hole in firewall */ 460127094Sdes PunchFWHole(pna_links); 46163899Sarchie#endif 462131699Sdes tc = (struct tcphdr *)ip_next(pip); 463127094Sdes alias_port = GetAliasPort(pna_links); 464127094Sdes memcpy(work, &alias_port, 2); 46563899Sarchie 466127094Sdes /* Compute TCP checksum for revised packet */ 467127094Sdes tc->th_sum = 0; 468147623Sglebius#ifdef _KERNEL 469147623Sglebius tc->th_x2 = 1; 470147623Sglebius#else 471127094Sdes tc->th_sum = TcpChecksum(pip); 472147623Sglebius#endif 473127094Sdes } 474127094Sdes } 475127094Sdes work += ntohs(msg_len); 47663899Sarchie } 47799207Sbrian 478131613Sdes return (0); 47963899Sarchie} 48063899Sarchie 481162674Spisostatic void 482131614SdesAliasHandleRtspOut(struct libalias *la, struct ip *pip, struct alias_link *lnk, int maxpacketsize) 48363899Sarchie{ 484127094Sdes int hlen, tlen, dlen; 485127094Sdes struct tcphdr *tc; 486127094Sdes char *data; 487127094Sdes const char *setup = "SETUP", *pna = "PNA", *str200 = "200"; 488127094Sdes const char *okstr = "OK", *client_port_str = "client_port"; 489127094Sdes const char *server_port_str = "server_port"; 490127094Sdes int i, parseOk; 49163899Sarchie 492131614Sdes (void)maxpacketsize; 493131614Sdes 494131699Sdes tc = (struct tcphdr *)ip_next(pip); 495127094Sdes hlen = (pip->ip_hl + tc->th_off) << 2; 496127094Sdes tlen = ntohs(pip->ip_len); 497127094Sdes dlen = tlen - hlen; 49863899Sarchie 499127094Sdes data = (char *)pip; 500127094Sdes data += hlen; 50163899Sarchie 502127094Sdes /* When aliasing a client, check for the SETUP request */ 503127094Sdes if ((ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1) || 504127094Sdes (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2)) { 50563899Sarchie 506131614Sdes if (dlen >= (int)strlen(setup)) { 507127094Sdes if (memcmp(data, setup, strlen(setup)) == 0) { 508131614Sdes alias_rtsp_out(la, pip, lnk, data, client_port_str); 509127094Sdes return; 510127094Sdes } 511127094Sdes } 512131614Sdes if (dlen >= (int)strlen(pna)) { 513127094Sdes if (memcmp(data, pna, strlen(pna)) == 0) { 514131614Sdes alias_pna_out(la, pip, lnk, data, dlen); 515127094Sdes } 516127094Sdes } 517127094Sdes } else { 51863899Sarchie 519127094Sdes /* 520127094Sdes * When aliasing a server, check for the 200 reply 521298995Spfg * Accommodate varying number of blanks between 200 & OK 522127094Sdes */ 52363899Sarchie 524131614Sdes if (dlen >= (int)strlen(str200)) { 52563899Sarchie 526127094Sdes for (parseOk = 0, i = 0; 527131614Sdes i <= dlen - (int)strlen(str200); 528127094Sdes i++) { 529127094Sdes if (memcmp(&data[i], str200, strlen(str200)) == 0) { 530127094Sdes parseOk = 1; 531127094Sdes break; 532127094Sdes } 533127094Sdes } 534127094Sdes if (parseOk) { 53563899Sarchie 536127094Sdes i += strlen(str200); /* skip string found */ 537127094Sdes while (data[i] == ' ') /* skip blank(s) */ 538127094Sdes i++; 53963899Sarchie 540131614Sdes if ((dlen - i) >= (int)strlen(okstr)) { 54199207Sbrian 542127094Sdes if (memcmp(&data[i], okstr, strlen(okstr)) == 0) 543131614Sdes alias_rtsp_out(la, pip, lnk, data, server_port_str); 54463899Sarchie 545127094Sdes } 546127094Sdes } 547127094Sdes } 548127094Sdes } 54963899Sarchie} 550