gluon-mesh-babel: HACK: basic, experimental babel config
This commit is contained in:
		
							parent
							
								
									33264bec97
								
							
						
					
					
						commit
						3247ca0e4a
					
				
							
								
								
									
										36
									
								
								package/gluon-mesh-babel/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								package/gluon-mesh-babel/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					include $(TOPDIR)/rules.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PKG_NAME:=gluon-mesh-babel
 | 
				
			||||||
 | 
					PKG_VERSION:=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(GLUONDIR)/include/package.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Package/gluon-mesh-babel
 | 
				
			||||||
 | 
					  SECTION:=gluon
 | 
				
			||||||
 | 
					  CATEGORY:=Gluon
 | 
				
			||||||
 | 
					  TITLE:=Babel mesh
 | 
				
			||||||
 | 
					  DEPENDS:=+gluon-core +babeld
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Build/Prepare
 | 
				
			||||||
 | 
						mkdir -p $(PKG_BUILD_DIR)
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Build/Configure
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Build/Compile
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Package/gluon-mesh-babel/install
 | 
				
			||||||
 | 
						$(CP) ./files/* $(1)/
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define Package/gluon-mesh-babel/postinst
 | 
				
			||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					$(call GluonCheckSite,check_site.lua)
 | 
				
			||||||
 | 
					endef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(eval $(call BuildPackage,gluon-mesh-babel))
 | 
				
			||||||
							
								
								
									
										2
									
								
								package/gluon-mesh-babel/check_site.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								package/gluon-mesh-babel/check_site.lua
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					need_string_match('babel_mesh.prefix', '^[%x:]+/64$')
 | 
				
			||||||
 | 
					need_boolean('mesh_on_wan', false)
 | 
				
			||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/lua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local uci = require('luci.model.uci').cursor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('firewall', 'rule', 'wan_babel',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    name = 'wan_babel',
 | 
				
			||||||
 | 
					    src = 'wan',
 | 
				
			||||||
 | 
					    src_ip = 'fe80::/64',
 | 
				
			||||||
 | 
					    dest_port = '6696',
 | 
				
			||||||
 | 
					    proto = 'udp',
 | 
				
			||||||
 | 
					    target = 'ACCEPT',
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('firewall', 'zone', 'mesh_babel',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    name = 'mesh_babel',
 | 
				
			||||||
 | 
					    input = 'ACCEPT',
 | 
				
			||||||
 | 
					    output = 'ACCEPT',
 | 
				
			||||||
 | 
					    forward = 'ACCEPT',
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:save('firewall')
 | 
				
			||||||
 | 
					uci:commit('firewall')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										104
									
								
								package/gluon-mesh-babel/files/lib/gluon/upgrade/300-gluon-mesh-babel-ip6
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										104
									
								
								package/gluon-mesh-babel/files/lib/gluon/upgrade/300-gluon-mesh-babel-ip6
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/lua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local nixio = require 'nixio'
 | 
				
			||||||
 | 
					local sysconfig = require 'gluon.sysconfig'
 | 
				
			||||||
 | 
					local uci = require('luci.model.uci').cursor()
 | 
				
			||||||
 | 
					local site = require 'gluon.site_config'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function IPv6(address)
 | 
				
			||||||
 | 
					--[[
 | 
				
			||||||
 | 
					(c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
 | 
				
			||||||
 | 
					(c) 2008 Steven Barth <steven@midlink.org>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License").
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						        http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					]]--
 | 
				
			||||||
 | 
						local data = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local borderl = address:sub(1, 1) == ":" and 2 or 1
 | 
				
			||||||
 | 
						local borderh, zeroh, chunk, block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if #address > 45 then return nil end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						repeat
 | 
				
			||||||
 | 
							borderh = address:find(":", borderl, true)
 | 
				
			||||||
 | 
							if not borderh then break end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							block = tonumber(address:sub(borderl, borderh - 1), 16)
 | 
				
			||||||
 | 
							if block and block <= 0xFFFF then
 | 
				
			||||||
 | 
								data[#data+1] = block
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								if zeroh or borderh - borderl > 1 then return nil end
 | 
				
			||||||
 | 
								zeroh = #data + 1
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							borderl = borderh + 1
 | 
				
			||||||
 | 
						until #data == 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chunk = address:sub(borderl)
 | 
				
			||||||
 | 
						if #chunk > 0 and #chunk <= 4 then
 | 
				
			||||||
 | 
							block = tonumber(chunk, 16)
 | 
				
			||||||
 | 
							if not block or block > 0xFFFF then return nil end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							data[#data+1] = block
 | 
				
			||||||
 | 
						elseif #chunk > 4 then
 | 
				
			||||||
 | 
							if #data == 7 or #chunk > 15 then return nil end
 | 
				
			||||||
 | 
							borderl = 1
 | 
				
			||||||
 | 
							for i=1, 4 do
 | 
				
			||||||
 | 
								borderh = chunk:find(".", borderl, true)
 | 
				
			||||||
 | 
								if not borderh and i < 4 then return nil end
 | 
				
			||||||
 | 
								borderh = borderh and borderh - 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								block = tonumber(chunk:sub(borderl, borderh))
 | 
				
			||||||
 | 
								if not block or block > 255 then return nil end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if i == 1 or i == 3 then
 | 
				
			||||||
 | 
									data[#data+1] = block * 256
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									data[#data] = data[#data] + block
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								borderl = borderh and borderh + 2
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if zeroh then
 | 
				
			||||||
 | 
							if #data == 8 then return nil end
 | 
				
			||||||
 | 
							while #data < 8 do
 | 
				
			||||||
 | 
								table.insert(data, zeroh, 0)
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if #data == 8 then
 | 
				
			||||||
 | 
							return data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function mac_to_ip(prefix, mac)
 | 
				
			||||||
 | 
					  local m1, m2, m3, m6, m7, m8 = string.match(mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)')
 | 
				
			||||||
 | 
					  local m4 = 0xff
 | 
				
			||||||
 | 
					  local m5 = 0xfe
 | 
				
			||||||
 | 
					  m1 = nixio.bit.bxor(tonumber(m1, 16), 0x02)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local h1 = 0x100 * m1 + tonumber(m2, 16)
 | 
				
			||||||
 | 
					  local h2 = 0x100 * tonumber(m3, 16) + m4
 | 
				
			||||||
 | 
					  local h3 = 0x100 * m5 + tonumber(m6, 16)
 | 
				
			||||||
 | 
					  local h4 = 0x100 * tonumber(m7, 16) + tonumber(m8, 16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local prefix, plen = string.match(prefix, '(.*)/(%d+)')
 | 
				
			||||||
 | 
					  plen = tonumber(plen, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  local p1, p2, p3, p4, p5, p6, p7, p8 = IPv6(prefix)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return string.format("%x:%x:%x:%x:%x:%x:%x:%x/%d", p1, p2, p3, p4, h1, h2, h3, h4, 128)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local ip = mac_to_ip(site.babel_mesh.prefix, sysconfig.primary_mac)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:set('network', 'loopback', 'ip6addr', ip)
 | 
				
			||||||
 | 
					uci:save('network')
 | 
				
			||||||
 | 
					uci:commit('network')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										34
									
								
								package/gluon-mesh-babel/files/lib/gluon/upgrade/300-gluon-mesh-babel-tables
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										34
									
								
								package/gluon-mesh-babel/files/lib/gluon/upgrade/300-gluon-mesh-babel-tables
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/lua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local uci = require('luci.model.uci').cursor()
 | 
				
			||||||
 | 
					local site = require 'gluon.site_config'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('babeld', 'general', 'gluon',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    export_table = 10,
 | 
				
			||||||
 | 
					    import_table = {
 | 
				
			||||||
 | 
					      255,
 | 
				
			||||||
 | 
					      11,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('network', 'rule6', 'babel_import_lookup',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    lookup = 11,
 | 
				
			||||||
 | 
					    priority = 64000,
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('network', 'rule6', 'babel_export_lookup',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    lookup = 10,
 | 
				
			||||||
 | 
					    priority = 64100,
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:save('babeld')
 | 
				
			||||||
 | 
					uci:save('network')
 | 
				
			||||||
 | 
					uci:commit('babeld')
 | 
				
			||||||
 | 
					uci:commit('network')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/lua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local uci = require('luci.model.uci').cursor()
 | 
				
			||||||
 | 
					local site = require 'gluon.site_config'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('babeld', 'filter', 'mesh_prefix',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    type = 'redistribute',
 | 
				
			||||||
 | 
					    ip = site.babel_mesh.prefix,
 | 
				
			||||||
 | 
					    eq = 128,
 | 
				
			||||||
 | 
					    action = 'allow',
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('babeld', 'filter', 'client_prefix',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    type = 'redistribute',
 | 
				
			||||||
 | 
					    ip = site.prefix6,
 | 
				
			||||||
 | 
					    eq = 128,
 | 
				
			||||||
 | 
					    action = 'allow',
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('babeld', 'filter', 'client_prefix',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    type = 'redistribute',
 | 
				
			||||||
 | 
					    ip = site.prefix6,
 | 
				
			||||||
 | 
					    eq = 128,
 | 
				
			||||||
 | 
					    action = 'allow',
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('babeld', 'filter', 'local_deny',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    type = 'redistribute',
 | 
				
			||||||
 | 
					    ['local'] = 1, -- local is a keyword
 | 
				
			||||||
 | 
					    action = 'deny',
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:section('babeld', 'filter', 'defaultroute',
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    type = 'redistribute',
 | 
				
			||||||
 | 
					    ip = '::/0',
 | 
				
			||||||
 | 
					    eq = 0,
 | 
				
			||||||
 | 
					    action = 'allow',
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:save('babeld')
 | 
				
			||||||
 | 
					uci:commit('babeld')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/lua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local site = require 'gluon.site_config'
 | 
				
			||||||
 | 
					local util = require 'gluon.util'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local uci = require('luci.model.uci').cursor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local function is_disabled(config, name)
 | 
				
			||||||
 | 
					  local disabled = config and config.disabled
 | 
				
			||||||
 | 
					  if uci:get('wireless', name) then
 | 
				
			||||||
 | 
					    disabled = uci:get_bool('wireless', name, 'disabled')
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return disabled and 1 or 0
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local function configure_mesh(config, radio, index, suffix)
 | 
				
			||||||
 | 
					  local name = 'mesh_' .. radio
 | 
				
			||||||
 | 
					  local disabled = is_disabled(config, name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uci:delete('network', name)
 | 
				
			||||||
 | 
					  uci:delete('wireless', name)
 | 
				
			||||||
 | 
					  uci:delete('babeld', name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if config then
 | 
				
			||||||
 | 
					    uci:section('network', 'interface', name,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        proto = 'none',
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local ifname = 'mesh' .. suffix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uci:section('wireless', 'wifi-iface', name,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        device = radio,
 | 
				
			||||||
 | 
					        network = name,
 | 
				
			||||||
 | 
					        mode = 'mesh',
 | 
				
			||||||
 | 
					        mesh_id = config.id,
 | 
				
			||||||
 | 
					        mesh_fwding = 0,
 | 
				
			||||||
 | 
					        mcast_rate = config.mcast_rate,
 | 
				
			||||||
 | 
					        ifname = ifname,
 | 
				
			||||||
 | 
					        disabled = disabled,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uci:section('babeld', 'interface', name,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        ifname = ifname,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local networks = uci:get_list('firewall', 'mesh_babel', 'network')
 | 
				
			||||||
 | 
					    local set = {}
 | 
				
			||||||
 | 
					    for _, l in ipairs(networks) do set[l] = true end
 | 
				
			||||||
 | 
					    set[name] = true
 | 
				
			||||||
 | 
					    networks = {}
 | 
				
			||||||
 | 
					    for k, _ in pairs(set) do table.insert(networks, k) end
 | 
				
			||||||
 | 
					    uci:set_list('firewall', 'mesh_babel', 'network', networks)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local function configure_radio(radio, index, config)
 | 
				
			||||||
 | 
					  local suffix = radio:match('^radio(%d+)$')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  configure_mesh(config.mesh, radio, index, suffix)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					util.iterate_radios(configure_radio)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:save('wireless')
 | 
				
			||||||
 | 
					uci:save('network')
 | 
				
			||||||
 | 
					uci:save('babeld')
 | 
				
			||||||
 | 
					uci:save('firewall')
 | 
				
			||||||
 | 
					uci:commit('wireless')
 | 
				
			||||||
 | 
					uci:commit('network')
 | 
				
			||||||
 | 
					uci:commit('babeld')
 | 
				
			||||||
 | 
					uci:commit('firewall')
 | 
				
			||||||
@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/lua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local uci = require('luci.model.uci').cursor()
 | 
				
			||||||
 | 
					local site = require 'gluon.site_config'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if site.mesh_on_wan then
 | 
				
			||||||
 | 
					  uci:section('babeld', 'interface', 'mesh_wan',
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ifname = 'br-wan',
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uci:add_to_set('firewall', 'mesh_babel', 'network', 'wan')
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:add_to_set('firewall', 'mesh_babel', 'network', 'client')
 | 
				
			||||||
 | 
					uci:add_to_set('firewall', 'mesh_babel', 'network', 'local_node4')
 | 
				
			||||||
 | 
					uci:add_to_set('firewall', 'mesh_babel', 'network', 'local_node6')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uci:save('babeld')
 | 
				
			||||||
 | 
					uci:save('firewall')
 | 
				
			||||||
 | 
					uci:commit('babeld')
 | 
				
			||||||
 | 
					uci:commit('firewall')
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user