mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
add zone_id to link-local ipv6 addresses
This commit is contained in:
15
lib/httpd.c
15
lib/httpd.c
@@ -115,7 +115,8 @@ httpd_remove_connection(httpd_t *httpd, http_connection_t *connection)
|
||||
}
|
||||
|
||||
static int
|
||||
httpd_add_connection(httpd_t *httpd, int fd, unsigned char *local, int local_len, unsigned char *remote, int remote_len)
|
||||
httpd_add_connection(httpd_t *httpd, int fd, unsigned char *local, int local_len, unsigned char *remote,
|
||||
int remote_len, unsigned int zone_id)
|
||||
{
|
||||
void *user_data;
|
||||
int i;
|
||||
@@ -131,7 +132,7 @@ httpd_add_connection(httpd_t *httpd, int fd, unsigned char *local, int local_len
|
||||
return -1;
|
||||
}
|
||||
|
||||
user_data = httpd->callbacks.conn_init(httpd->callbacks.opaque, local, local_len, remote, remote_len);
|
||||
user_data = httpd->callbacks.conn_init(httpd->callbacks.opaque, local, local_len, remote, remote_len, zone_id);
|
||||
if (!user_data) {
|
||||
logger_log(httpd->logger, LOGGER_ERR, "Error initializing HTTP request handler");
|
||||
return -1;
|
||||
@@ -152,6 +153,7 @@ httpd_accept_connection(httpd_t *httpd, int server_fd, int is_ipv6)
|
||||
struct sockaddr_storage local_saddr;
|
||||
socklen_t local_saddrlen;
|
||||
unsigned char *local, *remote;
|
||||
unsigned int local_zone_id, remote_zone_id;
|
||||
int local_len, remote_len;
|
||||
int ret, fd;
|
||||
|
||||
@@ -172,9 +174,10 @@ httpd_accept_connection(httpd_t *httpd, int server_fd, int is_ipv6)
|
||||
|
||||
logger_log(httpd->logger, LOGGER_INFO, "Accepted %s client on socket %d",
|
||||
(is_ipv6 ? "IPv6" : "IPv4"), fd);
|
||||
local = netutils_get_address(&local_saddr, &local_len);
|
||||
remote = netutils_get_address(&remote_saddr, &remote_len);
|
||||
|
||||
local = netutils_get_address(&local_saddr, &local_len, &local_zone_id);
|
||||
remote = netutils_get_address(&remote_saddr, &remote_len, &remote_zone_id);
|
||||
assert (local_zone_id == remote_zone_id);
|
||||
|
||||
#ifdef NOHOLD
|
||||
/* remove existing connections to make way for new connections:
|
||||
* this will only occur if max_connections > 2 */
|
||||
@@ -190,7 +193,7 @@ httpd_accept_connection(httpd_t *httpd, int server_fd, int is_ipv6)
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = httpd_add_connection(httpd, fd, local, local_len, remote, remote_len);
|
||||
ret = httpd_add_connection(httpd, fd, local, local_len, remote, remote_len, local_zone_id);
|
||||
if (ret == -1) {
|
||||
shutdown(fd, SHUT_RDWR);
|
||||
closesocket(fd);
|
||||
|
||||
@@ -23,7 +23,8 @@ typedef struct httpd_s httpd_t;
|
||||
|
||||
struct httpd_callbacks_s {
|
||||
void* opaque;
|
||||
void* (*conn_init)(void *opaque, unsigned char *local, int locallen, unsigned char *remote, int remotelen);
|
||||
void* (*conn_init)(void *opaque, unsigned char *local, int locallen, unsigned char *remote,
|
||||
int remotelen, unsigned int zone_id);
|
||||
void (*conn_request)(void *ptr, http_request_t *request, http_response_t **response);
|
||||
void (*conn_destroy)(void *ptr);
|
||||
};
|
||||
|
||||
@@ -53,17 +53,17 @@ netutils_cleanup()
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
netutils_get_address(void *sockaddr, int *length)
|
||||
netutils_get_address(void *sockaddr, int *length, unsigned int *zone_id)
|
||||
{
|
||||
unsigned char ipv4_prefix[] = { 0,0,0,0,0,0,0,0,0,0,255,255 };
|
||||
struct sockaddr *address = sockaddr;
|
||||
|
||||
assert(address);
|
||||
assert(length);
|
||||
|
||||
assert(zone_id);
|
||||
if (address->sa_family == AF_INET) {
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
*zone_id = 0;
|
||||
sin = (struct sockaddr_in *)address;
|
||||
*length = sizeof(sin->sin_addr.s_addr);
|
||||
return (unsigned char *)&sin->sin_addr.s_addr;
|
||||
@@ -73,9 +73,11 @@ netutils_get_address(void *sockaddr, int *length)
|
||||
sin6 = (struct sockaddr_in6 *)address;
|
||||
if (!memcmp(sin6->sin6_addr.s6_addr, ipv4_prefix, 12)) {
|
||||
/* Actually an embedded IPv4 address */
|
||||
*zone_id = 0;
|
||||
*length = sizeof(sin6->sin6_addr.s6_addr)-12;
|
||||
return (sin6->sin6_addr.s6_addr+12);
|
||||
}
|
||||
*zone_id = (unsigned int) sin6->sin6_scope_id;
|
||||
*length = sizeof(sin6->sin6_addr.s6_addr);
|
||||
return sin6->sin6_addr.s6_addr;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ int netutils_init();
|
||||
void netutils_cleanup();
|
||||
|
||||
int netutils_init_socket(unsigned short *port, int use_ipv6, int use_udp);
|
||||
unsigned char *netutils_get_address(void *sockaddr, int *length);
|
||||
unsigned char *netutils_get_address(void *sockaddr, int *length, unsigned int *zone_id);
|
||||
int netutils_parse_address(int family, const char *src, void *dst, int dstlen);
|
||||
|
||||
#endif
|
||||
|
||||
35
lib/raop.c
35
lib/raop.c
@@ -88,6 +88,8 @@ struct raop_conn_s {
|
||||
unsigned char *remote;
|
||||
int remotelen;
|
||||
|
||||
unsigned int zone_id;
|
||||
|
||||
bool have_active_remote;
|
||||
};
|
||||
typedef struct raop_conn_s raop_conn_t;
|
||||
@@ -95,10 +97,10 @@ typedef struct raop_conn_s raop_conn_t;
|
||||
#include "raop_handlers.h"
|
||||
|
||||
static void *
|
||||
conn_init(void *opaque, unsigned char *local, int locallen, unsigned char *remote, int remotelen) {
|
||||
conn_init(void *opaque, unsigned char *local, int locallen, unsigned char *remote, int remotelen, unsigned int zone_id) {
|
||||
raop_t *raop = opaque;
|
||||
raop_conn_t *conn;
|
||||
|
||||
char ip_address[40];
|
||||
assert(raop);
|
||||
|
||||
conn = calloc(1, sizeof(raop_conn_t));
|
||||
@@ -122,26 +124,12 @@ conn_init(void *opaque, unsigned char *local, int locallen, unsigned char *remot
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (locallen == 4) {
|
||||
logger_log(conn->raop->logger, LOGGER_INFO,
|
||||
"Local: %d.%d.%d.%d",
|
||||
local[0], local[1], local[2], local[3]);
|
||||
} else if (locallen == 16) {
|
||||
logger_log(conn->raop->logger, LOGGER_INFO,
|
||||
"Local: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
local[0], local[1], local[2], local[3], local[4], local[5], local[6], local[7],
|
||||
local[8], local[9], local[10], local[11], local[12], local[13], local[14], local[15]);
|
||||
}
|
||||
if (remotelen == 4) {
|
||||
logger_log(conn->raop->logger, LOGGER_INFO,
|
||||
"Remote: %d.%d.%d.%d",
|
||||
remote[0], remote[1], remote[2], remote[3]);
|
||||
} else if (remotelen == 16) {
|
||||
logger_log(conn->raop->logger, LOGGER_INFO,
|
||||
"Remote: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
remote[0], remote[1], remote[2], remote[3], remote[4], remote[5], remote[6], remote[7],
|
||||
remote[8], remote[9], remote[10], remote[11], remote[12], remote[13], remote[14], remote[15]);
|
||||
}
|
||||
|
||||
utils_ipaddress_to_string(locallen, local, zone_id, ip_address, (int) sizeof(ip_address));
|
||||
logger_log(conn->raop->logger, LOGGER_INFO, "Local : %s", ip_address);
|
||||
|
||||
utils_ipaddress_to_string(remotelen, remote, zone_id, ip_address, (int) sizeof(ip_address));
|
||||
logger_log(conn->raop->logger, LOGGER_INFO, "Remote: %s", ip_address);
|
||||
|
||||
conn->local = malloc(locallen);
|
||||
assert(conn->local);
|
||||
@@ -151,8 +139,11 @@ conn_init(void *opaque, unsigned char *local, int locallen, unsigned char *remot
|
||||
assert(conn->remote);
|
||||
memcpy(conn->remote, remote, remotelen);
|
||||
|
||||
conn->zone_id = zone_id;
|
||||
|
||||
conn->locallen = locallen;
|
||||
conn->remotelen = remotelen;
|
||||
|
||||
conn->have_active_remote = false;
|
||||
|
||||
if (raop->callbacks.conn_init) {
|
||||
|
||||
@@ -65,8 +65,8 @@ struct raop_callbacks_s {
|
||||
void (*export_dacp) (void *cls, const char *active_remote, const char *dacp_id);
|
||||
};
|
||||
typedef struct raop_callbacks_s raop_callbacks_t;
|
||||
raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote, int remote_addr_len,
|
||||
unsigned short timing_rport, timing_protocol_t *time_protocol);
|
||||
raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote,
|
||||
int remote_addr_len, unsigned short timing_rport, timing_protocol_t *time_protocol);
|
||||
|
||||
RAOP_API raop_t *raop_init(raop_callbacks_t *callbacks);
|
||||
RAOP_API int raop_init2(raop_t *raop, int max_clients, const char *device_id, const char *keyfile);
|
||||
|
||||
@@ -737,28 +737,23 @@ raop_handler_setup(raop_conn_t *conn,
|
||||
conn->raop_ntp = NULL;
|
||||
conn->raop_rtp = NULL;
|
||||
conn->raop_rtp_mirror = NULL;
|
||||
if (conn->remotelen == 4 || conn->remotelen == 16) {
|
||||
char remote[40];
|
||||
if (conn->remotelen == 4) {
|
||||
/* IPV4 */
|
||||
snprintf(remote, sizeof(remote), "%d.%d.%d.%d", conn->remote[0], conn->remote[1],
|
||||
conn->remote[2], conn->remote[3]);
|
||||
} else {
|
||||
/*IPV6*/
|
||||
snprintf(remote, sizeof(remote), "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
conn->remote[0], conn->remote[1], conn->remote[2], conn->remote[3],
|
||||
conn->remote[4], conn->remote[5], conn->remote[6], conn->remote[7],
|
||||
conn->remote[8], conn->remote[9], conn->remote[10], conn->remote[11],
|
||||
conn->remote[12], conn->remote[13], conn->remote[14], conn->remote[15]);
|
||||
}
|
||||
conn->raop_ntp = raop_ntp_init(conn->raop->logger, &conn->raop->callbacks, remote,
|
||||
conn->remotelen, (unsigned short) timing_rport, &time_protocol);
|
||||
raop_ntp_start(conn->raop_ntp, &timing_lport, conn->raop->max_ntp_timeouts);
|
||||
conn->raop_rtp = raop_rtp_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp,
|
||||
remote, conn->remotelen, aeskey, aesiv);
|
||||
conn->raop_rtp_mirror = raop_rtp_mirror_init(conn->raop->logger, &conn->raop->callbacks,
|
||||
conn->raop_ntp, remote, conn->remotelen, aeskey);
|
||||
char remote[40];
|
||||
int len = utils_ipaddress_to_string(conn->remotelen, conn->remote, conn->zone_id, remote, (int) sizeof(remote));
|
||||
if (!len || len > sizeof(remote)) {
|
||||
char *str = utils_data_to_string(conn->remote, conn->remotelen, 16);
|
||||
logger_log(conn->raop->logger, LOGGER_ERR, "failed to extract valid client ip address:\n"
|
||||
"*** UxPlay will be unable to send communications to client.\n"
|
||||
"*** address length %d, zone_id %u address data:\n%sparser returned \"%s\"\n",
|
||||
conn->remotelen, conn->zone_id, str, remote);
|
||||
free(str);
|
||||
}
|
||||
conn->raop_ntp = raop_ntp_init(conn->raop->logger, &conn->raop->callbacks, remote,
|
||||
conn->remotelen, (unsigned short) timing_rport, &time_protocol);
|
||||
raop_ntp_start(conn->raop_ntp, &timing_lport, conn->raop->max_ntp_timeouts);
|
||||
conn->raop_rtp = raop_rtp_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp,
|
||||
remote, conn->remotelen, aeskey, aesiv);
|
||||
conn->raop_rtp_mirror = raop_rtp_mirror_init(conn->raop->logger, &conn->raop->callbacks,
|
||||
conn->raop_ntp, remote, conn->remotelen, aeskey);
|
||||
|
||||
plist_t res_event_port_node = plist_new_uint(conn->raop->port);
|
||||
plist_t res_timing_port_node = plist_new_uint(timing_lport);
|
||||
|
||||
26
lib/utils.c
26
lib/utils.c
@@ -256,3 +256,29 @@ void ntp_timestamp_to_seconds(uint64_t ntp_timestamp, char *timestamp, size_t ma
|
||||
strftime(timestamp, 3, "%S", &ts);
|
||||
snprintf(timestamp + 2, 11,".%9.9lu", (unsigned long) ntp_timestamp % SECOND_IN_NSECS);
|
||||
}
|
||||
|
||||
int utils_ipaddress_to_string(int addresslen, const unsigned char *address, unsigned int zone_id, char *string, int sizeof_string) {
|
||||
int ret = 0;
|
||||
unsigned char ipv6_link_local_prefix[] = { 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
|
||||
assert(sizeof_string > 0);
|
||||
assert(string);
|
||||
if (addresslen != 4 && addresslen != 16) { //invalid address length (only ipv4 and ipv6 allowed)
|
||||
string[0] = '\0';
|
||||
}
|
||||
if (addresslen == 4) { /* IPV4 */
|
||||
ret = snprintf(string, sizeof_string, "%d.%d.%d.%d", address[0], address[1], address[2], address[3]);
|
||||
} else if (zone_id) { /* IPV6 link-local */
|
||||
if (memcmp(address, ipv6_link_local_prefix, 8)) {
|
||||
string[0] = '\0'; //only link-local ipv6 addresses can have a zone_id
|
||||
} else {
|
||||
ret = snprintf(string, sizeof_string, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x%%%u",
|
||||
address[8], address[9], address[10], address[11],
|
||||
address[12], address[13], address[14], address[15], zone_id);
|
||||
}
|
||||
} else { /* IPV6 standard*/
|
||||
ret = snprintf(string, sizeof_string, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
address[0], address[1], address[2], address[3], address[4], address[5], address[6], address[7],
|
||||
address[8], address[9], address[10], address[11], address[12], address[13], address[14], address[15]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -30,5 +30,6 @@ char *utils_data_to_string(const unsigned char *data, int datalen, int chars_per
|
||||
char *utils_data_to_text(const char *data, int datalen);
|
||||
void ntp_timestamp_to_time(uint64_t ntp_timestamp, char *timestamp, size_t maxsize);
|
||||
void ntp_timestamp_to_seconds(uint64_t ntp_timestamp, char *timestamp, size_t maxsize);
|
||||
|
||||
int utils_ipaddress_to_string(int addresslen, const unsigned char *address,
|
||||
unsigned int zone_id, char *string, int len);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user