123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- --- a/main.c
- +++ b/main.c
- @@ -78,6 +78,7 @@ static void usage(const char *argv0) {
- #if IR
- " -i [<filename>]\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n"
- #endif
- + " -I <interface>\t\tNetwork interface used to send discovery\n"
- " -m <mac addr>\t\tSet mac address, format: ab:cd:ef:12:34:56\n"
- " -M <modelname>\tSet the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")\n"
- " -n <name>\t\tSet the player name\n"
- @@ -233,6 +234,8 @@ int main(int argc, char **argv) {
- extern bool pcm_check_header;
- char *logfile = NULL;
- u8_t mac[6];
- + char *iface = NULL;
- + in_addr_t bcast_addr = 0;
- unsigned stream_buf_size = STREAMBUF_SIZE;
- unsigned output_buf_size = 0; // set later
- unsigned rates[MAX_SUPPORTED_SAMPLERATES] = { 0 };
- @@ -271,6 +274,7 @@ int main(int argc, char **argv) {
-
- int maxSampleRate = 0;
-
- + memset(mac, 0, sizeof(mac));
- char *optarg = NULL;
- int optind = 1;
- int i;
- @@ -278,8 +282,6 @@ int main(int argc, char **argv) {
- #define MAXCMDLINE 512
- char cmdline[MAXCMDLINE] = "";
-
- - get_mac(mac);
- -
- for (i = 0; i < argc && (strlen(argv[i]) + strlen(cmdline) + 2 < MAXCMDLINE); i++) {
- strcat(cmdline, argv[i]);
- strcat(cmdline, " ");
- @@ -287,7 +289,7 @@ int main(int argc, char **argv) {
-
- while (optind < argc && strlen(argv[optind]) >= 2 && argv[optind][0] == '-') {
- char *opt = argv[optind] + 1;
- - if (strstr("oabcCdefmMnNpPrs"
- + if (strstr("oabcCdefImMnNpPrs"
- #if ALSA
- "UV"
- #endif
- @@ -382,6 +384,9 @@ int main(int argc, char **argv) {
- case 'f':
- logfile = optarg;
- break;
- + case 'I':
- + iface = optarg;
- + break;
- case 'm':
- {
- int byte = 0;
- @@ -667,6 +672,11 @@ int main(int argc, char **argv) {
- winsock_init();
- #endif
-
- + if (!(bcast_addr = get_iface_info(log_slimproto, iface, mac))) {
- + fprintf(stderr, "Error binding to network or none given\n");
- + exit(1);
- + }
- +
- stream_init(log_stream, stream_buf_size);
-
- if (!strcmp(output_device, "-")) {
- @@ -710,7 +720,7 @@ int main(int argc, char **argv) {
- exit(1);
- }
-
- - slimproto(log_slimproto, server, mac, name, namefile, modelname, maxSampleRate);
- + slimproto(log_slimproto, server, bcast_addr, mac, name, namefile, modelname, maxSampleRate);
-
- decode_close();
- stream_close();
- --- a/squeezelite.h
- +++ b/squeezelite.h
- @@ -403,7 +403,7 @@ typedef enum { EVENT_TIMEOUT = 0, EVENT_
-
- char *next_param(char *src, char c);
- u32_t gettime_ms(void);
- -void get_mac(u8_t *mac);
- +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac);
- void set_nonblock(sockfd s);
- int connect_timeout(sockfd sock, const struct sockaddr *addr, socklen_t addrlen, int timeout);
- void server_addr(char *server, in_addr_t *ip_ptr, unsigned *port_ptr);
- @@ -459,7 +459,7 @@ void buf_init(struct buffer *buf, size_t
- void buf_destroy(struct buffer *buf);
-
- // slimproto.c
- -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate);
- +void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate);
- void slimproto_stop(void);
- void wake_controller(void);
-
- --- a/slimproto.c
- +++ b/slimproto.c
- @@ -119,7 +119,7 @@ void send_packet(u8_t *packet, size_t le
- }
- }
-
- -static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t mac[6]) {
- +static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t *mac) {
- const char *base_cap = "Model=squeezelite,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Firmware=" VERSION;
- struct HELO_packet pkt;
-
- @@ -782,7 +782,7 @@ void wake_controller(void) {
- wake_signal(wake_e);
- }
-
- -in_addr_t discover_server(void) {
- +in_addr_t discover_server(in_addr_t bcast_addr) {
- struct sockaddr_in d;
- struct sockaddr_in s;
- char *buf;
- @@ -798,7 +798,7 @@ in_addr_t discover_server(void) {
- memset(&d, 0, sizeof(d));
- d.sin_family = AF_INET;
- d.sin_port = htons(PORT);
- - d.sin_addr.s_addr = htonl(INADDR_BROADCAST);
- + d.sin_addr.s_addr = bcast_addr;
-
- pollinfo.fd = disc_sock;
- pollinfo.events = POLLIN;
- @@ -829,7 +829,7 @@ in_addr_t discover_server(void) {
- #define FIXED_CAP_LEN 256
- #define VAR_CAP_LEN 128
-
- -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate) {
- +void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate) {
- struct sockaddr_in serv_addr;
- static char fixed_cap[FIXED_CAP_LEN], var_cap[VAR_CAP_LEN] = "";
- bool reconnect = false;
- @@ -849,7 +849,7 @@ void slimproto(log_level level, char *se
- }
-
- if (!slimproto_ip) {
- - slimproto_ip = discover_server();
- + slimproto_ip = discover_server(bcast_addr);
- }
-
- if (!slimproto_port) {
- @@ -924,7 +924,7 @@ void slimproto(log_level level, char *se
-
- // rediscover server if it was not set at startup
- if (!server && ++failed_connect > 5) {
- - slimproto_ip = serv_addr.sin_addr.s_addr = discover_server();
- + slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(bcast_addr);
- }
-
- } else {
- --- a/utils.c
- +++ b/utils.c
- @@ -22,11 +22,11 @@
- #include "squeezelite.h"
-
- #if LINUX || OSX || FREEBSD
- -#include <sys/ioctl.h>
- +#include <sys/types.h>
- #include <net/if.h>
- -#include <netdb.h>
- -#if FREEBSD
- #include <ifaddrs.h>
- +#include <netdb.h>
- +#if FREEBSD || OSX
- #include <net/if_dl.h>
- #include <net/if_types.h>
- #endif
- @@ -44,15 +44,11 @@
- #if WIN
- #include <iphlpapi.h>
- #endif
- -#if OSX
- -#include <net/if_dl.h>
- -#include <net/if_types.h>
- -#include <ifaddrs.h>
- -#include <netdb.h>
- -#endif
-
- #include <fcntl.h>
-
- +static log_level loglevel;
- +
- // logging functions
- const char *logtime(void) {
- static char buf[100];
- @@ -114,58 +110,101 @@ u32_t gettime_ms(void) {
- #endif
- }
-
- -// mac address
- -#if LINUX && !defined(SUN)
- -// search first 4 interfaces returned by IFCONF
- -void get_mac(u8_t mac[]) {
- - char *utmac;
- - struct ifconf ifc;
- - struct ifreq *ifr, *ifend;
- - struct ifreq ifreq;
- - struct ifreq ifs[4];
- +// Get broadcast address for interface (given or first available)
- +// Return MAC address if none given
- +#if LINUX || OSX || FREEBSD
-
- - utmac = getenv("UTMAC");
- - if (utmac)
- - {
- - if ( strlen(utmac) == 17 )
- - {
- - if (sscanf(utmac,"%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
- - &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) == 6)
- - {
- - return;
- - }
- - }
- +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac) {
- + struct ifaddrs *addrs, *ifa;
- + struct sockaddr *sdl;
- + char ifname[16];
- + unsigned char *ptr;
- + in_addr_t bcast_addr = 0;
- + int have_mac = 0, have_ifname = 0;
- +
- + loglevel = level;
- +
- + // Check for non-zero MAC
- + if ((mac[0] | mac[1] | mac[2]) != 0)
- + have_mac = 1;
- +
- + // Copy interface name, if it was provided.
- + if (iface != NULL)
- + {
- + if( strlen(iface) > sizeof(ifname) )
- + return -1;
-
- + strncpy(ifname, iface, sizeof(ifname));
- + have_ifname = 1;
- }
-
- - mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
- + if (getifaddrs(&addrs) == 0) {
- + //iterate to find corresponding ethernet address
- + for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
- + // Skip LOOPBACK interfaces, DOWN interfaces and interfaces that
- + // don't support BROADCAST.
- + if ((ifa->ifa_flags & IFF_LOOPBACK)
- + || !(ifa->ifa_flags & IFF_UP)
- + || !(ifa->ifa_flags & IFF_BROADCAST))
- + {
- + continue;
- + }
-
- - int s = socket(AF_INET, SOCK_DGRAM, 0);
- + if (!have_ifname)
- + {
- + // We have found a valid interface name. Keep it.
- + strncpy(ifname, ifa->ifa_name, sizeof(ifname));
- + have_ifname = 1;
- + } else {
- + if (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) != 0)
- + {
- + // This is not the interface we're looking for.
- + continue;
- + }
- + }
-
- - ifc.ifc_len = sizeof(ifs);
- - ifc.ifc_req = ifs;
-
- - if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
- - ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
- + // Check address family.
- + if ((ifa->ifa_addr->sa_family == AF_INET) &&
- + (((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr != 0))
- + {
- + // Get broadcast address and MAC address
- + bcast_addr = ((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr;
- + break;
- + }
- + else
- + {
- + // Address is not IPv4
- + if (iface == NULL)
- + have_ifname = 0;
- + }
- +
- + }
-
- - for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
- - if (ifr->ifr_addr.sa_family == AF_INET) {
- -
- - strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
- - if (ioctl (s, SIOCGIFHWADDR, &ifreq) == 0) {
- - memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6);
- - if (mac[0]+mac[1]+mac[2] != 0) {
- - break;
- - }
- + // Find MAC address matching interface
- + if (!have_mac && (bcast_addr != 0)) {
- + for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
- + if ((ifa->ifa_addr->sa_family == PF_PACKET) &&
- + (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) == 0)) {
- + sdl = (struct sockaddr *)(ifa->ifa_addr);
- + ptr = (unsigned char *)sdl->sa_data;
- + memcpy(mac, ptr + 10, 6);
- + have_mac = 1;
- }
- }
- }
- +
- + freeifaddrs(addrs);
- }
-
- - close(s);
- + LOG_INFO("Interface: %s, broadcast: %08X, macaddr = %02x:%02x:%02x:%02x:%02x:%02x",
- + ifname, bcast_addr, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
- +
- + return bcast_addr;
- }
- #endif
-
- +
- #if SUN
- void get_mac(u8_t mac[]) {
- struct arpreq parpreq;
- @@ -232,30 +271,6 @@ void get_mac(u8_t mac[]) {
- }
- #endif
-
- -#if OSX || FREEBSD
- -void get_mac(u8_t mac[]) {
- - struct ifaddrs *addrs, *ptr;
- - const struct sockaddr_dl *dlAddr;
- - const unsigned char *base;
- -
- - mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
- -
- - if (getifaddrs(&addrs) == 0) {
- - ptr = addrs;
- - while (ptr) {
- - if (ptr->ifa_addr->sa_family == AF_LINK && ((const struct sockaddr_dl *) ptr->ifa_addr)->sdl_type == IFT_ETHER) {
- - dlAddr = (const struct sockaddr_dl *)ptr->ifa_addr;
- - base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
- - memcpy(mac, base, min(dlAddr->sdl_alen, 6));
- - break;
- - }
- - ptr = ptr->ifa_next;
- - }
- - freeifaddrs(addrs);
- - }
- -}
- -#endif
- -
- #if WIN
- #pragma comment(lib, "IPHLPAPI.lib")
- void get_mac(u8_t mac[]) {
|