1/* 2** igmpproxy - IGMP proxy based multicast router 3** Copyright (C) 2005 Johnny Egeland <johnny@rlo.org> 4** 5** This program is free software; you can redistribute it and/or modify 6** it under the terms of the GNU General Public License as published by 7** the Free Software Foundation; either version 2 of the License, or 8** (at your option) any later version. 9** 10** This program is distributed in the hope that it will be useful, 11** but WITHOUT ANY WARRANTY; without even the implied warranty of 12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13** GNU General Public License for more details. 14** 15** You should have received a copy of the GNU General Public License 16** along with this program; if not, write to the Free Software 17** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18** 19**---------------------------------------------------------------------------- 20** 21** This software is derived work from the following software. The original 22** source code has been modified from it's original state by the author 23** of igmpproxy. 24** 25** smcroute 0.92 - Copyright (C) 2001 Carsten Schill <carsten@cschill.de> 26** - Licensed under the GNU General Public License, version 2 27** 28** mrouted 3.9-beta3 - COPYRIGHT 1989 by The Board of Trustees of 29** Leland Stanford Junior University. 30** - Original license can be found in the "doc/mrouted-LINCESE" file. 31** 32*/ 33/** 34* mroute-api.c 35* 36* This module contains the interface routines to the Linux mrouted API 37*/ 38 39 40#define USE_LINUX_IN_H 41#include "defs.h" 42 43// MAX_MC_VIFS from mclab.h must have same value as MAXVIFS from mroute.h 44#if MAX_MC_VIFS != MAXVIFS 45# error "constants don't match, correct mclab.h" 46#endif 47 48// need an IGMP socket as interface for the mrouted API 49// - receives the IGMP messages 50int MRouterFD; /* socket for all network I/O */ 51char *recv_buf; /* input packet buffer */ 52char *send_buf; /* output packet buffer */ 53 54 55// my internal virtual interfaces descriptor vector 56static struct VifDesc { 57 struct IfDesc *IfDp; 58} VifDescVc[ MAXVIFS ]; 59 60 61 62/* 63** Initialises the mrouted API and locks it by this exclusively. 64** 65** returns: - 0 if the functions succeeds 66** - the errno value for non-fatal failure condition 67*/ 68int enableMRouter() 69{ 70 int Va = 1; 71 72 if ( (MRouterFD = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP)) < 0 ) 73 log( LOG_ERR, errno, "IGMP socket open" ); 74 75 if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_INIT, 76 (void *)&Va, sizeof( Va ) ) ) 77 return errno; 78 79 return 0; 80} 81 82/* 83** Diables the mrouted API and relases by this the lock. 84** 85*/ 86void disableMRouter() 87{ 88 if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_DONE, NULL, 0 ) 89 || close( MRouterFD ) 90 ) { 91 MRouterFD = 0; 92 log( LOG_ERR, errno, "MRT_DONE/close" ); 93 } 94 95 MRouterFD = 0; 96} 97 98/* 99** Adds the interface '*IfDp' as virtual interface to the mrouted API 100** 101*/ 102void addVIF( struct IfDesc *IfDp ) 103{ 104 struct vifctl VifCtl; 105 struct VifDesc *VifDp; 106 107 /* search free VifDesc 108 */ 109 for ( VifDp = VifDescVc; VifDp < VCEP( VifDescVc ); VifDp++ ) { 110 if ( ! VifDp->IfDp ) 111 break; 112 } 113 114 /* no more space 115 */ 116 if ( VifDp >= VCEP( VifDescVc ) ) 117 log( LOG_ERR, ENOMEM, "addVIF, out of VIF space" ); 118 119 VifDp->IfDp = IfDp; 120 121 VifCtl.vifc_vifi = VifDp - VifDescVc; 122 VifCtl.vifc_flags = 0; /* no tunnel, no source routing, register ? */ 123 VifCtl.vifc_threshold = VifDp->IfDp->threshold; // Packet TTL must be at least 1 to pass them 124 VifCtl.vifc_rate_limit = VifDp->IfDp->ratelimit; // Ratelimit 125 126 VifCtl.vifc_lcl_addr.s_addr = VifDp->IfDp->InAdr.s_addr; 127 VifCtl.vifc_rmt_addr.s_addr = INADDR_ANY; 128 129 // Set the index... 130 VifDp->IfDp->index = VifCtl.vifc_vifi; 131 132 log( LOG_NOTICE, 0, "adding VIF, Ix %d Fl 0x%x IP 0x%08x %s, Threshold: %d, Ratelimit: %d", 133 VifCtl.vifc_vifi, VifCtl.vifc_flags, VifCtl.vifc_lcl_addr.s_addr, VifDp->IfDp->Name, 134 VifCtl.vifc_threshold, VifCtl.vifc_rate_limit); 135 136 IF_DEBUG { 137 struct SubnetList *currSubnet; 138 for(currSubnet = IfDp->allowednets; currSubnet; currSubnet = currSubnet->next) { 139 log(LOG_DEBUG, 0, " Network for [%s] : %s", 140 IfDp->Name, 141 inetFmts(currSubnet->subnet_addr, currSubnet->subnet_mask, s1)); 142 } 143 } 144 145 if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_ADD_VIF, 146 (char *)&VifCtl, sizeof( VifCtl ) ) ) 147 log( LOG_ERR, errno, "MRT_ADD_VIF" ); 148 149} 150 151/* 152** Adds the multicast routed '*Dp' to the kernel routes 153** 154** returns: - 0 if the function succeeds 155** - the errno value for non-fatal failure condition 156*/ 157int addMRoute( struct MRouteDesc *Dp ) 158{ 159 struct mfcctl CtlReq; 160 161 CtlReq.mfcc_origin = Dp->OriginAdr; 162 CtlReq.mfcc_mcastgrp = Dp->McAdr; 163 CtlReq.mfcc_parent = Dp->InVif; 164 165 /* copy the TTL vector 166 */ 167 if ( sizeof( CtlReq.mfcc_ttls ) != sizeof( Dp->TtlVc ) 168 || VCMC( CtlReq.mfcc_ttls ) != VCMC( Dp->TtlVc ) 169 ) 170 log( LOG_ERR, 0, "data types doesn't match in " __FILE__ ", source adaption needed !" ); 171 172 memcpy( CtlReq.mfcc_ttls, Dp->TtlVc, sizeof( CtlReq.mfcc_ttls ) ); 173 174 { 175 char FmtBuO[ 32 ], FmtBuM[ 32 ]; 176 177 log( LOG_NOTICE, 0, "Adding MFC: %s -> %s, InpVIf: %d", 178 fmtInAdr( FmtBuO, CtlReq.mfcc_origin ), 179 fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ), 180 CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent 181 ); 182 } 183 184 if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_ADD_MFC, 185 (void *)&CtlReq, sizeof( CtlReq ) ) ) 186 log( LOG_WARNING, errno, "MRT_ADD_MFC" ); 187} 188 189/* 190** Removes the multicast routed '*Dp' from the kernel routes 191** 192** returns: - 0 if the function succeeds 193** - the errno value for non-fatal failure condition 194*/ 195int delMRoute( struct MRouteDesc *Dp ) 196{ 197 struct mfcctl CtlReq; 198 199 CtlReq.mfcc_origin = Dp->OriginAdr; 200 CtlReq.mfcc_mcastgrp = Dp->McAdr; 201 CtlReq.mfcc_parent = Dp->InVif; 202 203 /* clear the TTL vector 204 */ 205 memset( CtlReq.mfcc_ttls, 0, sizeof( CtlReq.mfcc_ttls ) ); 206 207 { 208 char FmtBuO[ 32 ], FmtBuM[ 32 ]; 209 210 log( LOG_NOTICE, 0, "Removing MFC: %s -> %s, InpVIf: %d", 211 fmtInAdr( FmtBuO, CtlReq.mfcc_origin ), 212 fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ), 213 CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent 214 ); 215 } 216 217 if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_DEL_MFC, 218 (void *)&CtlReq, sizeof( CtlReq ) ) ) 219 log( LOG_WARNING, errno, "MRT_DEL_MFC" ); 220} 221 222/* 223** Returns for the virtual interface index for '*IfDp' 224** 225** returns: - the vitrual interface index if the interface is registered 226** - -1 if no virtual interface exists for the interface 227** 228*/ 229int getVifIx( struct IfDesc *IfDp ) 230{ 231 struct VifDesc *Dp; 232 233 for ( Dp = VifDescVc; Dp < VCEP( VifDescVc ); Dp++ ) 234 if ( Dp->IfDp == IfDp ) 235 return Dp - VifDescVc; 236 237 return -1; 238} 239 240 241 242