Deleted Added
sdiff udiff text old ( 230976 ) new ( 235789 )
full compact
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}