diff --git a/getifaddr.c b/getifaddr.c index e34c801..2bd52db 100644 --- a/getifaddr.c +++ b/getifaddr.c @@ -66,7 +66,7 @@ #include "log.h" static int -getifaddr(const char *ifname, int notify) +getifaddr(const char *ifname) { #if HAVE_GETIFADDRS struct ifaddrs *ifap, *p; @@ -96,14 +96,9 @@ getifaddr(const char *ifname, int notify) addr_in = (struct sockaddr_in *)p->ifa_netmask; memcpy(&lan_addr[n_lan_addr].mask, &addr_in->sin_addr, sizeof(lan_addr[n_lan_addr].mask)); lan_addr[n_lan_addr].ifindex = if_nametoindex(p->ifa_name); - lan_addr[n_lan_addr].snotify = OpenAndConfSSDPNotifySocket(lan_addr[n_lan_addr].addr.s_addr); + lan_addr[n_lan_addr].snotify = OpenAndConfSSDPNotifySocket(&lan_addr[n_lan_addr]); if (lan_addr[n_lan_addr].snotify >= 0) - { - if (notify) - SendSSDPNotifies(lan_addr[n_lan_addr].snotify, lan_addr[n_lan_addr].str, - runtime_vars.port, runtime_vars.notify_interval); n_lan_addr++; - } if (ifname || n_lan_addr >= MAX_LAN_ADDR) break; } @@ -156,14 +151,9 @@ getifaddr(const char *ifname, int notify) memcpy(&addr, &(ifr->ifr_addr), sizeof(addr)); memcpy(&lan_addr[n_lan_addr].mask, &addr.sin_addr, sizeof(addr)); lan_addr[n_lan_addr].ifindex = if_nametoindex(ifr->ifr_name); - lan_addr[n_lan_addr].snotify = OpenAndConfSSDPNotifySocket(lan_addr[i].addr.s_addr); + lan_addr[n_lan_addr].snotify = OpenAndConfSSDPNotifySocket(&lan_addr[i]); if (lan_addr[n_lan_addr].snotify >= 0) - { - if (notify) - SendSSDPNotifies(lan_addr[n_lan_addr].snotify, lan_addr[n_lan_addr].str, - runtime_vars.port, runtime_vars.notify_interval); n_lan_addr++; - } if (ifname || n_lan_addr >= MAX_LAN_ADDR) break; } @@ -305,26 +295,41 @@ get_remote_mac(struct in_addr ip_addr, unsigned char *mac) } void -reload_ifaces(int notify) +reload_ifaces(int force_notify) { - int i; + struct in_addr old_addr[MAX_LAN_ADDR]; + int i, j; + memset(&old_addr, 0xFF, sizeof(old_addr)); for (i = 0; i < n_lan_addr; i++) { + memcpy(&old_addr[i], &lan_addr[i].addr, sizeof(struct in_addr)); close(lan_addr[i].snotify); } n_lan_addr = 0; i = 0; do { - getifaddr(runtime_vars.ifaces[i], notify); + getifaddr(runtime_vars.ifaces[i]); i++; } while (runtime_vars.ifaces[i]); for (i = 0; i < n_lan_addr; i++) { - DPRINTF(E_INFO, L_GENERAL, "Enabled interface %s/%s\n", - lan_addr[i].str, inet_ntoa(lan_addr[i].mask)); + for (j = 0; j < MAX_LAN_ADDR; j++) + { + if (memcmp(&lan_addr[i].addr, &old_addr[j], sizeof(struct in_addr)) == 0) + break; + } + /* Send out startup notifies if it's a new interface, or on SIGHUP */ + if (force_notify || j == MAX_LAN_ADDR) + { + DPRINTF(E_INFO, L_GENERAL, "Enabling interface %s/%s\n", + lan_addr[i].str, inet_ntoa(lan_addr[i].mask)); + SendSSDPGoodbyes(lan_addr[i].snotify); + SendSSDPNotifies(lan_addr[i].snotify, lan_addr[i].str, + runtime_vars.port, runtime_vars.notify_interval); + } } } @@ -384,6 +389,6 @@ ProcessMonitorEvent(int s) nlh = NLMSG_NEXT(nlh, len); } if (changed) - reload_ifaces(1); + reload_ifaces(0); #endif } diff --git a/minidlna.c b/minidlna.c index 00b55f4..46b7cb9 100644 --- a/minidlna.c +++ b/minidlna.c @@ -155,6 +155,15 @@ sigterm(int sig) quitting = 1; } +static void +sigusr1(int sig) +{ + signal(sig, sigusr1); + DPRINTF(E_WARN, L_GENERAL, "received signal %d, clear cache\n", sig); + + memset(&clients, '\0', sizeof(clients)); +} + static void sighup(int sig) { @@ -903,7 +912,6 @@ init(int argc, char **argv) } set_startup_time(); - reload_ifaces(0); /* presentation url */ if (presurl) @@ -922,6 +930,7 @@ init(int argc, char **argv) DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGPIPE"); if (signal(SIGHUP, &sighup) == SIG_ERR) DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGHUP"); + signal(SIGUSR1, &sigusr1); sa.sa_handler = process_handle_child_termination; if (sigaction(SIGCHLD, &sa, NULL)) DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGCHLD"); @@ -942,7 +951,7 @@ int main(int argc, char **argv) { int ret, i; - int sudp = -1, shttpl = -1; + int shttpl = -1; int smonitor = -1; LIST_HEAD(httplisthead, upnphttp) upnphttphead; struct upnphttp * e = 0; @@ -1003,8 +1012,8 @@ main(int argc, char **argv) #endif smonitor = OpenAndConfMonitorSocket(); - sudp = OpenAndConfSSDPReceiveSocket(); - if (sudp < 0) + sssdp = OpenAndConfSSDPReceiveSocket(); + if (sssdp < 0) { DPRINTF(E_INFO, L_GENERAL, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd\n"); if (SubmitServicesToMiniSSDPD(lan_addr[0].str, runtime_vars.port) < 0) @@ -1037,7 +1046,8 @@ main(int argc, char **argv) sbeacon = -1; #endif - SendSSDPGoodbyes(); + reload_ifaces(0); + lastnotifytime.tv_sec = time(NULL) + runtime_vars.notify_interval; /* main loop */ while (!quitting) @@ -1113,10 +1123,10 @@ main(int argc, char **argv) /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */ FD_ZERO(&readset); - if (sudp >= 0) + if (sssdp >= 0) { - FD_SET(sudp, &readset); - max_fd = MAX(max_fd, sudp); + FD_SET(sssdp, &readset); + max_fd = MAX(max_fd, sssdp); } if (shttpl >= 0) @@ -1165,10 +1175,10 @@ main(int argc, char **argv) } upnpevents_processfds(&readset, &writeset); /* process SSDP packets */ - if (sudp >= 0 && FD_ISSET(sudp, &readset)) + if (sssdp >= 0 && FD_ISSET(sssdp, &readset)) { - /*DPRINTF(E_DEBUG, L_GENERAL, "Received UDP Packet\n");*/ - ProcessSSDPRequest(sudp, (unsigned short)runtime_vars.port); + /*DPRINTF(E_DEBUG, L_GENERAL, "Received SSDP Packet\n");*/ + ProcessSSDPRequest(sssdp, (unsigned short)runtime_vars.port); } #ifdef TIVO_SUPPORT if (sbeacon >= 0 && FD_ISSET(sbeacon, &readset)) @@ -1259,8 +1269,8 @@ shutdown: LIST_REMOVE(e, entries); Delete_upnphttp(e); } - if (sudp >= 0) - close(sudp); + if (sssdp >= 0) + close(sssdp); if (shttpl >= 0) close(shttpl); #ifdef TIVO_SUPPORT @@ -1268,11 +1278,9 @@ shutdown: close(sbeacon); #endif - if (SendSSDPGoodbyes() < 0) - DPRINTF(E_ERROR, L_GENERAL, "Failed to broadcast good-bye notifications\n"); - for (i = 0; i < n_lan_addr; i++) { + SendSSDPGoodbyes(lan_addr[i].snotify); close(lan_addr[i].snotify); } diff --git a/minissdp.c b/minissdp.c index 3687073..cf4d922 100644 --- a/minissdp.c +++ b/minissdp.c @@ -127,7 +127,7 @@ OpenAndConfSSDPReceiveSocket(void) /* open the UDP socket used to send SSDP notifications to * the multicast group reserved for them */ int -OpenAndConfSSDPNotifySocket(in_addr_t addr) +OpenAndConfSSDPNotifySocket(struct lan_addr_s *iface) { int s; unsigned char loopchar = 0; @@ -143,7 +143,7 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr) return -1; } - mc_if.s_addr = addr; /*inet_addr(addr);*/ + mc_if.s_addr = iface->addr.s_addr; if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0) { @@ -170,7 +170,7 @@ OpenAndConfSSDPNotifySocket(in_addr_t addr) memset(&sockname, 0, sizeof(struct sockaddr_in)); sockname.sin_family = AF_INET; - sockname.sin_addr.s_addr = addr; /*inet_addr(addr);*/ + sockname.sin_addr.s_addr = iface->addr.s_addr; if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0) { @@ -294,7 +294,7 @@ SendSSDPNotifies(int s, const char *host, unsigned short port, DPRINTF(E_WARN, L_SSDP, "SendSSDPNotifies(): truncated output\n"); l = sizeof(bufr); } - DPRINTF(E_MAXDEBUG, L_SSDP, "Sending ssdp:alive\n"); + DPRINTF(E_MAXDEBUG, L_SSDP, "Sending ssdp:alive [%d]\n", s); n = sendto(s, bufr, l, 0, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); if (n < 0) @@ -589,7 +589,7 @@ ProcessSSDPRequest(int s, unsigned short port) mx++; while (mx[mx_len]!='\r' && mx[mx_len]!='\n') mx_len++; - mx_val = strtol(mx, &mx_end, 10); + mx_val = strtol(mx, &mx_end, 10); } else if (strncasecmp(bufr+i, "MAN:", 4) == 0) { @@ -602,8 +602,7 @@ ProcessSSDPRequest(int s, unsigned short port) } } /*DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH packet received from %s:%d\n", - inet_ntoa(sendername.sin_addr), - ntohs(sendername.sin_port) );*/ + inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port) );*/ if (GETFLAG(DLNA_STRICT_MASK) && (ntohs(sendername.sin_port) <= 1024 || ntohs(sendername.sin_port) == 1900)) { DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad source port %d]\n", @@ -639,7 +638,7 @@ ProcessSSDPRequest(int s, unsigned short port) inet_ntoa(sendername.sin_addr)); return; } - DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH from %s:%d ST: %.*s, MX: %.*s, MAN: %.*s\n", + DPRINTF(E_DEBUG, L_SSDP, "SSDP M-SEARCH from %s:%d ST: %.*s, MX: %.*s, MAN: %.*s\n", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port), st_len, st, mx_len, mx, man_len, man); @@ -698,18 +697,18 @@ ProcessSSDPRequest(int s, unsigned short port) else { DPRINTF(E_WARN, L_SSDP, "Unknown udp packet received from %s:%d\n", - inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port)); + inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port)); } } /* This will broadcast ssdp:byebye notifications to inform * the network that UPnP is going down. */ int -SendSSDPGoodbyes(void) +SendSSDPGoodbyes(int s) { struct sockaddr_in sockname; int n, l; - int i, j; + int i; int dup, ret = 0; char bufr[512]; @@ -720,29 +719,29 @@ SendSSDPGoodbyes(void) for (dup = 0; dup < 2; dup++) { - for (j = 0; j < n_lan_addr; j++) + for (i = 0; known_service_types[i]; i++) { - for (i = 0; known_service_types[i]; i++) + l = snprintf(bufr, sizeof(bufr), + "NOTIFY * HTTP/1.1\r\n" + "HOST:%s:%d\r\n" + "NT:%s%s\r\n" + "USN:%s%s%s%s\r\n" + "NTS:ssdp:byebye\r\n" + "\r\n", + SSDP_MCAST_ADDR, SSDP_PORT, + known_service_types[i], + (i > 1 ? "1" : ""), uuidvalue, + (i > 0 ? "::" : ""), + (i > 0 ? known_service_types[i] : ""), + (i > 1 ? "1" : "")); + DPRINTF(E_MAXDEBUG, L_SSDP, "Sending ssdp:byebye [%s]\n", s); + n = sendto(s, bufr, l, 0, + (struct sockaddr *)&sockname, sizeof(struct sockaddr_in) ); + if (n < 0) { - l = snprintf(bufr, sizeof(bufr), - "NOTIFY * HTTP/1.1\r\n" - "HOST:%s:%d\r\n" - "NT:%s%s\r\n" - "USN:%s%s%s%s\r\n" - "NTS:ssdp:byebye\r\n" - "\r\n", - SSDP_MCAST_ADDR, SSDP_PORT, - known_service_types[i], (i>1?"1":""), - uuidvalue, (i>0?"::":""), (i>0?known_service_types[i]:""), (i>1?"1":"") ); - DPRINTF(E_MAXDEBUG, L_SSDP, "Sending ssdp:byebye\n"); - n = sendto(lan_addr[j].snotify, bufr, l, 0, - (struct sockaddr *)&sockname, sizeof(struct sockaddr_in) ); - if (n < 0) - { - DPRINTF(E_ERROR, L_SSDP, "sendto(udp_shutdown=%d): %s\n", lan_addr[j].snotify, strerror(errno)); - ret = -1; - break; - } + DPRINTF(E_ERROR, L_SSDP, "sendto(udp_shutdown=%d): %s\n", s, strerror(errno)); + ret = -1; + break; } } } @@ -773,7 +772,7 @@ SubmitServicesToMiniSSDPD(const char *host, unsigned short port) if (connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) { DPRINTF(E_ERROR, L_SSDP, "connect(\"%s\"): %s", - minissdpdsocketpath, strerror(errno)); + minissdpdsocketpath, strerror(errno)); close(s); return -1; } @@ -810,7 +809,7 @@ SubmitServicesToMiniSSDPD(const char *host, unsigned short port) return -1; } } - close(s); + close(s); return 0; } diff --git a/minissdp.h b/minissdp.h index 5f93d24..f6a5c16 100644 --- a/minissdp.h +++ b/minissdp.h @@ -31,13 +31,13 @@ int OpenAndConfSSDPReceiveSocket(void); -int OpenAndConfSSDPNotifySocket(in_addr_t addr); +int OpenAndConfSSDPNotifySocket(struct lan_addr_s *iface); void SendSSDPNotifies(int s, const char *host, unsigned short port, unsigned int lifetime); void ProcessSSDPRequest(int s, unsigned short port); -int SendSSDPGoodbyes(void); +int SendSSDPGoodbyes(int s); int SubmitServicesToMiniSSDPD(const char *host, unsigned short port); diff --git a/upnpglobalvars.c b/upnpglobalvars.c index d7cd586..73ceeca 100644 --- a/upnpglobalvars.c +++ b/upnpglobalvars.c @@ -53,9 +53,6 @@ #include "config.h" #include "upnpglobalvars.h" -/* LAN address */ -/*const char * listen_addr = 0;*/ - /* startup time */ time_t startup_time = 0; @@ -78,6 +75,7 @@ char presentationurl[PRESENTATIONURL_MAX_LEN]; int n_lan_addr = 0; struct lan_addr_s lan_addr[MAX_LAN_ADDR]; +int sssdp = -1; /* Path of the Unix socket used to communicate with MiniSSDPd */ const char * minissdpdsocketpath = "/var/run/minissdpd.sock"; diff --git a/upnpglobalvars.h b/upnpglobalvars.h index e5266be..e335b7f 100644 --- a/upnpglobalvars.h +++ b/upnpglobalvars.h @@ -215,10 +215,9 @@ extern char pnpx_hwid[]; #endif /* lan addresses */ -/* MAX_LAN_ADDR : maximum number of interfaces - * to listen to SSDP traffic */ extern int n_lan_addr; extern struct lan_addr_s lan_addr[]; +extern int sssdp; extern const char *minissdpdsocketpath;