aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md11
-rw-r--r--pacredir.c94
-rw-r--r--pacredir.h24
3 files changed, 96 insertions, 33 deletions
diff --git a/README.md b/README.md
index 6f27df9..182866e 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ downloads its package files from online mirrors, transferring all the
bits via WAN connection.
But often other Arch systems may be around that already have the files
-available on local storage - just a fast LAN connection way. This is
+available on local storage - just a fast LAN connection away. This is
where `pacredir` can help. It uses [Avahi](http://avahi.org/) to find
other instances and get the files there if available.
@@ -23,7 +23,6 @@ To compile and run `pacredir` you need:
* [curl](http://curl.haxx.se/)
* [iniparser](http://ndevilla.free.fr/iniparser/)
* [darkhttpd](http://dmr.ath.cx/net/darkhttpd/)
-* [nss-mdns](http://0pointer.de/lennart/projects/nss-mdns/)
* [markdown](http://daringfireball.net/projects/markdown/) (HTML documentation)
`Arch Linux` installs development files for the packages by default, so
@@ -49,11 +48,9 @@ Additionally systemd service files are installed to
Usage
-----
-Make sure [multicast-
-DNS](https://wiki.archlinux.org/index.php/Avahi#Hostname_resolution)
-works. Then enable systemd services `pacserve`, `pacdbserve` and
-`pacredir`, open TCP ports 7078 and 7079 and add the following line to
-your repository definitions in `pacman.conf`:
+Enable systemd services `pacserve`, `pacdbserve` and `pacredir`, open TCP
+ports `7078` and `7079` and add the following line to your repository
+definitions in `pacman.conf`:
> Include = /etc/pacman.d/pacredir
diff --git a/pacredir.c b/pacredir.c
index 60fca60..9325d74 100644
--- a/pacredir.c
+++ b/pacredir.c
@@ -46,21 +46,23 @@ char * get_fqdn(const char * hostname, const char * domainname) {
}
/*** get_url ***/
-char * get_url(const char * hostname, const uint16_t port, const char * uri) {
+char * get_url(const char * hostname, const char * address, const uint16_t port, const char * uri) {
+ const char * host;
char * url;
+ host = (*address ? address : hostname);
+
url = malloc(10 /* static chars of an url & null char */
- + strlen(hostname)
+ + strlen(host)
+ 5 /* max strlen of decimal 16bit value */
+ strlen(uri));
- sprintf(url, "http://%s:%d/%s",
- hostname, port, uri);
+ sprintf(url, "http://%s:%d/%s", host, port, uri);
return url;
}
/*** add_host ***/
-int add_host(const char * host, const uint16_t port, const char * type) {
+int add_host(const char * host, const char * address, const uint16_t port, const char * type) {
struct hosts * tmphosts = hosts;
struct request request;
@@ -79,6 +81,7 @@ int add_host(const char * host, const uint16_t port, const char * type) {
if (verbose > 0)
write_log(stdout, "Adding host %s with service %s (port %d)\n",
host, type, port);
+
tmphosts->host = strdup(host);
tmphosts->pacserve.port = 0;
@@ -96,6 +99,11 @@ int add_host(const char * host, const uint16_t port, const char * type) {
tmphosts->next->next = NULL;
update:
+ if (address != NULL)
+ memcpy(tmphosts->address, address, AVAHI_ADDRESS_STR_MAX);
+ else
+ memset(tmphosts->address, 0, AVAHI_ADDRESS_STR_MAX);
+
if (strcmp(type, PACSERVE) == 0) {
tmphosts->pacserve.online = 1;
tmphosts->pacserve.port = port;
@@ -108,7 +116,7 @@ update:
/* do a first request and let get_http_code() set the bad status */
request.host = tmphosts->host;
- request.url = get_url(request.host, request.service->port, "");
+ request.url = get_url(request.host, tmphosts->address, request.service->port, "");
request.http_code = 0;
request.last_modified = 0;
get_http_code(&request);
@@ -139,6 +147,48 @@ int remove_host(const char * host, const char * type) {
return EXIT_SUCCESS;
}
+/*** resolve_callback ***
+ * Called whenever a service has been resolved successfully or timed out */
+static void resolve_callback(AvahiServiceResolver *r,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host,
+ const AvahiAddress *address,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ void* userdata) {
+ char ipaddress[AVAHI_ADDRESS_STR_MAX];
+ char intname[IFNAMSIZ];
+
+ assert(r);
+
+ if_indextoname(interface, intname);
+
+ switch (event) {
+ case AVAHI_RESOLVER_FAILURE:
+ write_log(stderr, "Failed to resolve service '%s' of type '%s' in domain '%s': %s\n",
+ name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
+ break;
+
+ case AVAHI_RESOLVER_FOUND:
+ avahi_address_snprint(ipaddress, AVAHI_ADDRESS_STR_MAX, address);
+
+ if (verbose > 0)
+ write_log(stdout, "Found service %s on host %s (%s) on interface %s\n",
+ type, host, ipaddress, intname);
+
+ add_host(host, ipaddress, strcmp(type, PACSERVE) == 0 ? PORT_PACSERVE : PORT_PACDBSERVE, type);
+ break;
+ }
+
+ avahi_service_resolver_free(r);
+}
+
/*** browse_callback ***
* Called whenever a new services becomes available on the LAN or is removed from the LAN */
static void browse_callback(AvahiServiceBrowser *b,
@@ -148,18 +198,21 @@ static void browse_callback(AvahiServiceBrowser *b,
const char *name,
const char *type,
const char *domain,
- AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ AvahiLookupResultFlags flags,
void* userdata) {
char * host;
char intname[IFNAMSIZ];
struct ignore_interfaces * tmp_ignore_interfaces = ignore_interfaces;
+ AvahiClient * c;
assert(b);
+ c = userdata;
+ if_indextoname(interface, intname);
+
switch (event) {
case AVAHI_BROWSER_FAILURE:
-
- write_log(stderr, "%s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
+ write_log(stderr, "Failed to browse: %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
avahi_simple_poll_quit(simple_poll);
return;
@@ -170,7 +223,6 @@ static void browse_callback(AvahiServiceBrowser *b,
goto out;
/* check whether to ignore the interface */
- if_indextoname(interface, intname);
while (tmp_ignore_interfaces->next != NULL) {
if (strcmp(intname, tmp_ignore_interfaces->interface) == 0) {
if (verbose > 0)
@@ -181,11 +233,9 @@ static void browse_callback(AvahiServiceBrowser *b,
tmp_ignore_interfaces = tmp_ignore_interfaces->next;
}
- if (verbose > 0)
- write_log(stdout, "Found service %s on host %s on interface %s\n",
- type, host, intname);
-
- add_host(host, strcmp(type, PACSERVE) == 0 ? PORT_PACSERVE : PORT_PACDBSERVE, type);
+ if ((avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_INET, 0, resolve_callback, c)) == NULL)
+ write_log(stderr, "Failed to create resolver for service '%s' of type '%s' in domain '%s': %s\n",
+ name, type, domain, avahi_strerror(avahi_client_errno(c)));
out:
free(host);
@@ -213,7 +263,7 @@ out:
/*** client_callback ***/
static void client_callback(AvahiClient *c,
AvahiClientState state,
- AVAHI_GCC_UNUSED void * userdata) {
+ void * userdata) {
assert(c);
if (state == AVAHI_CLIENT_FAILURE) {
@@ -431,12 +481,12 @@ static int ahc_echo(void * cls,
request->service = &(tmphosts->pacdbserve);
else
request->service = &(tmphosts->pacserve);
- request->url = get_url(tmphosts->host, request->service->port, basename);
+ request->url = get_url(tmphosts->host, tmphosts->address, request->service->port, basename);
request->http_code = 0;
request->last_modified = 0;
if (verbose > 0)
- write_log(stdout, "Trying: %s\n", request->url);
+ write_log(stdout, "Trying %s: %s\n", request->host, request->url);
if ((error = pthread_create(&tid[req_count], NULL, get_http_code, (void *)request)) != 0)
write_log(stderr, "Could not run thread number %d, errno %d\n", req_count, error);
@@ -648,7 +698,7 @@ int main(int argc, char ** argv) {
*strchr(value, ':') = 0;
} else
port = PORT_PACSERVE;
- add_host(value, port, PACSERVE);
+ add_host(value, NULL, port, PACSERVE);
value = strtok(NULL, DELIMITER);
}
free(values);
@@ -667,7 +717,7 @@ int main(int argc, char ** argv) {
*strchr(value, ':') = 0;
} else
port = PORT_PACDBSERVE;
- add_host(value, port, PACDBSERVE);
+ add_host(value, NULL, port, PACDBSERVE);
value = strtok(NULL, DELIMITER);
}
free(values);
@@ -690,13 +740,13 @@ int main(int argc, char ** argv) {
}
/* create the service browser for PACSERVE */
- if ((pacserve = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, PACSERVE, NULL, 0, browse_callback, NULL)) == NULL) {
+ if ((pacserve = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, PACSERVE, NULL, 0, browse_callback, client)) == NULL) {
write_log(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
goto fail;
}
/* create the service browser for PACDBSERVE */
- if ((pacdbserve = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, PACDBSERVE, NULL, 0, browse_callback, NULL)) == NULL) {
+ if ((pacdbserve = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, PACDBSERVE, NULL, 0, browse_callback, client)) == NULL) {
write_log(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
goto fail;
}
diff --git a/pacredir.h b/pacredir.h
index 161845e..2cd8cca 100644
--- a/pacredir.h
+++ b/pacredir.h
@@ -61,6 +61,8 @@ struct services {
struct hosts {
/* host name */
char * host;
+ /* resolved address */
+ char address[AVAHI_ADDRESS_STR_MAX];
/* online status and bad time for services */
struct services pacserve;
struct services pacdbserve;
@@ -97,13 +99,27 @@ int write_log(FILE *stream, const char *format, ...);
/* get_fqdn */
char * get_fqdn(const char * hostname, const char * domainname);
/* get_url */
-char * get_url(const char * hostname, const uint16_t port, const char * uri);
+char * get_url(const char * hostname, const char * address, const uint16_t port, const char * uri);
/* add_host */
-int add_host(const char * host, const uint16_t port, const char * type);
+int add_host(const char * host, const char * address, const uint16_t port, const char * type);
/* remove_host */
int remove_host(const char * host, const char * type);
+/* resolve_callback */
+static void resolve_callback(AvahiServiceResolver *r,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host,
+ const AvahiAddress *address,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ void* userdata);
/* browse_callback */
static void browse_callback(AvahiServiceBrowser *b,
AvahiIfIndex interface,
@@ -112,12 +128,12 @@ static void browse_callback(AvahiServiceBrowser *b,
const char *name,
const char *type,
const char *domain,
- AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ AvahiLookupResultFlags flags,
void* userdata);
/* client_callback */
static void client_callback(AvahiClient *c,
AvahiClientState state,
- AVAHI_GCC_UNUSED void * userdata);
+ void * userdata);
/* get_http_code */
static void * get_http_code(void * data);