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 Stanford.txt file.
31**
32*/
33/**
34*   mcgroup contains functions for joining and leaving multicast groups.
35*
36*/
37
38#include "igmpproxy.h"
39
40
41/**
42*   Common function for joining or leaving a MCast group.
43*/
44static int joinleave( int Cmd, int UdpSock, struct IfDesc *IfDp, uint32_t mcastaddr ) {
45    struct ip_mreq CtlReq;
46    const char *CmdSt = Cmd == 'j' ? "join" : "leave";
47
48    memset(&CtlReq, 0, sizeof(CtlReq));
49    CtlReq.imr_multiaddr.s_addr = mcastaddr;
50    CtlReq.imr_interface.s_addr = IfDp->InAdr.s_addr;
51
52    {
53        my_log( LOG_NOTICE, 0, "%sMcGroup: %s on %s", CmdSt,
54            inetFmt( mcastaddr, s1 ), IfDp ? IfDp->Name : "<any>" );
55    }
56
57    if( setsockopt( UdpSock, IPPROTO_IP,
58          Cmd == 'j' ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP,
59          (void *)&CtlReq, sizeof( CtlReq ) ) )
60    {
61        my_log( LOG_WARNING, errno, "MRT_%s_MEMBERSHIP failed", Cmd == 'j' ? "ADD" : "DROP" );
62        return 1;
63    }
64
65    return 0;
66}
67
68/**
69*   Joins the MC group with the address 'McAdr' on the interface 'IfName'.
70*   The join is bound to the UDP socket 'UdpSock', so if this socket is
71*   closed the membership is dropped.
72*
73*   @return 0 if the function succeeds, 1 if parameters are wrong or the join fails
74*/
75int joinMcGroup( int UdpSock, struct IfDesc *IfDp, uint32_t mcastaddr ) {
76    return joinleave( 'j', UdpSock, IfDp, mcastaddr );
77}
78
79/**
80*   Leaves the MC group with the address 'McAdr' on the interface 'IfName'.
81*
82*   @return 0 if the function succeeds, 1 if parameters are wrong or the join fails
83*/
84int leaveMcGroup( int UdpSock, struct IfDesc *IfDp, uint32_t mcastaddr ) {
85    return joinleave( 'l', UdpSock, IfDp, mcastaddr );
86}
87