commit
						e0a9be549f
					
				
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
								
							| @ -200,7 +200,8 @@ feeds: FORCE | ||||
| 	rm -rf $(TOPDIR)/package/feeds | ||||
| 	mkdir $(TOPDIR)/package/feeds | ||||
| 	[ ! -f $(GLUON_SITEDIR)/modules ] || . $(GLUON_SITEDIR)/modules && for feed in $$GLUON_SITE_FEEDS; do ln -s ../../../packages/$$feed $(TOPDIR)/package/feeds/$$feed; done | ||||
| 	. $(GLUONDIR)/modules && for feed in $$GLUON_FEEDS; do ln -s ../../../packages/$$feed $(TOPDIR)/package/feeds/$$feed; done | ||||
| 	ln -s ../../../package $(TOPDIR)/package/feeds/gluon | ||||
| 	. $(GLUONDIR)/modules && for feed in $$GLUON_FEEDS; do ln -s ../../../packages/$$feed $(TOPDIR)/package/feeds/module_$$feed; done | ||||
| 	+$(GLUONMAKE_EARLY) prepare-tmpinfo | ||||
| 
 | ||||
| config: FORCE | ||||
| @ -284,7 +285,7 @@ prepare-image: FORCE | ||||
| 	+$(SUBMAKE) -C $(TOPDIR)/target/linux/$(BOARD)/image -f $(GLUONDIR)/include/Makefile.image prepare KDIR="$(BOARD_KDIR)" | ||||
| 
 | ||||
| prepare: FORCE | ||||
| 	@$(STAGING_DIR_HOST)/bin/lua $(GLUONDIR)/packages/gluon/gluon/gluon-core/files/usr/lib/lua/gluon/site_config.lua \
 | ||||
| 	@$(STAGING_DIR_HOST)/bin/lua $(GLUONDIR)/package/gluon-core/files/usr/lib/lua/gluon/site_config.lua \
 | ||||
| 		|| (echo 'Your site configuration did not pass validation.'; false) | ||||
| 
 | ||||
| 	mkdir -p $(GLUON_IMAGEDIR) $(BOARD_BUILDDIR) | ||||
|  | ||||
| @ -16,7 +16,7 @@ our mailinglist to discuss it first. | ||||
| 
 | ||||
| Please refrain from using the master branch for anything else but development purposes! | ||||
| Use the most recent release instead. You can list all relaseses by running `git branch -a` | ||||
| and switch to one by running `git checkout v2014.3;make update`. | ||||
| and switch to one by running `git checkout v2014.4;make update`. | ||||
| 
 | ||||
| If you're using the autoupdater, do not autoupdate nodes with anything but releases. | ||||
| If you upgrade using random master commits the nodes *will break* eventually. | ||||
|  | ||||
| @ -26,7 +26,7 @@ fi | ||||
| 
 | ||||
| pushd "$(dirname "$0")/.." >/dev/null | ||||
| 
 | ||||
| find packages -name Makefile | while read makefile; do | ||||
| find ./package packages -name Makefile | while read makefile; do | ||||
| 	dir="$(dirname "$makefile")" | ||||
| 
 | ||||
| 	pushd "$dir" >/dev/null | ||||
| @ -36,7 +36,7 @@ find packages -name Makefile | while read makefile; do | ||||
| 	package="$(basename "$dir")" | ||||
| 
 | ||||
