From 7be55fb636d4694f94bbef43cb8275b85619bac1 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Tue, 24 Mar 2020 17:10:19 -0400 Subject: [PATCH] network scan : add network scan Now that we are getting all the DNS SD possible iiod hosts, return them as part of the scan context. This enables 'iio_info -s' to return IP and USB contexts. Signed-off-by: Robin Getz --- dns_sd.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++ iio-private.h | 6 +++ scan.c | 22 +++++++++ 3 files changed, 151 insertions(+) diff --git a/dns_sd.c b/dns_sd.c index 387e60d84..326030bf5 100644 --- a/dns_sd.c +++ b/dns_sd.c @@ -59,6 +59,93 @@ static void dnssd_remove_node(struct dns_sd_discovery_data **ddata, int n) *ddata = d; } +/* The only way to support scan context from the network is when + * DNS Service Discovery is turned on + */ + +struct iio_scan_backend_context { + struct addrinfo *res; +}; + +static int dnssd_fill_context_info(struct iio_context_info *info, + char *hostname, char *addr_str, int port) +{ + struct iio_context *ctx; + char uri[MAXHOSTNAMELEN + 3]; + char description[255], *p; + const char *hw_model, *serial; + int i; + + ctx = network_create_context(addr_str); + if (!ctx) { + ERROR("No context at %s\n", addr_str); + return -ENOMEM; + } + + if (port == IIOD_PORT) + sprintf(uri, "ip:%s", hostname); + else + sprintf(uri, "ip:%s:%d", hostname, port); + + hw_model = iio_context_get_attr_value(ctx, "hw_model"); + serial = iio_context_get_attr_value(ctx, "hw_serial"); + + if (hw_model && serial) { + snprintf(description, sizeof(description), "%s (%s), serial=%s", + addr_str, hw_model, serial); + } else if (hw_model) { + snprintf(description, sizeof(description), "%s %s", addr_str, hw_model); + } else if (serial) { + snprintf(description, sizeof(description), "%s %s", addr_str, serial); + } else if (ctx->nb_devices == 0) { + snprintf(description, sizeof(description), "%s", ctx->description); + } else { + snprintf(description, sizeof(description), "%s (", addr_str); + p = description + strlen(description); + for (i = 0; i < ctx->nb_devices - 1; i++) { + if (ctx->devices[i]->name) { + snprintf(p, sizeof(description) - strlen(description) -1, + "%s,", ctx->devices[i]->name); + p += strlen(p); + } + } + p--; + *p = ')'; + } + + iio_context_destroy(ctx); + + info->uri = iio_strdup(uri); + if (!info->uri) + return -ENOMEM; + + info->description = iio_strdup(description); + if (!info->description) { + free(info->uri); + return -ENOMEM; + } + + return 0; +} + +struct iio_scan_backend_context * dnssd_context_scan_init(void) +{ + struct iio_scan_backend_context *ctx; + + ctx = malloc(sizeof(*ctx)); + if (!ctx) { + errno = ENOMEM; + return NULL; + } + + return ctx; +} + +void dnssd_context_scan_free(struct iio_scan_backend_context *ctx) +{ + free(ctx); +} + /* * remove the ones in the list that you can't connect to * This is sort of silly, but we have seen non-iio devices advertised @@ -147,6 +234,42 @@ void remove_dup_discovery_data(struct dns_sd_discovery_data **ddata) *ddata = d; } +int dnssd_context_scan(struct iio_scan_backend_context *ctx, + struct iio_scan_result *scan_result) +{ + struct iio_context_info **info; + struct dns_sd_discovery_data *ddata, *ndata; + int ret = 0; + + ret = dnssd_find_hosts(&ddata); + + /* if we return an error when no devices are found, then other scans will fail */ + if (ret == -ENXIO) + return 0; + + if (ret < 0) + return ret; + + for (ndata = ddata; ndata->next != NULL; ndata = ndata->next) { + info = iio_scan_result_add(scan_result, 1); + if (!info) { + ERROR("Out of memory when adding new scan result\n"); + ret = -ENOMEM; + break; + } + + ret = dnssd_fill_context_info(*info, + ndata->hostname, ndata->addr_str,ndata->port); + if (ret < 0) { + DEBUG("Failed to add %s (%s) err: %d\n", ndata->hostname, ndata->addr_str, ret); + break; + } + } + + dnssd_free_all_discovery_data(ddata); + return ret; +} + int dnssd_discover_host(char *addr_str, size_t addr_len, uint16_t *port) { struct dns_sd_discovery_data *ddata; diff --git a/iio-private.h b/iio-private.h index 685c29022..7077bbae6 100644 --- a/iio-private.h +++ b/iio-private.h @@ -275,6 +275,12 @@ void usb_context_scan_free(struct iio_scan_backend_context *ctx); int usb_context_scan(struct iio_scan_backend_context *ctx, struct iio_scan_result *scan_result); +struct iio_scan_backend_context * dnssd_context_scan_init(void); +void dnssd_context_scan_free(struct iio_scan_backend_context *ctx); + +int dnssd_context_scan(struct iio_scan_backend_context *ctx, + struct iio_scan_result *scan_result); + /* This function is not part of the API, but is used by the IIO daemon */ __api ssize_t iio_device_get_sample_size_mask(const struct iio_device *dev, const uint32_t *mask, size_t words); diff --git a/scan.c b/scan.c index dc1be04f6..6f56e4587 100644 --- a/scan.c +++ b/scan.c @@ -25,6 +25,9 @@ struct iio_scan_context { #ifdef WITH_USB_BACKEND struct iio_scan_backend_context *usb_ctx; +#endif +#ifdef HAVE_DNS_SD + struct iio_scan_backend_context *dnssd_ctx; #endif bool scan_local; }; @@ -68,6 +71,17 @@ ssize_t iio_scan_context_get_info_list(struct iio_scan_context *ctx, } #endif +#ifdef HAVE_DNS_SD + if (ctx->dnssd_ctx) { + int ret = dnssd_context_scan(ctx->dnssd_ctx, &scan_result); + if (ret < 0) { + if (scan_result.info) + iio_context_info_list_free(scan_result.info); + return ret; + } + } +#endif + *info = scan_result.info; return (ssize_t) scan_result.size; @@ -146,6 +160,10 @@ struct iio_scan_context * iio_create_scan_context( if (!backend || !strcmp(backend, "usb")) ctx->usb_ctx = usb_context_scan_init(); #endif +#ifdef HAVE_DNS_SD + if (!backend || !strcmp(backend, "ip")) + ctx->dnssd_ctx = dnssd_context_scan_init(); +#endif return ctx; } @@ -155,6 +173,10 @@ void iio_scan_context_destroy(struct iio_scan_context *ctx) #ifdef WITH_USB_BACKEND if (ctx->usb_ctx) usb_context_scan_free(ctx->usb_ctx); +#endif +#ifdef HAVE_DNS_SD + if (ctx->dnssd_ctx) + dnssd_context_scan_free(ctx->dnssd_ctx); #endif free(ctx); }