2 ** igmpproxy - IGMP proxy based multicast router
3 ** Copyright (C) 2005 Johnny Egeland <johnny@rlo.org>
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.
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.
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
19 **----------------------------------------------------------------------------
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
25 ** smcroute 0.92 - Copyright (C) 2001 Carsten Schill <carsten@cschill.de>
26 ** - Licensed under the GNU General Public License, version 2
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 Stanford.txt file.
34 #include "igmpproxy.h"
36 struct IfDesc IfDescVc
[ MAX_IF
], *IfDescEp
= IfDescVc
;
39 ** Builds up a vector with the interface of the machine. Calls to the other functions of
40 ** the module will fail if they are called before the vector is build.
44 struct ifreq IfVc
[ sizeof( IfDescVc
) / sizeof( IfDescVc
[ 0 ] ) ];
49 if ( (Sock
= socket( AF_INET
, SOCK_DGRAM
, 0 )) < 0 )
50 my_log( LOG_ERR
, errno
, "RAW socket open" );
55 struct ifconf IoCtlReq
;
57 IoCtlReq
.ifc_buf
= (void *)IfVc
;
58 IoCtlReq
.ifc_len
= sizeof( IfVc
);
60 if ( ioctl( Sock
, SIOCGIFCONF
, &IoCtlReq
) < 0 )
61 my_log( LOG_ERR
, errno
, "ioctl SIOCGIFCONF" );
63 IfEp
= (void *)((char *)IfVc
+ IoCtlReq
.ifc_len
);
66 /* loop over interfaces and copy interface info to IfDescVc
69 struct ifreq
*IfPt
, *IfNext
;
71 // Temp keepers of interface params...
72 uint32_t addr
, subnet
, mask
;
74 for ( IfPt
= IfVc
; IfPt
< IfEp
; IfPt
= IfNext
) {
78 IfNext
= (struct ifreq
*)((char *)&IfPt
->ifr_addr
+
79 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
82 sizeof(struct sockaddr_in
)
85 if (IfNext
< IfPt
+ 1)
88 strncpy( IfDescEp
->Name
, IfPt
->ifr_name
, sizeof( IfDescEp
->Name
) );
90 // Currently don't set any allowed nets...
91 //IfDescEp->allowednets = NULL;
93 // Set the index to -1 by default.
96 /* don't retrieve more info for non-IP interfaces
98 if ( IfPt
->ifr_addr
.sa_family
!= AF_INET
) {
99 IfDescEp
->InAdr
.s_addr
= 0; /* mark as non-IP interface */
104 // Get the interface adress...
105 IfDescEp
->InAdr
= ((struct sockaddr_in
*)&IfPt
->ifr_addr
)->sin_addr
;
106 addr
= IfDescEp
->InAdr
.s_addr
;
108 memcpy( IfReq
.ifr_name
, IfDescEp
->Name
, sizeof( IfReq
.ifr_name
) );
109 IfReq
.ifr_addr
.sa_family
= AF_INET
;
110 ((struct sockaddr_in
*)&IfReq
.ifr_addr
)->sin_addr
.s_addr
= addr
;
112 // Get the subnet mask...
113 if (ioctl(Sock
, SIOCGIFNETMASK
, &IfReq
) < 0)
114 my_log(LOG_ERR
, errno
, "ioctl SIOCGIFNETMASK for %s", IfReq
.ifr_name
);
115 mask
= ((struct sockaddr_in
*)&IfReq
.ifr_addr
)->sin_addr
.s_addr
;
116 subnet
= addr
& mask
;
121 ** lo 0x0049 -> Running, Loopback, Up
122 ** ethx 0x1043 -> Multicast, Running, Broadcast, Up
123 ** ipppx 0x0091 -> NoArp, PointToPoint, Up
124 ** grex 0x00C1 -> NoArp, Running, Up
125 ** ipipx 0x00C1 -> NoArp, Running, Up
127 if ( ioctl( Sock
, SIOCGIFFLAGS
, &IfReq
) < 0 )
128 my_log( LOG_ERR
, errno
, "ioctl SIOCGIFFLAGS" );
130 IfDescEp
->Flags
= IfReq
.ifr_flags
;
132 // Insert the verified subnet as an allowed net...
133 IfDescEp
->allowednets
= (struct SubnetList
*)malloc(sizeof(struct SubnetList
));
134 if(IfDescEp
->allowednets
== NULL
) my_log(LOG_ERR
, 0, "Out of memory !");
136 // Create the network address for the IF..
137 IfDescEp
->allowednets
->next
= NULL
;
138 IfDescEp
->allowednets
->subnet_mask
= mask
;
139 IfDescEp
->allowednets
->subnet_addr
= subnet
;
141 // Set the default params for the IF...
142 IfDescEp
->state
= IF_STATE_DISABLED
;
143 IfDescEp
->robustness
= DEFAULT_ROBUSTNESS
;
144 IfDescEp
->threshold
= DEFAULT_THRESHOLD
; /* ttl limit */
145 IfDescEp
->ratelimit
= DEFAULT_RATELIMIT
;
148 // Debug log the result...
149 my_log( LOG_DEBUG
, 0, "buildIfVc: Interface %s Addr: %s, Flags: 0x%04x, Network: %s",
151 fmtInAdr( FmtBu
, IfDescEp
->InAdr
),
153 inetFmts(subnet
,mask
, s1
));
163 ** Returns a pointer to the IfDesc of the interface 'IfName'
165 ** returns: - pointer to the IfDesc of the requested interface
166 ** - NULL if no interface 'IfName' exists
169 struct IfDesc
*getIfByName( const char *IfName
) {
172 for ( Dp
= IfDescVc
; Dp
< IfDescEp
; Dp
++ )
173 if ( ! strcmp( IfName
, Dp
->Name
) )
180 ** Returns a pointer to the IfDesc of the interface 'Ix'
182 ** returns: - pointer to the IfDesc of the requested interface
183 ** - NULL if no interface 'Ix' exists
186 struct IfDesc
*getIfByIx( unsigned Ix
) {
187 struct IfDesc
*Dp
= &IfDescVc
[ Ix
];
188 return Dp
< IfDescEp
? Dp
: NULL
;
192 * Returns a pointer to the IfDesc whose subnet matches
193 * the supplied IP adress. The IP must match a interfaces
194 * subnet, or any configured allowed subnet on a interface.
196 struct IfDesc
*getIfByAddress( uint32_t ipaddr
) {
199 struct SubnetList
*currsubnet
;
200 struct IfDesc
*res
= NULL
;
201 uint32_t last_subnet_mask
= 0;
203 for ( Dp
= IfDescVc
; Dp
< IfDescEp
; Dp
++ ) {
204 // Loop through all registered allowed nets of the VIF...
205 for(currsubnet
= Dp
->allowednets
; currsubnet
!= NULL
; currsubnet
= currsubnet
->next
) {
206 // Check if the ip falls in under the subnet....
207 if(currsubnet
->subnet_mask
> last_subnet_mask
&& (ipaddr
& currsubnet
->subnet_mask
) == currsubnet
->subnet_addr
) {
209 last_subnet_mask
= currsubnet
->subnet_mask
;
218 * Returns a pointer to the IfDesc whose subnet matches
219 * the supplied IP adress. The IP must match a interfaces
220 * subnet, or any configured allowed subnet on a interface.
222 struct IfDesc
*getIfByVifIndex( unsigned vifindex
) {
225 for ( Dp
= IfDescVc
; Dp
< IfDescEp
; Dp
++ ) {
226 if(Dp
->index
== vifindex
) {
236 * Function that checks if a given ipaddress is a valid
237 * address for the supplied VIF.
239 int isAdressValidForIf( struct IfDesc
* intrface
, uint32_t ipaddr
) {
240 struct SubnetList
*currsubnet
;
242 if(intrface
== NULL
) {
245 // Loop through all registered allowed nets of the VIF...
246 for(currsubnet
= intrface
->allowednets
; currsubnet
!= NULL
; currsubnet
= currsubnet
->next
) {
247 // Check if the ip falls in under the subnet....
248 if((ipaddr
& currsubnet
->subnet_mask
) == currsubnet
->subnet_addr
) {