+/* Tries to add 'sock' as a listener for 'multicast_group'. Returns 0 if
+ * successful, otherwise a positive errno value.
+ *
+ * Multicast group numbers are always positive.
+ *
+ * It is not an error to attempt to join a multicast group to which a socket
+ * already belongs. */
+int
+nl_sock_join_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
+{
+ if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+ &multicast_group, sizeof multicast_group) < 0) {
+ VLOG_WARN("could not join multicast group %u (%s)",
+ multicast_group, strerror(errno));
+ return errno;
+ }
+ return 0;
+}
+
+/* Tries to make 'sock' stop listening to 'multicast_group'. Returns 0 if
+ * successful, otherwise a positive errno value.
+ *
+ * Multicast group numbers are always positive.
+ *
+ * It is not an error to attempt to leave a multicast group to which a socket
+ * does not belong.
+ *
+ * On success, reading from 'sock' will still return any messages that were
+ * received on 'multicast_group' before the group was left. */
+int
+nl_sock_leave_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
+{
+ if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
+ &multicast_group, sizeof multicast_group) < 0) {
+ VLOG_WARN("could not leave multicast group %u (%s)",
+ multicast_group, strerror(errno));
+ return errno;
+ }
+ return 0;
+}
+