Commit based upon d6442850bde61f0c3e7e2ae3247b4a856073c5e0
[librecmc/package-feed.git] / sound / squeezelite / patches / 010-select_broadcast_interface.patch
1 --- a/main.c
2 +++ b/main.c
3 @@ -78,6 +78,7 @@ static void usage(const char *argv0) {
4  #if IR
5                    "  -i [<filename>]\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n"
6  #endif
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 @@ -233,6 +234,8 @@ int main(int argc, char **argv) {
12         extern bool pcm_check_header;
13         char *logfile = NULL;
14         u8_t mac[6];
15 +       char *iface = 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 @@ -271,6 +274,7 @@ int main(int argc, char **argv) {
21  
22         int maxSampleRate = 0;
23  
24 +       memset(mac, 0, sizeof(mac));
25         char *optarg = NULL;
26         int optind = 1;
27         int i;
28 @@ -278,8 +282,6 @@ int main(int argc, char **argv) {
29  #define MAXCMDLINE 512
30         char cmdline[MAXCMDLINE] = "";
31  
32 -       get_mac(mac);
33 -
34         for (i = 0; i < argc && (strlen(argv[i]) + strlen(cmdline) + 2 < MAXCMDLINE); i++) {
35                 strcat(cmdline, argv[i]);
36                 strcat(cmdline, " ");
37 @@ -287,7 +289,7 @@ int main(int argc, char **argv) {
38  
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"
43  #if ALSA
44                                    "UV"
45  #endif
46 @@ -382,6 +384,9 @@ int main(int argc, char **argv) {
47                 case 'f':
48                         logfile = optarg;
49                         break;
50 +               case 'I':
51 +                       iface = optarg;
52 +                       break;
53                 case 'm':
54                         {
55                                 int byte = 0;
56 @@ -667,6 +672,11 @@ int main(int argc, char **argv) {
57         winsock_init();
58  #endif
59  
60 +       if (!(bcast_addr = get_iface_info(log_slimproto, iface, mac))) {
61 +               fprintf(stderr, "Error binding to network or none given\n");
62 +               exit(1);
63 +       }
64 +
65         stream_init(log_stream, stream_buf_size);
66  
67         if (!strcmp(output_device, "-")) {
68 @@ -710,7 +720,7 @@ int main(int argc, char **argv) {
69                 exit(1);
70         }
71  
72 -       slimproto(log_slimproto, server, mac, name, namefile, modelname, maxSampleRate);
73 +       slimproto(log_slimproto, server, bcast_addr, mac, name, namefile, modelname, maxSampleRate);
74  
75         decode_close();
76         stream_close();
77 --- a/squeezelite.h
78 +++ b/squeezelite.h
79 @@ -403,7 +403,7 @@ typedef enum { EVENT_TIMEOUT = 0, EVENT_
80  
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 @@ -459,7 +459,7 @@ void buf_init(struct buffer *buf, size_t
89  void buf_destroy(struct buffer *buf);
90  
91  // slimproto.c
92 -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate);
93 +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);
94  void slimproto_stop(void);
95  void wake_controller(void);
96  
97 --- a/slimproto.c
98 +++ b/slimproto.c
99 @@ -119,7 +119,7 @@ void send_packet(u8_t *packet, size_t le
100         }
101  }
102  
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;
107  
108 @@ -782,7 +782,7 @@ void wake_controller(void) {
109         wake_signal(wake_e);
110  }
111  
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;
116         char *buf;
117 @@ -798,7 +798,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;
123  
124         pollinfo.fd = disc_sock;
125         pollinfo.events = POLLIN;
126 @@ -829,7 +829,7 @@ in_addr_t discover_server(void) {
127  #define FIXED_CAP_LEN 256
128  #define VAR_CAP_LEN   128
129  
130 -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate) {
131 +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) {
132         struct sockaddr_in serv_addr;
133         static char fixed_cap[FIXED_CAP_LEN], var_cap[VAR_CAP_LEN] = "";
134         bool reconnect = false;
135 @@ -849,7 +849,7 @@ void slimproto(log_level level, char *se
136         }
137  
138         if (!slimproto_ip) {
139 -               slimproto_ip = discover_server();
140 +               slimproto_ip = discover_server(bcast_addr);
141         }
142  
143         if (!slimproto_port) {
144 @@ -924,7 +924,7 @@ void slimproto(log_level level, char *se
145  
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);
150                         }
151  
152                 } else {
153 --- a/utils.c
154 +++ b/utils.c
155 @@ -22,11 +22,11 @@
156  #include "squeezelite.h"
157  
158  #if LINUX || OSX || FREEBSD
159 -#include <sys/ioctl.h>
160 +#include <sys/types.h>
161  #include <net/if.h>
162 -#include <netdb.h>
163 -#if FREEBSD
164  #include <ifaddrs.h>
165 +#include <netdb.h>
166 +#if FREEBSD || OSX
167  #include <net/if_dl.h>
168  #include <net/if_types.h>
169  #endif
170 @@ -44,15 +44,11 @@
171  #if WIN
172  #include <iphlpapi.h>
173  #endif
174 -#if OSX
175 -#include <net/if_dl.h>
176 -#include <net/if_types.h>
177 -#include <ifaddrs.h>
178 -#include <netdb.h>
179 -#endif
180  
181  #include <fcntl.h>
182  
183 +static log_level loglevel;
184 +
185  // logging functions
186  const char *logtime(void) {
187         static char buf[100];
188 @@ -114,58 +110,101 @@ u32_t gettime_ms(void) {
189  #endif
190  }
191  
192 -// mac address
193 -#if LINUX && !defined(SUN)
194 -// search first 4 interfaces returned by IFCONF
195 -void get_mac(u8_t mac[]) {
196 -       char *utmac;
197 -       struct ifconf ifc;
198 -       struct ifreq *ifr, *ifend;
199 -       struct ifreq ifreq;
200 -       struct ifreq ifs[4];
201 +// Get broadcast address for interface (given or first available)
202 +// Return MAC address if none given
203 +#if LINUX || OSX || FREEBSD
204  
205 -       utmac = getenv("UTMAC");
206 -       if (utmac)
207 -       {
208 -               if ( strlen(utmac) == 17 )
209 -               {
210 -                       if (sscanf(utmac,"%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
211 -                               &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) == 6)
212 -                       {
213 -                               return;
214 -                       }
215 -               }
216 +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac) {
217 +       struct ifaddrs *addrs, *ifa;
218 +       struct sockaddr *sdl;
219 +       char ifname[16];
220 +       unsigned char *ptr;
221 +       in_addr_t bcast_addr = 0;
222 +       int have_mac = 0, have_ifname = 0;
223 +
224 +       loglevel = level;
225 +
226 +       // Check for non-zero MAC
227 +       if ((mac[0] | mac[1] | mac[2]) != 0)
228 +               have_mac = 1;
229 +
230 +        // Copy interface name, if it was provided.
231 +        if (iface != NULL)
232 +        {
233 +                if( strlen(iface) > sizeof(ifname) )
234 +                        return -1;
235  
236 +                strncpy(ifname, iface, sizeof(ifname));
237 +                have_ifname = 1;
238         }
239  
240 -       mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
241 +       if (getifaddrs(&addrs) == 0) {
242 +               //iterate to find corresponding ethernet address
243 +               for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
244 +                       // Skip LOOPBACK interfaces, DOWN interfaces and interfaces that
245 +                       // don't support BROADCAST.
246 +                       if ((ifa->ifa_flags & IFF_LOOPBACK)
247 +                                || !(ifa->ifa_flags & IFF_UP)
248 +                                || !(ifa->ifa_flags & IFF_BROADCAST))
249 +                       {
250 +                               continue;
251 +                       }
252  
253 -       int s = socket(AF_INET, SOCK_DGRAM, 0);
254 +                       if (!have_ifname)
255 +                       {
256 +                               // We have found a valid interface name. Keep it.
257 +                               strncpy(ifname, ifa->ifa_name, sizeof(ifname));
258 +                               have_ifname = 1;
259 +                       } else {
260 +                               if (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) != 0)
261 +                               {
262 +                                       // This is not the interface we're looking for.
263 +                                       continue;
264 +                               }
265 +                       }
266  
267 -       ifc.ifc_len = sizeof(ifs);
268 -       ifc.ifc_req = ifs;
269  
270 -       if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
271 -               ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
272 +                       // Check address family.
273 +                       if ((ifa->ifa_addr->sa_family == AF_INET) &&
274 +                           (((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr != 0))
275 +                       {
276 +                               // Get broadcast address and MAC address
277 +                               bcast_addr = ((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr;
278 +                               break;
279 +                       }
280 +                       else
281 +                       {
282 +                               // Address is not IPv4
283 +                               if (iface == NULL)
284 +                                       have_ifname = 0;
285 +                       }
286 +
287 +               }
288  
289 -               for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
290 -                       if (ifr->ifr_addr.sa_family == AF_INET) {
291 -
292 -                               strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
293 -                               if (ioctl (s, SIOCGIFHWADDR, &ifreq) == 0) {
294 -                                       memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6);
295 -                                       if (mac[0]+mac[1]+mac[2] != 0) {
296 -                                               break;
297 -                                       }
298 +               // Find MAC address matching interface
299 +               if (!have_mac && (bcast_addr != 0)) {
300 +                       for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
301 +                               if ((ifa->ifa_addr->sa_family == PF_PACKET) &&
302 +                                   (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) == 0)) {
303 +                                       sdl = (struct sockaddr *)(ifa->ifa_addr);
304 +                                       ptr = (unsigned char *)sdl->sa_data;
305 +                                       memcpy(mac, ptr + 10, 6);
306 +                                       have_mac = 1;
307                                 }
308                         }
309                 }
310 +
311 +               freeifaddrs(addrs);
312         }
313  
314 -       close(s);
315 +       LOG_INFO("Interface: %s, broadcast: %08X, macaddr = %02x:%02x:%02x:%02x:%02x:%02x",
316 +                ifname, bcast_addr, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
317 +
318 +       return bcast_addr;
319  }
320  #endif
321  
322 +
323  #if SUN
324  void get_mac(u8_t mac[]) {
325         struct  arpreq          parpreq;
326 @@ -232,30 +271,6 @@ void get_mac(u8_t mac[]) {
327  }
328  #endif
329  
330 -#if OSX || FREEBSD
331 -void get_mac(u8_t mac[]) {
332 -       struct ifaddrs *addrs, *ptr;
333 -       const struct sockaddr_dl *dlAddr;
334 -       const unsigned char *base;
335 -       
336 -       mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
337 -       
338 -       if (getifaddrs(&addrs) == 0) {
339 -               ptr = addrs;
340 -               while (ptr) {
341 -                       if (ptr->ifa_addr->sa_family == AF_LINK && ((const struct sockaddr_dl *) ptr->ifa_addr)->sdl_type == IFT_ETHER) {
342 -                               dlAddr = (const struct sockaddr_dl *)ptr->ifa_addr;
343 -                               base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
344 -                               memcpy(mac, base, min(dlAddr->sdl_alen, 6));
345 -                               break;
346 -                       }
347 -                       ptr = ptr->ifa_next;
348 -               }
349 -               freeifaddrs(addrs);
350 -       }
351 -}
352 -#endif
353 -
354  #if WIN
355  #pragma comment(lib, "IPHLPAPI.lib")
356  void get_mac(u8_t mac[]) {