static AvahiSEntryGroup* add_dns_servers(AvahiServer *s, AvahiSEntryGroup* g, char **l) { char **p; assert(s); assert(l); if (!g) g = avahi_s_entry_group_new(s, NULL, NULL); assert(avahi_s_entry_group_is_empty(g)); for (p = l; *p; p++) { AvahiAddress a; if (!avahi_address_parse(*p, AVAHI_PROTO_UNSPEC, &a)) avahi_log_warn("Failed to parse address '%s', ignoring.", *p); else if (avahi_server_add_dns_server_address(s, g, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, NULL, AVAHI_DNS_SERVER_RESOLVE, &a, 53) < 0) { avahi_s_entry_group_free(g); avahi_log_error("Failed to add DNS server address: %s", avahi_strerror(avahi_server_errno(s))); return NULL; } } avahi_s_entry_group_commit(g); return g; }
int avahi_is_valid_fqdn(const char *t) { char label[AVAHI_LABEL_MAX]; char normalized[AVAHI_DOMAIN_NAME_MAX]; const char *k = t; AvahiAddress a; assert(t); if (strlen(t) >= AVAHI_DOMAIN_NAME_MAX) return 0; if (!avahi_is_valid_domain_name(t)) return 0; /* Check if there are at least two labels*/ if (!(avahi_unescape_label(&k, label, sizeof(label)))) return 0; if (label[0] == 0 || !k) return 0; if (!(avahi_unescape_label(&k, label, sizeof(label)))) return 0; if (label[0] == 0 || !k) return 0; /* Make sure that the name is not an IP address */ if (!(avahi_normalize_name(t, normalized, sizeof(normalized)))) return 0; if (avahi_address_parse(normalized, AVAHI_PROTO_UNSPEC, &a)) return 0; return 1; }
static void update_wide_area_servers(void) { AvahiAddress a[AVAHI_WIDE_AREA_SERVERS_MAX]; unsigned n = 0; char **p; if (!resolv_conf_name_servers) { avahi_server_set_wide_area_servers(avahi_server, NULL, 0); return; } for (p = resolv_conf_name_servers; *p && n < AVAHI_WIDE_AREA_SERVERS_MAX; p++) { if (!avahi_address_parse(*p, AVAHI_PROTO_UNSPEC, &a[n])) avahi_log_warn("Failed to parse address '%s', ignoring.", *p); else n++; } avahi_server_set_wide_area_servers(avahi_server, a, n); }
static void add_static_host_to_server(StaticHost *h) { AvahiAddress a; int err; if (!h->group) h->group = avahi_s_entry_group_new (avahi_server, entry_group_callback, h); if (!avahi_address_parse (h->ip, AVAHI_PROTO_UNSPEC, &a)) { avahi_log_error("Static host name %s: avahi_address_parse failed", h->host); return; } if ((err = avahi_server_add_address(avahi_server, h->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, h->host, &a))) { avahi_log_error ("Static host name %s: avahi_server_add_address failure: %s", h->host, avahi_strerror(err)); return; } avahi_s_entry_group_commit (h->group); }
void service_found(void *user_data, Avahi::Resolver *resolver, Avahi::Service service, AvahiLookupResultFlags flags) { char caddress[AVAHI_ADDRESS_STR_MAX]; if (flags & (AVAHI_LOOKUP_RESULT_LOCAL|AVAHI_LOOKUP_RESULT_OUR_OWN)) return; avahi_address_snprint(caddress, sizeof(caddress), service.GetAddress()); #if 0 std::cout << "Resolved " << service.GetName() << std::endl; std::cout << "\tFlags = " << flags << std::endl; std::cout << "\tType = " << service.GetType() << std::endl; std::cout << "\tName = " << service.GetName() << std::endl; std::cout << "\tDomain = " << service.GetDomain() << std::endl; std::cout << "\tInterface = " << service.GetInterface() << std::endl; std::cout << "\tProtocol = " << service.GetProtocol() << std::endl; std::cout << "\tHostname = " << service.GetHostName() << std::endl; std::cout << "\tAddress = " << caddress << std::endl; StringList lst = service.GetTxt(); StringList::iterator it; for (it = lst.begin(); it != lst.end(); ++it) std::cout << "\tTXT = " << *it << std::endl; #endif #if 0 service.SetName("X" + service.GetName()); service.SetHostName("X" + service.GetHostName()); AvahiAddress address; avahi_address_parse("172.16.76.2", AVAHI_PROTO_UNSPEC, &address); service.SetAddress(&address); #endif service.SetInterface(if_nametoindex("eth1")); avahi->Publish(service); delete resolver; }
DBusHandlerResult avahi_dbus_msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) { DBusError error; EntryGroupInfo *i = userdata; assert(c); assert(m); assert(i); dbus_error_init(&error); avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", dbus_message_get_interface(m), dbus_message_get_path(m), dbus_message_get_member(m)); /* Introspection */ if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) return avahi_dbus_handle_introspect(c, m, "org.freedesktop.Avahi.EntryGroup.xml"); /* Access control */ if (strcmp(dbus_message_get_sender(m), i->client->name)) return avahi_dbus_respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL); if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) { if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { avahi_log_warn("Error parsing EntryGroup::Free message"); goto fail; } avahi_dbus_entry_group_free(i); return avahi_dbus_respond_ok(c, m); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) { if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { avahi_log_warn("Error parsing EntryGroup::Commit message"); goto fail; } if (avahi_s_entry_group_commit(i->entry_group) < 0) return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); return avahi_dbus_respond_ok(c, m); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) { if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { avahi_log_warn("Error parsing EntryGroup::Reset message"); goto fail; } avahi_s_entry_group_reset(i->entry_group); i->n_entries = 0; return avahi_dbus_respond_ok(c, m); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) { if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { avahi_log_warn("Error parsing EntryGroup::IsEmpty message"); goto fail; } return avahi_dbus_respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group)); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) { AvahiEntryGroupState state; if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { avahi_log_warn("Error parsing EntryGroup::GetState message"); goto fail; } state = avahi_s_entry_group_get_state(i->entry_group); return avahi_dbus_respond_int32(c, m, (int32_t) state); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) { int32_t interface, protocol; uint32_t flags; char *type, *name, *domain, *host; uint16_t port; AvahiStringList *strlst = NULL; if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, DBUS_TYPE_INT32, &protocol, DBUS_TYPE_UINT32, &flags, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &type, DBUS_TYPE_STRING, &domain, DBUS_TYPE_STRING, &host, DBUS_TYPE_UINT16, &port, DBUS_TYPE_INVALID) || !type || !name || avahi_dbus_read_strlst(m, 8, &strlst) < 0) { avahi_log_warn("Error parsing EntryGroup::AddService message"); goto fail; } if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= server->n_entries_per_entry_group_max) { avahi_string_list_free(strlst); return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); } if (domain && !*domain) domain = NULL; if (host && !*host) host = NULL; if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) { avahi_string_list_free(strlst); return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); } if (!(flags & AVAHI_PUBLISH_UPDATE)) i->n_entries ++; avahi_string_list_free(strlst); return avahi_dbus_respond_ok(c, m); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) { int32_t interface, protocol; uint32_t flags; char *type, *name, *domain, *subtype; if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, DBUS_TYPE_INT32, &protocol, DBUS_TYPE_UINT32, &flags, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &type, DBUS_TYPE_STRING, &domain, DBUS_TYPE_STRING, &subtype, DBUS_TYPE_INVALID) || !type || !name || !subtype) { avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message"); goto fail; } if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= server->n_entries_per_entry_group_max) return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); if (domain && !*domain) domain = NULL; if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0) return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); if (!(flags & AVAHI_PUBLISH_UPDATE)) i->n_entries ++; return avahi_dbus_respond_ok(c, m); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) { int32_t interface, protocol; uint32_t flags; char *type, *name, *domain; AvahiStringList *strlst; if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, DBUS_TYPE_INT32, &protocol, DBUS_TYPE_UINT32, &flags, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &type, DBUS_TYPE_STRING, &domain, DBUS_TYPE_INVALID) || !type || !name || avahi_dbus_read_strlst(m, 6, &strlst)) { avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message"); goto fail; } if (domain && !*domain) domain = NULL; if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) { avahi_string_list_free(strlst); return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); } avahi_string_list_free(strlst); return avahi_dbus_respond_ok(c, m); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) { int32_t interface, protocol; uint32_t flags; char *name, *address; AvahiAddress a; if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, DBUS_TYPE_INT32, &protocol, DBUS_TYPE_UINT32, &flags, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID) || !name || !address) { avahi_log_warn("Error parsing EntryGroup::AddAddress message"); goto fail; } if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= server->n_entries_per_entry_group_max) return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL); if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0) return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); if (!(flags & AVAHI_PUBLISH_UPDATE)) i->n_entries ++; return avahi_dbus_respond_ok(c, m); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddRecord")) { int32_t interface, protocol; uint32_t flags, ttl, size; uint16_t clazz, type; char *name; void *rdata; AvahiRecord *r; if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, DBUS_TYPE_INT32, &protocol, DBUS_TYPE_UINT32, &flags, DBUS_TYPE_STRING, &name, DBUS_TYPE_UINT16, &clazz, DBUS_TYPE_UINT16, &type, DBUS_TYPE_UINT32, &ttl, DBUS_TYPE_INVALID) || !name || avahi_dbus_read_rdata (m, 7, &rdata, &size)) { avahi_log_warn("Error parsing EntryGroup::AddRecord message"); goto fail; } if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= server->n_entries_per_entry_group_max) return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); if (!avahi_is_valid_domain_name (name)) return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL); if (!(r = avahi_record_new_full (name, clazz, type, ttl))) return avahi_dbus_respond_error(c, m, AVAHI_ERR_NO_MEMORY, NULL); if (avahi_rdata_parse (r, rdata, size) < 0) { avahi_record_unref (r); return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_RDATA, NULL); } if (avahi_server_add(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, r) < 0) { avahi_record_unref (r); return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); } if (!(flags & AVAHI_PUBLISH_UPDATE)) i->n_entries ++; avahi_record_unref (r); return avahi_dbus_respond_ok(c, m); } avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m)); fail: if (dbus_error_is_set(&error)) dbus_error_free(&error); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
int main(int argc, char *argv[]) { int ret = 1, error; Config config; const char *argv0; avahi_init_i18n(); setlocale(LC_ALL, ""); if ((argv0 = strrchr(argv[0], '/'))) argv0++; else argv0 = argv[0]; if (parse_command_line(&config, argv0, argc, argv) < 0) goto fail; switch (config.command) { case COMMAND_UNSPEC: ret = 1; fprintf(stderr, _("No command specified.\n")); break; case COMMAND_HELP: help(stdout, argv0); ret = 0; break; case COMMAND_VERSION: printf("%s "PACKAGE_VERSION"\n", argv0); ret = 0; break; case COMMAND_RESOLVE_HOST_NAME: case COMMAND_RESOLVE_ADDRESS: { int i; if (!(simple_poll = avahi_simple_poll_new())) { fprintf(stderr, _("Failed to create simple poll object.\n")); goto fail; } if (sigint_install(simple_poll) < 0) goto fail; if (!(client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error))) { fprintf(stderr, _("Failed to create client object: %s\n"), avahi_strerror(error)); goto fail; } if (config.verbose) { const char *version, *hn; if (!(version = avahi_client_get_version_string(client))) { fprintf(stderr, _("Failed to query version string: %s\n"), avahi_strerror(avahi_client_errno(client))); goto fail; } if (!(hn = avahi_client_get_host_name_fqdn(client))) { fprintf(stderr, _("Failed to query host name: %s\n"), avahi_strerror(avahi_client_errno(client))); goto fail; } fprintf(stderr, _("Server version: %s; Host name: %s\n"), version, hn); } n_resolving = 0; for (i = optind; i < argc; i++) { if (config.command == COMMAND_RESOLVE_HOST_NAME) { if (!(avahi_host_name_resolver_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, argv[i], config.proto, 0, host_name_resolver_callback, NULL))) { fprintf(stderr, _("Failed to create host name resolver: %s\n"), avahi_strerror(avahi_client_errno(client))); goto fail; } } else { AvahiAddress a; assert(config.command == COMMAND_RESOLVE_ADDRESS); if (!avahi_address_parse(argv[i], AVAHI_PROTO_UNSPEC, &a)) { fprintf(stderr, _("Failed to parse address '%s'\n"), argv[i]); goto fail; } if (!(avahi_address_resolver_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, &a, 0, address_resolver_callback, NULL))) { fprintf(stderr, _("Failed to create address resolver: %s\n"), avahi_strerror(avahi_client_errno(client))); goto fail; } } n_resolving++; } avahi_simple_poll_loop(simple_poll); ret = 0; break; } } fail: if (client) avahi_client_free(client); sigint_uninstall(); if (simple_poll) avahi_simple_poll_free(simple_poll); return ret; }
static void handle_line(Client *c, const char *s) { char cmd[64], arg[64]; int n_args; assert(c); assert(s); if (c->state != CLIENT_IDLE) return; if ((n_args = sscanf(s, "%63s %63s", cmd, arg)) < 1 ) { client_output_printf(c, "%+i Failed to parse command, try \"HELP\".\n", AVAHI_ERR_INVALID_OPERATION); c->state = CLIENT_DEAD; return; } if (strcmp(cmd, "HELP") == 0) { client_output_printf(c, "+ Available commands are:\n" "+ RESOLVE-HOSTNAME <hostname>\n" "+ RESOLVE-HOSTNAME-IPV6 <hostname>\n" "+ RESOLVE-HOSTNAME-IPV4 <hostname>\n" "+ RESOLVE-ADDRESS <address>\n" "+ BROWSE-DNS-SERVERS\n" "+ BROWSE-DNS-SERVERS-IPV4\n" "+ BROWSE-DNS-SERVERS-IPV6\n"); c->state = CLIENT_DEAD; } else if (strcmp(cmd, "F**K") == 0 && n_args == 1) { client_output_printf(c, "+ F**K: Go f**k yourself!\n"); c->state = CLIENT_DEAD; } else if (strcmp(cmd, "RESOLVE-HOSTNAME-IPV4") == 0 && n_args == 2) { c->state = CLIENT_RESOLVE_HOSTNAME; if (!(c->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, arg, c->afquery = AVAHI_PROTO_INET, AVAHI_LOOKUP_USE_MULTICAST, host_name_resolver_callback, c))) goto fail; avahi_log_debug(__FILE__": Got %s request for '%s'.", cmd, arg); } else if (strcmp(cmd, "RESOLVE-HOSTNAME-IPV6") == 0 && n_args == 2) { c->state = CLIENT_RESOLVE_HOSTNAME; if (!(c->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, arg, c->afquery = AVAHI_PROTO_INET6, AVAHI_LOOKUP_USE_MULTICAST, host_name_resolver_callback, c))) goto fail; avahi_log_debug(__FILE__": Got %s request for '%s'.", cmd, arg); } else if (strcmp(cmd, "RESOLVE-HOSTNAME") == 0 && n_args == 2) { c->state = CLIENT_RESOLVE_HOSTNAME; if (!(c->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, arg, c->afquery = AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_MULTICAST, host_name_resolver_callback, c))) goto fail; avahi_log_debug(__FILE__": Got %s request for '%s'.", cmd, arg); } else if (strcmp(cmd, "RESOLVE-ADDRESS") == 0 && n_args == 2) { AvahiAddress addr; if (!(avahi_address_parse(arg, AVAHI_PROTO_UNSPEC, &addr))) { client_output_printf(c, "%+i Failed to parse address \"%s\".\n", AVAHI_ERR_INVALID_ADDRESS, arg); c->state = CLIENT_DEAD; } else { c->state = CLIENT_RESOLVE_ADDRESS; if (!(c->address_resolver = avahi_s_address_resolver_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, &addr, AVAHI_LOOKUP_USE_MULTICAST, address_resolver_callback, c))) goto fail; } avahi_log_debug(__FILE__": Got %s request for '%s'.", cmd, arg); } else if (strcmp(cmd, "BROWSE-DNS-SERVERS-IPV4") == 0 && n_args == 1) { c->state = CLIENT_BROWSE_DNS_SERVERS; if (!(c->dns_server_browser = avahi_s_dns_server_browser_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DNS_SERVER_RESOLVE, c->afquery = AVAHI_PROTO_INET, AVAHI_LOOKUP_USE_MULTICAST, dns_server_browser_callback, c))) goto fail; client_output_printf(c, "+ Browsing ...\n"); avahi_log_debug(__FILE__": Got %s request.", cmd); } else if (strcmp(cmd, "BROWSE-DNS-SERVERS-IPV6") == 0 && n_args == 1) { c->state = CLIENT_BROWSE_DNS_SERVERS; if (!(c->dns_server_browser = avahi_s_dns_server_browser_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DNS_SERVER_RESOLVE, c->afquery = AVAHI_PROTO_INET6, AVAHI_LOOKUP_USE_MULTICAST, dns_server_browser_callback, c))) goto fail; client_output_printf(c, "+ Browsing ...\n"); avahi_log_debug(__FILE__": Got %s request.", cmd); } else if (strcmp(cmd, "BROWSE-DNS-SERVERS") == 0 && n_args == 1) { c->state = CLIENT_BROWSE_DNS_SERVERS; if (!(c->dns_server_browser = avahi_s_dns_server_browser_new(avahi_server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DNS_SERVER_RESOLVE, c->afquery = AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_MULTICAST, dns_server_browser_callback, c))) goto fail; client_output_printf(c, "+ Browsing ...\n"); avahi_log_debug(__FILE__": Got %s request.", cmd); } else { client_output_printf(c, "%+i Invalid command \"%s\", try \"HELP\".\n", AVAHI_ERR_INVALID_OPERATION, cmd); c->state = CLIENT_DEAD; avahi_log_debug(__FILE__": Got invalid request '%s'.", cmd); } return; fail: client_output_printf(c, "%+i %s\n", avahi_server_errno(avahi_server), avahi_strerror(avahi_server_errno(avahi_server))); c->state = CLIENT_DEAD; }
static int parse_command_line(Config *c, const char *argv0, int argc, char *argv[]) { int o; enum { ARG_SUBTYPE = 256 }; static const struct option long_options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "service", no_argument, NULL, 's' }, { "address", no_argument, NULL, 'a' }, { "verbose", no_argument, NULL, 'v' }, { "domain", required_argument, NULL, 'd' }, { "host", required_argument, NULL, 'H' }, { "subtype", required_argument, NULL, ARG_SUBTYPE}, { "no-fail", no_argument, NULL, 'f' }, { NULL, 0, NULL, 0 } }; assert(c); c->command = strstr(argv0, "address") ? COMMAND_PUBLISH_ADDRESS : (strstr(argv0, "service") ? COMMAND_PUBLISH_SERVICE : COMMAND_UNSPEC); c->verbose = c->no_fail = 0; c->host = c->name = c->domain = c->stype = NULL; c->port = 0; c->txt = c->subtypes = NULL; opterr = 0; while ((o = getopt_long(argc, argv, "hVsavd:H:f", long_options, NULL)) >= 0) { switch(o) { case 'h': c->command = COMMAND_HELP; break; case 'V': c->command = COMMAND_VERSION; break; case 's': c->command = COMMAND_PUBLISH_SERVICE; break; case 'a': c->command = COMMAND_PUBLISH_ADDRESS; break; case 'v': c->verbose = 1; break; case 'd': avahi_free(c->domain); c->domain = avahi_strdup(optarg); break; case 'H': avahi_free(c->host); c->host = avahi_strdup(optarg); break; case 'f': c->no_fail = 1; break; case ARG_SUBTYPE: c->subtypes = avahi_string_list_add(c->subtypes, optarg); break; default: fprintf(stderr, "Invalid command line argument: %c\n", o); return -1; } } if (c->command == COMMAND_PUBLISH_ADDRESS) { if (optind+2 != argc) { fprintf(stderr, "Bad number of arguments\n"); return -1; } avahi_free(c->name); c->name = avahi_strdup(argv[optind]); avahi_address_parse(argv[optind+1], AVAHI_PROTO_UNSPEC, &c->address); } else if (c->command == COMMAND_PUBLISH_SERVICE) { char *e; long int p; int i; if (optind+3 > argc) { fprintf(stderr, "Bad number of arguments\n"); return -1; } c->name = avahi_strdup(argv[optind]); c->stype = avahi_strdup(argv[optind+1]); errno = 0; p = strtol(argv[optind+2], &e, 0); if (errno != 0 || *e || p < 0 || p > 0xFFFF) { fprintf(stderr, "Failed to parse port number: %s\n", argv[optind+2]); return -1; } c->port = p; for (i = optind+3; i < argc; i++) c->txt = avahi_string_list_add(c->txt, argv[i]); } return 0; }
DBusHandlerResult avahi_address_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message) { AvahiAddressResolver *r = NULL; DBusError error; const char *path; assert(client); assert(message); dbus_error_init (&error); if (!(path = dbus_message_get_path(message))) goto fail; for (r = client->address_resolvers; r; r = r->address_resolvers_next) if (strcmp (r->path, path) == 0) break; if (!r) goto fail; switch (event) { case AVAHI_RESOLVER_FOUND: { int32_t interface, protocol, aprotocol; uint32_t flags; char *name, *address; AvahiAddress a; if (!dbus_message_get_args( message, &error, DBUS_TYPE_INT32, &interface, DBUS_TYPE_INT32, &protocol, DBUS_TYPE_INT32, &aprotocol, DBUS_TYPE_STRING, &address, DBUS_TYPE_STRING, &name, DBUS_TYPE_UINT32, &flags, DBUS_TYPE_INVALID) || dbus_error_is_set (&error)) { fprintf(stderr, "Failed to parse resolver event.\n"); goto fail; } assert(address); if (!avahi_address_parse(address, (AvahiProtocol) aprotocol, &a)) { fprintf(stderr, "Failed to parse address\n"); goto fail; } r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, &a, name, (AvahiLookupResultFlags) flags, r->userdata); break; } case AVAHI_RESOLVER_FAILURE: { char *etxt; if (!dbus_message_get_args( message, &error, DBUS_TYPE_STRING, &etxt, DBUS_TYPE_INVALID) || dbus_error_is_set (&error)) { fprintf(stderr, "Failed to parse resolver event.\n"); goto fail; } avahi_client_set_errno(r->client, avahi_error_dbus_to_number(etxt)); r->callback(r, r->interface, r->protocol, event, &r->address, NULL, 0, r->userdata); break; } } return DBUS_HANDLER_RESULT_HANDLED; fail: dbus_error_free (&error); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
DBusHandlerResult avahi_service_resolver_event (AvahiClient *client, AvahiResolverEvent event, DBusMessage *message) { AvahiServiceResolver *r = NULL; DBusError error; const char *path; AvahiStringList *strlst = NULL; assert(client); assert(message); dbus_error_init (&error); if (!(path = dbus_message_get_path(message))) goto fail; for (r = client->service_resolvers; r; r = r->service_resolvers_next) if (strcmp (r->path, path) == 0) break; if (!r) goto fail; switch (event) { case AVAHI_RESOLVER_FOUND: { int j; int32_t interface, protocol, aprotocol; uint32_t flags; char *name, *type, *domain, *host, *address; uint16_t port; DBusMessageIter iter, sub; AvahiAddress a; if (!dbus_message_get_args( message, &error, DBUS_TYPE_INT32, &interface, DBUS_TYPE_INT32, &protocol, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &type, DBUS_TYPE_STRING, &domain, DBUS_TYPE_STRING, &host, DBUS_TYPE_INT32, &aprotocol, DBUS_TYPE_STRING, &address, DBUS_TYPE_UINT16, &port, DBUS_TYPE_INVALID) || dbus_error_is_set (&error)) { fprintf(stderr, "Failed to parse resolver event.\n"); goto fail; } dbus_message_iter_init(message, &iter); for (j = 0; j < 9; j++) dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) { fprintf(stderr, "Error parsing service resolving message\n"); goto fail; } strlst = NULL; dbus_message_iter_recurse(&iter, &sub); for (;;) { DBusMessageIter sub2; int at; const uint8_t *k; int n; if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID) break; assert(at == DBUS_TYPE_ARRAY); if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) { fprintf(stderr, "Error parsing service resolving message\n"); goto fail; } dbus_message_iter_recurse(&sub, &sub2); k = NULL; n = 0; dbus_message_iter_get_fixed_array(&sub2, &k, &n); if (k && n > 0) strlst = avahi_string_list_add_arbitrary(strlst, k, n); dbus_message_iter_next(&sub); } dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) { fprintf(stderr, "Failed to parse resolver event.\n"); goto fail; } dbus_message_iter_get_basic(&iter, &flags); assert(address); if (address[0] == 0) address = NULL; else avahi_address_parse(address, (AvahiProtocol) aprotocol, &a); r->callback(r, (AvahiIfIndex) interface, (AvahiProtocol) protocol, AVAHI_RESOLVER_FOUND, name, type, domain, host, address ? &a : NULL, port, strlst, (AvahiLookupResultFlags) flags, r->userdata); avahi_string_list_free(strlst); break; } case AVAHI_RESOLVER_FAILURE: { char *etxt; if (!dbus_message_get_args( message, &error, DBUS_TYPE_STRING, &etxt, DBUS_TYPE_INVALID) || dbus_error_is_set (&error)) { fprintf(stderr, "Failed to parse resolver event.\n"); goto fail; } avahi_client_set_errno(r->client, avahi_error_dbus_to_number(etxt)); r->callback(r, r->interface, r->protocol, event, r->name, r->type, r->domain, NULL, NULL, 0, NULL, 0, r->userdata); break; } } return DBUS_HANDLER_RESULT_HANDLED; fail: dbus_error_free (&error); avahi_string_list_free(strlst); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
int main(int argc, char*argv[]) { int ret = 1; argp_program_version = "1.0"; static char doc[] = "Commotion Service Manager"; static struct argp_option options[] = { {"bind", 'b', "URI", 0, "commotiond management socket"}, {"nodaemon", 'n', 0, 0, "Do not fork into the background" }, {"out", 'o', "FILE", 0, "Output file to write services to when USR1 signal is received" }, {"pid", 'p', "FILE", 0, "Specify PID file"}, #ifdef USE_UCI {"uci", 'u', 0, 0, "Store service cache in UCI" }, #endif { 0 } }; /* Set defaults */ arguments.co_sock = DEFAULT_CO_SOCK; #ifdef USE_UCI arguments.uci = 0; #endif arguments.nodaemon = 0; arguments.output_file = DEFAULT_FILENAME; arguments.pid_file = PIDFILE; static struct argp argp = { options, parse_opt, NULL, doc }; argp_parse (&argp, argc, argv, 0, 0, &arguments); //fprintf(stdout,"uci: %d, out: %s\n",arguments.uci,arguments.output_file); if (!arguments.nodaemon) daemon_start(arguments.pid_file); CHECK(co_init(),"Failed to initialize Commotion client"); struct sigaction sa = {0}; sa.sa_handler = print_services; CHECK(sigaction(SIGUSR1,&sa,NULL) == 0, "Failed to set signal handler"); sa.sa_handler = shutdown; CHECK(sigaction(SIGINT,&sa,NULL) == 0, "Failed to set signal handler"); CHECK(sigaction(SIGTERM,&sa,NULL) == 0, "Failed to set signal handler"); /* Initialize the psuedo-RNG */ srand(time(NULL)); /* Allocate main loop object */ CHECK((simple_poll = avahi_simple_poll_new()),"Failed to create simple poll object."); /* Do not publish any local records */ avahi_server_config_init(&config); config.publish_hinfo = 0; config.publish_addresses = 0; config.publish_workstation = 0; config.publish_domain = 0; /* Set a unicast DNS server for wide area DNS-SD */ avahi_address_parse("192.168.50.1", AVAHI_PROTO_UNSPEC, &config.wide_area_servers[0]); config.n_wide_area_servers = 1; config.enable_wide_area = 1; // Start timer to create server struct timeval tv = {0}; avahi_elapse_time(&tv, 0, 0); avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll), &tv, start_server, NULL); // create expiration event for service /* Run the main loop */ avahi_simple_poll_loop(simple_poll); ret = 0; error: /* Free the configuration data */ avahi_server_config_free(&config); co_shutdown(); /* Cleanup things */ if (stb) avahi_s_service_type_browser_free(stb); if (server) avahi_server_free(server); if (simple_poll) avahi_simple_poll_free(simple_poll); return ret; }
void static_hosts_load(int in_chroot) { FILE *f; unsigned int line = 0; StaticHost *h, *next; const char *filename = in_chroot ? "/hosts" : AVAHI_CONFIG_DIR "/hosts"; if (!(f = fopen(filename, "r"))) { if (errno != ENOENT) avahi_log_error ("Failed to open static hosts file: %s", strerror (errno)); return; } current_iteration++; while (!feof(f)) { unsigned int len; char ln[256], *s; char *host, *ip; AvahiAddress a; if (!fgets(ln, sizeof (ln), f)) break; line++; /* Find the start of the line, ignore whitespace */ s = ln + strspn(ln, " \t"); /* Set the end of the string to NULL */ s[strcspn(s, "#\r\n")] = 0; /* Ignore blank lines */ if (*s == 0) continue; /* Read the first string (ip) up to the next whitespace */ len = strcspn(s, " \t"); ip = avahi_strndup(s, len); /* Skip past it */ s += len; /* Find the next token */ s += strspn(s, " \t"); len = strcspn(s, " \t"); host = avahi_strndup(s, len); if (*host == 0) { avahi_log_error("%s:%d: Error, unexpected end of line!", filename, line); avahi_free(host); avahi_free(ip); goto fail; } /* Skip over the host */ s += len; /* Skip past any more spaces */ s += strspn(s, " \t"); /* Anything left? */ if (*s != 0) { avahi_log_error ("%s:%d: Junk on the end of the line!", filename, line); avahi_free(host); avahi_free(ip); goto fail; } if (!avahi_address_parse(ip, AVAHI_PROTO_UNSPEC, &a)) { avahi_log_error("Static host name %s: failed to parse address %s", host, ip); avahi_free(host); avahi_free(ip); goto fail; } avahi_free(ip); if ((h = static_host_find(host, &a))) avahi_free(host); else { h = static_host_new(); h->host = host; h->address = a; avahi_log_info("Loading new static hostname %s.", h->host); } h->iteration = current_iteration; } for (h = hosts; h; h = next) { next = h->hosts_next; if (h->iteration != current_iteration) { avahi_log_info("Static hostname %s vanished, removing.", h->host); static_host_free(h); } } fail: fclose(f); }