3 @@ -69,6 +69,7 @@ static void usage(const char *argv0) {
5 " -i [<filename>]\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n"
7 + " -I <interface>\t\tNetwork interface used to send discovery\n"
8 " -m <mac addr>\t\tSet mac address, format: ab:cd:ef:12:34:56\n"
9 " -M <modelname>\tSet the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")\n"
10 " -n <name>\t\tSet the player name\n"
11 @@ -197,6 +198,8 @@ int main(int argc, char **argv) {
12 char *modelname = NULL;
16 + in_addr_t bcast_addr = 0;
17 unsigned stream_buf_size = STREAMBUF_SIZE;
18 unsigned output_buf_size = 0; // set later
19 unsigned rates[MAX_SUPPORTED_SAMPLERATES] = { 0 };
20 @@ -233,6 +236,7 @@ int main(int argc, char **argv) {
21 log_level log_ir = lWARN;
24 + memset(mac, 0, sizeof(mac));
28 @@ -240,8 +244,6 @@ int main(int argc, char **argv) {
29 #define MAXCMDLINE 512
30 char cmdline[MAXCMDLINE] = "";
34 for (i = 0; i < argc && (strlen(argv[i]) + strlen(cmdline) + 2 < MAXCMDLINE); i++) {
35 strcat(cmdline, argv[i]);
37 @@ -249,7 +251,7 @@ int main(int argc, char **argv) {
39 while (optind < argc && strlen(argv[optind]) >= 2 && argv[optind][0] == '-') {
40 char *opt = argv[optind] + 1;
41 - if (strstr("oabcCdefmMnNpPrs"
42 + if (strstr("oabcCdefImMnNpPrs"
46 @@ -334,6 +336,9 @@ int main(int argc, char **argv) {
56 @@ -556,6 +561,11 @@ int main(int argc, char **argv) {
60 + if (!(bcast_addr = get_iface_info(log_slimproto, iface, mac))) {
61 + fprintf(stderr, "Error binding to network or none given\n");
65 stream_init(log_stream, stream_buf_size);
67 if (!strcmp(output_device, "-")) {
68 @@ -599,7 +609,7 @@ int main(int argc, char **argv) {
72 - slimproto(log_slimproto, server, mac, name, namefile, modelname);
73 + slimproto(log_slimproto, server, bcast_addr, mac, name, namefile, modelname);
79 @@ -374,7 +374,7 @@ typedef enum { EVENT_TIMEOUT = 0, EVENT_
81 char *next_param(char *src, char c);
82 u32_t gettime_ms(void);
83 -void get_mac(u8_t *mac);
84 +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac);
85 void set_nonblock(sockfd s);
86 int connect_timeout(sockfd sock, const struct sockaddr *addr, socklen_t addrlen, int timeout);
87 void server_addr(char *server, in_addr_t *ip_ptr, unsigned *port_ptr);
88 @@ -426,7 +426,7 @@ void buf_init(struct buffer *buf, size_t
89 void buf_destroy(struct buffer *buf);
92 -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname);
93 +void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t *mac, const char *name, const char *namefile, const char *modelname);
94 void slimproto_stop(void);
95 void wake_controller(void);
99 @@ -107,7 +107,7 @@ void send_packet(u8_t *packet, size_t le
103 -static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t mac[6]) {
104 +static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t *mac) {
105 const char *base_cap = "Model=squeezelite,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Firmware=" VERSION;
106 struct HELO_packet pkt;
108 @@ -730,7 +730,7 @@ void wake_controller(void) {
112 -in_addr_t discover_server(void) {
113 +in_addr_t discover_server(in_addr_t bcast_addr) {
114 struct sockaddr_in d;
115 struct sockaddr_in s;
117 @@ -746,7 +746,7 @@ in_addr_t discover_server(void) {
118 memset(&d, 0, sizeof(d));
119 d.sin_family = AF_INET;
120 d.sin_port = htons(PORT);
121 - d.sin_addr.s_addr = htonl(INADDR_BROADCAST);
122 + d.sin_addr.s_addr = bcast_addr;
124 pollinfo.fd = disc_sock;
125 pollinfo.events = POLLIN;
126 @@ -777,7 +777,7 @@ in_addr_t discover_server(void) {
127 #define FIXED_CAP_LEN 256
128 #define VAR_CAP_LEN 128
130 -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname) {
131 +void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t *mac, const char *name, const char *namefile, const char *modelname) {
132 struct sockaddr_in serv_addr;
133 static char fixed_cap[FIXED_CAP_LEN], var_cap[VAR_CAP_LEN] = "";
134 bool reconnect = false;
135 @@ -795,7 +795,7 @@ void slimproto(log_level level, char *se
139 - slimproto_ip = discover_server();
140 + slimproto_ip = discover_server(bcast_addr);
143 if (!slimproto_port) {
144 @@ -870,7 +870,7 @@ void slimproto(log_level level, char *se
146 // rediscover server if it was not set at startup
147 if (!server && ++failed_connect > 5) {
148 - slimproto_ip = serv_addr.sin_addr.s_addr = discover_server();
149 + slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(bcast_addr);
156 #include "squeezelite.h"
158 #if LINUX || OSX || FREEBSD
159 -#include <sys/ioctl.h>
160 +#include <sys/types.h>
167 #include <net/if_dl.h>
168 #include <net/if_types.h>
172 #include <iphlpapi.h>
175 -#include <net/if_dl.h>
176 -#include <net/if_types.h>
177 -#include <ifaddrs.h>
183 +static log_level loglevel;
186 const char *logtime(void) {
187 static char buf[100];
188 @@ -99,67 +95,101 @@ u32_t gettime_ms(void) {
194 -// search first 4 interfaces returned by IFCONF
195 -void get_mac(u8_t mac[]) {
197 - struct ifreq *ifr, *ifend;
198 - struct ifreq ifreq;
199 - struct ifreq ifs[4];
201 - mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
203 - int s = socket(AF_INET, SOCK_DGRAM, 0);
205 - ifc.ifc_len = sizeof(ifs);
208 - if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
209 - ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
211 - for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
212 - if (ifr->ifr_addr.sa_family == AF_INET) {
214 - strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
215 - if (ioctl (s, SIOCGIFHWADDR, &ifreq) == 0) {
216 - memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6);
217 - if (mac[0]+mac[1]+mac[2] != 0) {
220 +// Get broadcast address for interface (given or first available)
221 +// Return MAC address if none given
222 +#if LINUX || OSX || FREEBSD
224 +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac) {
225 + struct ifaddrs *addrs, *ifa;
226 + struct sockaddr *sdl;
228 + unsigned char *ptr;
229 + in_addr_t bcast_addr = 0;
230 + int have_mac = 0, have_ifname = 0;
234 + // Check for non-zero MAC
235 + if ((mac[0] | mac[1] | mac[2]) != 0)
238 + // Copy interface name, if it was provided.
241 + if( strlen(iface) > sizeof(ifname) )
244 + strncpy(ifname, iface, sizeof(ifname));
248 + if (getifaddrs(&addrs) == 0) {
249 + //iterate to find corresponding ethernet address
250 + for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
251 + // Skip LOOPBACK interfaces, DOWN interfaces and interfaces that
252 + // don't support BROADCAST.
253 + if ((ifa->ifa_flags & IFF_LOOPBACK)
254 + || !(ifa->ifa_flags & IFF_UP)
255 + || !(ifa->ifa_flags & IFF_BROADCAST))
262 + // We have found a valid interface name. Keep it.
263 + strncpy(ifname, ifa->ifa_name, sizeof(ifname));
266 + if (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) != 0)
268 + // This is not the interface we're looking for.
280 -void get_mac(u8_t mac[]) {
281 - struct ifaddrs *addrs, *ptr;
282 - const struct sockaddr_dl *dlAddr;
283 - const unsigned char *base;
285 - mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
287 - if (getifaddrs(&addrs) == 0) {
290 - if (ptr->ifa_addr->sa_family == AF_LINK && ((const struct sockaddr_dl *) ptr->ifa_addr)->sdl_type == IFT_ETHER) {
291 - dlAddr = (const struct sockaddr_dl *)ptr->ifa_addr;
292 - base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
293 - memcpy(mac, base, min(dlAddr->sdl_alen, 6));
294 + // Check address family.
295 + if ((ifa->ifa_addr->sa_family == AF_INET) &&
296 + (((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr != 0))
298 + // Get broadcast address and MAC address
299 + bcast_addr = ((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr;
302 - ptr = ptr->ifa_next;
305 + // Address is not IPv4
312 + // Find MAC address matching interface
313 + if (!have_mac && (bcast_addr != 0)) {
314 + for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
315 + if ((ifa->ifa_addr->sa_family == PF_PACKET) &&
316 + (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) == 0)) {
317 + sdl = (struct sockaddr *)(ifa->ifa_addr);
318 + ptr = (unsigned char *)sdl->sa_data;
319 + memcpy(mac, ptr + 10, 6);
328 + LOG_INFO("Interface: %s, broadcast: %08X, macaddr = %02x:%02x:%02x:%02x:%02x:%02x",
329 + ifname, bcast_addr, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
337 #pragma comment(lib, "IPHLPAPI.lib")
338 void get_mac(u8_t mac[]) {