[mcproxy] Add support for mcproxy v1.1.0.
[feed/routing.git] / mcproxy / patches / 200-uclibc_sourcefilter.patch
1 --- a/mcproxy/src/utils/mc_socket.cpp
2 +++ b/mcproxy/src/utils/mc_socket.cpp
3 @@ -37,6 +37,135 @@
4 #include <numeric>
5 #include <unistd.h>
6
7 +#ifdef __UCLIBC__
8 +#include <assert.h>
9 +#include <netax25/ax25.h>
10 +#include <netipx/ipx.h>
11 +#include <stdlib.h>
12 +#include <sys/param.h>
13 +#include <sys/socket.h>
14 +
15 +extern "C" {
16 +static const struct
17 +{
18 + int sol;
19 + int af;
20 + socklen_t size;
21 +} sol_map[] =
22 + {
23 + /* Sort the array according to importance of the protocols. Add
24 + more protocols when they become available. */
25 + { SOL_IP, AF_INET, sizeof(struct sockaddr_in) },
26 + { SOL_IPV6, AF_INET6, sizeof(struct sockaddr_in6) },
27 + { SOL_AX25, AF_AX25, sizeof(struct sockaddr_ax25) },
28 + { SOL_IPX, AF_IPX, sizeof(struct sockaddr_ipx) },
29 + { SOL_PACKET, AF_PACKET, sizeof(struct sockaddr_ll) }
30 + };
31 +#define NSOL_MAP (sizeof(sol_map) / sizeof(sol_map[0]))
32 +
33 +/* Try to determine the socket level value. Ideally both side and
34 + family are set. But sometimes only the size is correct and the
35 + family value might be bogus. Loop over the array entries and look
36 + for a perfect match or the first match based on size. */
37 +int __get_sol(int af, socklen_t len)
38 +{
39 + int first_size_sol = -1;
40 + for (size_t cnt = 0; cnt < NSOL_MAP; ++cnt) {
41 + /* Just a test so that we make sure the special value used to
42 + signal the "we have so far no socket level value" is OK. */
43 + assert(sol_map[cnt].sol != -1);
44 +
45 + if (len == sol_map[cnt].size) {
46 + /* The size matches, which is a requirement. If the family
47 + matches, too, we have a winner. Otherwise we remember the
48 + socket level value for this protocol if it is the first
49 + match. */
50 + if (af == sol_map[cnt].af)
51 + return sol_map[cnt].sol;
52 +
53 + if (first_size_sol == -1)
54 + first_size_sol = sol_map[cnt].sol;
55 + }
56 + }
57 +
58 + return first_size_sol;
59 +}
60 +
61 +int getsourcefilter(int s, uint32_t interface, const struct sockaddr *group,
62 + socklen_t grouplen, uint32_t *fmode, uint32_t *numsrc,
63 + struct sockaddr_storage *slist)
64 +{
65 + socklen_t needed = GROUP_FILTER_SIZE(*numsrc);
66 + struct group_filter *gf;
67 +
68 + gf = (struct group_filter *) malloc(needed);
69 + if (gf == NULL)
70 + return -1;
71 +
72 + gf->gf_interface = interface;
73 + memcpy(&gf->gf_group, group, grouplen);
74 + gf->gf_numsrc = *numsrc;
75 +
76 + /* We need to provide the appropriate socket level value. */
77 + int result;
78 + int sol = __get_sol(group->sa_family, grouplen);
79 + if (sol == -1) {
80 + result = -1;
81 + }
82 + else {
83 + result = getsockopt(s, sol, MCAST_MSFILTER, gf, &needed);
84 +
85 + /* If successful, copy the results to the places the caller wants
86 + them in. */
87 + if (result == 0) {
88 + *fmode = gf->gf_fmode;
89 + memcpy(slist, gf->gf_slist,
90 + MIN(*numsrc, gf->gf_numsrc)
91 + * sizeof(struct sockaddr_storage));
92 + *numsrc = gf->gf_numsrc;
93 + }
94 + }
95 +
96 + free(gf);
97 +
98 + return result;
99 +}
100 +
101 +int setsourcefilter(int s, uint32_t interface, const struct sockaddr *group,
102 + socklen_t grouplen, uint32_t fmode, uint32_t numsrc,
103 + const struct sockaddr_storage *slist)
104 +{
105 + /* We have to create an struct ip_msfilter object which we can pass
106 + to the kernel. */
107 + size_t needed = GROUP_FILTER_SIZE(numsrc);
108 + struct group_filter *gf;
109 +
110 + gf = (struct group_filter *) malloc(needed);
111 + if (gf == NULL)
112 + return -1;
113 +
114 + gf->gf_interface = interface;
115 + memcpy(&gf->gf_group, group, grouplen);
116 + gf->gf_fmode = fmode;
117 + gf->gf_numsrc = numsrc;
118 + memcpy(gf->gf_slist, slist, numsrc * sizeof(struct sockaddr_storage));
119 +
120 + /* We need to provide the appropriate socket level value. */
121 + int result;
122 + int sol = __get_sol(group->sa_family, grouplen);
123 + if (sol == -1) {
124 + result = -1;
125 + }
126 + else
127 + result = setsockopt(s, sol, MCAST_MSFILTER, gf, needed);
128 +
129 + free(gf);
130 +
131 + return result;
132 +}
133 +}
134 +#endif /* __UCLIBC__ */
135 +
136 std::string ipAddrResolver(std::string ipAddr)
137 {
138 std::string str[][2] = {