mcproxy: fix up sourcefilter patch
[feed/routing.git] / mcproxy / patches / 0003-add-sourcefilter.patch
1 Index: mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/mc_socket.cpp
2 ===================================================================
3 --- mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99.orig/mcproxy/src/utils/mc_socket.cpp
4 +++ mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/mc_socket.cpp
5 @@ -37,6 +37,10 @@
6 #include <numeric>
7 #include <unistd.h>
8
9 +#ifndef __GLIBC__
10 +#include "sourcefilter.cpp"
11 +#endif /* __GLIBC__ */
12 +
13 std::string ipAddrResolver(std::string ipAddr)
14 {
15 std::string str[][2] = {
16 Index: mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/sourcefilter.cpp
17 ===================================================================
18 --- /dev/null
19 +++ mcproxy-2017-08-24-93b5ace42268160ebbfff4c61818fb15fa2d9b99/mcproxy/src/utils/sourcefilter.cpp
20 @@ -0,0 +1,165 @@
21 +/* Get source filter. Linux version.
22 + Copyright (C) 2004-2014 Free Software Foundation, Inc.
23 + This file is part of the GNU C Library.
24 + Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
25 +
26 + The GNU C Library is free software; you can redistribute it and/or
27 + modify it under the terms of the GNU Lesser General Public
28 + License as published by the Free Software Foundation; either
29 + version 2.1 of the License, or (at your option) any later version.
30 +
31 + The GNU C Library is distributed in the hope that it will be useful,
32 + but WITHOUT ANY WARRANTY; without even the implied warranty of
33 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 + Lesser General Public License for more details.
35 +
36 + You should have received a copy of the GNU Lesser General Public
37 + License along with the GNU C Library; if not, see
38 + <http://www.gnu.org/licenses/>. */
39 +
40 +#include <assert.h>
41 +#include <errno.h>
42 +#include <stdlib.h>
43 +#include <string.h>
44 +#include <stdint.h>
45 +#include <netinet/in.h>
46 +#include <netpacket/packet.h>
47 +#include <sys/param.h>
48 +#include <sys/socket.h>
49 +
50 +static const struct
51 +{
52 + int sol;
53 + int af;
54 + socklen_t size;
55 +} sol_map[] =
56 + {
57 + /* Sort the array according to importance of the protocols. Add
58 + more protocols when they become available. */
59 + { SOL_IP, AF_INET, sizeof (struct sockaddr_in) },
60 + { SOL_IPV6, AF_INET6, sizeof (struct sockaddr_in6) },
61 + { SOL_PACKET, AF_PACKET, sizeof (struct sockaddr_ll) }
62 + };
63 +#define NSOL_MAP (sizeof (sol_map) / sizeof (sol_map[0]))
64 +
65 +
66 +/* Try to determine the socket level value. Ideally both side and
67 + family are set. But sometimes only the size is correct and the
68 + family value might be bogus. Loop over the array entries and look
69 + for a perfect match or the first match based on size. */
70 +static int
71 +__get_sol (int af, socklen_t len)
72 +{
73 + int first_size_sol = -1;
74 +
75 + for (size_t cnt = 0; cnt < NSOL_MAP; ++cnt)
76 + {
77 + /* Just a test so that we make sure the special value used to
78 + signal the "we have so far no socket level value" is OK. */
79 + assert (sol_map[cnt].sol != -1);
80 +
81 + if (len == sol_map[cnt].size)
82 + {
83 + /* The size matches, which is a requirement. If the family
84 + matches, too, we have a winner. Otherwise we remember the
85 + socket level value for this protocol if it is the first
86 + match. */
87 + if (af == sol_map[cnt].af)
88 + /* Bingo! */
89 + return sol_map[cnt].sol;
90 +
91 + if (first_size_sol == -1)
92 + first_size_sol = sol_map[cnt].sol;
93 + }
94 + }
95 +
96 + return first_size_sol;
97 +}
98 +
99 +
100 +int
101 +getsourcefilter (int s, uint32_t interface, const struct sockaddr *group,
102 + socklen_t grouplen, uint32_t *fmode, uint32_t *numsrc,
103 + struct sockaddr_storage *slist)
104 +{
105 + /* We have to create an struct ip_msfilter object which we can pass
106 + to the kernel. */
107 + socklen_t needed = GROUP_FILTER_SIZE (*numsrc);
108 + struct group_filter *gf;
109 + gf = (struct group_filter *) malloc (needed);
110 + if (gf == NULL)
111 + return -1;
112 +
113 + gf->gf_interface = interface;
114 + memcpy (&gf->gf_group, group, grouplen);
115 + gf->gf_numsrc = *numsrc;
116 +
117 + /* We need to provide the appropriate socket level value. */
118 + int result;
119 + int sol = __get_sol (group->sa_family, grouplen);
120 + if (sol == -1)
121 + {
122 + errno = EINVAL;
123 + result = -1;
124 + }
125 + else
126 + {
127 + result = getsockopt (s, sol, MCAST_MSFILTER, gf, &needed);
128 +
129 + /* If successful, copy the results to the places the caller wants
130 + them in. */
131 + if (result == 0)
132 + {
133 + *fmode = gf->gf_fmode;
134 + memcpy (slist, gf->gf_slist,
135 + MIN (*numsrc, gf->gf_numsrc)
136 + * sizeof (struct sockaddr_storage));
137 + *numsrc = gf->gf_numsrc;
138 + }
139 + }
140 +
141 + int save_errno = errno;
142 + free (gf);
143 + errno = save_errno;
144 +
145 + return result;
146 +}
147 +
148 +
149 +int
150 +setsourcefilter (int s, uint32_t interface, const struct sockaddr *group,
151 + socklen_t grouplen, uint32_t fmode, uint32_t numsrc,
152 + const struct sockaddr_storage *slist)
153 +{
154 + /* We have to create an struct ip_msfilter object which we can pass
155 + to the kernel. */
156 + size_t needed = GROUP_FILTER_SIZE (numsrc);
157 +
158 + struct group_filter *gf;
159 + gf = (struct group_filter *) malloc (needed);
160 + if (gf == NULL)
161 + return -1;
162 +
163 + gf->gf_interface = interface;
164 + memcpy (&gf->gf_group, group, grouplen);
165 + gf->gf_fmode = fmode;
166 + gf->gf_numsrc = numsrc;
167 + memcpy (gf->gf_slist, slist, numsrc * sizeof (struct sockaddr_storage));
168 +
169 + /* We need to provide the appropriate socket level value. */
170 + int result;
171 + int sol = __get_sol (group->sa_family, grouplen);
172 + if (sol == -1)
173 + {
174 + errno = EINVAL;
175 + result = -1;
176 + }
177 + else
178 + result = setsockopt (s, sol, MCAST_MSFILTER, gf, needed);
179 +
180 + int save_errno = errno;
181 + free (gf);
182 + errno = save_errno;
183 +
184 + return result;
185 +}