void renew_mcast_membership(struct lan_addr_s *iface) { if (DropMulticastMembership(sssdp, iface) < 0) { DPRINTF(E_DEBUG, L_SSDP, "Failed to drop multicast membership for address %s\n", iface->str); } if (AddMulticastMembership(sssdp, iface) < 0) { DPRINTF(E_ERROR, L_SSDP, "Failed to add multicast membership for address %s\n", iface->str); } }
int ProcessInterfaceDown(struct ifinfomsg *ifi) { struct lan_iface_s * lan_iface; struct lan_iface_s * lan_iface2; /* check if we have this iface */ for(lan_iface = lan_ifaces.lh_first; lan_iface != NULL; lan_iface = lan_iface->list.le_next) if (lan_iface->iface.index == ifi->ifi_index) break; if (lan_iface == NULL) return 0; /* one of our interfaces is going down, clean up */ syslog(LOG_INFO, "Interface down: %s", lan_iface->iface.name); /* remove multicast membership for SSDP */ if(DropMulticastMembership(sudp, lan_iface->lan_addr->addr.s_addr, lan_iface->iface.index) < 0) syslog(LOG_WARNING, "Failed to drop multicast membership for interface %s (%s)", lan_iface->iface.name, lan_iface->lan_addr->str); else syslog(LOG_INFO, "Multicast membership dropped for %s (%s)", lan_iface->iface.name, lan_iface->lan_addr->str); /* closing SSDP notify socket */ close(lan_iface->snotify); #ifdef ENABLE_NATPMP /* closing NAT-PMP socket if it's not used anymore */ for(lan_iface2 = lan_ifaces.lh_first; lan_iface2 != NULL; lan_iface2 = lan_iface2->list.le_next) if (lan_iface2 != lan_iface && lan_iface2->snatpmp == lan_iface->snatpmp) break; if (lan_iface2 == NULL) close(lan_iface->snatpmp); #endif /* del corresponding lan_iface entry */ LIST_REMOVE(lan_iface, list); free(lan_iface); return 0; }
/* open the UDP socket used to send SSDP notifications to * the multicast group reserved for them */ int OpenAndConfSSDPNotifySocket(struct lan_addr_s *iface) { int s; unsigned char loopchar = 0; /* no need int bcast = 1; */ uint8_t ttl = 2; /* UDA v1.1 says : The TTL for the IP packet SHOULD default to 2 and SHOULD be configurable. */ struct in_addr mc_if; struct sockaddr_in sockname; s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { DPRINTF(E_ERROR, L_SSDP, "socket(udp_notify): %s\n", strerror(errno)); return -1; } mc_if.s_addr = iface->addr.s_addr; if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0) { DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, IP_MULTICAST_LOOP): %s\n", strerror(errno)); close(s); return -1; } if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mc_if, sizeof(mc_if)) < 0) { DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, IP_MULTICAST_IF): %s\n", strerror(errno)); close(s); return -1; } setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); /* no need if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast)) < 0) { DPRINTF(E_ERROR, L_SSDP, "setsockopt(udp_notify, SO_BROADCAST): %s\n", strerror(errno)); close(s); return -1; } */ memset(&sockname, 0, sizeof(struct sockaddr_in)); sockname.sin_family = AF_INET; sockname.sin_addr.s_addr = iface->addr.s_addr; if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0) { DPRINTF(E_ERROR, L_SSDP, "bind(udp_notify): %s\n", strerror(errno)); close(s); return -1; } if (DropMulticastMembership(sssdp, iface) < 0) { DPRINTF(E_DEBUG, L_SSDP, "Failed to drop multicast membership for address %s\n", iface->str); } if (AddMulticastMembership(sssdp, iface) < 0) { DPRINTF(E_WARN, L_SSDP, "Failed to add multicast membership for address %s\n", iface->str); } return s; }