X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-dnsconfd%2Fmain.c;h=719fbebc46ed725ad1552a65454fb3e69d5656e5;hb=ca3addf6ae9aa830ccb45fe69ab9b9608d42b51c;hp=cca0b68118a1195c7487f513580a8feca944933c;hpb=f6924be4422c2477796301cda4a3c663d7e62909;p=catta diff --git a/avahi-dnsconfd/main.c b/avahi-dnsconfd/main.c index cca0b68..719fbeb 100644 --- a/avahi-dnsconfd/main.c +++ b/avahi-dnsconfd/main.c @@ -1,18 +1,16 @@ -/* $Id$ */ - /*** This file is part of avahi. - + avahi is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + avahi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with avahi; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -23,11 +21,11 @@ #include #endif -#include #include #include #include #include +#include #include #include #include @@ -61,8 +59,6 @@ static enum { BROWSING } state = ACKWAIT; -static int quit = 0; - static enum { DAEMON_RUN, DAEMON_KILL, @@ -72,7 +68,13 @@ static enum { DAEMON_CHECK } command = DAEMON_RUN; +static int quit = 0; static int daemonize = 0; +static int use_syslog = 0; + +#if !HAVE_DECL_ENVIRON +extern char **environ; +#endif typedef struct DNSServerInfo DNSServerInfo; @@ -89,7 +91,7 @@ static void server_info_free(DNSServerInfo *i) { assert(i); avahi_free(i->address); - + AVAHI_LLIST_REMOVE(DNSServerInfo, servers, servers, i); avahi_free(i); } @@ -109,7 +111,7 @@ static DNSServerInfo* get_server_info(AvahiIfIndex interface, AvahiProtocol prot static DNSServerInfo* new_server_info(AvahiIfIndex interface, AvahiProtocol protocol, const char *address) { DNSServerInfo *i; - + assert(address); i = avahi_new(DNSServerInfo, 1); @@ -118,7 +120,7 @@ static DNSServerInfo* new_server_info(AvahiIfIndex interface, AvahiProtocol prot i->address = avahi_strdup(address); AVAHI_LLIST_PREPEND(DNSServerInfo, servers, servers, i); - + return i; } @@ -126,7 +128,7 @@ static int set_cloexec(int fd) { int n; assert(fd >= 0); - + if ((n = fcntl(fd, F_GETFD)) < 0) return -1; @@ -149,7 +151,7 @@ static int open_socket(void) { daemon_log(LOG_ERR, "fcntl(): %s", strerror(errno)); goto fail; } - + memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; strncpy(sa.sun_path, AVAHI_SOCKET, sizeof(sa.sun_path)-1); @@ -157,13 +159,13 @@ static int open_socket(void) { if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) { daemon_log(LOG_ERR, "connect(): %s", strerror(errno)); - daemon_log(LOG_INFO, "Failed to connect to the daemon. This probably means that you"); - daemon_log(LOG_INFO, "didn't start avahi-daemon before avahi-dnsconfd."); + daemon_log(LOG_INFO, "Failed to connect to the daemon. This probably means that you"); + daemon_log(LOG_INFO, "didn't start avahi-daemon before avahi-dnsconfd."); goto fail; } return fd; - + fail: if (fd >= 0) close(fd); @@ -196,11 +198,21 @@ static ssize_t loop_write(int fd, const void*data, size_t size) { static char *concat_dns_servers(AvahiIfIndex interface) { DNSServerInfo *i; char *r = NULL; - + for (i = servers; i; i = i->servers_next) if (i->interface == interface || interface <= 0) { + DNSServerInfo *j; char *t; + /* Filter out double entries */ + for (j = servers; j != i; j = j->servers_next) + if (j->interface == interface || interface <= 0) + if (strcmp(i->address, j->address) == 0) + break; + + if (j != i) + continue; + if (!r) t = avahi_strdup(i->address); else @@ -213,41 +225,10 @@ static char *concat_dns_servers(AvahiIfIndex interface) { return r; } -static char *getifname(AvahiIfIndex interface, char *name, size_t len) { - int fd = -1; - char *ret = NULL; - struct ifreq ifr; - - assert(interface >= 0); - - if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - daemon_log(LOG_ERR, "socket(): %s", strerror(errno)); - goto finish; - } - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_ifindex = (int) interface; - - if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) { - daemon_log(LOG_ERR, "SIOCGIFNAME: %s\n", strerror(errno)); - goto finish; - } - - strncpy(name, ifr.ifr_name, len-1); - name[len-1] = 0; - ret = name; - -finish: - if (fd >= 0) - close(fd); - - return ret; -} - static void set_env(const char *name, const char *value) { char **e; size_t l; - + assert(name); assert(value); @@ -257,7 +238,7 @@ static void set_env(const char *name, const char *value) { /* Search for the variable */ if (strlen(*e) < l+1) continue; - + if (strncmp(*e, name, l) != 0 || (*e)[l] != '=') continue; @@ -274,23 +255,23 @@ static void run_script(int new, AvahiIfIndex interface, AvahiProtocol protocol, char *p; int ret; char ia[16], pa[16]; - char name[IFNAMSIZ+1]; + char name[IF_NAMESIZE]; assert(interface > 0); - if (!getifname(interface, name, sizeof(name))) + if (!if_indextoname(interface, name)) return; - + p = concat_dns_servers(interface); set_env(ENV_INTERFACE_DNS_SERVERS, p ? p : ""); - avahi_free(p); + avahi_free(p); p = concat_dns_servers(-1); set_env(ENV_DNS_SERVERS, p ? p : ""); - avahi_free(p); + avahi_free(p); set_env(ENV_INTERFACE, name); - + snprintf(ia, sizeof(ia), "%i", (int) interface); snprintf(pa, sizeof(pa), "%i", (int) protocol); @@ -315,16 +296,16 @@ static int new_line(const char *l) { AvahiIfIndex interface; AvahiProtocol protocol; int i_interface, i_protocol, port; - char a[64]; - - assert(state == BROWSING); + char a[AVAHI_ADDRESS_STR_MAX]; + + assert(state == BROWSING); if (*l != '<' && *l != '>') { daemon_log(LOG_ERR, "Avahi sent us an invalid browsing line: %s", l); return -1; } - if (sscanf(l+1, "%i %i %64s %i", &i_interface, &i_protocol, a, &port) != 4) { + if (sscanf(l+1, "%i %i %39s %i", &i_interface, &i_protocol, a, &port) != 4) { daemon_log(LOG_ERR, "Failed to parse browsing line: %s", l); return -1; } @@ -343,7 +324,7 @@ static int new_line(const char *l) { } else { DNSServerInfo *i; - if (port == 53) + if (port == 53) if ((i = get_server_info(interface, protocol, a))) { daemon_log(LOG_INFO, "DNS Server %s removed (interface: %i.%s)", a, interface, avahi_proto_to_string(protocol)); server_info_free(i); @@ -352,13 +333,13 @@ static int new_line(const char *l) { } } - + return 0; } static int do_connect(void) { int fd = -1; - + if ((fd = open_socket()) < 0) goto fail; @@ -373,7 +354,7 @@ static int do_connect(void) { fail: if (fd >= 0) close(fd); - + return -1; } @@ -383,7 +364,7 @@ static void free_dns_server_info_list(void) { AvahiProtocol protocol = servers->protocol; char *address = avahi_strdup(servers->address); server_info_free(servers); - + run_script(0, interface, protocol, address); avahi_free(address); } @@ -394,6 +375,7 @@ static void help(FILE *f, const char *argv0) { "%s [options]\n" " -h --help Show this help\n" " -D --daemonize Daemonize after startup\n" + " -s --syslog Write log messages to syslog(3) instead of STDERR\n" " -k --kill Kill a running daemon\n" " -r --refresh Request a running daemon to refresh DNS server data\n" " -c --check Return 0 if a daemon is already running\n" @@ -403,18 +385,19 @@ static void help(FILE *f, const char *argv0) { static int parse_command_line(int argc, char *argv[]) { int c; - + static const struct option long_options[] = { { "help", no_argument, NULL, 'h' }, { "daemonize", no_argument, NULL, 'D' }, + { "syslog", no_argument, NULL, 's' }, { "kill", no_argument, NULL, 'k' }, { "version", no_argument, NULL, 'V' }, { "refresh", no_argument, NULL, 'r' }, { "check", no_argument, NULL, 'c' }, + { NULL, 0, NULL, 0 } }; - opterr = 0; - while ((c = getopt_long(argc, argv, "hDkVrc", long_options, NULL)) >= 0) { + while ((c = getopt_long(argc, argv, "hDkVrcs", long_options, NULL)) >= 0) { switch(c) { case 'h': @@ -423,6 +406,9 @@ static int parse_command_line(int argc, char *argv[]) { case 'D': daemonize = 1; break; + case 's': + use_syslog = 1; + break; case 'k': command = DAEMON_KILL; break; @@ -436,7 +422,6 @@ static int parse_command_line(int argc, char *argv[]) { command = DAEMON_CHECK; break; default: - fprintf(stderr, "Invalid command line argument: %c\n", c); return -1; } } @@ -445,7 +430,7 @@ static int parse_command_line(int argc, char *argv[]) { fprintf(stderr, "Too many arguments\n"); return -1; } - + return 0; } @@ -455,14 +440,14 @@ static int run_daemon(void) { size_t buflen = 0; AVAHI_LLIST_HEAD_INIT(DNSServerInfo, servers); - + daemon_signal_init(SIGINT, SIGTERM, SIGCHLD, SIGHUP, 0); /* Allocate some memory for our environment variables */ putenv(avahi_strdup(ENV_INTERFACE"=")); putenv(avahi_strdup(ENV_DNS_SERVERS"=")); putenv(avahi_strdup(ENV_INTERFACE_DNS_SERVERS"=")); - + if ((fd = do_connect()) < 0) goto finish; @@ -511,19 +496,19 @@ static int run_daemon(void) { case SIGCHLD: waitpid(-1, NULL, WNOHANG); break; - + case SIGHUP: daemon_log(LOG_INFO, "Refreshing DNS Server list"); - + close(fd); free_dns_server_info_list(); - + if ((fd = do_connect()) < 0) goto finish; - + break; } - + } else if (FD_ISSET(fd, &rfds)) { ssize_t r; char *n; @@ -549,27 +534,27 @@ static int run_daemon(void) { if (buflen >= sizeof(buf)-1) { /* The incoming line is horribly long */ buf[sizeof(buf)-1] = 0; - + if (new_line(buf) < 0) goto finish; - + buflen = 0; } } } - + finish: free_dns_server_info_list(); if (fd >= 0) close(fd); - + daemon_signal_done(); if (ret != 0 && daemonize) daemon_retval_send(1); - + return ret; } @@ -589,7 +574,7 @@ int main(int argc, char *argv[]) { daemon_pid_file_ident = daemon_log_ident = argv0; daemon_pid_file_proc = pid_file_proc; - + if (parse_command_line(argc, argv) < 0) goto finish; @@ -608,7 +593,7 @@ int main(int argc, char *argv[]) { if (daemonize) { daemon_retval_init(); - + if ((pid = daemon_fork()) < 0) goto finish; else if (pid != 0) { @@ -616,7 +601,7 @@ int main(int argc, char *argv[]) { /** Parent **/ if ((ret = daemon_retval_wait(20)) < 0) { - daemon_log(LOG_ERR, "Could not recieve return value from daemon process."); + daemon_log(LOG_ERR, "Could not receive return value from daemon process."); goto finish; } @@ -627,6 +612,9 @@ int main(int argc, char *argv[]) { /* Child */ } + if (use_syslog || daemonize) + daemon_log_use = DAEMON_LOG_SYSLOG; + chdir("/"); if (daemon_pid_file_create() < 0) { @@ -644,18 +632,18 @@ int main(int argc, char *argv[]) { r = 0; } else if (command == DAEMON_HELP) { help(stdout, argv0); - + r = 0; } else if (command == DAEMON_VERSION) { printf("%s "PACKAGE_VERSION"\n", argv0); - + r = 0; } else if (command == DAEMON_KILL) { if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) { daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno)); goto finish; } - + r = 0; } else if (command == DAEMON_REFRESH) { if (daemon_pid_file_kill(SIGHUP) < 0) { @@ -672,7 +660,7 @@ finish: if (daemonize) daemon_retval_done(); - + if (wrote_pid_file) daemon_pid_file_remove();