/* Open and configure the socket listening for * SSDP udp packets sent on 239.255.255.250 port 1900 */ int OpenAndConfSSDPReceiveSocket() { int s; int i; int j = 1; struct sockaddr_in sockname; if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket(udp): %m"); return -1; } memset(&sockname, 0, sizeof(struct sockaddr_in)); sockname.sin_family = AF_INET; sockname.sin_port = htons(SSDP_PORT); /* NOTE : it seems it doesnt work when binding on the specific address */ /*sockname.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);*/ sockname.sin_addr.s_addr = htonl(INADDR_ANY); /*sockname.sin_addr.s_addr = inet_addr(ifaddr);*/ if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &j, sizeof(j)) < 0) { syslog(LOG_WARNING, "setsockopt(udp, SO_REUSEADDR): %m"); } if(bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "bind(udp): %m"); close(s); return -1; } i = n_lan_addr; while(i>0) { i--; if(AddMulticastMembership(s, lan_addr[i].addr.s_addr) < 0) { syslog(LOG_WARNING, "Failed to add multicast membership for address %s", lan_addr[i].str ); } } return s; }
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); } }
/* Open and configure the socket listening for * SSDP udp packets sent on 239.255.255.250 port 1900 */ int OpenAndConfSSDPReceiveSocket(void) { int s; int i = 1; struct sockaddr_in sockname; s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { DPRINTF(E_ERROR, L_SSDP, "socket(udp): %s\n", strerror(errno)); return -1; } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) DPRINTF(E_WARN, L_SSDP, "setsockopt(udp, SO_REUSEADDR): %s\n", strerror(errno)); memset(&sockname, 0, sizeof(struct sockaddr_in)); sockname.sin_family = AF_INET; sockname.sin_port = htons(SSDP_PORT); /* NOTE : it seems it doesnt work when binding on the specific address */ sockname.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0) { DPRINTF(E_ERROR, L_SSDP, "bind(udp): %s\n", strerror(errno)); close(s); return -1; } i = n_lan_addr; while (i > 0) { i--; if (AddMulticastMembership(s, lan_addr[i].addr.s_addr) < 0) { DPRINTF(E_WARN, L_SSDP, "Failed to add multicast membership for address %s\n", lan_addr[i].str ); } } return s; }
/* Open and configure the socket listening for * SSDP udp packets sent on 239.255.255.250 port 1900 * SSDP v6 udp packets sent on FF02::C, or FF05::C, port 1900 */ int OpenAndConfSSDPReceiveSocket(int ipv6) { int s; struct sockaddr_storage sockname; socklen_t sockname_len; struct lan_addr_s * lan_addr; int j = 1; if( (s = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "%s: socket(udp): %m", "OpenAndConfSSDPReceiveSocket"); return -1; } memset(&sockname, 0, sizeof(struct sockaddr_storage)); if(ipv6) { struct sockaddr_in6 * saddr = (struct sockaddr_in6 *)&sockname; saddr->sin6_family = AF_INET6; saddr->sin6_port = htons(SSDP_PORT); saddr->sin6_addr = in6addr_any; sockname_len = sizeof(struct sockaddr_in6); } else { struct sockaddr_in * saddr = (struct sockaddr_in *)&sockname; saddr->sin_family = AF_INET; saddr->sin_port = htons(SSDP_PORT); /* NOTE : it seems it doesnt work when binding on the specific address */ /*saddr->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);*/ saddr->sin_addr.s_addr = htonl(INADDR_ANY); /*saddr->sin_addr.s_addr = inet_addr(ifaddr);*/ sockname_len = sizeof(struct sockaddr_in); } if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &j, sizeof(j)) < 0) { syslog(LOG_WARNING, "setsockopt(udp, SO_REUSEADDR): %m"); } if(!set_non_blocking(s)) { syslog(LOG_WARNING, "%s: set_non_blocking(): %m", "OpenAndConfSSDPReceiveSocket"); } if(bind(s, (struct sockaddr *)&sockname, sockname_len) < 0) { syslog(LOG_ERR, "%s: bind(udp%s): %m", "OpenAndConfSSDPReceiveSocket", ipv6 ? "6" : ""); close(s); return -1; } #ifdef ENABLE_IPV6 if(ipv6) { AddMulticastMembershipIPv6(s); } else #endif { for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) { if(AddMulticastMembership(s, lan_addr->addr.s_addr) < 0) { syslog(LOG_WARNING, "Failed to add multicast membership for interface %s", lan_addr->str ? lan_addr->str : "NULL"); } } } return s; }
/* disabled at the moment */ int ProcessInterfaceUp(struct ifinfomsg *ifi) { struct lan_iface_s * lan_iface; struct lan_iface_s * lan_iface2; struct lan_addr_s * lan_addr; char ifname[IFNAMSIZ]; char ifstraddr[16]; struct in_addr ifaddr; /* check if we already 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; if (if_indextoname(ifi->ifi_index, ifname) == NULL) { syslog(LOG_ERR, "if_indextoname(%d, ifname) failed", ifi->ifi_index); return -1; } if (getifaddr(ifname, ifstraddr, 16) < 0) { syslog(LOG_DEBUG, "getifaddr(%s, ifaddr, 16) failed", ifname); return 1; } if (inet_pton(AF_INET, ifstraddr, &ifaddr) != 1) { syslog(LOG_ERR, "inet_pton(AF_INET, \"%s\", &ifaddr) failed", ifstraddr); return -1; } /* check if this new interface has address which we need to listen to */ for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) { if (lan_addr->addr.s_addr != ifaddr.s_addr) continue; syslog(LOG_INFO, "Interface up: %s (%s)", ifname, ifstraddr); /* adding new lan_iface entry */ lan_iface = (struct lan_iface_s *) malloc(sizeof(struct lan_iface_s)); if (lan_iface == NULL) { syslog(LOG_ERR, "malloc(sizeof(struct lan_iface_s): %m"); continue; } lan_iface->lan_addr = lan_addr; strncpy(lan_iface->iface.name, ifname, IFNAMSIZ); lan_iface->iface.index = ifi->ifi_index; lan_iface->iface.addr = ifaddr; lan_iface->snotify = -1; #ifdef ENABLE_NATPMP lan_iface->snatpmp = -1; #endif LIST_INSERT_HEAD(&lan_ifaces, lan_iface, list); /* adding multicast membership for SSDP */ if(AddMulticastMembership(sudp, ifaddr.s_addr, ifi->ifi_index) < 0) syslog(LOG_WARNING, "Failed to add multicast membership for interface %s (%s)", ifname, ifstraddr); else syslog(LOG_INFO, "Multicast membership added for %s (%s)", ifname, ifstraddr); /* create SSDP notify socket */ if (OpenAndConfSSDPNotifySocket(lan_iface) < 0) syslog(LOG_WARNING, "Failed to open SSDP notify socket for interface %s (%s)", ifname, ifstraddr); #ifdef ENABLE_NATPMP /* create NAT-PMP socket */ for(lan_iface2 = lan_ifaces.lh_first; lan_iface2 != NULL; lan_iface2 = lan_iface2->list.le_next) if (lan_iface2->lan_addr->addr.s_addr == lan_iface->lan_addr->addr.s_addr && lan_iface2->snatpmp >= 0) lan_iface->snatpmp = lan_iface2->snatpmp; if (lan_iface->snatpmp < 0) { lan_iface->snatpmp = OpenAndConfNATPMPSocket(ifaddr.s_addr); if (lan_iface->snatpmp < 0) syslog(LOG_ERR, "OpenAndConfNATPMPSocket(ifaddr.s_addr) failed for %s (%s)", ifname, ifstraddr); else syslog(LOG_INFO, "Listening for NAT-PMP connection on %s:%d", ifstraddr, NATPMP_PORT); } #endif } 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; }