diff --git a/lib/src/discovery.c b/lib/src/discovery.c index ad93814..9199554 100644 --- a/lib/src/discovery.c +++ b/lib/src/discovery.c @@ -163,6 +163,13 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery, if(r < 0) CHIAKI_LOGE(discovery->log, "Discovery failed to setsockopt SO_BROADCAST"); +//#ifdef __FreeBSD__ +// const int onesbcast = 1; +// r = setsockopt(discovery->socket, IPPROTO_IP, IP_ONESBCAST, &onesbcast, sizeof(onesbcast)); +// if(r < 0) +// CHIAKI_LOGE(discovery->log, "Discovery failed to setsockopt IP_ONESBCAST"); +//#endif + return CHIAKI_ERR_SUCCESS; } @@ -183,7 +190,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_send(ChiakiDiscovery *discovery, if((size_t)len >= sizeof(buf)) return CHIAKI_ERR_BUF_TOO_SMALL; - int rc = sendto(discovery->socket, buf, (size_t)len + 1, 0, addr, addr_size); + int rc = sendto_broadcast(discovery->log, discovery->socket, buf, (size_t)len + 1, 0, addr, addr_size); if(rc < 0) { CHIAKI_LOGE(discovery->log, "Discovery failed to send: %s", strerror(errno)); diff --git a/lib/src/regist.c b/lib/src/regist.c index 3fa6114..8c43df3 100644 --- a/lib/src/regist.c +++ b/lib/src/regist.c @@ -276,7 +276,7 @@ static ChiakiErrorCode regist_search(ChiakiRegist *regist, struct addrinfo *addr ChiakiErrorCode err = CHIAKI_ERR_SUCCESS; CHIAKI_LOGI(regist->log, "Regist sending search packet"); - int r = sendto(sock, "SRC2", 4, 0, &send_addr, send_addr_len); + int r = sendto_broadcast(regist->log, sock, "SRC2", 4, 0, &send_addr, send_addr_len); if(r < 0) { CHIAKI_LOGE(regist->log, "Regist failed to send search: %s", strerror(errno)); diff --git a/lib/src/utils.h b/lib/src/utils.h index a4bbfc1..a88208f 100644 --- a/lib/src/utils.h +++ b/lib/src/utils.h @@ -19,6 +19,7 @@ #define CHIAKI_UTILS_H #include +#include #ifdef _WIN32 #include #else @@ -27,6 +28,13 @@ #include #endif +#ifdef __FreeBSD__ +#include +#include +#include +#include +#endif + #include static inline ChiakiErrorCode set_port(struct sockaddr *sa, uint16_t port) @@ -60,6 +68,46 @@ static inline const char *sockaddr_str(struct sockaddr *addr, char *addr_buf, si return NULL; } +static inline int sendto_broadcast(ChiakiLog *log, chiaki_socket_t s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) +{ +#ifdef __FreeBSD__ + // see https://wiki.freebsd.org/NetworkRFCCompliance + if(to->sa_family == AF_INET && ((const struct sockaddr_in *)to)->sin_addr.s_addr == htonl(INADDR_BROADCAST)) + { + struct ifaddrs *ifap; + if(getifaddrs(&ifap) < 0) + { + CHIAKI_LOGE(log, "Failed to getifaddrs for Broadcast: %s", strerror(errno)); + return -1; + } + int r = -1; + for(struct ifaddrs *a=ifap; a; a=a->ifa_next) + { + if(!a->ifa_broadaddr) + continue; + if(!(a->ifa_flags & IFF_BROADCAST)) + continue; + if(a->ifa_broadaddr->sa_family != to->sa_family) + continue; + ((struct sockaddr_in *)a->ifa_broadaddr)->sin_port = ((const struct sockaddr_in *)to)->sin_port; + char addr_buf[64]; + const char *addr_str = sockaddr_str(a->ifa_broadaddr, addr_buf, sizeof(addr_buf)); + CHIAKI_LOGV(log, "Broadcast to %s on %s", addr_str ? addr_str : "(null)", a->ifa_name); + int sr = sendto(s, msg, len, flags, a->ifa_broadaddr, sizeof(*a->ifa_broadaddr)); + if(sr < 0) + { + CHIAKI_LOGE(log, "Broadcast on iface %s failed: %s", a->ifa_name, strerror(errno)); + continue; + } + r = sr; + } + freeifaddrs(ifap); + return r; + } +#endif + return sendto(s, msg, len, flags, to, tolen); +} + static inline void xor_bytes(uint8_t *dst, uint8_t *src, size_t sz) { while(sz > 0)