137131Sbrian/*- 237131Sbrian * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org> 337131Sbrian * with the aid of code written by 437131Sbrian * Junichi SATOH <junichi@astec.co.jp> 1996, 1997. 537131Sbrian * All rights reserved. 637131Sbrian * 737131Sbrian * Redistribution and use in source and binary forms, with or without 837131Sbrian * modification, are permitted provided that the following conditions 937131Sbrian * are met: 1037131Sbrian * 1. Redistributions of source code must retain the above copyright 1137131Sbrian * notice, this list of conditions and the following disclaimer. 1237131Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1337131Sbrian * notice, this list of conditions and the following disclaimer in the 1437131Sbrian * documentation and/or other materials provided with the distribution. 1537131Sbrian * 1637131Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1737131Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1837131Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1937131Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2037131Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2137131Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2237131Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2337131Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2437131Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2537131Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2637131Sbrian * SUCH DAMAGE. 2737131Sbrian */ 2837131Sbrian 2984195Sdillon#include <sys/cdefs.h> 3084195Sdillon__FBSDID("$FreeBSD$"); 3184195Sdillon 32145921Sglebius#ifdef _KERNEL 33145921Sglebius#include <sys/param.h> 34162674Spiso#include <sys/kernel.h> 35162674Spiso#include <sys/module.h> 36145921Sglebius#else 37162674Spiso#include <errno.h> 38145921Sglebius#include <sys/types.h> 39124621Sphk#include <stdio.h> 40145921Sglebius#endif 41145921Sglebius 4237131Sbrian#include <netinet/in_systm.h> 4337131Sbrian#include <netinet/in.h> 4437131Sbrian#include <netinet/ip.h> 4537131Sbrian#include <netinet/udp.h> 4637131Sbrian 47145921Sglebius#ifdef _KERNEL 48145932Sglebius#include <netinet/libalias/alias.h> 49145921Sglebius#include <netinet/libalias/alias_local.h> 50162674Spiso#include <netinet/libalias/alias_mod.h> 51145921Sglebius#else 5237131Sbrian#include "alias_local.h" 53162674Spiso#include "alias_mod.h" 54145921Sglebius#endif 5537131Sbrian 56162674Spiso#define CUSEEME_PORT_NUMBER 7648 57162674Spiso 58162674Spisostatic void 59259858SglebiusAliasHandleCUSeeMeOut(struct libalias *la, struct ip *pip, 60162674Spiso struct alias_link *lnk); 61162674Spiso 62162674Spisostatic void 63259858SglebiusAliasHandleCUSeeMeIn(struct libalias *la, struct ip *pip, 64162674Spiso struct in_addr original_addr); 65162674Spiso 66259858Sglebiusstatic int 67190841Spisofingerprint(struct libalias *la, struct alias_data *ah) 68162674Spiso{ 69162674Spiso 70162674Spiso if (ah->dport == NULL || ah->oaddr == NULL) 71162674Spiso return (-1); 72162674Spiso if (ntohs(*ah->dport) == CUSEEME_PORT_NUMBER) 73162674Spiso return (0); 74162674Spiso return (-1); 75162674Spiso} 76162674Spiso 77259858Sglebiusstatic int 78162674Spisoprotohandlerin(struct libalias *la, struct ip *pip, struct alias_data *ah) 79162674Spiso{ 80162674Spiso 81162674Spiso AliasHandleCUSeeMeIn(la, pip, *ah->oaddr); 82162674Spiso return (0); 83162674Spiso} 84162674Spiso 85259858Sglebiusstatic int 86162674Spisoprotohandlerout(struct libalias *la, struct ip *pip, struct alias_data *ah) 87162674Spiso{ 88162674Spiso 89162674Spiso AliasHandleCUSeeMeOut(la, pip, ah->lnk); 90162674Spiso return (0); 91162674Spiso} 92162674Spiso 93162674Spiso/* Kernel module definition. */ 94162674Spisostruct proto_handler handlers[] = { 95259858Sglebius { 96259858Sglebius .pri = 120, 97259858Sglebius .dir = OUT, 98259858Sglebius .proto = UDP, 99259858Sglebius .fingerprint = &fingerprint, 100162674Spiso .protohandler = &protohandlerout 101259858Sglebius }, 102162674Spiso { 103259858Sglebius .pri = 120, 104259858Sglebius .dir = IN, 105259858Sglebius .proto = UDP, 106259858Sglebius .fingerprint = &fingerprint, 107162674Spiso .protohandler = &protohandlerin 108259858Sglebius }, 109162674Spiso { EOH } 110162674Spiso}; 111162674Spiso 112162674Spisostatic int 113162674Spisomod_handler(module_t mod, int type, void *data) 114162674Spiso{ 115162674Spiso int error; 116162674Spiso 117162674Spiso switch (type) { 118162674Spiso case MOD_LOAD: 119162674Spiso error = 0; 120162674Spiso LibAliasAttachHandlers(handlers); 121162674Spiso break; 122162674Spiso case MOD_UNLOAD: 123162674Spiso error = 0; 124162674Spiso LibAliasDetachHandlers(handlers); 125162674Spiso break; 126162674Spiso default: 127162674Spiso error = EINVAL; 128162674Spiso } 129162674Spiso return (error); 130162674Spiso} 131162674Spiso 132162674Spiso#ifdef _KERNEL 133259858Sglebiusstatic 134162674Spiso#endif 135259858Sglebiusmoduledata_t 136162674Spisoalias_mod = { 137162674Spiso "alias_cuseeme", mod_handler, NULL 138162674Spiso}; 139162674Spiso 140162674Spiso#ifdef _KERNEL 141162674SpisoDECLARE_MODULE(alias_cuseeme, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 142162674SpisoMODULE_VERSION(alias_cuseeme, 1); 143162674SpisoMODULE_DEPEND(alias_cuseeme, libalias, 1, 1, 1); 144162674Spiso#endif 145162674Spiso 14637131Sbrian/* CU-SeeMe Data Header */ 14737131Sbrianstruct cu_header { 148127094Sdes u_int16_t dest_family; 149127094Sdes u_int16_t dest_port; 150127094Sdes u_int32_t dest_addr; 151127094Sdes int16_t family; 152127094Sdes u_int16_t port; 153127094Sdes u_int32_t addr; 154127094Sdes u_int32_t seq; 155127094Sdes u_int16_t msg; 156127094Sdes u_int16_t data_type; 157127094Sdes u_int16_t packet_len; 15837131Sbrian}; 15937131Sbrian 16037131Sbrian/* Open Continue Header */ 16137131Sbrianstruct oc_header { 162127094Sdes u_int16_t client_count; /* Number of client info structs */ 163127094Sdes u_int32_t seq_no; 164127094Sdes char user_name [20]; 165127094Sdes char reserved [4]; /* flags, version stuff, etc */ 16637131Sbrian}; 16737131Sbrian 16837131Sbrian/* client info structures */ 16937131Sbrianstruct client_info { 170127094Sdes u_int32_t address;/* Client address */ 171127094Sdes char reserved [8]; /* Flags, pruning bitfield, packet 172127094Sdes * counts etc */ 17337131Sbrian}; 17437131Sbrian 175162674Spisostatic void 176131614SdesAliasHandleCUSeeMeOut(struct libalias *la, struct ip *pip, struct alias_link *lnk) 17737131Sbrian{ 178131699Sdes struct udphdr *ud = ip_next(pip); 17937131Sbrian 180127094Sdes if (ntohs(ud->uh_ulen) - sizeof(struct udphdr) >= sizeof(struct cu_header)) { 181127094Sdes struct cu_header *cu; 182131614Sdes struct alias_link *cu_lnk; 18337131Sbrian 184131699Sdes cu = udp_next(ud); 185127094Sdes if (cu->addr) 186131614Sdes cu->addr = (u_int32_t) GetAliasAddress(lnk).s_addr; 18737131Sbrian 188131614Sdes cu_lnk = FindUdpTcpOut(la, pip->ip_src, GetDestAddress(lnk), 189127094Sdes ud->uh_dport, 0, IPPROTO_UDP, 1); 19099207Sbrian 19137131Sbrian#ifndef NO_FW_PUNCH 192131614Sdes if (cu_lnk) 193131614Sdes PunchFWHole(cu_lnk); 19437131Sbrian#endif 195127094Sdes } 19637131Sbrian} 19737131Sbrian 198162674Spisostatic void 199124621SphkAliasHandleCUSeeMeIn(struct libalias *la, struct ip *pip, struct in_addr original_addr) 20037131Sbrian{ 201127094Sdes struct in_addr alias_addr; 202127094Sdes struct udphdr *ud; 203127094Sdes struct cu_header *cu; 204127094Sdes struct oc_header *oc; 205127094Sdes struct client_info *ci; 206127094Sdes char *end; 207127094Sdes int i; 20837131Sbrian 209131614Sdes (void)la; 210127094Sdes alias_addr.s_addr = pip->ip_dst.s_addr; 211131699Sdes ud = ip_next(pip); 212131699Sdes cu = udp_next(ud); 213127094Sdes oc = (struct oc_header *)(cu + 1); 214127094Sdes ci = (struct client_info *)(oc + 1); 215127094Sdes end = (char *)ud + ntohs(ud->uh_ulen); 21637131Sbrian 217127094Sdes if ((char *)oc <= end) { 218127094Sdes if (cu->dest_addr) 219127094Sdes cu->dest_addr = (u_int32_t) original_addr.s_addr; 220127094Sdes if (ntohs(cu->data_type) == 101) 221127094Sdes /* Find and change our address */ 222127094Sdes for (i = 0; (char *)(ci + 1) <= end && i < oc->client_count; i++, ci++) 223127094Sdes if (ci->address == (u_int32_t) alias_addr.s_addr) { 224127094Sdes ci->address = (u_int32_t) original_addr.s_addr; 225127094Sdes break; 226127094Sdes } 227127094Sdes } 22837131Sbrian} 229