1%{ 2/*- 3 * Copyright (c) 2009-2010 The FreeBSD Foundation 4 * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> 5 * All rights reserved. 6 * 7 * This software was developed by Pawel Jakub Dawidek under sponsorship from 8 * the FreeBSD Foundation. --- 14 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * |
31 * $FreeBSD: head/sbin/hastd/parse.y 235789 2012-05-22 16:33:10Z bapt $ |
32 */ 33 34#include <sys/param.h> /* MAXHOSTNAMELEN */ 35#include <sys/queue.h> 36#include <sys/socket.h> 37#include <sys/sysctl.h> 38 39#include <arpa/inet.h> --- 32 unchanged lines hidden (view full) --- 72static int depth0_metaflush; 73 74static char depth1_provname[PATH_MAX]; 75static char depth1_localpath[PATH_MAX]; 76static int depth1_metaflush; 77 78extern void yyrestart(FILE *); 79 |
80static int isitme(const char *name); 81static bool family_supported(int family); 82static int node_names(char **namesp); |
83%} 84 85%token CONTROL PIDFILE LISTEN REPLICATION CHECKSUM COMPRESSION METAFLUSH 86%token TIMEOUT EXEC RESOURCE NAME LOCAL REMOTE SOURCE ON OFF 87%token FULLSYNC MEMSYNC ASYNC NONE CRC32 SHA256 HOLE LZF 88%token NUM STR OB CB 89 90%type <str> remote_str --- 621 unchanged lines hidden (view full) --- 712 pjdlog_error("source argument is too long."); 713 free($2); 714 return (1); 715 } 716 } 717 free($2); 718 } 719 ; |
720 721%% 722 723static int 724isitme(const char *name) 725{ 726 char buf[MAXHOSTNAMELEN]; 727 char *pos; 728 size_t bufsize; 729 730 /* 731 * First check if the given name matches our full hostname. 732 */ 733 if (gethostname(buf, sizeof(buf)) < 0) { 734 pjdlog_errno(LOG_ERR, "gethostname() failed"); 735 return (-1); 736 } 737 if (strcmp(buf, name) == 0) 738 return (1); 739 740 /* 741 * Now check if it matches first part of the host name. 742 */ 743 pos = strchr(buf, '.'); 744 if (pos != NULL && (size_t)(pos - buf) == strlen(name) && 745 strncmp(buf, name, pos - buf) == 0) { 746 return (1); 747 } 748 749 /* 750 * At the end check if name is equal to our host's UUID. 751 */ 752 bufsize = sizeof(buf); 753 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 754 pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 755 return (-1); 756 } 757 if (strcasecmp(buf, name) == 0) 758 return (1); 759 760 /* 761 * Looks like this isn't about us. 762 */ 763 return (0); 764} 765 766static bool 767family_supported(int family) 768{ 769 int sock; 770 771 sock = socket(family, SOCK_STREAM, 0); 772 if (sock == -1 && errno == EPROTONOSUPPORT) 773 return (false); 774 if (sock >= 0) 775 (void)close(sock); 776 return (true); 777} 778 779static int 780node_names(char **namesp) 781{ 782 static char names[MAXHOSTNAMELEN * 3]; 783 char buf[MAXHOSTNAMELEN]; 784 char *pos; 785 size_t bufsize; 786 787 if (gethostname(buf, sizeof(buf)) < 0) { 788 pjdlog_errno(LOG_ERR, "gethostname() failed"); 789 return (-1); 790 } 791 792 /* First component of the host name. */ 793 pos = strchr(buf, '.'); 794 if (pos != NULL && pos != buf) { 795 (void)strlcpy(names, buf, MIN((size_t)(pos - buf + 1), 796 sizeof(names))); 797 (void)strlcat(names, ", ", sizeof(names)); 798 } 799 800 /* Full host name. */ 801 (void)strlcat(names, buf, sizeof(names)); 802 (void)strlcat(names, ", ", sizeof(names)); 803 804 /* Host UUID. */ 805 bufsize = sizeof(buf); 806 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 807 pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 808 return (-1); 809 } 810 (void)strlcat(names, buf, sizeof(names)); 811 812 *namesp = names; 813 814 return (0); 815} 816 817void 818yyerror(const char *str) 819{ 820 821 pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 822 lineno, yytext, str); 823} 824 825struct hastd_config * 826yy_config_parse(const char *config, bool exitonerror) 827{ 828 int ret; 829 830 curres = NULL; 831 mynode = false; 832 depth = 0; 833 lineno = 0; 834 835 depth0_timeout = HAST_TIMEOUT; 836 depth0_replication = HAST_REPLICATION_FULLSYNC; 837 depth0_checksum = HAST_CHECKSUM_NONE; 838 depth0_compression = HAST_COMPRESSION_HOLE; 839 strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); 840 strlcpy(depth0_pidfile, HASTD_PIDFILE, sizeof(depth0_pidfile)); 841 TAILQ_INIT(&depth0_listen); 842 strlcpy(depth0_listen_tcp4, HASTD_LISTEN_TCP4, 843 sizeof(depth0_listen_tcp4)); 844 strlcpy(depth0_listen_tcp6, HASTD_LISTEN_TCP6, 845 sizeof(depth0_listen_tcp6)); 846 depth0_exec[0] = '\0'; 847 depth0_metaflush = 1; 848 849 lconfig = calloc(1, sizeof(*lconfig)); 850 if (lconfig == NULL) { 851 pjdlog_error("Unable to allocate memory for configuration."); 852 if (exitonerror) 853 exit(EX_TEMPFAIL); 854 return (NULL); 855 } 856 857 TAILQ_INIT(&lconfig->hc_listen); 858 TAILQ_INIT(&lconfig->hc_resources); 859 860 yyin = fopen(config, "r"); 861 if (yyin == NULL) { 862 pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 863 config); 864 yy_config_free(lconfig); 865 if (exitonerror) 866 exit(EX_OSFILE); 867 return (NULL); 868 } 869 yyrestart(yyin); 870 ret = yyparse(); 871 fclose(yyin); 872 if (ret != 0) { 873 yy_config_free(lconfig); 874 if (exitonerror) 875 exit(EX_CONFIG); 876 return (NULL); 877 } 878 879 /* 880 * Let's see if everything is set up. 881 */ 882 if (lconfig->hc_controladdr[0] == '\0') { 883 strlcpy(lconfig->hc_controladdr, depth0_control, 884 sizeof(lconfig->hc_controladdr)); 885 } 886 if (lconfig->hc_pidfile[0] == '\0') { 887 strlcpy(lconfig->hc_pidfile, depth0_pidfile, 888 sizeof(lconfig->hc_pidfile)); 889 } 890 if (!TAILQ_EMPTY(&depth0_listen)) 891 TAILQ_CONCAT(&lconfig->hc_listen, &depth0_listen, hl_next); 892 if (TAILQ_EMPTY(&lconfig->hc_listen)) { 893 struct hastd_listen *lst; 894 895 if (family_supported(AF_INET)) { 896 lst = calloc(1, sizeof(*lst)); 897 if (lst == NULL) { 898 pjdlog_error("Unable to allocate memory for listen address."); 899 yy_config_free(lconfig); 900 if (exitonerror) 901 exit(EX_TEMPFAIL); 902 return (NULL); 903 } 904 (void)strlcpy(lst->hl_addr, depth0_listen_tcp4, 905 sizeof(lst->hl_addr)); 906 TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 907 } else { 908 pjdlog_debug(1, 909 "No IPv4 support in the kernel, not listening on IPv4 address."); 910 } 911 if (family_supported(AF_INET6)) { 912 lst = calloc(1, sizeof(*lst)); 913 if (lst == NULL) { 914 pjdlog_error("Unable to allocate memory for listen address."); 915 yy_config_free(lconfig); 916 if (exitonerror) 917 exit(EX_TEMPFAIL); 918 return (NULL); 919 } 920 (void)strlcpy(lst->hl_addr, depth0_listen_tcp6, 921 sizeof(lst->hl_addr)); 922 TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 923 } else { 924 pjdlog_debug(1, 925 "No IPv6 support in the kernel, not listening on IPv6 address."); 926 } 927 if (TAILQ_EMPTY(&lconfig->hc_listen)) { 928 pjdlog_error("No address to listen on."); 929 yy_config_free(lconfig); 930 if (exitonerror) 931 exit(EX_TEMPFAIL); 932 return (NULL); 933 } 934 } 935 TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 936 PJDLOG_ASSERT(curres->hr_provname[0] != '\0'); 937 PJDLOG_ASSERT(curres->hr_localpath[0] != '\0'); 938 PJDLOG_ASSERT(curres->hr_remoteaddr[0] != '\0'); 939 940 if (curres->hr_replication == -1) { 941 /* 942 * Replication is not set at resource-level. 943 * Use global or default setting. 944 */ 945 curres->hr_replication = depth0_replication; 946 } 947 if (curres->hr_replication == HAST_REPLICATION_MEMSYNC) { 948 pjdlog_warning("Replication mode \"%s\" is not implemented, falling back to \"%s\".", 949 "memsync", "fullsync"); 950 curres->hr_replication = HAST_REPLICATION_FULLSYNC; 951 } 952 if (curres->hr_checksum == -1) { 953 /* 954 * Checksum is not set at resource-level. 955 * Use global or default setting. 956 */ 957 curres->hr_checksum = depth0_checksum; 958 } 959 if (curres->hr_compression == -1) { 960 /* 961 * Compression is not set at resource-level. 962 * Use global or default setting. 963 */ 964 curres->hr_compression = depth0_compression; 965 } 966 if (curres->hr_timeout == -1) { 967 /* 968 * Timeout is not set at resource-level. 969 * Use global or default setting. 970 */ 971 curres->hr_timeout = depth0_timeout; 972 } 973 if (curres->hr_exec[0] == '\0') { 974 /* 975 * Exec is not set at resource-level. 976 * Use global or default setting. 977 */ 978 strlcpy(curres->hr_exec, depth0_exec, 979 sizeof(curres->hr_exec)); 980 } 981 if (curres->hr_metaflush == -1) { 982 /* 983 * Metaflush is not set at resource-level. 984 * Use global or default setting. 985 */ 986 curres->hr_metaflush = depth0_metaflush; 987 } 988 } 989 990 return (lconfig); 991} 992 993void 994yy_config_free(struct hastd_config *config) 995{ 996 struct hastd_listen *lst; 997 struct hast_resource *res; 998 999 while ((lst = TAILQ_FIRST(&depth0_listen)) != NULL) { 1000 TAILQ_REMOVE(&depth0_listen, lst, hl_next); 1001 free(lst); 1002 } 1003 while ((lst = TAILQ_FIRST(&config->hc_listen)) != NULL) { 1004 TAILQ_REMOVE(&config->hc_listen, lst, hl_next); 1005 free(lst); 1006 } 1007 while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) { 1008 TAILQ_REMOVE(&config->hc_resources, res, hr_next); 1009 free(res); 1010 } 1011 free(config); 1012} |