| 	for file in "${SUFFIX}"/*; do | ||||
| 		echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}/${RED}${package}${RESET}/${SUFFIX})" | ||||
| 		echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${SUFFIX})" | ||||
| 	done | ||||
| 	popd >/dev/null | ||||
| done | sort | ||||
|  | ||||
| @ -18,23 +18,23 @@ See also | ||||
| EOHELP | ||||
| 	exit 1 | ||||
| fi | ||||
|   | ||||
| SECRET=$1 | ||||
|   | ||||
| manifest=$2 | ||||
| upper=$(mktemp) | ||||
| lower=$(mktemp) | ||||
|   | ||||
| 
 | ||||
| SECRET="$1" | ||||
| 
 | ||||
| manifest="$2" | ||||
| upper="$(mktemp)" | ||||
| lower="$(mktemp)" | ||||
| 
 | ||||
| awk "BEGIN    { sep=0 } | ||||
|      /^---\$/ { sep=1; next } | ||||
|               { if(sep==0) print > \"$upper\"; | ||||
|                 else       print > \"$lower\"}" \ | ||||
|     $manifest | ||||
|   | ||||
| ecdsasign $upper < $SECRET >> $lower | ||||
|   | ||||
| cat  $upper  > $manifest | ||||
| echo ---    >> $manifest | ||||
| cat  $lower >> $manifest | ||||
|   | ||||
| rm -f $upper $lower | ||||
|     "$manifest" | ||||
| 
 | ||||
| ecdsasign "$upper" < "$SECRET" >> "$lower" | ||||
| 
 | ||||
| cat  "$upper"  > "$manifest" | ||||
| echo ---      >> "$manifest" | ||||
| cat  "$lower" >> "$manifest" | ||||
| 
 | ||||
| rm -f "$upper" "$lower" | ||||
|  | ||||
| @ -47,7 +47,7 @@ master_doc = 'index' | ||||
| 
 | ||||
| # General information about the project. | ||||
| project = 'Gluon' | ||||
| copyright = '2014, Project Gluon' | ||||
| copyright = '2015, Project Gluon' | ||||
| 
 | ||||
| # The version info for the project you're documenting, acts as replacement for | ||||
| # |version| and |release|, also used in various other places throughout the | ||||
|  | ||||
							
								
								
									
										88
									
								
								docs/dev/i18n.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								docs/dev/i18n.rst
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| Internationalization support | ||||
| ============================ | ||||
| 
 | ||||
| General guidelines | ||||
| ------------------ | ||||
| 
 | ||||
| * All config mode packages must be fully translatable, with complete English and German texts. | ||||
| * All new expert mode packages be fully translatable. English texts are required, German texts recommended. | ||||
| * Existing expert mode packages should be made translatable as soon as possible. | ||||
| * The "message IDs" (which are the arguments to the ``translate`` function) should be the | ||||
|   English texts. | ||||
| 
 | ||||
| i18n support in LuCI | ||||
| -------------------- | ||||
| 
 | ||||
| Internationalization support can be found in the ``luci.i18n`` package. | ||||
| Strings are translated using the ``i18n.translate`` and ``i18n.translatef`` functions | ||||
| (``translate`` for static strings, ``translatef`` for printf-like formatted string). | ||||
| 
 | ||||
| Example from the ``gluon-config-mode-geo-location`` package:: | ||||
| 
 | ||||
|   local i18n = require "luci.i18n" | ||||
|   o = s:option(cbi.Flag, "_location", i18n.translate("Show node on the map")) | ||||
| 
 | ||||
| Adding translation templates to Gluon packages | ||||
| ---------------------------------------------- | ||||
| 
 | ||||
| The i18n support is based on the standard gettext system. For each translatable package, | ||||
| a translation template with extension ``.pot`` can be created using the ``i18n-scan.pl`` | ||||
| script from the LuCI repository:: | ||||
| 
 | ||||
|   cd package/gluon-config-mode-geo-location | ||||
|   mkdir i18n | ||||
|   cd i18n | ||||
|   ../../../packages/luci/build/i18n-scan.pl ../files > gluon-config-mode-geo-location.pot | ||||
| 
 | ||||
| The entries in the template can be reordered after the generation if desirable. Lots of standard | ||||
| translations like "Cancel" are already available in the LuCI base translation file (see | ||||
| ``packages/luci/po/templates/base.pot``) and can be removed from the template. | ||||
| 
 | ||||
| In addition, some additions to the Makefile must be made. Instead of OpenWrt's default package.mk, | ||||
| the Gluon version ``$(GLUONDIR)/include/package.mk`` must be used. The i18n files must be installed | ||||
| and PKG_CONFIG_DEPENDS must be added:: | ||||
| 
 | ||||
|   ... | ||||
|   include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
|   PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) | ||||
|   ... | ||||
|   define Build/Compile | ||||
|     $(call GluonBuildI18N,gluon-config-mode-geo-location,i18n) | ||||
|   endef | ||||
| 
 | ||||
|   define Package/gluon-config-mode-geo-location/install | ||||
|     ... | ||||
|     $(call GluonInstallI18N,gluon-config-mode-geo-location,$(1)) | ||||
|   endef | ||||
|   ... | ||||
| 
 | ||||
| 
 | ||||
| Adding translations | ||||
| ------------------- | ||||
| 
 | ||||
| A new translation file for a template can be added using the ``msginit`` command:: | ||||
| 
 | ||||
|   cd package/gluon-config-mode-geo-location/i18n | ||||
|   msginit -l de | ||||
| 
 | ||||
| This will create the file ``de.po`` in which the translations can be added. | ||||
| 
 | ||||
| The translation file can be updated to a new template version using the ``msgmerge`` command:: | ||||
| 
 | ||||
|   msgmerge -U de.po gluon-config-mode-geo-location.pot | ||||
| 
 | ||||
| After the merge, the translation file should be checked for "fuzzy matched" entries where | ||||
| the original English texts have changed. All entries from the the translation file should be | ||||
| translated in the ``.po`` file (or removed from it, so the original English texts are displayed | ||||
| instead). | ||||
| 
 | ||||
| Adding support for new languages | ||||
| -------------------------------- | ||||
| 
 | ||||
| A list of all languages supported by LuCI can be found in the ``include/package.mk`` file of | ||||
| the Gluon repository. Adding translations for these languages is straightforward using the ``msginit`` | ||||
| command. | ||||
| 
 | ||||
| For other languages, support must be added tu LuCI first, which constitutes completely translating | ||||
| the ``base.pot``. Please contact the upstream LuCI maintainers if you'd like to do this. | ||||
							
								
								
									
										154
									
								
								docs/index.rst
									
									
									
									
									
								
							
							
						
						
									
										154
									
								
								docs/index.rst
									
									
									
									
									
								
							| @ -40,57 +40,7 @@ Developer Documentation | ||||
|    dev/upgrade | ||||
|    dev/configmode | ||||
|    dev/wan | ||||
| 
 | ||||
| Supported Devices | ||||
| ----------------- | ||||
| 
 | ||||
| * Buffalo | ||||
| 
 | ||||
|   - WZR-HP-AG300H / WZR-600DHP | ||||
|   - WZR-HP-G450H | ||||
| 
 | ||||
| * D-Link | ||||
| 
 | ||||
|   - DIR-825 (B1) | ||||
| 
 | ||||
| * Linksys | ||||
| 
 | ||||
|   - WRT160NL | ||||
| 
 | ||||
| * TP-Link | ||||
| 
 | ||||
|   - CPE210 (v1) | ||||
|   - CPE220 (v1) | ||||
|   - CPE510 (v1) | ||||
|   - CPE520 (v1) | ||||
|   - TL-MR3020 (v1) | ||||
|   - TL-MR3040 (v1, v2) | ||||
|   - TL-MR3220 (v1) | ||||
|   - TL-MR3420 (v1, v2) | ||||
|   - TL-WA750RE (v1) | ||||
|   - TL-WA801N/ND (v2) | ||||
|   - TL-WA850RE (v1) | ||||
|   - TL-WA901N/ND (v2) | ||||
|   - TL-WDR3500 (v1) | ||||
|   - TL-WDR3600 (v1) | ||||
|   - TL-WDR4300 (v1) | ||||
|   - TL-WR1043N/ND (v1, v2) | ||||
|   - TL-WR703N (v1) | ||||
|   - TL-WR710N (v1) | ||||
|   - TL-WR740N (v1, v3, v4) | ||||
|   - TL-WR741N/ND (v1, v2, v4) | ||||
|   - TL-WR841N/ND (v3, v5, v7, v8, v9) | ||||
|   - TL-WR842N/ND (v1, v2) | ||||
|   - TL-WR941N/ND (v2, v3, v4) | ||||
| 
 | ||||
| * Ubiquiti | ||||
| 
 | ||||
|   - Bullet M2 | ||||
|   - Nanostation M2 | ||||
|   - Picostation M2 | ||||
|   - UniFi AP | ||||
|   - UniFi AP Outdoor | ||||
| 
 | ||||
|    dev/i18n | ||||
| 
 | ||||
| Releases | ||||
| -------- | ||||
| @ -104,6 +54,107 @@ Releases | ||||
|    releases/v2014.3 | ||||
| 
 | ||||
| 
 | ||||
| Supported Devices & Architectures | ||||
| --------------------------------- | ||||
| 
 | ||||
| ar71xx-generic | ||||
| ^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| * Allnet | ||||
| 
 | ||||
|   - ALL0315N | ||||
| 
 | ||||
| * Buffalo | ||||
| 
 | ||||
|   - WZR-HP-AG300H / WZR-600DHP | ||||
|   - WZR-HP-G450H | ||||
| 
 | ||||
| * D-Link | ||||
| 
 | ||||
|   - DIR-825 (B1) | ||||
|   - DIR-615 (C1) | ||||
| 
 | ||||
| * GL-Inet | ||||
| 
 | ||||
|   - 6408A (v1) | ||||
|   - 6416a (v1) | ||||
| 
 | ||||
| * Linksys | ||||
| 
 | ||||
|   - WRT160NL | ||||
| 
 | ||||
| * Netgear | ||||
| 
 | ||||
|   - WNDR3700 (v1, v2) | ||||
|   - WNDR3800 | ||||
| 
 | ||||
| * TP-Link | ||||
| 
 | ||||
|   - CPE210 (v1) | ||||
|   - CPE220 (v1) | ||||
|   - CPE510 (v1) | ||||
|   - CPE520 (v1) | ||||
|   - TL-MR3020 (v1) | ||||
|   - TL-MR3040 (v1, v2) | ||||
|   - TL-MR3220 (v1, v2) | ||||
|   - TL-MR3420 (v1, v2) | ||||
|   - TL-WA701N/ND (v1) | ||||
|   - TL-WA750RE (v1) | ||||
|   - TL-WA801N/ND (v2) | ||||
|   - TL-WA850RE (v1) | ||||
|   - TL-WA860RE (v1) | ||||
|   - TL-WA901N/ND (v2, v3) | ||||
|   - TL-WDR3500 (v1) | ||||
|   - TL-WDR3600 (v1) | ||||
|   - TL-WDR4300 (v1) | ||||
|   - TL-WR1043N/ND (v1, v2) | ||||
|   - TL-WR703N (v1) | ||||
|   - TL-WR710N (v1) | ||||
|   - TL-WR740N (v1, v3, v4) | ||||
|   - TL-WR741N/ND (v1, v2, v4) | ||||
|   - TL-WR743N/ND (v1, v2) | ||||
|   - TL-WR841N/ND (v3, v5, v7, v8, v9) | ||||
|   - TL-WR842N/ND (v1, v2) | ||||
|   - TL-WR941N/ND (v2, v3, v4, v5) | ||||
|   - TL-WR2543N/ND (v1) | ||||
| 
 | ||||
| * Ubiquiti | ||||
| 
 | ||||
|   - Bullet M2 | ||||
|   - Nanostation M2 | ||||
|   - Nanostation M XW | ||||
|   - Loco M XW | ||||
|   - Picostation M2 | ||||
|   - Rocket M2 | ||||
|   - UniFi AP | ||||
|   - UniFi AP Pro | ||||
|   - UniFi AP Outdoor | ||||
| 
 | ||||
| ar71xx-nand | ||||
| ^^^^^^^^^^^ | ||||
| 
 | ||||
| * Netgear | ||||
| 
 | ||||
|   - WNDR3700 (v4) | ||||
|   - WNDR3700 (v1) | ||||
| 
 | ||||
| mpc85xx-generic | ||||
| ^^^^^^^^^^^^^^^ | ||||
| 
 | ||||
| * TP-Link | ||||
| 
 | ||||
|   - TL-WDR4900 (v1) | ||||
| 
 | ||||
| x86-generic | ||||
| ^^^^^^^^^^^ | ||||
| * x86-generic | ||||
| * x86-virtualbox | ||||
| * x86-vmware | ||||
| 
 | ||||
| x86-kvm_guest | ||||
| ^^^^^^^^^^^^^ | ||||
| * x86-kvm | ||||
| 
 | ||||
| License | ||||
| ------- | ||||
| 
 | ||||
| @ -116,4 +167,3 @@ Indices and tables | ||||
| 
 | ||||
| * :ref:`genindex` | ||||
| * :ref:`search` | ||||
| 
 | ||||
|  | ||||
| @ -22,6 +22,45 @@ Site changes | ||||
|     to keep the old behaviour, you have to append the hyphen to the | ||||
|     ``hostname_prefix`` field of your ``site.conf``. | ||||
| 
 | ||||
|   - ``mesh_vpn_fastd``: The default peer group name ``backbone`` isn't hardcoded anymore, any | ||||
|     group name can be used. Instead, the ``fastd_mesh_vpn`` table must now contain an element ``groups``, | ||||
|     for example:: | ||||
| 
 | ||||
|       fastd_mesh_vpn = { | ||||
|           methods = {'salsa2012+umac'}, | ||||
|           mtu = 1426, | ||||
|           groups = { | ||||
|               backbone = { | ||||
|                   limit = 2, | ||||
|                   peers = { | ||||
|                       -- ... | ||||
|                   } | ||||
|               } | ||||
|           } | ||||
|       } | ||||
| 
 | ||||
|   - ``roles``: The display strings for the node roles aren't configured in the ``site.conf`` anymore, but | ||||
|     in the site i18n files. The ``site.conf`` section becomes:: | ||||
| 
 | ||||
|       roles = { | ||||
|           default = 'foo', | ||||
|           list = { | ||||
|               'foo', | ||||
|               'bar', | ||||
|           } | ||||
|       } | ||||
| 
 | ||||
|     The display string use i18n message IDs like ``gluon-luci-node-role:role:foo`` and ``gluon-luci-node-role:role:bar``. | ||||
| 
 | ||||
| 
 | ||||
| * ``site.mk`` | ||||
| 
 | ||||
|   - ``gluon-mesh-batman-adv-15`` is now the recommended batman-adv version for new Gluon deployments. | ||||
| 
 | ||||
|   - The packages ``gluon-setup-mode`` and ``gluon-config-mode-core`` must now be | ||||
|     added to ``GLUON_SITE_PACKAGES`` explicitly (to allow replacing them with | ||||
|     community-specific implementations). | ||||
| 
 | ||||
| Internals | ||||
| ~~~~~~~~~ | ||||
| 
 | ||||
|  | ||||
| @ -54,6 +54,8 @@ | ||||
| 
 | ||||
|     -- (optional) mesh VLAN on 802.11 ad-hoc interface (1-4095) | ||||
|     -- mesh_vlan = 14, | ||||
|     -- client_disabled = true, | ||||
|     -- mesh_disabled = false, | ||||
|   }, | ||||
| 
 | ||||
|   -- Wireless configuration for 5 GHz interfaces. | ||||
| @ -67,6 +69,8 @@ | ||||
|     mesh_bssid = 'xx:xx:xx:xx:xx:xx', | ||||
|     mesh_mcast_rate = 12000, | ||||
|     -- mesh_vlan = 14, | ||||
|     -- client_disabled = true, | ||||
|     -- mesh_disabled = false, | ||||
|   }, | ||||
| 
 | ||||
|   -- The next node feature allows clients to always reach the node it is | ||||
| @ -85,25 +89,41 @@ | ||||
|   fastd_mesh_vpn = { | ||||
|     -- List of crypto-methods to use. | ||||
|     methods = {'salsa2012+umac'}, | ||||
|     -- configurable = true, | ||||
| 
 | ||||
|     mtu = 1426, | ||||
|     backbone = { | ||||
|       -- Limit number of connected peers to reduce bandwidth. | ||||
|       limit = 2, | ||||
|     groups = { | ||||
|       backbone = { | ||||
|         -- Limit number of connected peers to reduce bandwidth. | ||||
|         limit = 2, | ||||
| 
 | ||||
|       -- List of peers. | ||||
|       peers = { | ||||
|         peer1 = { | ||||
|           key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', | ||||
|         -- List of peers. | ||||
|         peers = { | ||||
|           peer1 = { | ||||
|             key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', | ||||
| 
 | ||||
|           -- This is a list, so you might add multiple entries. | ||||
|           remotes = {'ipv4 "xxx.somehost.invalid" port xxxxxx'}, | ||||
|         }, | ||||
|         peer2 = { | ||||
|           key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', | ||||
|           -- You can also omit the ipv4 to allow both connection via ipv4 and ipv6 | ||||
|           remotes = {'"xxx.somehost2.invalid" port xxxxx'}, | ||||
|             -- This is a list, so you might add multiple entries. | ||||
|             remotes = {'ipv4 "xxx.somehost.invalid" port xxxxxx'}, | ||||
|           }, | ||||
|           peer2 = { | ||||
|             key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', | ||||
|             -- You can also omit the ipv4 to allow both connection via ipv4 and ipv6 | ||||
|             remotes = {'"xxx.somehost2.invalid" port xxxxx'}, | ||||
|           }, | ||||
|         }, | ||||
| 
 | ||||
|         -- Optional: nested peer groups | ||||
|         -- groups = { | ||||
|         --   backbone_sub = { | ||||
|         --     ... | ||||
|         --   }, | ||||
|         --   ... | ||||
|         -- }, | ||||
|       }, | ||||
|       -- Optional: additional peer groups, possibly with other limits | ||||
|       -- backbone2 = { | ||||
|       --   ... | ||||
|       -- }, | ||||
|     }, | ||||
|   }, | ||||
| 
 | ||||
| @ -136,13 +156,13 @@ | ||||
|   }, | ||||
| 
 | ||||
|   -- Node roles | ||||
|   -- roles { | ||||
|   -- roles = { | ||||
|   --   default = 'node', | ||||
|   --   list = { | ||||
|   --     node = 'Normal Node', | ||||
|   --     test = 'Test Node', | ||||
|   --     backbone = 'Backbone Node', | ||||
|   --     service = 'Service Node', | ||||
|   --     'node', | ||||
|   --     'test', | ||||
|   --     'backbone', | ||||
|   --     'service', | ||||
|   --   }, | ||||
|   -- }, | ||||
| 
 | ||||
|  | ||||
| @ -5,12 +5,13 @@ | ||||
| #		The gluon-mesh-batman-adv-* package must come first because of the dependency resolution
 | ||||
| 
 | ||||
| GLUON_SITE_PACKAGES := \
 | ||||
| 	gluon-mesh-batman-adv-14 \
 | ||||
| 	gluon-mesh-batman-adv-15 \
 | ||||
| 	gluon-alfred \
 | ||||
| 	gluon-announced \
 | ||||
| 	gluon-autoupdater \
 | ||||
| 	gluon-config-mode-autoupdater \
 | ||||
| 	gluon-config-mode-contact-info \
 | ||||
| 	gluon-config-mode-core \
 | ||||
| 	gluon-config-mode-geo-location \
 | ||||
| 	gluon-config-mode-hostname \
 | ||||
| 	gluon-config-mode-mesh-vpn \
 | ||||
| @ -22,6 +23,7 @@ GLUON_SITE_PACKAGES := \ | ||||
| 	gluon-next-node \
 | ||||
| 	gluon-mesh-vpn-fastd \
 | ||||
| 	gluon-radvd \
 | ||||
| 	gluon-setup-mode \
 | ||||
| 	gluon-status-page \
 | ||||
| 	haveged \
 | ||||
| 	iptables \
 | ||||
|  | ||||
| @ -67,12 +67,14 @@ wifi24 | ||||
|     ``htmode``, the adhoc ssid ``mesh_ssid`` used between devices, the adhoc | ||||
|     bssid ``mesh_bssid`` and the adhoc multicast rate ``mesh_mcast_rate``. | ||||
|     Optionally ``mesh_vlan`` can be used to setup VLAN on top of the 802.11 | ||||
|     ad-hoc interface. | ||||
|     ad-hoc interface. The options ``mesh_disabled`` and ``client_disabled`` | ||||
|     are optional, too. They allow to disable the SSID by default, e.g. for | ||||
|     preconfigured node. This only affects first configuraton. | ||||
|     Combined in an dictionary, e.g.: | ||||
|     :: | ||||
| 
 | ||||
|        wifi24 = { | ||||
|          ssid = 'http://kiel.freifunk.net/', | ||||
|          ssid = 'entenhausen.freifunk.net', | ||||
|          channel = 11, | ||||
|          htmode = 'HT40-', | ||||
|          mesh_ssid = 'ff:ff:ff:ee:ba:be', | ||||
| @ -90,24 +92,37 @@ next_node : package | ||||
|       next_node = { | ||||
|         ip4 = '10.23.42.1', | ||||
|         ip6 = 'fdca:ffee:babe:1::1', | ||||
|         mac = 'ca:ff:ee:ba:be' | ||||
|         mac = 'ca:ff:ee:ba:be:00' | ||||
|       } | ||||
| 
 | ||||
| 
 | ||||
| fastd_mesh_vpn | ||||
|     Remote server setup for vpn. | ||||
|     Remote server setup for the fastd-based mesh VPN. | ||||
| 
 | ||||
|     If `configurable` is false or unset, the method list will be replaced on updates | ||||
|     with the list in the site configuration. Setting `configurable` to `true` will allow the user to | ||||
|     add the method ``null`` to the front of the method list or remove ``null`` from it, | ||||
|     and make this change survive updates. Settings configurable is necessary for the | ||||
|     package `gluon-luci-mesh-vpn-fastd`, which adds a UI for this configuration. | ||||
| 
 | ||||
|     In any case, the ``null`` method should always be the first method in the list | ||||
|     if it is supported at all. You should only set `configurable` to `true` if the | ||||
|     configured peers support both the ``null`` method and methods with encryption. | ||||
|     :: | ||||
| 
 | ||||
|       fastd_mesh_vpn = { | ||||
|         methods = {'salsa2012+gmac'}, | ||||
|         methods = {'salsa2012+umac'}, | ||||
| 	-- configurable = true, | ||||
|         mtu = 1426, | ||||
|         backbone = { | ||||
|           limit = 2, | ||||
|           peers = { | ||||
|             ffki_rz = { | ||||
|               key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', | ||||
|               remotes = {'ipv4 "vpn1.entenhausen.freifunk.net" port 10000'}, | ||||
|             }, | ||||
|         groups = { | ||||
|           backbone = { | ||||
|             limit = 2, | ||||
|             peers = { | ||||
|               peer1 = { | ||||
|                 key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', | ||||
|                 remotes = {'ipv4 "vpn1.entenhausen.freifunk.net" port 10000'}, | ||||
|               }, | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| @ -115,6 +130,9 @@ fastd_mesh_vpn | ||||
| mesh_on_wan : optional | ||||
|     Enables the mesh on the WAN port (``true`` or ``false``). | ||||
| 
 | ||||
| mesh_on_lan : optional | ||||
|     Enables the mesh on the LAN port (``true`` or ``false``). | ||||
| 
 | ||||
| autoupdater : package | ||||
|     Configuration for the autoupdater feature of Gluon. | ||||
|     :: | ||||
| @ -146,15 +164,19 @@ roles : optional | ||||
|     ``default`` takes the default role which is set initially. This value should be | ||||
|     part of ``list``. If you want node owners to change the role via config mode add | ||||
|     the package ``gluon-luci-node-role`` to ``site.mk``. | ||||
| 
 | ||||
|     The strings to display in the LuCI interface can be configured per language in the | ||||
|     ``i18n/en.po``, ``i18n/de.po``, etc. files of the site repository using message IDs like | ||||
|     ``gluon-luci-node-role:role:node`` and ``gluon-luci-node-role:role:backbone``. | ||||
|     :: | ||||
| 
 | ||||
|       roles = { | ||||
|         default = 'node', | ||||
|         list = { | ||||
|           node = 'Normal Node', | ||||
|           test = 'Test Node', | ||||
|           backbone = 'Backbone Node', | ||||
|           service = 'Service Node', | ||||
|           'node', | ||||
|           'test', | ||||
|           'backbone', | ||||
|           'service', | ||||
|         }, | ||||
|       }, | ||||
| 
 | ||||
| @ -176,7 +198,7 @@ setup_mode : package | ||||
|     ``skip`` is set to ``true``. This is optional and may be left out. | ||||
|     :: | ||||
| 
 | ||||
|       setup_mode { | ||||
|       setup_mode = { | ||||
|         skip = true, | ||||
|       }, | ||||
| 
 | ||||
| @ -280,7 +302,7 @@ This is a non-exhaustive list of site-repos from various communities: | ||||
| * `site-ffgoe <https://github.com/freifunk-goettingen/site-ffgoe>`_ (Göttingen) | ||||
| * `site-ffhh <https://github.com/freifunkhamburg/site-ffhh>`_ (Hamburg) | ||||
| * `site-ffhgw <https://github.com/lorenzo-greifswald/site-ffhgw>`_ (Greifswald) | ||||
| * `site-ffhl <https://github.com/freifunk-gluon/site-ffhl>`_ (Lübeck) | ||||
| * `site-ffhl <https://github.com/freifunk-luebeck/site-ffhl>`_ (Lübeck) | ||||
| * `site-ffmd <https://github.com/FreifunkMD/site-ffmd>`_ (Magdeburg) | ||||
| * `site-ffmwu <https://github.com/freifunk-mwu/site-ffmwu>`_ (Mainz, Wiesbaden & Umgebung) | ||||
| * `site-ffmyk <https://github.com/FreifunkMYK/site-ffmyk>`_ (Mayen-Koblenz) | ||||
|  | ||||
							
								
								
									
										4
									
								
								modules
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								modules
									
									
									
									
									
								
							| @ -1,14 +1,14 @@ | ||||
| GLUON_FEEDS='openwrt gluon routing luci' | ||||
| 
 | ||||
| OPENWRT_REPO=git://git.openwrt.org/14.07/openwrt.git | ||||
| OPENWRT_COMMIT=64ae631f20eb349b47dae30c461ab33b5c4ac5c2 | ||||
| OPENWRT_COMMIT=179bab8b1700d74b28cc6cd25322f9a1ad670107 | ||||
| 
 | ||||
| PACKAGES_OPENWRT_REPO=git://github.com/openwrt/packages.git | ||||
| PACKAGES_OPENWRT_COMMIT=01fcd1f29174a56d6ddb59901ed8c67ea42c3a8f | ||||
| PACKAGES_OPENWRT_BRANCH=for-14.07 | ||||
| 
 | ||||
| PACKAGES_GLUON_REPO=git://github.com/freifunk-gluon/packages.git | ||||
| PACKAGES_GLUON_COMMIT=f5c0865d5025a7e6ad3ff6c21ca5206ac972ba75 | ||||
| PACKAGES_GLUON_COMMIT=e8ee21d116a0abc2e328b0ee181d79845654582e | ||||
| 
 | ||||
| PACKAGES_ROUTING_REPO=git://github.com/openwrt-routing/packages.git | ||||
| PACKAGES_ROUTING_COMMIT=5d4ad63897b435d5df0f39a49bd58962c22c33b8 | ||||
|  | ||||
							
								
								
									
										32
									
								
								package/gluon-alfred/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								package/gluon-alfred/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-alfred | ||||
| PKG_VERSION:=1 | ||||
| PKG_RELEASE:=1 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(INCLUDE_DIR)/package.mk | ||||
| 
 | ||||
| define Package/gluon-alfred | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   DEPENDS:=+gluon-core +gluon-announce +gluon-cron +alfred | ||||
|   TITLE:=Configure alfred | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-alfred/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-alfred)) | ||||
							
								
								
									
										1
									
								
								package/gluon-alfred/files/lib/gluon/cron/alfred
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								package/gluon-alfred/files/lib/gluon/cron/alfred
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| * * * * * /lib/gluon/announce/collect.lua nodeinfo | gzip | alfred -s 158; /lib/gluon/announce/collect.lua statistics | gzip | alfred -s 159; /lib/gluon/announce/collect.lua neighbours | gzip | alfred -s 160 | ||||
							
								
								
									
										19
									
								
								package/gluon-alfred/files/lib/gluon/upgrade/500-enable-alfred
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										19
									
								
								package/gluon-alfred/files/lib/gluon/upgrade/500-enable-alfred
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,19 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local uci = require 'luci.model.uci' | ||||
| local c = uci.cursor() | ||||
| 
 | ||||
| 
 | ||||
| c:delete('alfred', 'alfred') | ||||
| c:section('alfred', 'alfred', 'alfred', | ||||
| 	  { | ||||
| 		  interface = 'br-client', | ||||
| 		  mode = 'slave', | ||||
| 		  batmanif = 'bat0', | ||||
| 		  start_vis = '1', | ||||
| 		  run_facters = '0', | ||||
| 	  } | ||||
| ) | ||||
| 
 | ||||
| c:save('alfred') | ||||
| c:commit('alfred') | ||||
							
								
								
									
										32
									
								
								package/gluon-announce/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								package/gluon-announce/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-announce | ||||
| PKG_VERSION:=1 | ||||
| PKG_RELEASE:=1 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(INCLUDE_DIR)/package.mk | ||||
| 
 | ||||
| define Package/gluon-announce | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   DEPENDS:=+gluon-core +luci-lib-json +lua-ethtool-stats | ||||
|   TITLE:=Lua scripts announcing various information | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-announce/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-announce)) | ||||
							
								
								
									
										10
									
								
								package/gluon-announce/files/lib/gluon/announce/collect.lua
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								package/gluon-announce/files/lib/gluon/announce/collect.lua
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,10 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local announce = require 'gluon.announce' | ||||
| local json = require 'luci.json' | ||||
| local ltn12 = require 'luci.ltn12' | ||||
| 
 | ||||
| local announce_dir = '/lib/gluon/announce/' .. arg[1] .. '.d' | ||||
| 
 | ||||
| encoder = json.Encoder(announce.collect_dir(announce_dir)) | ||||
| ltn12.pump.all(encoder:source(), ltn12.sink.file(io.stdout)) | ||||
| @ -0,0 +1 @@ | ||||
| return require('gluon.util').node_id() | ||||
| @ -0,0 +1 @@ | ||||
| return require('platform_info').get_model() | ||||
| @ -0,0 +1,14 @@ | ||||
| local n = 0 | ||||
| 
 | ||||
| local cpus = util.trim(fs.readfile('/sys/devices/system/cpu/online')) | ||||
| 
 | ||||
| for _, entry in ipairs(cpus:split(',')) do | ||||
|   local x, y = entry:match('(%d+)-(%d+)') | ||||
|   if x then | ||||
|     n = n + tonumber(y) - tonumber(x) + 1 | ||||
|   else | ||||
|     n = n + 1 | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| return n | ||||
| @ -0,0 +1 @@ | ||||
| return uci:get_first('system', 'system', 'hostname') | ||||
| @ -0,0 +1 @@ | ||||
| return require('gluon.sysconfig').primary_mac | ||||
| @ -0,0 +1 @@ | ||||
| return require('gluon.util').node_id() | ||||
| @ -0,0 +1,4 @@ | ||||
| return { | ||||
| 	base = 'gluon-' .. util.trim(fs.readfile('/lib/gluon/gluon-version')), | ||||
| 	release = util.trim(fs.readfile('/lib/gluon/release')), | ||||
| } | ||||
| @ -0,0 +1,3 @@ | ||||
| local site = require 'gluon.site_config' | ||||
| 
 | ||||
| return site.site_code | ||||
| @ -0,0 +1 @@ | ||||
| return tonumber(fs.readfile('/proc/uptime'):match('^[^ ]+ ([^ ]+)')) | ||||
| @ -0,0 +1 @@ | ||||
| return tonumber(fs.readfile('/proc/loadavg'):match('^([^ ]+) ')) | ||||
| @ -0,0 +1,13 @@ | ||||
| local data = fs.readfile('/proc/meminfo') | ||||
| 
 | ||||
| local fields = {} | ||||
| for k, v in data:gmatch('([^\n:]+):%s*(%d+) kB') do | ||||
| 	fields[k] = tonumber(v) | ||||
| end | ||||
| 
 | ||||
| return { | ||||
| 	total = fields.MemTotal, | ||||
| 	free = fields.MemFree, | ||||
| 	buffers = fields.Buffers, | ||||
| 	cached = fields.Cached, | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| return require('gluon.util').node_id() | ||||
| @ -0,0 +1,3 @@ | ||||
| local running, total = fs.readfile('/proc/loadavg'):match('^[^ ]+ [^ ]+ [^ ]+ (%d+)/(%d+)') | ||||
| 
 | ||||
| return { running = tonumber(running), total = tonumber(total) } | ||||
| @ -0,0 +1,4 @@ | ||||
| local fs = require "nixio.fs" | ||||
| 
 | ||||
| local st = fs.statvfs("/") | ||||
| return 1 - st.bfree / st.blocks | ||||
| @ -0,0 +1 @@ | ||||
| return tonumber(fs.readfile('/proc/uptime'):match('^([^ ]+) ')) | ||||
							
								
								
									
										33
									
								
								package/gluon-announce/files/usr/lib/lua/gluon/announce.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								package/gluon-announce/files/usr/lib/lua/gluon/announce.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| module('gluon.announce', package.seeall) | ||||
| 
 | ||||
| fs = require 'luci.fs' | ||||
| uci = require('luci.model.uci').cursor() | ||||
| util = require 'luci.util' | ||||
| 
 | ||||
| local function collect_entry(entry) | ||||
| 	if fs.isdirectory(entry) then | ||||
| 		return collect_dir(entry) | ||||
| 	else | ||||
| 		return setfenv(loadfile(entry), _M)() | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| function collect_dir(dir) | ||||
| 	local ret = {} | ||||
| 
 | ||||
| 	for _, entry in ipairs(fs.dir(dir)) do | ||||
| 		if entry:sub(1, 1) ~= '.' then | ||||
| 			local ok, val = pcall(collect_entry, dir .. '/' .. entry) | ||||
| 			if ok then | ||||
| 				ret[entry] = val | ||||
| 			else | ||||
| 				io.stderr:write(val, '\n') | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	return ret | ||||
| end | ||||
| 
 | ||||
							
								
								
									
										32
									
								
								package/gluon-announced/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								package/gluon-announced/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-announced | ||||
| PKG_VERSION:=2 | ||||
| PKG_RELEASE:=1 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(INCLUDE_DIR)/package.mk | ||||
| 
 | ||||
| define Package/gluon-announced | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Provides node information to the network | ||||
|   DEPENDS:=+gluon-announce +respondd +lua-deflate | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-announced/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-announced)) | ||||
| @ -0,0 +1,45 @@ | ||||
| #!/bin/sh | ||||
| 
 | ||||
| . /usr/share/libubox/jshn.sh | ||||
| . /lib/functions/service.sh | ||||
| 
 | ||||
| DEVLIST=/var/run/gluon-announced.devs | ||||
| DAEMON=/usr/bin/respondd | ||||
| 
 | ||||
| ifname_to_dev () { | ||||
| 	json_load "$(ubus call network.interface.$1 status)" | ||||
| 	json_get_var dev device | ||||
| 
 | ||||
| 	echo "$dev" | ||||
| } | ||||
| 
 | ||||
| restart_announced () { | ||||
| 	SERVICE_USE_PID=1 | ||||
| 	SERVICE_WRITE_PID=1 | ||||
| 	SERVICE_DAEMONIZE=1 | ||||
| 
 | ||||
| 	DEVS=$(cat $DEVLIST | while read dev iface; do echo -n " -i $dev"; done) | ||||
| 
 | ||||
| 	service_stop $DAEMON | ||||
| 	service_start $DAEMON -g ff02::2:1001 -p 1001 -c 'return require("gluon.announced").handle_request' $DEVS | ||||
| } | ||||
| 
 | ||||
| case "$ACTION" in | ||||
| 	ifdown) | ||||
| 		sed -i "/$INTERFACE/d" $DEVLIST | ||||
| 		;; | ||||
| 	ifup) | ||||
| 		DEVICE="$(ifname_to_dev "$INTERFACE")" | ||||
| 		MESH="$(cat "/sys/class/net/$DEVICE/batman_adv/mesh_iface" 2>/dev/null)" | ||||
| 
 | ||||
| 		[ "$MESH" = "bat0" -o "$INTERFACE" = "client" ] || exit 0 | ||||
| 
 | ||||
| 		DEVS=$(cat $DEVLIST; echo $DEVICE $INTERFACE) | ||||
| 
 | ||||
| 		echo "$DEVS" | sort -u > $DEVLIST | ||||
| 
 | ||||
| 		restart_announced | ||||
| 
 | ||||
| 		;; | ||||
| esac | ||||
| 
 | ||||
							
								
								
									
										18
									
								
								package/gluon-announced/files/lib/gluon/upgrade/400-announced-firewall
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								package/gluon-announced/files/lib/gluon/upgrade/400-announced-firewall
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,18 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local uci = require('luci.model.uci').cursor() | ||||
| 
 | ||||
| -- Allow announced port on WAN to allow resolving neighbours over mesh-on-wan | ||||
| uci:section('firewall', 'rule', 'wan_announced', | ||||
|   { | ||||
|     name = 'wan_announced', | ||||
|     src = 'wan', | ||||
|     src_ip = 'fe80::/64', | ||||
|     dest_port = '1001', | ||||
|     proto = 'udp', | ||||
|     target = 'ACCEPT', | ||||
|   } | ||||
| ) | ||||
| 
 | ||||
| uci:save('firewall') | ||||
| uci:commit('firewall') | ||||
| @ -0,0 +1,33 @@ | ||||
| local announce = require 'gluon.announce' | ||||
| local deflate = require 'deflate' | ||||
| local json = require 'luci.json' | ||||
| 
 | ||||
| 
 | ||||
| local function collect(type) | ||||
|   return announce.collect_dir('/lib/gluon/announce/' .. type .. '.d') | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| module('gluon.announced', package.seeall) | ||||
| 
 | ||||
| function handle_request(query) | ||||
|   if query:match('^nodeinfo$') then | ||||
|     return json.encode(collect('nodeinfo')) | ||||
|   end | ||||
| 
 | ||||
|   local m = query:match('^GET ([a-z ]+)$') | ||||
|   if m then | ||||
|     local data = {} | ||||
| 
 | ||||
|     for q in m:gmatch('([a-z]+)') do | ||||
|       local ok, val = pcall(collect, q) | ||||
|       if ok then | ||||
|         data[q] = val | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     if next(data) then | ||||
|       return deflate.compress(json.encode(data)) | ||||
|     end | ||||
|   end | ||||
| end | ||||
							
								
								
									
										36
									
								
								package/gluon-authorized-keys/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-authorized-keys/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-authorized-keys | ||||
| PKG_VERSION:=2 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| define Package/gluon-authorized-keys | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Fill /etc/dropbear/authorized_keys from site.conf | ||||
|   DEPENDS:=+gluon-core | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-authorized-keys/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-authorized-keys/postinst | ||||
| #!/bin/sh
 | ||||
| $(call GluonCheckSite,check_site.lua) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-authorized-keys)) | ||||
							
								
								
									
										1
									
								
								package/gluon-authorized-keys/check_site.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								package/gluon-authorized-keys/check_site.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| need_string_array 'authorized_keys' | ||||
							
								
								
									
										22
									
								
								package/gluon-authorized-keys/files/lib/gluon/upgrade/100-authorized-keys
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								package/gluon-authorized-keys/files/lib/gluon/upgrade/100-authorized-keys
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,22 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local site = require 'gluon.site_config' | ||||
| local file = '/etc/dropbear/authorized_keys' | ||||
| 
 | ||||
| local keys = {} | ||||
| 
 | ||||
| function load_keys() | ||||
|   for line in io.lines(file) do | ||||
|     keys[line] = true | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| pcall(load_keys) | ||||
| 
 | ||||
| local f = io.open(file, 'a') | ||||
| for _, key in ipairs(site.authorized_keys) do | ||||
|   if not keys[key] then | ||||
|     f:write(key .. '\n') | ||||
|   end | ||||
| end | ||||
| f:close() | ||||
							
								
								
									
										42
									
								
								package/gluon-autoupdater/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								package/gluon-autoupdater/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-autoupdater | ||||
| PKG_VERSION:=4 | ||||
| PKG_RELEASE:=$(GLUON_BRANCH) | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| define Package/gluon-autoupdater | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   DEPENDS:=+gluon-core +gluon-cron +autoupdater | ||||
|   TITLE:=Automatically update firmware | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-autoupdater/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 
 | ||||
| 	if [ '$(GLUON_BRANCH)' ]; then \
 | ||||
| 		$(INSTALL_DIR) $(1)/lib/gluon/autoupdater; \
 | ||||
| 		echo '$(GLUON_BRANCH)' > $(1)/lib/gluon/autoupdater/default_branch; \
 | ||||
| 	fi | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-autoupdater/postinst | ||||
| #!/bin/sh
 | ||||
| $(call GluonCheckSite,check_site.lua) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-autoupdater)) | ||||
							
								
								
									
										12
									
								
								package/gluon-autoupdater/check_site.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								package/gluon-autoupdater/check_site.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| need_string 'autoupdater.branch' | ||||
| 
 | ||||
| local function check_branch(k, _) | ||||
|    local prefix = string.format('autoupdater.branches[%q].', k) | ||||
| 
 | ||||
|    need_string(prefix .. 'name') | ||||
|    need_string_array(prefix .. 'mirrors') | ||||
|    need_number(prefix .. 'good_signatures') | ||||
|    need_string_array(prefix .. 'pubkeys') | ||||
| end | ||||
| 
 | ||||
| need_table('autoupdater.branches', check_branch) | ||||
| @ -0,0 +1,7 @@ | ||||
| local autoupdater = uci:get_all('autoupdater', 'settings') | ||||
| if autoupdater then | ||||
| 	return { | ||||
| 		branch = autoupdater['branch'], | ||||
| 		enabled = uci:get_bool('autoupdater', 'settings', 'enabled'), | ||||
| 	} | ||||
| end | ||||
							
								
								
									
										57
									
								
								package/gluon-autoupdater/files/lib/gluon/upgrade/500-autoupdater
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										57
									
								
								package/gluon-autoupdater/files/lib/gluon/upgrade/500-autoupdater
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,57 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local site = require 'gluon.site_config' | ||||
| local uci = require 'luci.model.uci' | ||||
| 
 | ||||
| local c = uci.cursor() | ||||
| 
 | ||||
| 
 | ||||
| for name, config in pairs(site.autoupdater.branches) do | ||||
| 	c:delete('autoupdater', name) | ||||
| 	c:section('autoupdater', 'branch', name, | ||||
| 		  { | ||||
| 			  name = config.name, | ||||
| 			  mirror = config.mirrors, | ||||
| 			  good_signatures = config.good_signatures, | ||||
| 			  pubkey = config.pubkeys, | ||||
| 		  } | ||||
| 	) | ||||
| end | ||||
| 
 | ||||
| if not c:get('autoupdater', 'settings') then | ||||
| 	local enabled = 0 | ||||
| 	local branch = site.autoupdater.branch | ||||
| 
 | ||||
| 	local f = io.open('/lib/gluon/autoupdater/default_branch') | ||||
| 	if f then | ||||
| 		enabled = 1 | ||||
| 		branch = f:read('*line') | ||||
| 		f:close() | ||||
| 	end | ||||
| 
 | ||||
| 	c:section('autoupdater', 'autoupdater', 'settings', | ||||
| 		  { | ||||
| 			  enabled = enabled, | ||||
| 			  branch = branch, | ||||
| 		  } | ||||
| 	) | ||||
| end | ||||
| 
 | ||||
| c:set('autoupdater', 'settings', 'version_file', '/lib/gluon/release') | ||||
| 
 | ||||
| c:save('autoupdater') | ||||
| c:commit('autoupdater') | ||||
| 
 | ||||
| 
 | ||||
| local autoupdater_util = require 'autoupdater.util' | ||||
| autoupdater_util.randomseed() | ||||
| 
 | ||||
| 
 | ||||
| -- Perform updates at a random time between 04:00 and 05:00, and once an hour | ||||
| -- a fallback update (used after the regular updates haven't | ||||
| local minute = math.random(0, 59) | ||||
| 
 | ||||
| local f = io.open('/lib/gluon/cron/autoupdater', 'w') | ||||
| f:write(string.format('%i 4 * * * /usr/sbin/autoupdater\n', minute)) | ||||
| f:write(string.format('%i 0-3,5-23 * * * /usr/sbin/autoupdater --fallback\n', minute)) | ||||
| f:close() | ||||
							
								
								
									
										40
									
								
								package/gluon-config-mode-autoupdater/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								package/gluon-config-mode-autoupdater/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-config-mode-autoupdater | ||||
| PKG_VERSION:=1 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) | ||||
| 
 | ||||
| 
 | ||||
| define Package/gluon-config-mode-autoupdater | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Let the user know whether the autoupdater is enabled or not. | ||||
|   DEPENDS:=gluon-config-mode-core-virtual +gluon-autoupdater | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-config-mode-autoupdater/description | ||||
| 	Luci based config mode | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| 	$(call GluonBuildI18N,gluon-config-mode-autoupdater,i18n) | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-config-mode-autoupdater/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 	$(call GluonInstallI18N,gluon-config-mode-autoupdater,$(1)) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-config-mode-autoupdater)) | ||||
| @ -0,0 +1,19 @@ | ||||
| local cbi = require "luci.cbi" | ||||
| local i18n = require "luci.i18n" | ||||
| local uci = luci.model.uci.cursor() | ||||
| 
 | ||||
| local M = {} | ||||
| 
 | ||||
| function M.section(form) | ||||
|   local enabled = uci:get_bool("autoupdater", "settings", "enabled") | ||||
|   if enabled then | ||||
|     local s = form:section(cbi.SimpleSection, nil, | ||||
|       i18n.translate('This node will automatically update its firmware when a new version is available.')) | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| function M.handle(data) | ||||
|   return | ||||
| end | ||||
| 
 | ||||
| return M | ||||
							
								
								
									
										17
									
								
								package/gluon-config-mode-autoupdater/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								package/gluon-config-mode-autoupdater/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "PO-Revision-Date: 2015-03-18 16:03+0100\n" | ||||
| "Last-Translator: Matthias Schiffer <mschiffer@universe-factory.net>\n" | ||||
| "Language-Team: German\n" | ||||
| "Language: de\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| 
 | ||||
| msgid "" | ||||
| "This node will automatically update its firmware when a new version is " | ||||
| "available." | ||||
| msgstr "Dieser Knoten aktualisiert seine Firmware automatisch, sobald " | ||||
| "eine neue Version vorliegt." | ||||
| @ -0,0 +1,7 @@ | ||||
| msgid "" | ||||
| msgstr "Content-Type: text/plain; charset=UTF-8" | ||||
| 
 | ||||
| msgid "" | ||||
| "This node will automatically update its firmware when a new version is " | ||||
| "available." | ||||
| msgstr "" | ||||
							
								
								
									
										36
									
								
								package/gluon-config-mode-contact-info/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-config-mode-contact-info/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-config-mode-contact-info | ||||
| PKG_VERSION:=1 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) | ||||
| 
 | ||||
| 
 | ||||
| define Package/gluon-config-mode-contact-info | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Set a custom string that will be distributed in the mesh. | ||||
|   DEPENDS:=gluon-config-mode-core-virtual +gluon-node-info | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| 	$(call GluonBuildI18N,gluon-config-mode-contact-info,i18n) | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-config-mode-contact-info/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 	$(call GluonInstallI18N,gluon-config-mode-contact-info,$(1)) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-config-mode-contact-info)) | ||||
| @ -0,0 +1,34 @@ | ||||
| local cbi = require "luci.cbi" | ||||
| local i18n = require "luci.i18n" | ||||
| local uci = luci.model.uci.cursor() | ||||
| 
 | ||||
| local M = {} | ||||
| 
 | ||||
| function M.section(form) | ||||
|   local s = form:section(cbi.SimpleSection, nil, i18n.translate( | ||||
|     'You can provide your contact information here to ' | ||||
|       .. 'allow others to contact you. Please note that ' | ||||
|       .. 'this information will be visible <em>publicly</em> ' | ||||
|       .. 'on the internet together with your node\'s coordinates.' | ||||
|     ) | ||||
|   ) | ||||
| 
 | ||||
|   local o = s:option(cbi.Value, "_contact", i18n.translate("Contact info")) | ||||
|   o.default = uci:get_first("gluon-node-info", "owner", "contact", "") | ||||
|   o.rmempty = true | ||||
|   o.datatype = "string" | ||||
|   o.description = i18n.translate("e.g. E-mail or phone number") | ||||
|   o.maxlen = 140 | ||||
| end | ||||
| 
 | ||||
| function M.handle(data) | ||||
|   if data._contact ~= nil then | ||||
|     uci:set("gluon-node-info", uci:get_first("gluon-node-info", "owner"), "contact", data._contact) | ||||
|   else | ||||
|     uci:delete("gluon-node-info", uci:get_first("gluon-node-info", "owner"), "contact") | ||||
|   end | ||||
|   uci:save("gluon-node-info") | ||||
|   uci:commit("gluon-node-info") | ||||
| end | ||||
| 
 | ||||
| return M | ||||
							
								
								
									
										27
									
								
								package/gluon-config-mode-contact-info/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								package/gluon-config-mode-contact-info/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "PO-Revision-Date: 2015-03-19 01:32+0100\n" | ||||
| "Last-Translator: Matthias Schiffer <mschiffer@universe-factory.net>\n" | ||||
| "Language-Team: German\n" | ||||
| "Language: de\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| 
 | ||||
| msgid "Contact info" | ||||
| msgstr "Kontakt" | ||||
| 
 | ||||
| msgid "" | ||||
| "You can provide your contact information here to allow others to contact " | ||||
| "you. Please note that this information will be visible <em>publicly</em> on " | ||||
| "the internet together with your node's coordinates." | ||||
| msgstr "" | ||||
| "Hier kannst du einen <em>öffentlichen</em> Hinweis hinterlegen, um anderen " | ||||
| "zu ermöglichen, Kontakt mit dir aufzunehmen. Bitte beachte, dass " | ||||
| "dieser Hinweis auch öffentlich im Internet, zusammen mit den Koordinaten " | ||||
| "deines Knotens, einsehbar sein wird." | ||||
| 
 | ||||
| msgid "e.g. E-mail or phone number" | ||||
| msgstr "z.B. E-Mail oder Telefonnummer" | ||||
| @ -0,0 +1,14 @@ | ||||
| msgid "" | ||||
| msgstr "Content-Type: text/plain; charset=UTF-8" | ||||
| 
 | ||||
| msgid "Contact info" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "" | ||||
| "You can provide your contact information here to allow others to contact " | ||||
| "you. Please note that this information will be visible <em>publicly</em> on " | ||||
| "the internet together with your node's coordinates." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "e.g. E-mail or phone number" | ||||
| msgstr "" | ||||
							
								
								
									
										40
									
								
								package/gluon-config-mode-core/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								package/gluon-config-mode-core/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| # Copyright (C) 2012 Nils Schneider <nils at nilsschneider.net>
 | ||||
| # This is free software, licensed under the Apache 2.0 license.
 | ||||
| 
 | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-config-mode-core | ||||
| PKG_VERSION:=2 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) | ||||
| 
 | ||||
| 
 | ||||
| define Package/gluon-config-mode-core | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Luci based config mode for user friendly setup of new mesh nodes | ||||
|   DEPENDS:=gluon-setup-mode-virtual +gluon-luci-theme +gluon-lock-password $(GLUON_I18N_PACKAGES) | ||||
|   PROVIDES:=gluon-config-mode-core-virtual | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| 	$(call GluonBuildI18N,gluon-config-mode-core,i18n) | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-config-mode-core/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 	$(call GluonInstallI18N,gluon-config-mode-core,$(1)) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-config-mode-core)) | ||||
| @ -0,0 +1,3 @@ | ||||
| local i18n = require 'luci.i18n' | ||||
| 
 | ||||
| return function () luci.template.render_string(i18n.translate('gluon-config-mode:reboot')) end | ||||
| @ -0,0 +1,89 @@ | ||||
| --[[ | ||||
| Copyright 2013 Nils Schneider <nils@nilsschneider.net> | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
| 	http://www.apache.org/licenses/LICENSE-2.0 | ||||
| 
 | ||||
| $Id$ | ||||
| ]]-- | ||||
| 
 | ||||
| module("luci.controller.gluon-config-mode.index", package.seeall) | ||||
| 
 | ||||
| function index() | ||||
|   local uci_state = luci.model.uci.cursor_state() | ||||
| 
 | ||||
|   if uci_state:get_first("gluon-setup-mode", "setup_mode", "running", "0") == "1" then | ||||
|     local root = node() | ||||
|     if not root.target then | ||||
|       root.target = alias("gluon-config-mode") | ||||
|       root.index = true | ||||
|     end | ||||
| 
 | ||||
|     page          = node() | ||||
|     page.lock     = true | ||||
|     page.target   = alias("gluon-config-mode") | ||||
|     page.subindex = true | ||||
|     page.index    = false | ||||
| 
 | ||||
|     page          = node("gluon-config-mode") | ||||
|     page.title    = _("Wizard") | ||||
|     page.target   = alias("gluon-config-mode", "wizard") | ||||
|     page.order    = 5 | ||||
|     page.setuser  = "root" | ||||
|     page.setgroup = "root" | ||||
|     page.index    = true | ||||
| 
 | ||||
|     entry({"gluon-config-mode", "wizard"}, form("gluon-config-mode/wizard")).index = true | ||||
|     entry({"gluon-config-mode", "reboot"}, call("action_reboot")) | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| function action_reboot() | ||||
|   local uci = luci.model.uci.cursor() | ||||
| 
 | ||||
|   uci:set("gluon-setup-mode", uci:get_first("gluon-setup-mode", "setup_mode"), "configured", "1") | ||||
|   uci:save("gluon-setup-mode") | ||||
|   uci:commit("gluon-setup-mode") | ||||
| 
 | ||||
|   if nixio.fork() ~= 0 then | ||||
|     local fs = require "luci.fs" | ||||
| 
 | ||||
|     local parts_dir = "/lib/gluon/config-mode/reboot/" | ||||
|     local files = fs.dir(parts_dir) | ||||
| 
 | ||||
|     table.sort(files) | ||||
| 
 | ||||
|     local parts = {} | ||||
| 
 | ||||
|     for _, entry in ipairs(files) do | ||||
|       if entry:sub(1, 1) ~= '.' then | ||||
|         local f = dofile(parts_dir .. '/' .. entry) | ||||
|         if f ~= nil then | ||||
|           table.insert(parts, f) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     local hostname = uci:get_first("system", "system", "hostname") | ||||
| 
 | ||||
|     luci.template.render("gluon/config-mode/reboot", { parts=parts | ||||
|                                                      , hostname=hostname | ||||
|                                                      }) | ||||
|   else | ||||
|     debug.setfenv(io.stdout, debug.getfenv(io.open '/dev/null')) | ||||
|     io.stdout:close() | ||||
| 
 | ||||
|     -- Sleep a little so the browser can fetch everything required to | ||||
|     -- display the reboot page, then reboot the device. | ||||
|     nixio.nanosleep(2) | ||||
| 
 | ||||
|     -- Run reboot with popen so it gets its own std filehandles. | ||||
|     io.popen("reboot") | ||||
| 
 | ||||
|     -- Prevent any further execution in this child. | ||||
|     os.exit() | ||||
|   end | ||||
| end | ||||
| @ -0,0 +1,38 @@ | ||||
| local wizard_dir = "/lib/gluon/config-mode/wizard/" | ||||
| local i18n = luci.i18n | ||||
| local uci = luci.model.uci.cursor() | ||||
| local fs = require "luci.fs" | ||||
| local f, s | ||||
| 
 | ||||
| local wizard = {} | ||||
| local files = fs.dir(wizard_dir) | ||||
| 
 | ||||
| table.sort(files) | ||||
| 
 | ||||
| for _, entry in ipairs(files) do | ||||
|   if entry:sub(1, 1) ~= '.' then | ||||
|     table.insert(wizard, dofile(wizard_dir .. '/' .. entry)) | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| f = SimpleForm("wizard") | ||||
| f.reset = false | ||||
| f.template = "gluon/cbi/config-mode" | ||||
| 
 | ||||
| for _, s in ipairs(wizard) do | ||||
|   s.section(f) | ||||
| end | ||||
| 
 | ||||
| function f.handle(self, state, data) | ||||
|   if state == FORM_VALID then | ||||
|     for _, s in ipairs(wizard) do | ||||
|       s.handle(data) | ||||
|     end | ||||
| 
 | ||||
|     luci.http.redirect(luci.dispatcher.build_url("gluon-config-mode", "reboot")) | ||||
|   end | ||||
| 
 | ||||
|   return true | ||||
| end | ||||
| 
 | ||||
| return f | ||||
| @ -0,0 +1,46 @@ | ||||
| <%- | ||||
| 	local sysconfig = require 'gluon.sysconfig' | ||||
| 	local i18n = require 'luci.i18n' | ||||
| 	local template = require 'luci.template' | ||||
| -%> | ||||
| 
 | ||||
| <h2><%:Welcome!%></h2> | ||||
| <p> | ||||
| 	<%= template.render_string(i18n.translate('gluon-config-mode:welcome'), {hostname=hostname, sysconfig=sysconfig}) %> | ||||
| </p> | ||||
| 
 | ||||
| <% if not self.embedded then %> | ||||
| <form method="post" enctype="multipart/form-data" action="<%=REQUEST_URI%>"> | ||||
| 	<div> | ||||
| 		<script type="text/javascript" src="<%=resource%>/cbi.js"></script> | ||||
| 		<input type="hidden" name="cbi.submit" value="1" /> | ||||
| 	</div> | ||||
| <% end %> | ||||
| 	<div class="cbi-map" id="cbi-<%=self.config%>"> | ||||
| 		<% if self.title and #self.title > 0 then %><h2><a id="content" name="content"><%=self.title%></a></h2><% end %> | ||||
| 		<% if self.description and #self.description > 0 then %><div class="cbi-map-descr"><%=self.description%></div><% end %> | ||||
| 		<% self:render_children() %> | ||||
| 		<br /> | ||||
| 	</div> | ||||
| <%- if self.message then %> | ||||
| 	<div><%=self.message%></div> | ||||
| <%- end %> | ||||
| <%- if self.errmessage then %> | ||||
| 	<div class="error"><%=self.errmessage%></div> | ||||
| <%- end %> | ||||
| <% if not self.embedded then %> | ||||
| 	<div class="cbi-page-actions"> | ||||
| <%- | ||||
| 		if type(self.hidden) == "table" then | ||||
| 		  for k, v in pairs(self.hidden) do | ||||
| -%> | ||||
| 		<input type="hidden" id="<%=k%>" name="<%=k%>" value="<%=pcdata(v)%>" /> | ||||
| <%- | ||||
| 		  end | ||||
| 		end | ||||
| %> | ||||
| 		<input class="cbi-button cbi-button-save" type="submit" value="<%:Save & restart%>" /> | ||||
| 		<script type="text/javascript">cbi_d_update();</script> | ||||
| 	</div> | ||||
| </form> | ||||
| <% end %> | ||||
| @ -0,0 +1,17 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%=luci.i18n.context.lang%>" lang="<%=luci.i18n.context.lang%>"> | ||||
|   <head> | ||||
|     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | ||||
|     <title><%=hostname%> is rebooting</title> | ||||
|     <link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" /> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div id="maincontainer"> | ||||
|       <div id="maincontent"> | ||||
|         <h2><%:Your node's setup is now complete.%></h2> | ||||
|         <% for k, v in ipairs(parts) do v() end %> | ||||
|       </div> | ||||
|     </div> | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										24
									
								
								package/gluon-config-mode-core/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								package/gluon-config-mode-core/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "PO-Revision-Date: 2015-03-19 02:07+0100\n" | ||||
| "Last-Translator: Matthias Schiffer <mschiffer@universe-factory.net>\n" | ||||
| "Language-Team: German\n" | ||||
| "Language: de\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| 
 | ||||
| #, fuzzy | ||||
| msgid "Save & restart" | ||||
| msgstr "Speichern & Neustarten" | ||||
| 
 | ||||
| msgid "Welcome!" | ||||
| msgstr "Willkommen!" | ||||
| 
 | ||||
| msgid "Wizard" | ||||
| msgstr "Wizard" | ||||
| 
 | ||||
| msgid "Your node's setup is now complete." | ||||
| msgstr "Dein Knoten ist nun fertig eingerichtet." | ||||
| @ -0,0 +1,14 @@ | ||||
| msgid "" | ||||
| msgstr "Content-Type: text/plain; charset=UTF-8" | ||||
| 
 | ||||
| msgid "Save & restart" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Welcome!" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Wizard" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Your node's setup is now complete." | ||||
| msgstr "" | ||||
							
								
								
									
										36
									
								
								package/gluon-config-mode-geo-location/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-config-mode-geo-location/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-config-mode-geo-location | ||||
| PKG_VERSION:=1 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) | ||||
| 
 | ||||
| 
 | ||||
| define Package/gluon-config-mode-geo-location | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Set geographic location of a node | ||||
|   DEPENDS:=gluon-config-mode-core-virtual +gluon-node-info | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| 	$(call GluonBuildI18N,gluon-config-mode-geo-location,i18n) | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-config-mode-geo-location/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 	$(call GluonInstallI18N,gluon-config-mode-geo-location,$(1)) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-config-mode-geo-location)) | ||||
| @ -0,0 +1,60 @@ | ||||
| local cbi = require "luci.cbi" | ||||
| local i18n = require "luci.i18n" | ||||
| local uci = luci.model.uci.cursor() | ||||
| 
 | ||||
| local M = {} | ||||
| 
 | ||||
| function M.section(form) | ||||
|   local s = form:section(cbi.SimpleSection, nil, i18n.translate( | ||||
|     'If you want the location of your node to be displayed on the map, ' | ||||
|       .. 'you can enter its coordinates here. Specifying the altitude ' | ||||
|       .. 'is optional and should only be done if a proper value is known.')) | ||||
| 
 | ||||
| 
 | ||||
|   local o | ||||
| 
 | ||||
|   o = s:option(cbi.Flag, "_location", i18n.translate("Show node on the map")) | ||||
|   o.default = uci:get_first("gluon-node-info", "location", "share_location", o.disabled) | ||||
|   o.rmempty = false | ||||
| 
 | ||||
|   o = s:option(cbi.Value, "_latitude", i18n.translate("Latitude")) | ||||
|   o.default = uci:get_first("gluon-node-info", "location", "latitude") | ||||
|   o:depends("_location", "1") | ||||
|   o.rmempty = false | ||||
|   o.datatype = "float" | ||||
|   o.description = i18n.translatef("e.g. %s", "53.873621") | ||||
| 
 | ||||
|   o = s:option(cbi.Value, "_longitude", i18n.translate("Longitude")) | ||||
|   o.default = uci:get_first("gluon-node-info", "location", "longitude") | ||||
|   o:depends("_location", "1") | ||||
|   o.rmempty = false | ||||
|   o.datatype = "float" | ||||
|   o.description = i18n.translatef("e.g. %s", "10.689901") | ||||
| 
 | ||||
|   o = s:option(cbi.Value, "_altitude", i18n.translate("Altitude")) | ||||
|   o.default = uci:get_first("gluon-node-info", "location", "altitude") | ||||
|   o:depends("_location", "1") | ||||
|   o.rmempty = true | ||||
|   o.datatype = "float" | ||||
|   o.description = i18n.translatef("e.g. %s", "11.51") | ||||
| 
 | ||||
| end | ||||
| 
 | ||||
| function M.handle(data) | ||||
|   local sname = uci:get_first("gluon-node-info", "location") | ||||
| 
 | ||||
|   uci:set("gluon-node-info", sname, "share_location", data._location) | ||||
|   if data._location and data._latitude ~= nil and data._longitude ~= nil then | ||||
|     uci:set("gluon-node-info", sname, "latitude", data._latitude) | ||||
|     uci:set("gluon-node-info", sname, "longitude", data._longitude) | ||||
|     if data._altitude ~= nil then | ||||
|       uci:set("gluon-node-info", sname, "altitude", data._altitude) | ||||
|     else | ||||
|       uci:delete("gluon-node-info", sname, "altitude") | ||||
|     end | ||||
|   end | ||||
|   uci:save("gluon-node-info") | ||||
|   uci:commit("gluon-node-info") | ||||
| end | ||||
| 
 | ||||
| return M | ||||
							
								
								
									
										36
									
								
								package/gluon-config-mode-geo-location/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-config-mode-geo-location/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: gluon-config-mode-geo-location\n" | ||||
| "PO-Revision-Date: 2015-03-23 02:18+0100\n" | ||||
| "Last-Translator: Martin Weinelt <martin@darmstadt.freifunk.net>\n" | ||||
| "Language-Team: German\n" | ||||
| "Language: de\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| 
 | ||||
| msgid "" | ||||
| "If you want the location of your node to be displayed on the map, you can " | ||||
| "enter its coordinates here. Specifying the altitude is optional and should " | ||||
| "only be done if a proper value is known." | ||||
| msgstr "" | ||||
| "Um deinen Knoten auf der Karte anzeigen zu können, benötigen wir seine " | ||||
| "Koordinaten. Hier hast du die Möglichkeit, diese zu hinterlegen. Die " | ||||
| "Höhenangabe ist optional und sollte nur gesetzt werden, wenn ein exakter " | ||||
| "Wert bekannt ist." | ||||
| 
 | ||||
| msgid "Latitude" | ||||
| msgstr "Breitengrad" | ||||
| 
 | ||||
| msgid "Longitude" | ||||
| msgstr "Längengrad" | ||||
| 
 | ||||
| msgid "Altitude" | ||||
| msgstr "Höhenmeter über Normalnull" | ||||
| 
 | ||||
| msgid "Show node on the map" | ||||
| msgstr "Knoten auf der Karte anzeigen" | ||||
| 
 | ||||
| msgid "e.g. %s" | ||||
| msgstr "z.B. %s" | ||||
| @ -0,0 +1,23 @@ | ||||
| msgid "" | ||||
| msgstr "Content-Type: text/plain; charset=UTF-8" | ||||
| 
 | ||||
| msgid "" | ||||
| "If you want the location of your node to be displayed on the map, you can " | ||||
| "enter its coordinates here. Specifying the altitude is optional and should " | ||||
| "only be done if a proper value is known." | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Latitude" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Longitude" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Altitude" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Show node on the map" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "e.g. %s" | ||||
| msgstr "" | ||||
							
								
								
									
										36
									
								
								package/gluon-config-mode-hostname/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-config-mode-hostname/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-config-mode-hostname | ||||
| PKG_VERSION:=1 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) | ||||
| 
 | ||||
| 
 | ||||
| define Package/gluon-config-mode-hostname | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Set the hostname | ||||
|   DEPENDS:=gluon-config-mode-core-virtual | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| 	$(call GluonBuildI18N,gluon-config-mode-hostname,i18n) | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-config-mode-hostname/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 	$(call GluonInstallI18N,gluon-config-mode-hostname,$(1)) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-config-mode-hostname)) | ||||
| @ -0,0 +1,21 @@ | ||||
| local cbi = require "luci.cbi" | ||||
| local i18n = require "luci.i18n" | ||||
| local uci = luci.model.uci.cursor() | ||||
| 
 | ||||
| local M = {} | ||||
| 
 | ||||
| function M.section(form) | ||||
|   local s = form:section(cbi.SimpleSection, nil, nil) | ||||
|   local o = s:option(cbi.Value, "_hostname", i18n.translate("Node name")) | ||||
|   o.value = uci:get_first("system", "system", "hostname") | ||||
|   o.rmempty = false | ||||
|   o.datatype = "hostname" | ||||
| end | ||||
| 
 | ||||
| function M.handle(data) | ||||
|   uci:set("system", uci:get_first("system", "system"), "hostname", data._hostname) | ||||
|   uci:save("system") | ||||
|   uci:commit("system") | ||||
| end | ||||
| 
 | ||||
| return M | ||||
							
								
								
									
										14
									
								
								package/gluon-config-mode-hostname/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								package/gluon-config-mode-hostname/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "PO-Revision-Date: 2015-03-19 00:54+0100\n" | ||||
| "Last-Translator: Matthias Schiffer <mschiffer@universe-factory.net>\n" | ||||
| "Language-Team: German\n" | ||||
| "Language: de\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| 
 | ||||
| msgid "Node name" | ||||
| msgstr "Name dieses Knotens" | ||||
| @ -0,0 +1,5 @@ | ||||
| msgid "" | ||||
| msgstr "Content-Type: text/plain; charset=UTF-8" | ||||
| 
 | ||||
| msgid "Node name" | ||||
| msgstr "" | ||||
							
								
								
									
										36
									
								
								package/gluon-config-mode-mesh-vpn/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-config-mode-mesh-vpn/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-config-mode-mesh-vpn | ||||
| PKG_VERSION:=2 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) | ||||
| 
 | ||||
| 
 | ||||
| define Package/gluon-config-mode-mesh-vpn | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Toggle mesh-vpn and bandwidth limit | ||||
|   DEPENDS:=gluon-config-mode-core-virtual +gluon-mesh-vpn-fastd +gluon-simple-tc | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| 	$(call GluonBuildI18N,gluon-config-mode-mesh-vpn,i18n) | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-config-mode-mesh-vpn/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 	$(call GluonInstallI18N,gluon-config-mode-mesh-vpn,$(1)) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-config-mode-mesh-vpn)) | ||||
| @ -0,0 +1,29 @@ | ||||
| local uci = luci.model.uci.cursor() | ||||
| local meshvpn_enabled = uci:get("fastd", "mesh_vpn", "enabled", "0") | ||||
| 
 | ||||
| if meshvpn_enabled ~= "1" then | ||||
|   return nil | ||||
| else | ||||
|   local i18n = require "luci.i18n" | ||||
|   local util = require "luci.util" | ||||
|   local site = require 'gluon.site_config' | ||||
|   local sysconfig = require 'gluon.sysconfig' | ||||
| 
 | ||||
|   local pubkey = util.trim(util.exec("/etc/init.d/fastd show_key " .. "mesh_vpn")) | ||||
|   local hostname = uci:get_first("system", "system", "hostname") | ||||
| 
 | ||||
|   local msg = [[<p>]] .. i18n.translate('gluon-config-mode:pubkey') .. [[</p> | ||||
|                <div class="the-key"> | ||||
|                  # <%= hostname %> | ||||
|                  <br/> | ||||
|                <%= pubkey %> | ||||
|                </div>]] | ||||
| 
 | ||||
|   return function () | ||||
|            luci.template.render_string(msg, { pubkey=pubkey | ||||
|                                             , hostname=hostname | ||||
|                                             , site=site | ||||
|                                             , sysconfig=sysconfig | ||||
|                                             }) | ||||
|          end | ||||
| end | ||||
| @ -0,0 +1,64 @@ | ||||
| local cbi = require "luci.cbi" | ||||
| local i18n = require "luci.i18n" | ||||
| local uci = luci.model.uci.cursor() | ||||
| 
 | ||||
| local M = {} | ||||
| 
 | ||||
| function M.section(form) | ||||
|   local msg = i18n.translate('Your internet connection can be used to establish an ' .. | ||||
|                              'encrypted connection with other nodes. ' .. | ||||
|                              'Enable this option if there are no other nodes reachable ' .. | ||||
|                              'over WLAN in your vicinity or you want to make a part of ' .. | ||||
|                              'your connection\'s bandwidth available for the network. You can limit how ' .. | ||||
|                              'much bandwidth the node will use at most.') | ||||
|   local s = form:section(cbi.SimpleSection, nil, msg) | ||||
| 
 | ||||
|   local o | ||||
| 
 | ||||
|   o = s:option(cbi.Flag, "_meshvpn", i18n.translate("Use internet connection (mesh VPN)")) | ||||
|   o.default = uci:get_bool("fastd", "mesh_vpn", "enabled") and o.enabled or o.disabled | ||||
|   o.rmempty = false | ||||
| 
 | ||||
|   o = s:option(cbi.Flag, "_limit_enabled", i18n.translate("Limit bandwidth")) | ||||
|   o:depends("_meshvpn", "1") | ||||
|   o.default = uci:get_bool("gluon-simple-tc", "mesh_vpn", "enabled") and o.enabled or o.disabled | ||||
|   o.rmempty = false | ||||
| 
 | ||||
|   o = s:option(cbi.Value, "_limit_ingress", i18n.translate("Downstream (kbit/s)")) | ||||
|   o:depends("_limit_enabled", "1") | ||||
|   o.value = uci:get("gluon-simple-tc", "mesh_vpn", "limit_ingress") | ||||
|   o.rmempty = false | ||||
|   o.datatype = "integer" | ||||
| 
 | ||||
|   o = s:option(cbi.Value, "_limit_egress", i18n.translate("Upstream (kbit/s)")) | ||||
|   o:depends("_limit_enabled", "1") | ||||
|   o.value = uci:get("gluon-simple-tc", "mesh_vpn", "limit_egress") | ||||
|   o.rmempty = false | ||||
|   o.datatype = "integer" | ||||
| end | ||||
| 
 | ||||
| function M.handle(data) | ||||
|   uci:set("fastd", "mesh_vpn", "enabled", data._meshvpn) | ||||
|   uci:save("fastd") | ||||
|   uci:commit("fastd") | ||||
| 
 | ||||
|   -- checks for nil needed due to o:depends(...) | ||||
|   if data._limit_enabled ~= nil then | ||||
|     uci:set("gluon-simple-tc", "mesh_vpn", "interface") | ||||
|     uci:set("gluon-simple-tc", "mesh_vpn", "enabled", data._limit_enabled) | ||||
|     uci:set("gluon-simple-tc", "mesh_vpn", "ifname", "mesh-vpn") | ||||
| 
 | ||||
|     if data._limit_ingress ~= nil then | ||||
|       uci:set("gluon-simple-tc", "mesh_vpn", "limit_ingress", data._limit_ingress) | ||||
|     end | ||||
| 
 | ||||
|     if data._limit_egress ~= nil then | ||||
|       uci:set("gluon-simple-tc", "mesh_vpn", "limit_egress", data._limit_egress) | ||||
|     end | ||||
| 
 | ||||
|     uci:commit("gluon-simple-tc") | ||||
|     uci:commit("gluon-simple-tc") | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| return M | ||||
							
								
								
									
										36
									
								
								package/gluon-config-mode-mesh-vpn/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-config-mode-mesh-vpn/i18n/de.po
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\n" | ||||
| "PO-Revision-Date: 2015-03-19 22:05+0100\n" | ||||
| "Last-Translator: Matthias Schiffer <mschiffer@universe-factory.net>\n" | ||||
| "Language-Team: German\n" | ||||
| "Language: de\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| 
 | ||||
| msgid "Downstream (kbit/s)" | ||||
| msgstr "Downstream (kbit/s)" | ||||
| 
 | ||||
| msgid "Limit bandwidth" | ||||
| msgstr "Bandbreite begrenzen" | ||||
| 
 | ||||
| msgid "Upstream (kbit/s)" | ||||
| msgstr "Upstream (kbit/s)" | ||||
| 
 | ||||
| msgid "Use internet connection (mesh VPN)" | ||||
| msgstr "Internetverbindung nutzen (Mesh-VPN)" | ||||
| 
 | ||||
| msgid "" | ||||
| "Your internet connection can be used to establish an encrypted connection " | ||||
| "with other nodes. Enable this option if there are no other nodes reachable " | ||||
| "over WLAN in your vicinity or you want to make a part of your connection's " | ||||
| "bandwidth available for the network. You can limit how much bandwidth the " | ||||
| "node will use at most." | ||||
| msgstr "" | ||||
| "Dein Knoten kann deine Internetverbindung nutzen um darüber eine " | ||||
| "verschlüsselte Verbindung zu anderen Knoten aufzubauen. Die dafür " | ||||
| "genutzte Bandbreite kannst du beschränken. Aktiviere die Option, falls keine " | ||||
| "per WLAN erreichbaren Nachbarknoten in deiner Nähe sind oder du deine " | ||||
| "Internetverbindung für das Mesh-Netzwerk zur Verfügung stellen möchtest." | ||||
| @ -0,0 +1,22 @@ | ||||
| msgid "" | ||||
| msgstr "Content-Type: text/plain; charset=UTF-8" | ||||
| 
 | ||||
| msgid "Downstream (kbit/s)" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Limit bandwidth" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Upstream (kbit/s)" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "Use internet connection (mesh VPN)" | ||||
| msgstr "" | ||||
| 
 | ||||
| msgid "" | ||||
| "Your internet connection can be used to establish an encrypted connection " | ||||
| "with other nodes. Enable this option if there are no other nodes reachable " | ||||
| "over WLAN in your vicinity or you want to make a part of your connection's " | ||||
| "bandwidth available for the network. You can limit how much bandwidth the " | ||||
| "node will use at most." | ||||
| msgstr "" | ||||
							
								
								
									
										59
									
								
								package/gluon-core/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								package/gluon-core/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-core | ||||
| PKG_VERSION:=3 | ||||
| PKG_RELEASE:=$(GLUON_VERSION) | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(GLUONDIR)/include/package.mk | ||||
| 
 | ||||
| define Package/gluon-core | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Base files of Gluon | ||||
|   DEPENDS:=+gluon-site +lua-platform-info +luci-lib-nixio +odhcp6c +firewall | ||||
| endef | ||||
| 
 | ||||
| 
 | ||||
| define LangConfig | ||||
| config GLUON_LANG_$(1) | ||||
| 	bool "$(GLUON_LANG_$(1)) language support" | ||||
| 	depends on PACKAGE_gluon-core | ||||
| 	default n | ||||
| 
 | ||||
| endef | ||||
| 
 | ||||
| 
 | ||||
| define Package/gluon-core/config | ||||
| $(foreach lang,$(GLUON_SUPPORTED_LANGS),$(call LangConfig,$(lang))) | ||||
| endef | ||||
| 
 | ||||
| 
 | ||||
| define Package/gluon-core/description | ||||
| 	Gluon community wifi mesh firmware framework: core | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-core/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 
 | ||||
| 	$(INSTALL_DIR) $(1)/lib/gluon | ||||
| 	echo "$(GLUON_VERSION)" > $(1)/lib/gluon/gluon-version | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-core/postinst | ||||
| #!/bin/sh
 | ||||
| $(call GluonCheckSite,check_site.lua) | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-core)) | ||||
							
								
								
									
										10
									
								
								package/gluon-core/check_site.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								package/gluon-core/check_site.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| need_string 'site_code' | ||||
| need_string 'site_name' | ||||
| 
 | ||||
| need_string('hostname_prefix', false) | ||||
| need_string 'timezone' | ||||
| 
 | ||||
| need_string_array('ntp_servers', false) | ||||
| 
 | ||||
| need_string_match('prefix4', '^%d+.%d+.%d+.%d+/%d+$') | ||||
| need_string_match('prefix6', '^[%x:]+/%d+$') | ||||
							
								
								
									
										5
									
								
								package/gluon-core/files/etc/uci-defaults/zzz-gluon-upgrade
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										5
									
								
								package/gluon-core/files/etc/uci-defaults/zzz-gluon-upgrade
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,5 @@ | ||||
| #!/bin/sh | ||||
| 
 | ||||
| for script in /lib/gluon/upgrade/*; do | ||||
| 	"$script" | ||||
| done | ||||
							
								
								
									
										10
									
								
								package/gluon-core/files/lib/gluon/upgrade/001-upgrade
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								package/gluon-core/files/lib/gluon/upgrade/001-upgrade
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,10 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local fs = require 'luci.fs' | ||||
| local sysconfig = require 'gluon.sysconfig' | ||||
| 
 | ||||
| 
 | ||||
| if fs.isfile('/lib/gluon/version/core') and not sysconfig.gluon_version then | ||||
|   -- This isn't an initial upgrade, so set gluon_version | ||||
|   sysconfig.gluon_version = '' | ||||
| end | ||||
							
								
								
									
										42
									
								
								package/gluon-core/files/lib/gluon/upgrade/010-primary-mac
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										42
									
								
								package/gluon-core/files/lib/gluon/upgrade/010-primary-mac
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,42 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local sysconfig = require 'gluon.sysconfig' | ||||
| 
 | ||||
| 
 | ||||
| if sysconfig.primary_mac then | ||||
|   os.exit(0) | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| local platform = require 'gluon.platform' | ||||
| 
 | ||||
| local fs = require 'luci.fs' | ||||
| local util = require 'luci.util' | ||||
| 
 | ||||
| 
 | ||||
| local try_files = { | ||||
|   '/sys/class/ieee80211/phy0/macaddress', | ||||
|   '/sys/class/net/eth0/address', | ||||
| } | ||||
| 
 | ||||
| if platform.match('ar71xx', 'generic', {'tl-wdr3600', 'tl-wdr4300'}) then | ||||
|   table.insert(try_files, 1, '/sys/class/ieee80211/phy1/macaddress') | ||||
| end | ||||
| 
 | ||||
| if platform.match('ar71xx', 'generic', {'unifi-outdoor-plus'}) then | ||||
|   table.insert(try_files, 1, '/sys/class/net/eth0/address') | ||||
| end | ||||
| 
 | ||||
| if platform.match('ar71xx', 'generic', {'archer-c5', 'archer-c7'}) then | ||||
|   table.insert(try_files, 1, '/sys/class/net/eth1/address') | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| for _, file in ipairs(try_files) do | ||||
|   local addr = fs.readfile(file) | ||||
| 
 | ||||
|   if addr then | ||||
|     sysconfig.primary_mac = util.trim(addr) | ||||
|     break | ||||
|   end | ||||
| end | ||||
							
								
								
									
										36
									
								
								package/gluon-core/files/lib/gluon/upgrade/020-interfaces
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-core/files/lib/gluon/upgrade/020-interfaces
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,36 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local sysconfig = require 'gluon.sysconfig' | ||||
| local gluon_util = require 'gluon.util' | ||||
| local platform = require 'gluon.platform' | ||||
| 
 | ||||
| local uci = require('luci.model.uci').cursor() | ||||
| 
 | ||||
| 
 | ||||
| if not (sysconfig.lan_ifname or sysconfig.wan_ifname) then | ||||
|   local function iface_exists(name) | ||||
|     return (gluon_util.exec('ip', 'link', 'show', 'dev', (name:gsub('%..*$', ''))) == 0) | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
|   local lan_ifname = uci:get('network', 'lan', 'ifname') | ||||
|   local wan_ifname = uci:get('network', 'wan', 'ifname') | ||||
| 
 | ||||
|   if platform.match('ar71xx', 'generic', {'cpe510', 'nanostation-m', 'nanostation-m-xw', 'unifi-outdoor-plus'}) then | ||||
|     lan_ifname, wan_ifname = wan_ifname, lan_ifname | ||||
|   end | ||||
| 
 | ||||
|   if wan_ifname and iface_exists(wan_ifname) then | ||||
|     sysconfig.wan_ifname = wan_ifname | ||||
|     sysconfig.lan_ifname = lan_ifname | ||||
|   else | ||||
|     sysconfig.wan_ifname = lan_ifname | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
|   uci:delete('network', 'lan') | ||||
|   uci:delete('network', 'wan') | ||||
| 
 | ||||
|   uci:save('network') | ||||
|   uci:commit('network') | ||||
| end | ||||
							
								
								
									
										18
									
								
								package/gluon-core/files/lib/gluon/upgrade/030-system
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								package/gluon-core/files/lib/gluon/upgrade/030-system
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,18 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local sysconfig = require 'gluon.sysconfig' | ||||
| 
 | ||||
| -- Initial | ||||
| if not sysconfig.gluon_version then | ||||
|   local site = require 'gluon.site_config' | ||||
|   local util = require 'gluon.util' | ||||
|   local uci = require('luci.model.uci').cursor() | ||||
| 
 | ||||
|   local system = uci:get_first('system', 'system') | ||||
| 
 | ||||
|   uci:set('system', system, 'hostname', (site.hostname_prefix or '') .. util.node_id()) | ||||
|   uci:set('system', system, 'timezone', site.timezone) | ||||
| 
 | ||||
|   uci:save('system') | ||||
|   uci:commit('system') | ||||
| end | ||||
							
								
								
									
										5
									
								
								package/gluon-core/files/lib/gluon/upgrade/100-dnsmasq
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										5
									
								
								package/gluon-core/files/lib/gluon/upgrade/100-dnsmasq
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,5 @@ | ||||
| #!/bin/sh | ||||
| 
 | ||||
| if [ -e /etc/dnsmasq.conf ]; then | ||||
| 	sed -i -e '/^conf-dir=\/lib\/gluon\/dnsmasq\.d$/d' -e '/^conf-dir=\/var\/gluon\/dnsmasq\.d$/d' /etc/dnsmasq.conf | ||||
| fi | ||||
							
								
								
									
										59
									
								
								package/gluon-core/files/lib/gluon/upgrade/110-network
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										59
									
								
								package/gluon-core/files/lib/gluon/upgrade/110-network
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,59 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local uci = require('luci.model.uci').cursor() | ||||
| local sysctl = require 'gluon.sysctl' | ||||
| local sysconfig = require 'gluon.sysconfig' | ||||
| 
 | ||||
| 
 | ||||
| uci:section('network', 'interface', 'wan', | ||||
| 	    { | ||||
| 	      ifname = sysconfig.wan_ifname, | ||||
| 	      type = 'bridge', | ||||
| 	      igmp_snooping = 0, | ||||
| 	      peerdns = 0, | ||||
| 	      auto = 1, | ||||
| 	    } | ||||
| ) | ||||
| 
 | ||||
| if not uci:get('network', 'wan', 'proto') then | ||||
|   uci:set('network', 'wan', 'proto', 'dhcp') | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| uci:section('network', 'interface', 'wan6', | ||||
| 	    { | ||||
| 	      ifname = 'br-wan', | ||||
| 	      peerdns = 0, | ||||
| 	      ip6table = 1, | ||||
| 	    } | ||||
| ) | ||||
| 
 | ||||
| if not uci:get('network', 'wan6', 'proto') then | ||||
|   uci:set('network', 'wan6', 'proto', 'dhcpv6') | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| uci:section('network', 'rule6', 'wan6_lookup', | ||||
| 	    { | ||||
| 	       mark = '0x01/0x01', | ||||
| 	       lookup = 1, | ||||
| 	    } | ||||
| ) | ||||
| 
 | ||||
| uci:section('network', 'route6', 'wan6_unreachable', | ||||
| 	    { | ||||
| 	       type = 'unreachable', | ||||
| 	       interface = 'loopback', | ||||
| 	       target = '::/0', | ||||
| 	       gateway = '::', | ||||
| 	       table = 1, | ||||
| 	       metric = 65535, | ||||
| 	    } | ||||
| ) | ||||
| 
 | ||||
| uci:save('network') | ||||
| uci:commit('network') | ||||
| 
 | ||||
| 
 | ||||
| sysctl.set('net.ipv6.conf.all.accept_ra', 0) | ||||
| sysctl.set('net.ipv6.conf.default.accept_ra', 0) | ||||
							
								
								
									
										14
									
								
								package/gluon-core/files/lib/gluon/upgrade/120-ntp-servers
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								package/gluon-core/files/lib/gluon/upgrade/120-ntp-servers
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,14 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local site = require 'gluon.site_config' | ||||
| local uci = require 'luci.model.uci' | ||||
| 
 | ||||
| if not site.ntp_servers or #site.ntp_servers == 0 then | ||||
| 	os.exit(0) | ||||
| end | ||||
| 
 | ||||
| local c = uci.cursor() | ||||
| c:delete('system', 'ntp', 'server') | ||||
| c:set_list('system', 'ntp', 'server', site.ntp_servers) | ||||
| c:save('system') | ||||
| c:commit('system') | ||||
							
								
								
									
										5
									
								
								package/gluon-core/files/lib/gluon/upgrade/130-reboot-on-oom
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										5
									
								
								package/gluon-core/files/lib/gluon/upgrade/130-reboot-on-oom
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,5 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local sysctl = require 'gluon.sysctl' | ||||
| 
 | ||||
| sysctl.set('vm.panic_on_oom', 1) | ||||
							
								
								
									
										30
									
								
								package/gluon-core/files/lib/gluon/upgrade/140-firewall-rules
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										30
									
								
								package/gluon-core/files/lib/gluon/upgrade/140-firewall-rules
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,30 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local site = require 'gluon.site_config' | ||||
| local uci = require 'luci.model.uci' | ||||
| 
 | ||||
| local c = uci.cursor() | ||||
| 
 | ||||
| 
 | ||||
| local function reject_input_on_wan(zone) | ||||
| 	if zone.name == 'wan' then | ||||
| 		c:set('firewall', zone['.name'], 'input', 'REJECT') | ||||
| 		c:set('firewall', zone['.name'], 'conntrack', '1') | ||||
| 	end | ||||
| 
 | ||||
| 	return true | ||||
| end | ||||
| c:foreach('firewall', 'zone', reject_input_on_wan) | ||||
| 
 | ||||
| c:section('firewall', 'rule', 'wan_ssh', | ||||
| 	  { | ||||
| 		  name = 'wan_ssh', | ||||
| 		  src = 'wan', | ||||
| 		  dest_port = '22', | ||||
| 		  proto = 'tcp', | ||||
| 		  target = 'ACCEPT', | ||||
| 	  } | ||||
| ) | ||||
| 
 | ||||
| c:save('firewall') | ||||
| c:commit('firewall') | ||||
							
								
								
									
										12
									
								
								package/gluon-core/files/lib/gluon/upgrade/200-wireless
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								package/gluon-core/files/lib/gluon/upgrade/200-wireless
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,12 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local sysconfig = require 'gluon.sysconfig' | ||||
| 
 | ||||
| -- Initial | ||||
| if not sysconfig.gluon_version then | ||||
|   local uci = require('luci.model.uci').cursor() | ||||
| 
 | ||||
|   uci:delete_all('wireless', 'wifi-iface') | ||||
|   uci:save('wireless') | ||||
|   uci:commit('wireless') | ||||
| end | ||||
							
								
								
									
										11
									
								
								package/gluon-core/files/lib/gluon/upgrade/999-version
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								package/gluon-core/files/lib/gluon/upgrade/999-version
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,11 @@ | ||||
| #!/usr/bin/lua | ||||
| 
 | ||||
| local sysconfig = require 'gluon.sysconfig' | ||||
| 
 | ||||
| local fs = require 'luci.fs' | ||||
| local util = require 'luci.util' | ||||
| 
 | ||||
| 
 | ||||
| -- Save the Gluon version in the sysconfig so we know which version we | ||||
| -- upgraded from after the next upgrade | ||||
| sysconfig.gluon_version = util.trim(fs.readfile('/lib/gluon/gluon-version')) | ||||
							
								
								
									
										1
									
								
								package/gluon-core/files/lib/upgrade/keep.d/gluon
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								package/gluon-core/files/lib/upgrade/keep.d/gluon
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| /lib/gluon/core/sysconfig/ | ||||
							
								
								
									
										31
									
								
								package/gluon-core/files/usr/lib/lua/gluon/platform.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								package/gluon-core/files/usr/lib/lua/gluon/platform.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| local platform_info = require 'platform_info' | ||||
| local util = require 'luci.util' | ||||
| 
 | ||||
| local setmetatable = setmetatable | ||||
| 
 | ||||
| 
 | ||||
| module 'gluon.platform' | ||||
| 
 | ||||
| setmetatable(_M, | ||||
| 	     { | ||||
| 		__index = platform_info, | ||||
| 	     } | ||||
| ) | ||||
| 
 | ||||
| function match(target, subtarget, boards) | ||||
|    if get_target() ~= target then | ||||
|       return false | ||||
|    end | ||||
| 
 | ||||
|    if get_subtarget() ~= subtarget then | ||||
|       return false | ||||
|    end | ||||
| 
 | ||||
|    if not util.contains(boards, get_board_name()) then | ||||
|       return false | ||||
|    end | ||||
| 
 | ||||
|    return true | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										21
									
								
								package/gluon-core/files/usr/lib/lua/gluon/site_config.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								package/gluon-core/files/usr/lib/lua/gluon/site_config.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| local config = os.getenv('GLUON_SITE_CONFIG') or '/lib/gluon/site.conf' | ||||
| 
 | ||||
| local function loader() | ||||
|    coroutine.yield('return ') | ||||
|    coroutine.yield(io.open(config):read('*a')) | ||||
| end | ||||
| 
 | ||||
| -- setfenv doesn't work with Lua 5.2 anymore, but we're using 5.1 | ||||
| local site_config = setfenv(assert(load(coroutine.wrap(loader), 'site.conf')), {})() | ||||
| 
 | ||||
| local setmetatable = setmetatable | ||||
| 
 | ||||
| module 'gluon.site_config' | ||||
| 
 | ||||
| setmetatable(_M, | ||||
| 	{ | ||||
| 		__index = site_config, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| return _M | ||||
							
								
								
									
										34
									
								
								package/gluon-core/files/usr/lib/lua/gluon/sysconfig.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								package/gluon-core/files/usr/lib/lua/gluon/sysconfig.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| local sysconfigdir = '/lib/gluon/core/sysconfig/' | ||||
| 
 | ||||
| local function get(_, name) | ||||
| 	local f = io.open(sysconfigdir .. name) | ||||
| 	if f then | ||||
| 		local ret = f:read('*line') | ||||
| 		f:close() | ||||
| 		return (ret or '') | ||||
| 	end | ||||
| 	return nil | ||||
| end | ||||
| 
 | ||||
| local function set(_, name, val) | ||||
| 	if val then | ||||
| 		local f = io.open(sysconfigdir .. name, 'w+') | ||||
| 		f:write(val) | ||||
| 		f:close() | ||||
| 	else | ||||
| 		os.remove(sysconfigdir .. name) | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| local setmetatable = setmetatable | ||||
| 
 | ||||
| module 'gluon.sysconfig' | ||||
| 
 | ||||
| setmetatable(_M, | ||||
| 	{ | ||||
| 		__index = get, | ||||
| 		__newindex = set, | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| return _M | ||||
							
								
								
									
										8
									
								
								package/gluon-core/files/usr/lib/lua/gluon/sysctl.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								package/gluon-core/files/usr/lib/lua/gluon/sysctl.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| local util = require 'gluon.util' | ||||
| 
 | ||||
| 
 | ||||
| module 'gluon.sysctl' | ||||
| 
 | ||||
| function set(name, value) | ||||
| 	util.replace_prefix('/etc/sysctl.conf', name .. '=', name .. '=' .. value .. '\n') | ||||
| end | ||||
							
								
								
									
										33
									
								
								package/gluon-core/files/usr/lib/lua/gluon/users.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								package/gluon-core/files/usr/lib/lua/gluon/users.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| local util = require 'gluon.util' | ||||
| 
 | ||||
| local os = os | ||||
| local string = string | ||||
| 
 | ||||
| 
 | ||||
| module 'gluon.users' | ||||
| 
 | ||||
| function add_user(username, uid, gid) | ||||
| 	util.lock('/var/lock/passwd') | ||||
| 	util.replace_prefix('/etc/passwd', username .. ':', string.format('%s:*:%u:%u::/var:/bin/false\n', username, uid, gid)) | ||||
| 	util.replace_prefix('/etc/shadow', username .. ':', string.format('%s:*:0:0:99999:7:::\n', username)) | ||||
| 	util.unlock('/var/lock/passwd') | ||||
| end | ||||
| 
 | ||||
| function remove_user(username) | ||||
| 	util.lock('/var/lock/passwd') | ||||
| 	util.replace_prefix('/etc/passwd', username .. ':') | ||||
| 	util.replace_prefix('/etc/shadow', username .. ':') | ||||
| 	util.unlock('/var/lock/passwd') | ||||
| end | ||||
| 
 | ||||
| function add_group(groupname, gid) | ||||
| 	util.lock('/var/lock/group') | ||||
| 	util.replace_prefix('/etc/group', groupname .. ':', string.format('%s:x:%u:\n', groupname, gid)) | ||||
| 	util.unlock('/var/lock/group') | ||||
| end | ||||
| 
 | ||||
| function remove_group(groupname) | ||||
| 	util.lock('/var/lock/group') | ||||
| 	util.replace_prefix('/etc/group', groupname .. ':') | ||||
| 	util.unlock('/var/lock/group') | ||||
| end | ||||
							
								
								
									
										79
									
								
								package/gluon-core/files/usr/lib/lua/gluon/util.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								package/gluon-core/files/usr/lib/lua/gluon/util.lua
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| -- Writes all lines from the file input to the file output except those starting with prefix | ||||
| -- Doesn't close the output file, but returns the file object | ||||
| local function do_filter_prefix(input, output, prefix) | ||||
| 	local f = io.open(output, 'w+') | ||||
| 	local l = prefix:len() | ||||
| 
 | ||||
| 	for line in io.lines(input) do | ||||
| 		if line:sub(1, l) ~= prefix then | ||||
| 			f:write(line, '\n') | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	return f | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| local function escape_args(ret, arg0, ...) | ||||
| 	if not arg0 then | ||||
| 		return ret | ||||
| 	end | ||||
| 
 | ||||
| 	return escape_args(ret .. "'" .. string.gsub(arg0, "'", "'\\''") .. "' ", ...) | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| local os = os | ||||
| local string = string | ||||
| local tonumber = tonumber | ||||
| 
 | ||||
| local nixio = require 'nixio' | ||||
| local sysconfig = require 'gluon.sysconfig' | ||||
| 
 | ||||
| 
 | ||||
| module 'gluon.util' | ||||
| 
 | ||||
| function exec(...) | ||||
| 	return os.execute(escape_args('', ...)) | ||||
| end | ||||
| 
 | ||||
| -- Removes all lines starting with a prefix from a file, optionally adding a new one | ||||
| function replace_prefix(file, prefix, add) | ||||
| 	local tmp = file .. '.tmp' | ||||
| 	local f = do_filter_prefix(file, tmp, prefix) | ||||
| 	if add then | ||||
| 		f:write(add) | ||||
| 	end | ||||
| 	f:close() | ||||
| 	os.rename(tmp, file) | ||||
| end | ||||
| 
 | ||||
| function lock(file) | ||||
| 	exec('lock', file) | ||||
| end | ||||
| 
 | ||||
| function unlock(file) | ||||
| 	exec('lock', '-u', file) | ||||
| end | ||||
| 
 | ||||
| function node_id() | ||||
|   return string.gsub(sysconfig.primary_mac, ':', '') | ||||
| end | ||||
| 
 | ||||
| -- Generates a (hopefully) unique MAC address | ||||
| -- The first parameter defines the function and the second | ||||
| -- parameter an ID to add to the MAC address | ||||
| -- Functions and IDs defined so far: | ||||
| -- (1, 0): WAN (for mesh-on-WAN) | ||||
| -- (1, 1): LAN (for mesh-on-LAN) | ||||
| -- (2, n): client interface for the n'th radio | ||||
| -- (3, n): adhoc interface for n'th radio | ||||
| -- (4, 0): mesh VPN | ||||
| function generate_mac(f, i) | ||||
|   local m1, m2, m3, m4, m5, m6 = string.match(sysconfig.primary_mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)') | ||||
|   m1 = nixio.bit.bor(tonumber(m1, 16), 0x02) | ||||
|   m2 = (tonumber(m2, 16)+f) % 0x100 | ||||
|   m3 = (tonumber(m3, 16)+i) % 0x100 | ||||
| 
 | ||||
|   return string.format('%02x:%02x:%02x:%s:%s:%s', m1, m2, m3, m4, m5, m6) | ||||
| end | ||||
							
								
								
									
										40
									
								
								package/gluon-cron/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								package/gluon-cron/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
| 
 | ||||
| PKG_NAME:=gluon-cron | ||||
| PKG_VERSION:=1 | ||||
| PKG_RELEASE:=1 | ||||
| 
 | ||||
| PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) | ||||
| 
 | ||||
| include $(INCLUDE_DIR)/package.mk | ||||
| 
 | ||||
| define Package/gluon-cron | ||||
|   SECTION:=gluon | ||||
|   CATEGORY:=Gluon | ||||
|   TITLE:=Cron support | ||||
|   DEPENDS:=+gluon-core | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-cron/description | ||||
| 	Gluon community wifi mesh firmware framework: cron support | ||||
| endef | ||||
| 
 | ||||
| define Build/Prepare | ||||
| 	mkdir -p $(PKG_BUILD_DIR) | ||||
| 	$(CP) ./src/* $(PKG_BUILD_DIR)/ | ||||
| endef | ||||
| 
 | ||||
| define Build/Configure | ||||
| endef | ||||
| 
 | ||||
| define Build/Compile | ||||
| 	CFLAGS="$(TARGET_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) | ||||
| endef | ||||
| 
 | ||||
| define Package/gluon-cron/install | ||||
| 	$(CP) ./files/* $(1)/ | ||||
| 	$(INSTALL_DIR) $(1)/usr/sbin | ||||
| 	$(INSTALL_BIN) $(PKG_BUILD_DIR)/gluon-crond $(1)/usr/sbin/ | ||||
| endef | ||||
| 
 | ||||
| $(eval $(call BuildPackage,gluon-cron)) | ||||
							
								
								
									
										18
									
								
								package/gluon-cron/files/etc/init.d/gluon-cron
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								package/gluon-cron/files/etc/init.d/gluon-cron
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,18 @@ | ||||
| #!/bin/sh /etc/rc.common | ||||
| # Copyright (C) 2013 Project Gluon | ||||
| 
 | ||||
| START=50 | ||||
| 
 | ||||
| SERVICE_USE_PID=1 | ||||
| SERVICE_WRITE_PID=1 | ||||
| SERVICE_DAEMONIZE=1 | ||||
| 
 | ||||
| CRONDIR=/lib/gluon/cron | ||||
| 
 | ||||
| start () { | ||||
| 	service_start /usr/sbin/gluon-crond "$CRONDIR" | ||||
| } | ||||
| 
 | ||||
| stop() { | ||||
| 	service_stop /usr/sbin/gluon-crond | ||||
| } | ||||
							
								
								
									
										0
									
								
								package/gluon-cron/files/lib/gluon/cron/.keep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								package/gluon-cron/files/lib/gluon/cron/.keep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										3
									
								
								package/gluon-cron/src/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								package/gluon-cron/src/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| all: gluon-crond | ||||
| 
 | ||||
| gluon-crond: gluon-crond.c | ||||
							
								
								
									
										316
									
								
								package/gluon-cron/src/gluon-crond.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								package/gluon-cron/src/gluon-crond.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,316 @@ | ||||
| /*
 | ||||
|   Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net> | ||||
|   All rights reserved. | ||||
| 
 | ||||
|   Redistribution and use in source and binary forms, with or without | ||||
|   modification, are permitted provided that the following conditions are met: | ||||
| 
 | ||||
|     1. Redistributions of source code must retain the above copyright notice, | ||||
|        this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright notice, | ||||
|        this list of conditions and the following disclaimer in the documentation | ||||
|        and/or other materials provided with the distribution. | ||||
| 
 | ||||
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
|   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
|   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
|   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
|   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
|   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/time.h> | ||||
| #include <dirent.h> | ||||
| #include <signal.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <strings.h> | ||||
| #include <syslog.h> | ||||
| #include <time.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| 
 | ||||
| typedef struct job { | ||||
| 	struct job *next; | ||||
| 
 | ||||
| 	uint64_t minutes; | ||||
| 	uint32_t hours; | ||||
| 	uint32_t doms; | ||||
| 	uint16_t months; | ||||
| 	uint8_t dows; | ||||
| 
 | ||||
| 	char *command; | ||||
| } job_t; | ||||
| 
 | ||||
| 
 | ||||
| static const char const *const MONTHS[12] = { | ||||
| 	"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" | ||||
| }; | ||||
| 
 | ||||
| static const char const *const WEEKDAYS[7] = { | ||||
| 	"sun", "mon", "tue", "wed", "thu", "fri", "sat" | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static const char *crondir; | ||||
| 
 | ||||
| static job_t *jobs = NULL; | ||||
| 
 | ||||
| 
 | ||||
| static void usage(void) { | ||||
| 	fprintf(stderr, "Usage: gluon-crond <crondir>\n"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static inline uint64_t bit(unsigned b) { | ||||
| 	return ((uint64_t)1) << b; | ||||
| } | ||||
| 
 | ||||
| static int strict_atoi(const char *s) { | ||||
| 	char *end; | ||||
| 	int ret = strtol(s, &end, 10); | ||||
| 
 | ||||
| 	if (*end) | ||||
| 		return -1; | ||||
| 	else | ||||
| 		return ret; | ||||
| } | ||||
| 
 | ||||
| static uint64_t parse_strings(const char *input, const char *const *strings, size_t n) { | ||||
| 	size_t i; | ||||
| 	for (i = 0; i < n; i++) { | ||||
| 		if (strcasecmp(input, strings[i]) == 0) | ||||
| 			return bit(i); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static uint64_t parse_times(char *input, int min, int n) { | ||||
| 	uint64_t ret = 0; | ||||
| 	int step = 1; | ||||
| 
 | ||||
| 	char *comma = strchr(input, ','); | ||||
| 	if (comma) { | ||||
| 		*comma = 0; | ||||
| 		ret = parse_times(comma+1, min, n); | ||||
| 
 | ||||
| 		if (!ret) | ||||
| 			return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	char *slash = strchr(input, '/'); | ||||
| 	if (slash) { | ||||
| 		*slash = 0; | ||||
| 		step = strict_atoi(slash+1); | ||||
| 
 | ||||
| 		if (step <= 0) | ||||
| 			return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	int begin, end; | ||||
| 	char *minus = strchr(input, '-'); | ||||
| 	if (minus) { | ||||
| 		*minus = 0; | ||||
| 		begin = strict_atoi(input); | ||||
| 		end = strict_atoi(minus+1); | ||||
| 	} | ||||
| 	else if (strcmp(input, "*") == 0) { | ||||
| 		begin = min; | ||||
| 		end = min+n-1; | ||||
| 	} | ||||
| 	else { | ||||
| 		begin = end = strict_atoi(input); | ||||
| 	} | ||||
| 
 | ||||
| 	if (begin < min || end < min) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	int i; | ||||
| 	for (i = begin-min; i <= end-min; i += step) | ||||
| 		ret |= bit(i % n); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int handle_line(const char *line) { | ||||
| 	job_t job = {}; | ||||
| 	int ret = -1; | ||||
| 	char *columns[5]; | ||||
| 	int i; | ||||
| 	int len; | ||||
| 
 | ||||
| 	int matches = sscanf(line, "%ms %ms %ms %ms %ms %n", &columns[0], &columns[1], &columns[2], &columns[3], &columns[4], &len); | ||||
| 	if (matches != 5 && matches != 6) { | ||||
| 		if (matches <= 0) | ||||
| 			ret = 0; | ||||
| 
 | ||||
| 		goto end; | ||||
| 	} | ||||
| 
 | ||||
| 	job.minutes = parse_times(columns[0], 0, 60); | ||||
| 	if (!job.minutes) | ||||
| 		goto end; | ||||
| 
 | ||||
| 	job.hours = parse_times(columns[1], 0, 24); | ||||
| 	if (!job.hours) | ||||
| 		goto end; | ||||
| 
 | ||||
| 	job.doms = parse_times(columns[2], 1, 31); | ||||
| 	if (!job.doms) | ||||
| 		goto end; | ||||
| 
 | ||||
| 
 | ||||
| 	job.months = parse_strings(columns[3], MONTHS, 12); | ||||
| 
 | ||||
| 	if (!job.months) | ||||
| 		job.months = parse_times(columns[3], 1, 12); | ||||
| 	if (!job.months) | ||||
| 		goto end; | ||||
| 
 | ||||
| 	job.dows = parse_strings(columns[4], WEEKDAYS, 7); | ||||
| 	if (!job.dows) | ||||
| 		job.dows = parse_times(columns[4], 0, 7); | ||||
| 	if (!job.dows) | ||||
| 		goto end; | ||||
| 
 | ||||
| 	job.command = strdup(line+len); | ||||
| 
 | ||||
| 	job_t *jobp = malloc(sizeof(job_t)); | ||||
| 	*jobp = job; | ||||
| 
 | ||||
| 	jobp->next = jobs; | ||||
| 	jobs = jobp; | ||||
| 
 | ||||
| 	ret = 0; | ||||
| 
 | ||||
|   end: | ||||
| 	for (i = 0; i < matches && i < 5; i++) | ||||
| 		free(columns[i]); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void read_crontab(const char *name) { | ||||
| 	FILE *file = fopen(name, "r"); | ||||
| 	if (!file) { | ||||
| 		syslog(LOG_WARNING, "unable to read crontab `%s'", name); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	char line[16384]; | ||||
| 	unsigned lineno = 0; | ||||
| 
 | ||||
| 	while (fgets(line, sizeof(line), file)) { | ||||
| 		lineno++; | ||||
| 
 | ||||
| 		char *comment = strchr(line, '#'); | ||||
| 		if (comment) | ||||
| 			*comment = 0; | ||||
| 
 | ||||
| 		if (handle_line(line)) | ||||
| 			syslog(LOG_WARNING, "syntax error in `%s', line %u", name, lineno); | ||||
| 	} | ||||
| 
 | ||||
| 	fclose(file); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void read_crondir(void) { | ||||
| 	DIR *dir; | ||||
| 
 | ||||
| 	if (chdir(crondir) || ((dir = opendir(".")) == NULL)) { | ||||
| 		fprintf(stderr, "Unable to read crondir `%s'\n", crondir); | ||||
| 		usage(); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	struct dirent *ent; | ||||
| 	while ((ent = readdir(dir)) != NULL) { | ||||
| 		if (ent->d_name[0] == '.') | ||||
| 			continue; | ||||
| 
 | ||||
| 		read_crontab(ent->d_name); | ||||
| 	} | ||||
| 
 | ||||
| 	closedir(dir); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void run_job(const job_t *job) { | ||||
| 	pid_t pid = fork(); | ||||
| 	if (pid == 0) { | ||||
| 		execl("/bin/sh", "/bin/sh", "-c", job->command, (char*)NULL); | ||||
| 		syslog(LOG_ERR, "unable to run job: exec failed"); | ||||
| 		_exit(1); | ||||
| 	} | ||||
| 	else if (pid < 0) { | ||||
| 		syslog(LOG_ERR, "unable to run job: fork failed"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void check_job(const job_t *job, const struct tm *tm) { | ||||
| 	if (!(job->minutes & bit(tm->tm_min))) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (!(job->hours & bit(tm->tm_hour))) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (!(job->doms & bit(tm->tm_mday-1))) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (!(job->months & bit(tm->tm_mon))) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (!(job->dows & bit(tm->tm_wday))) | ||||
| 		return; | ||||
| 
 | ||||
| 	run_job(job); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int main(int argc, char *argv[]) { | ||||
| 	if (argc != 2) { | ||||
| 		usage(); | ||||
| 
 | ||||
| 		exit(argc < 2 ? 0 : 1); | ||||
| 	} | ||||
| 
 | ||||
| 	crondir = argv[1]; | ||||
| 
 | ||||
| 	signal(SIGCHLD, SIG_IGN); | ||||
| 
 | ||||
| 	read_crondir(); | ||||
| 
 | ||||
| 	time_t t = time(NULL); | ||||
| 	struct tm *tm = localtime(&t); | ||||
| 	int minute = tm->tm_min; | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		sleep(60 - t%60); | ||||
| 
 | ||||
| 		t = time(NULL); | ||||
| 		tm = localtime(&t); | ||||
| 
 | ||||
| 		minute = (minute+1)%60; | ||||
| 		if (tm->tm_min != minute) { | ||||
| 			/* clock has moved, don't execute jobs */ | ||||
| 			minute = tm->tm_min; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		job_t *job; | ||||
| 		for (job = jobs; job; job = job->next) | ||||
| 			check_job(job, tm); | ||||
| 	} | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user