Commits

Dmitrij Tejblum authored and Denis Ovsienko committed 10d04cdb419
lib: use "protocol-independed API" from RFC3678, if that is available

(This commit is based on the patch from BZ#420, and should fix that bug.) * configure.ac: detect availability of that API * sockopt.c (setsockopt_ipv4_multicast): use it for join/leave IPv4 multicast groups
No tags

lib/sockopt.c

Modified
202 202 * (e.g. Linux, Solaris) behave when leaving groups on down interfaces,
203 203 * but this behavior should not be harmful if they behave the same way,
204 204 * allow leaves, or implicitly leave all groups joined to down interfaces.
205 205 */
206 206 int
207 207 setsockopt_ipv4_multicast(int sock,
208 208 int optname,
209 209 unsigned int mcast_addr,
210 210 unsigned int ifindex)
211 211 {
212 +#ifdef HAVE_RFC3678
213 + struct group_req gr;
214 + struct sockaddr_in *si;
215 + int ret;
216 + memset (&gr, 0, sizeof(gr));
217 + si = (struct sockaddr_in *)&gr.gr_group;
218 + gr.gr_interface = ifindex;
219 + si->sin_family = AF_INET;
220 +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
221 + si->sin_len = sizeof(struct sockaddr_in);
222 +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
223 + si->sin_addr.s_addr = mcast_addr;
224 + ret = setsockopt(sock, IPPROTO_IP, (optname == IP_ADD_MEMBERSHIP) ?
225 + MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr));
226 + if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
227 + {
228 + setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr));
229 + ret = setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void *)&gr, sizeof(gr));
230 + }
231 + return ret;
212 232
213 -#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
233 +#elif defined(HAVE_STRUCT_IP_MREQN_IMR_IFINDEX) && !defined(__FreeBSD__)
214 234 struct ip_mreqn mreqn;
215 235 int ret;
216 236
217 237 assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP);
218 238 memset (&mreqn, 0, sizeof(mreqn));
219 239
220 - if (mcast_addr)
221 - mreqn.imr_multiaddr.s_addr = mcast_addr;
222 -
240 + mreqn.imr_multiaddr.s_addr = mcast_addr;
223 241 mreqn.imr_ifindex = ifindex;
224 242
225 243 ret = setsockopt(sock, IPPROTO_IP, optname,
226 244 (void *)&mreqn, sizeof(mreqn));
227 245 if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
228 246 {
229 247 /* see above: handle possible problem when interface comes back up */
230 248 char buf[1][INET_ADDRSTRLEN];
231 249 zlog_info("setsockopt_ipv4_multicast attempting to drop and "
232 250 "re-add (fd %d, mcast %s, ifindex %u)",

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut